From 59816998adee12467ecdfe33c8582497d5f5c46d Mon Sep 17 00:00:00 2001
From: Chris Kearney <chris@kearneymail.com>
Date: Sat, 13 May 2017 16:44:25 -0700
Subject: [PATCH] refactor of the json file persistence so that i can share
 code- merchant updates to support json format

---
 .../commands/admin/LoadItemCommand.java       |   2 +-
 .../creeper/configuration/ConfigureNpc.java   |  15 +-
 .../creeper/core_game/GameManager.java        |   9 +-
 .../comandante/creeper/items/ItemType.java    | 704 +++++++++---------
 .../creeper/merchant/BlackbeardRogue.java     |   5 +-
 .../creeper/merchant/Blacksmith.java          |   5 +-
 .../creeper/merchant/GrimulfWizard.java       |   5 +-
 .../creeper/merchant/JimBanker.java           |   5 +-
 .../creeper/merchant/KetilCommissary.java     |   5 +-
 .../creeper/merchant/LloydBartender.java      |   5 +-
 .../creeper/merchant/LockerRoomGuy.java       |   5 +-
 .../comandante/creeper/merchant/Merchant.java |  36 +-
 .../creeper/merchant/MerchantManager.java     |  14 +-
 .../creeper/merchant/MerchantMetadata.java    |  53 ++
 .../creeper/merchant/NigelBartender.java      |   5 +-
 .../creeper/merchant/OldWiseMan.java          |   5 +-
 .../creeper/merchant/WentworthTailor.java     |   5 +-
 .../comandante/creeper/merchant/Wizard.java   |   5 +-
 .../creeper/player/PlayerMetadata.java        |   2 +-
 .../creeper/storage/FilebasedJsonStorage.java |  68 ++
 .../creeper/storage/ItemStorage.java          |  70 +-
 .../creeper/storage/NpcStorage.java           |  61 +-
 .../creeper/items/ItemMetadataTest.java       | 231 +++---
 23 files changed, 671 insertions(+), 649 deletions(-)
 create mode 100644 src/main/java/com/comandante/creeper/merchant/MerchantMetadata.java
 create mode 100644 src/main/java/com/comandante/creeper/storage/FilebasedJsonStorage.java

diff --git a/src/main/java/com/comandante/creeper/command/commands/admin/LoadItemCommand.java b/src/main/java/com/comandante/creeper/command/commands/admin/LoadItemCommand.java
index 2512eddd..7597911d 100644
--- a/src/main/java/com/comandante/creeper/command/commands/admin/LoadItemCommand.java
+++ b/src/main/java/com/comandante/creeper/command/commands/admin/LoadItemCommand.java
@@ -73,7 +73,7 @@ public class LoadItemCommand extends Command {
             }
             httpGet.reset();
 
-            gameManager.getItemStorage().saveItemMetaData(itemMetadata);
+            gameManager.getItemStorage().saveItemMetadata(itemMetadata);
             write("Item Saved. - " + itemMetadata.getInternalItemName() + "\r\n");
 
         });
diff --git a/src/main/java/com/comandante/creeper/configuration/ConfigureNpc.java b/src/main/java/com/comandante/creeper/configuration/ConfigureNpc.java
index 2999e9b4..22a44afa 100644
--- a/src/main/java/com/comandante/creeper/configuration/ConfigureNpc.java
+++ b/src/main/java/com/comandante/creeper/configuration/ConfigureNpc.java
@@ -6,10 +6,13 @@ import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.entity.EntityManager;
 import com.comandante.creeper.items.Forage;
 import com.comandante.creeper.items.ItemMetadata;
+import com.comandante.creeper.merchant.LloydBartender;
+import com.comandante.creeper.merchant.MerchantItemForSale;
 import com.comandante.creeper.npc.Npc;
 import com.comandante.creeper.spawner.ItemSpawner;
 import com.comandante.creeper.spawner.NpcSpawner;
 import com.comandante.creeper.spawner.SpawnRule;
+import com.google.common.collect.Lists;
 
 import java.io.IOException;
 import java.util.List;
@@ -63,13 +66,13 @@ public class ConfigureNpc {
 //        entityManager.addEntity(itemSpawner2);
 //        entityManager.addEntity(itemSpawner5);
 
-//        Map<Integer, MerchantItemForSale> itemsForSale = Maps.newLinkedHashMap();
-//        itemsForSale.put(1, new MerchantItemForSale(ItemType.SMALL_HEALTH_POTION, 8));
-//        itemsForSale.put(2, new MerchantItemForSale(ItemType.PURPLE_DRANK, 80));
-//        itemsForSale.put(3, new MerchantItemForSale(ItemType.BIGGERS_SKIN_SATCHEL, 25000));
+        List<MerchantItemForSale> itemsForSale = Lists.newArrayList();
+        itemsForSale.add(new MerchantItemForSale("small health potion", 8));
+        itemsForSale.add(new MerchantItemForSale("purple drank", 80));
+        itemsForSale.add(new MerchantItemForSale("biggers skin satchel", 25000));
 //
-//        LloydBartender lloydBartender = new LloydBartender(gameManager, new Loot(18, 26, Sets.<ItemType>newHashSet()), itemsForSale);
-//        gameManager.getRoomManager().addMerchant(64, lloydBartender);
+        LloydBartender lloydBartender = new LloydBartender(gameManager, itemsForSale);
+        gameManager.getRoomManager().addMerchant(64, lloydBartender);
 //
 //        Map<Integer, MerchantItemForSale> nigelForSale = Maps.newLinkedHashMap();
 //        nigelForSale.put(1, new MerchantItemForSale(ItemType.SMALL_HEALTH_POTION, 6));
diff --git a/src/main/java/com/comandante/creeper/core_game/GameManager.java b/src/main/java/com/comandante/creeper/core_game/GameManager.java
index fe69c9dc..ba31db77 100644
--- a/src/main/java/com/comandante/creeper/core_game/GameManager.java
+++ b/src/main/java/com/comandante/creeper/core_game/GameManager.java
@@ -26,6 +26,7 @@ import com.comandante.creeper.stats.Levels;
 import com.comandante.creeper.stats.Stats;
 import com.comandante.creeper.stats.StatsBuilder;
 import com.comandante.creeper.stats.modifier.StatsModifierFactory;
+import com.comandante.creeper.storage.FilebasedJsonStorage;
 import com.comandante.creeper.storage.ItemStorage;
 import com.comandante.creeper.storage.NpcStorage;
 import com.comandante.creeper.world.FloorManager;
@@ -89,7 +90,7 @@ public class GameManager {
     private final ItemStorage itemStorage;
     private final HttpClient httpclient;
     private final Gson gson;
-
+    private final FilebasedJsonStorage filebasedJsonStorage;
 
 
     public GameManager(CreeperConfiguration creeperConfiguration, RoomManager roomManager, PlayerManager playerManager, EntityManager entityManager, MapsManager mapsManager, ChannelCommunicationUtils channelUtils, HttpClient httpClient) {
@@ -120,9 +121,9 @@ public class GameManager {
         this.eventProcessor.startAsync();
         this.detainmentRoom = buildDetainmentRoom();
         this.gson = new GsonBuilder().setPrettyPrinting().create();
-        this.npcStorage = new NpcStorage(this, gson);
-        this.itemStorage = new ItemStorage(gson);
-
+        this.filebasedJsonStorage = new FilebasedJsonStorage(gson);
+        this.npcStorage = new NpcStorage(this, filebasedJsonStorage);
+        this.itemStorage = new ItemStorage(filebasedJsonStorage);
         this.httpclient = httpClient;
     }
 
diff --git a/src/main/java/com/comandante/creeper/items/ItemType.java b/src/main/java/com/comandante/creeper/items/ItemType.java
index fe1d2988..eeb30d0e 100644
--- a/src/main/java/com/comandante/creeper/items/ItemType.java
+++ b/src/main/java/com/comandante/creeper/items/ItemType.java
@@ -1,352 +1,352 @@
-//package com.comandante.creeper.items;
-//
-//import com.comandante.creeper.core_game.service.TimeTracker;
-//import com.comandante.creeper.server.player_communication.Color;
-//import com.google.common.collect.Sets;
-//
-//import java.util.Arrays;
-//import java.util.List;
-//import java.util.Set;
-//
-//import static com.comandante.creeper.server.player_communication.Color.*;
-//
-//public enum ItemType {
-//
-//    UNKNOWN(0, Arrays.asList(""), "", "", "", false, 0, 0, false, com.comandante.creeper.items.Rarity.RARE, 0, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//    KEY(1, Arrays.asList("key", "gold key", "shiny gold key"),
-//            "a shiny " + YELLOW + "gold key" + RESET,
-//            "a shiny " + YELLOW + "gold key" + RESET + " catches your eye.",
-//            "A basic key with nothing really remarkable other than its made of gold.",
-//            false,
-//            0,
-//            60,
-//            false,
-//            Rarity.BASIC,
-//            10, Sets.<TimeTracker.TimeOfDay>newHashSet(TimeTracker.TimeOfDay.NIGHT)),
-//
-//    SMALL_HEALTH_POTION(2, Arrays.asList("potion", "health potion", "vial", "small vial of health potion", "p"),
-//            "a small vial of " + RED + "health potion" + RESET,
-//            "a small vial of " + RED + "health potion" + RESET + " rests on the ground.",
-//            "a small vial of " + RED + "health potion" + RESET + " that restores 50 health" + RESET,
-//            true,
-//            0,
-//            60,
-//            false,
-//            Rarity.OFTEN,
-//            1, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BERSERKER_BATON(3, Arrays.asList("baton", "a berserker baton", "b"),
-//            Color.CYAN + "a berserker baton" + Color.RESET,
-//            "a berserker baton rests upon the ground.",
-//            "a berserker baton",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            100, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BERSEKER_BOOTS(4, Arrays.asList("boots", "boot", "berserker boots", "b"),
-//            Color.CYAN + "berserker boots" + Color.RESET,
-//            "a pair of berserker boots are here on the ground.",
-//            "a pair of berserker boots",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            50, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BERSERKER_CHEST(5, Arrays.asList("chest", "berserker chest", "c"),
-//            Color.CYAN + "berserker chest" + Color.RESET,
-//            "a berserker chest is on the ground.",
-//            "a berserker chest",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            70, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BERSEKER_SHORTS(6, Arrays.asList("shorts", "berserker shorts", "s"),
-//            Color.CYAN + "berserker shorts" + Color.RESET,
-//            "a pair of berserker shorts are here on the ground.",
-//            "a pair of berserker shorts",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            80, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BERSERKER_BRACERS(7, Arrays.asList("bracers", "berserker bracers", "b"),
-//            Color.CYAN + "berserker bracers" + Color.RESET,
-//            "a pair of berserker bracers are here on the ground.",
-//            "a pair of berserker bracers",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            40, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BERSEKER_HELM(8, Arrays.asList("helm", "berserker helm", "h"),
-//            Color.CYAN + "berserker helm" + Color.RESET,
-//            "a berserker helm is on the ground.",
-//            "a berserker helm",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            40, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    MARIJUANA(9, Arrays.asList("marijuana", "weed", "m", "w", "f", "flowers"),
-//            Color.GREEN + "marijuana" + Color.RESET + " flowers" + Color.RESET,
-//            "some " + Color.GREEN + "marijuana" + Color.RESET + " flowers" + Color.RESET + " are here on the ground.",
-//            "some " + Color.GREEN + "marijuana" + Color.RESET + " flowers" + Color.RESET,
-//            true,
-//            0,
-//            60,
-//            false,
-//            Rarity.BASIC,
-//            10, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    PURPLE_DRANK(10, Arrays.asList("drank", "purple drank", "p", "purple", "lean", "sizzurp"),
-//            "a double cup of " + MAGENTA + "purple" + RESET + " drank",
-//            "a double cup of " + MAGENTA + "purple" + RESET + " drank rests on the ground.",
-//            "a tonic called " + MAGENTA + "purple" + RESET + " drank that restores health" + RESET,
-//            true,
-//            0,
-//            60,
-//            false,
-//            Rarity.BASIC,
-//            30, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    LEATHER_SATCHEL(11, Arrays.asList("leather satchel", "satchel"),
-//            "a " + Color.GREEN + "leather satchel" + Color.RESET,
-//            "a " + Color.GREEN + "leather satchel" + Color.RESET,
-//            "a " + Color.GREEN + "leather satchel" + Color.RESET + " (15 items)",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            800, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    BIGGERS_SKIN_SATCHEL(12, Arrays.asList("biggers skin satchel", "skin satchel"),
-//            "a " + Color.GREEN + "biggers skin satchel" + Color.RESET,
-//            "a " + Color.GREEN + "biggers skin satchel" + Color.RESET,
-//            "a " + Color.GREEN + "biggers skin satchel" + Color.RESET + " with room to store 100 items.",
-//            false,
-//            0,
-//            60,
-//            true,
-//            Rarity.BASIC,
-//            3000, Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    LIGHTNING_SPELLBOOKNG(
-//            // itemTypeCode
-//            13,
-//            // triggers
-//            Arrays.asList("lightning book", "lightning spell book", "book", "spell book"),
-//            // name
-//            "a " + Color.YELLOW + "lightning" + Color.RESET + " spell book." + Color.RESET,
-//            // resting name
-//            "a " + Color.YELLOW + "lightning" + Color.RESET + " spell book." + Color.RESET,
-//            // description
-//            "a " + Color.YELLOW + "lightning" + Color.RESET + " spell book." + Color.RESET,
-//            // disposable?
-//            true,
-//            // max uses
-//            0,
-//            // half life ticks
-//            60,
-//            // equipment/can you wear it?
-//            false,
-//            // controls how often it will spawn (if configured in a spawn)
-//            Rarity.RARE,
-//            // default sell value (gold)
-//            3000,
-//            // Some items have time of days where they are "valid" and times when they are not.  If they are not valid for MORNING (for example) they will turn to dust as soon as the world switches to morning.
-//            Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//    STICK_OF_JUSTICE(
-//            // itemTypeCode
-//            14,
-//            // triggers
-//            Arrays.asList("stick of justice", "justice", "stick"),
-//            // name
-//            "a " + Color.BOLD_ON + Color.MAGENTA + "stick" + Color.BOLD_OFF + Color.GREEN + " of " + Color.BOLD_ON + Color.BLUE + "justice" + Color.RESET,
-//            // resting name
-//            "a " + Color.BOLD_ON + Color.MAGENTA + "stick" + Color.BOLD_OFF + Color.GREEN + " of " + Color.BOLD_ON + Color.BLUE + "justice" + Color.RESET,
-//            // description
-//            "a " + Color.BOLD_ON + Color.MAGENTA + "stick" + Color.BOLD_OFF + Color.GREEN + " of " + Color.BOLD_ON + Color.BLUE + "justice" + Color.RESET,
-//            // disposable?
-//            true,
-//            // max uses
-//            0,
-//            // half life ticks
-//            60,
-//            // equipment/can you wear it?
-//            false,
-//            // controls how often it will spawn (if configured in a spawn)
-//            Rarity.RARE,
-//            // default sell value (gold)
-//            3000,
-//            // Some items have time of days where they are "valid" and times when they are not.  If they are not valid for MORNING (for example) they will turn to dust as soon as the world switches to morning.
-//            Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    RED_CLAW_BEANIE(
-//            // itemTypeCode
-//            15,
-//            // triggers
-//            Arrays.asList("beanie", "red-claw beanie", "b"),
-//            // name
-//            Color.RED + "red-claw " + Color.RESET + "beanie" + Color.RESET,
-//            // resting name
-//            "a " + Color.RED + "red-claw " + Color.RESET + "beanie is on the ground.",
-//            // description
-//            "a red-claw beanie",
-//            // disposable?
-//            false,
-//            // max uses
-//            0,
-//            // half life ticks
-//            60,
-//            // equipment?
-//            true,
-//            Rarity.LEGENDARY,
-//            // default sell value (gold)
-//            3500,
-//            Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    RED_CLAW_HOODIE(
-//            // itemTypeCode
-//            16,
-//            // triggers
-//            Arrays.asList("hoodie", "red-claw hoodie", "h"),
-//            // name
-//            Color.RED + "red-claw " + Color.RESET + "hoodie" + Color.RESET,
-//            // resting name
-//            "a " + Color.RED + "red-claw " + Color.RESET + "hoodie is on the ground.",
-//            // description
-//            "a red-claw hoodie",
-//            // disposable?
-//            false,
-//            // max uses
-//            0,
-//            // half life ticks
-//            60,
-//            // equipment?
-//            true,
-//            Rarity.LEGENDARY,
-//            // default sell value (gold)
-//            3500,
-//            Sets.<TimeTracker.TimeOfDay>newHashSet()),
-//
-//    RED_CLAW_PANTS(
-//            // itemTypeCode
-//            17,
-//            // triggers
-//            Arrays.asList("pants", "red-claw pants", "p"),
-//            // name
-//            Color.RED + "red-claw " + Color.RESET + "pants" + Color.RESET,
-//            // resting name
-//            "a " + Color.RED + "red-claw " + Color.RESET + "pants is on the ground.",
-//            // description
-//            "a red-claw pants",
-//            // disposable?
-//            false,
-//            // max uses
-//            0,
-//            // half life ticks
-//            60,
-//            // equipment?
-//            true,
-//            Rarity.LEGENDARY,
-//            // default sell value (gold)
-//            3500,
-//            Sets.<TimeTracker.TimeOfDay>newHashSet()),;
-//
-//    private final Integer itemTypeCode;
-//    private final List<String> itemTriggers;
-//    private final String restingName;
-//    private final String itemName;
-//    private final String itemDescription;
-//    private final boolean isDisposable;
-//    private final int maxUses;
-//    private final int itemHalfLifeTicks;
-//    private final boolean isEquipment;
-//    private final Rarity rarity;
-//    private final int valueInGold;
-//    private final Set<TimeTracker.TimeOfDay> validTimeOfDays;
-//
-//    ItemType(Integer itemTypeCode, List<String> itemTriggers, String itemName, String restingName, String itemDescription, boolean isDisposable, int maxUses, int itemHalfLifeTicks, boolean isEquipment, Rarity rarity, int valueInGold, Set<TimeTracker.TimeOfDay> validTimeOfDays) {
-//        this.itemTypeCode = itemTypeCode;
-//        this.itemTriggers = itemTriggers;
-//        this.itemName = itemName;
-//        this.restingName = restingName;
-//        this.itemDescription = itemDescription;
-//        this.maxUses = maxUses;
-//        this.isDisposable = maxUses > 0 || isDisposable;
-//        this.itemHalfLifeTicks = itemHalfLifeTicks;
-//        this.isEquipment = isEquipment;
-//        this.rarity = rarity;
-//        this.valueInGold = valueInGold;
-//        this.validTimeOfDays = validTimeOfDays;
-//    }
-//
-//    public Rarity getRarity() {
-//        return rarity;
-//    }
-//
-//    public String getRestingName() {
-//        return restingName;
-//    }
-//
-//    public Integer getItemTypeCode() {
-//        return itemTypeCode;
-//    }
-//
-//    public List<String> getItemTriggers() {
-//        return itemTriggers;
-//    }
-//
-//    public String getItemName() {
-//        return itemName;
-//    }
-//
-//    public String getItemDescription() {
-//        return itemDescription;
-//    }
-//
-//    public boolean isDisposable() {
-//        return isDisposable;
-//    }
-//
-//    public int getMaxUses() {
-//        return maxUses;
-//    }
-//
-//    public int getValueInGold() {
-//        return valueInGold;
-//    }
-//
-//    public Set<TimeTracker.TimeOfDay> getValidTimeOfDays() {
-//        return validTimeOfDays;
-//    }
-//
-//    public int getItemHalfLifeTicks() {
-//        return itemHalfLifeTicks;
-//    }
-//
-//    public static ItemType itemTypeFromCode(Integer code) {
-//        ItemType[] values = values();
-//        for (ItemType type : values) {
-//            if (type.getItemTypeCode().equals(code)) {
-//                return type;
-//            }
-//        }
-//        return ItemType.UNKNOWN;
-//    }
-//}
+package com.comandante.creeper.items;
+
+import com.comandante.creeper.core_game.service.TimeTracker;
+import com.comandante.creeper.server.player_communication.Color;
+import com.google.common.collect.Sets;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import static com.comandante.creeper.server.player_communication.Color.*;
+
+public enum ItemType {
+
+    UNKNOWN(0, Arrays.asList(""), "", "", "", false, 0, 0, false, com.comandante.creeper.items.Rarity.RARE, 0, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+    KEY(1, Arrays.asList("key", "gold key", "shiny gold key"),
+            "a shiny " + YELLOW + "gold key" + RESET,
+            "a shiny " + YELLOW + "gold key" + RESET + " catches your eye.",
+            "A basic key with nothing really remarkable other than its made of gold.",
+            false,
+            0,
+            60,
+            false,
+            Rarity.BASIC,
+            10, Sets.<TimeTracker.TimeOfDay>newHashSet(TimeTracker.TimeOfDay.NIGHT)),
+
+    SMALL_HEALTH_POTION(2, Arrays.asList("potion", "health potion", "vial", "small vial of health potion", "p"),
+            "a small vial of " + RED + "health potion" + RESET,
+            "a small vial of " + RED + "health potion" + RESET + " rests on the ground.",
+            "a small vial of " + RED + "health potion" + RESET + " that restores 50 health" + RESET,
+            true,
+            0,
+            60,
+            false,
+            Rarity.OFTEN,
+            1, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BERSERKER_BATON(3, Arrays.asList("baton", "a berserker baton", "b"),
+            Color.CYAN + "a berserker baton" + Color.RESET,
+            "a berserker baton rests upon the ground.",
+            "a berserker baton",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            100, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BERSEKER_BOOTS(4, Arrays.asList("boots", "boot", "berserker boots", "b"),
+            Color.CYAN + "berserker boots" + Color.RESET,
+            "a pair of berserker boots are here on the ground.",
+            "a pair of berserker boots",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            50, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BERSERKER_CHEST(5, Arrays.asList("chest", "berserker chest", "c"),
+            Color.CYAN + "berserker chest" + Color.RESET,
+            "a berserker chest is on the ground.",
+            "a berserker chest",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            70, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BERSEKER_SHORTS(6, Arrays.asList("shorts", "berserker shorts", "s"),
+            Color.CYAN + "berserker shorts" + Color.RESET,
+            "a pair of berserker shorts are here on the ground.",
+            "a pair of berserker shorts",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            80, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BERSERKER_BRACERS(7, Arrays.asList("bracers", "berserker bracers", "b"),
+            Color.CYAN + "berserker bracers" + Color.RESET,
+            "a pair of berserker bracers are here on the ground.",
+            "a pair of berserker bracers",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            40, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BERSEKER_HELM(8, Arrays.asList("helm", "berserker helm", "h"),
+            Color.CYAN + "berserker helm" + Color.RESET,
+            "a berserker helm is on the ground.",
+            "a berserker helm",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            40, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    MARIJUANA(9, Arrays.asList("marijuana", "weed", "m", "w", "f", "flowers"),
+            Color.GREEN + "marijuana" + Color.RESET + " flowers" + Color.RESET,
+            "some " + Color.GREEN + "marijuana" + Color.RESET + " flowers" + Color.RESET + " are here on the ground.",
+            "some " + Color.GREEN + "marijuana" + Color.RESET + " flowers" + Color.RESET,
+            true,
+            0,
+            60,
+            false,
+            Rarity.BASIC,
+            10, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    PURPLE_DRANK(10, Arrays.asList("drank", "purple drank", "p", "purple", "lean", "sizzurp"),
+            "a double cup of " + MAGENTA + "purple" + RESET + " drank",
+            "a double cup of " + MAGENTA + "purple" + RESET + " drank rests on the ground.",
+            "a tonic called " + MAGENTA + "purple" + RESET + " drank that restores health" + RESET,
+            true,
+            0,
+            60,
+            false,
+            Rarity.BASIC,
+            30, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    LEATHER_SATCHEL(11, Arrays.asList("leather satchel", "satchel"),
+            "a " + Color.GREEN + "leather satchel" + Color.RESET,
+            "a " + Color.GREEN + "leather satchel" + Color.RESET,
+            "a " + Color.GREEN + "leather satchel" + Color.RESET + " (15 items)",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            800, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    BIGGERS_SKIN_SATCHEL(12, Arrays.asList("biggers skin satchel", "skin satchel"),
+            "a " + Color.GREEN + "biggers skin satchel" + Color.RESET,
+            "a " + Color.GREEN + "biggers skin satchel" + Color.RESET,
+            "a " + Color.GREEN + "biggers skin satchel" + Color.RESET + " with room to store 100 items.",
+            false,
+            0,
+            60,
+            true,
+            Rarity.BASIC,
+            3000, Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    LIGHTNING_SPELLBOOKNG(
+            // itemTypeCode
+            13,
+            // triggers
+            Arrays.asList("lightning book", "lightning spell book", "book", "spell book"),
+            // name
+            "a " + Color.YELLOW + "lightning" + Color.RESET + " spell book." + Color.RESET,
+            // resting name
+            "a " + Color.YELLOW + "lightning" + Color.RESET + " spell book." + Color.RESET,
+            // description
+            "a " + Color.YELLOW + "lightning" + Color.RESET + " spell book." + Color.RESET,
+            // disposable?
+            true,
+            // max uses
+            0,
+            // half life ticks
+            60,
+            // equipment/can you wear it?
+            false,
+            // controls how often it will spawn (if configured in a spawn)
+            Rarity.RARE,
+            // default sell value (gold)
+            3000,
+            // Some items have time of days where they are "valid" and times when they are not.  If they are not valid for MORNING (for example) they will turn to dust as soon as the world switches to morning.
+            Sets.<TimeTracker.TimeOfDay>newHashSet()),
+    STICK_OF_JUSTICE(
+            // itemTypeCode
+            14,
+            // triggers
+            Arrays.asList("stick of justice", "justice", "stick"),
+            // name
+            "a " + Color.BOLD_ON + Color.MAGENTA + "stick" + Color.BOLD_OFF + Color.GREEN + " of " + Color.BOLD_ON + Color.BLUE + "justice" + Color.RESET,
+            // resting name
+            "a " + Color.BOLD_ON + Color.MAGENTA + "stick" + Color.BOLD_OFF + Color.GREEN + " of " + Color.BOLD_ON + Color.BLUE + "justice" + Color.RESET,
+            // description
+            "a " + Color.BOLD_ON + Color.MAGENTA + "stick" + Color.BOLD_OFF + Color.GREEN + " of " + Color.BOLD_ON + Color.BLUE + "justice" + Color.RESET,
+            // disposable?
+            true,
+            // max uses
+            0,
+            // half life ticks
+            60,
+            // equipment/can you wear it?
+            false,
+            // controls how often it will spawn (if configured in a spawn)
+            Rarity.RARE,
+            // default sell value (gold)
+            3000,
+            // Some items have time of days where they are "valid" and times when they are not.  If they are not valid for MORNING (for example) they will turn to dust as soon as the world switches to morning.
+            Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    RED_CLAW_BEANIE(
+            // itemTypeCode
+            15,
+            // triggers
+            Arrays.asList("beanie", "red-claw beanie", "b"),
+            // name
+            Color.RED + "red-claw " + Color.RESET + "beanie" + Color.RESET,
+            // resting name
+            "a " + Color.RED + "red-claw " + Color.RESET + "beanie is on the ground.",
+            // description
+            "a red-claw beanie",
+            // disposable?
+            false,
+            // max uses
+            0,
+            // half life ticks
+            60,
+            // equipment?
+            true,
+            Rarity.LEGENDARY,
+            // default sell value (gold)
+            3500,
+            Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    RED_CLAW_HOODIE(
+            // itemTypeCode
+            16,
+            // triggers
+            Arrays.asList("hoodie", "red-claw hoodie", "h"),
+            // name
+            Color.RED + "red-claw " + Color.RESET + "hoodie" + Color.RESET,
+            // resting name
+            "a " + Color.RED + "red-claw " + Color.RESET + "hoodie is on the ground.",
+            // description
+            "a red-claw hoodie",
+            // disposable?
+            false,
+            // max uses
+            0,
+            // half life ticks
+            60,
+            // equipment?
+            true,
+            Rarity.LEGENDARY,
+            // default sell value (gold)
+            3500,
+            Sets.<TimeTracker.TimeOfDay>newHashSet()),
+
+    RED_CLAW_PANTS(
+            // itemTypeCode
+            17,
+            // triggers
+            Arrays.asList("pants", "red-claw pants", "p"),
+            // name
+            Color.RED + "red-claw " + Color.RESET + "pants" + Color.RESET,
+            // resting name
+            "a " + Color.RED + "red-claw " + Color.RESET + "pants is on the ground.",
+            // description
+            "a red-claw pants",
+            // disposable?
+            false,
+            // max uses
+            0,
+            // half life ticks
+            60,
+            // equipment?
+            true,
+            Rarity.LEGENDARY,
+            // default sell value (gold)
+            3500,
+            Sets.<TimeTracker.TimeOfDay>newHashSet()),;
+
+    private final Integer itemTypeCode;
+    private final List<String> itemTriggers;
+    private final String restingName;
+    private final String itemName;
+    private final String itemDescription;
+    private final boolean isDisposable;
+    private final int maxUses;
+    private final int itemHalfLifeTicks;
+    private final boolean isEquipment;
+    private final Rarity rarity;
+    private final int valueInGold;
+    private final Set<TimeTracker.TimeOfDay> validTimeOfDays;
+
+    ItemType(Integer itemTypeCode, List<String> itemTriggers, String itemName, String restingName, String itemDescription, boolean isDisposable, int maxUses, int itemHalfLifeTicks, boolean isEquipment, Rarity rarity, int valueInGold, Set<TimeTracker.TimeOfDay> validTimeOfDays) {
+        this.itemTypeCode = itemTypeCode;
+        this.itemTriggers = itemTriggers;
+        this.itemName = itemName;
+        this.restingName = restingName;
+        this.itemDescription = itemDescription;
+        this.maxUses = maxUses;
+        this.isDisposable = maxUses > 0 || isDisposable;
+        this.itemHalfLifeTicks = itemHalfLifeTicks;
+        this.isEquipment = isEquipment;
+        this.rarity = rarity;
+        this.valueInGold = valueInGold;
+        this.validTimeOfDays = validTimeOfDays;
+    }
+
+    public Rarity getRarity() {
+        return rarity;
+    }
+
+    public String getRestingName() {
+        return restingName;
+    }
+
+    public Integer getItemTypeCode() {
+        return itemTypeCode;
+    }
+
+    public List<String> getItemTriggers() {
+        return itemTriggers;
+    }
+
+    public String getItemName() {
+        return itemName;
+    }
+
+    public String getItemDescription() {
+        return itemDescription;
+    }
+
+    public boolean isDisposable() {
+        return isDisposable;
+    }
+
+    public int getMaxUses() {
+        return maxUses;
+    }
+
+    public int getValueInGold() {
+        return valueInGold;
+    }
+
+    public Set<TimeTracker.TimeOfDay> getValidTimeOfDays() {
+        return validTimeOfDays;
+    }
+
+    public int getItemHalfLifeTicks() {
+        return itemHalfLifeTicks;
+    }
+
+    public static ItemType itemTypeFromCode(Integer code) {
+        ItemType[] values = values();
+        for (ItemType type : values) {
+            if (type.getItemTypeCode().equals(code)) {
+                return type;
+            }
+        }
+        return ItemType.UNKNOWN;
+    }
+}
diff --git a/src/main/java/com/comandante/creeper/merchant/BlackbeardRogue.java b/src/main/java/com/comandante/creeper/merchant/BlackbeardRogue.java
index dbf9f53a..4fb9dc20 100644
--- a/src/main/java/com/comandante/creeper/merchant/BlackbeardRogue.java
+++ b/src/main/java/com/comandante/creeper/merchant/BlackbeardRogue.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -21,7 +20,7 @@ public class BlackbeardRogue extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public BlackbeardRogue(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public BlackbeardRogue(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/Blacksmith.java b/src/main/java/com/comandante/creeper/merchant/Blacksmith.java
index 7ff02d08..1943d206 100644
--- a/src/main/java/com/comandante/creeper/merchant/Blacksmith.java
+++ b/src/main/java/com/comandante/creeper/merchant/Blacksmith.java
@@ -1,13 +1,12 @@
 package com.comandante.creeper.merchant;
 
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -32,7 +31,7 @@ public class Blacksmith extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public Blacksmith(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public Blacksmith(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/GrimulfWizard.java b/src/main/java/com/comandante/creeper/merchant/GrimulfWizard.java
index 3b61d195..526cad78 100644
--- a/src/main/java/com/comandante/creeper/merchant/GrimulfWizard.java
+++ b/src/main/java/com/comandante/creeper/merchant/GrimulfWizard.java
@@ -1,13 +1,12 @@
 package com.comandante.creeper.merchant;
 
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -22,7 +21,7 @@ public class GrimulfWizard extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public GrimulfWizard(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public GrimulfWizard(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/JimBanker.java b/src/main/java/com/comandante/creeper/merchant/JimBanker.java
index 8db155e5..4d740233 100644
--- a/src/main/java/com/comandante/creeper/merchant/JimBanker.java
+++ b/src/main/java/com/comandante/creeper/merchant/JimBanker.java
@@ -1,13 +1,12 @@
 package com.comandante.creeper.merchant;
 
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -22,7 +21,7 @@ public class JimBanker extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME + Color.RESET;
 
-    public JimBanker(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public JimBanker(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage, MerchantType.BANK);
     }
 
diff --git a/src/main/java/com/comandante/creeper/merchant/KetilCommissary.java b/src/main/java/com/comandante/creeper/merchant/KetilCommissary.java
index 13a32292..f01357b8 100644
--- a/src/main/java/com/comandante/creeper/merchant/KetilCommissary.java
+++ b/src/main/java/com/comandante/creeper/merchant/KetilCommissary.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -21,7 +20,7 @@ public class KetilCommissary extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public KetilCommissary(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public KetilCommissary(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/LloydBartender.java b/src/main/java/com/comandante/creeper/merchant/LloydBartender.java
index 7af2274e..6f6f297b 100644
--- a/src/main/java/com/comandante/creeper/merchant/LloydBartender.java
+++ b/src/main/java/com/comandante/creeper/merchant/LloydBartender.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -29,7 +28,7 @@ public class LloydBartender extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public LloydBartender(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public LloydBartender(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/LockerRoomGuy.java b/src/main/java/com/comandante/creeper/merchant/LockerRoomGuy.java
index 952e6459..854af255 100644
--- a/src/main/java/com/comandante/creeper/merchant/LockerRoomGuy.java
+++ b/src/main/java/com/comandante/creeper/merchant/LockerRoomGuy.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -21,7 +20,7 @@ public class LockerRoomGuy extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.RED + NAME + Color.RESET;
 
-    public LockerRoomGuy(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public LockerRoomGuy(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage, MerchantType.LOCKER);
     }
 
diff --git a/src/main/java/com/comandante/creeper/merchant/Merchant.java b/src/main/java/com/comandante/creeper/merchant/Merchant.java
index f0907c9f..ceedad93 100644
--- a/src/main/java/com/comandante/creeper/merchant/Merchant.java
+++ b/src/main/java/com/comandante/creeper/merchant/Merchant.java
@@ -1,7 +1,6 @@
 package com.comandante.creeper.merchant;
 
 import com.comandante.creeper.core_game.GameManager;
-import com.comandante.creeper.entity.CreeperEntity;
 import com.comandante.creeper.items.ItemMetadata;
 import org.nocrala.tools.texttablefmt.BorderStyle;
 import org.nocrala.tools.texttablefmt.ShownBorders;
@@ -10,22 +9,22 @@ import org.nocrala.tools.texttablefmt.Table;
 import java.text.NumberFormat;
 import java.util.*;
 
-public abstract class Merchant extends CreeperEntity {
+public abstract class Merchant {
 
     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 List<MerchantItemForSale> merchantItemForSales;
     private final String welcomeMessage;
     private final MerchantType merchantType;
 
-    public Merchant(GameManager gameManager, String name, String colorName, Set<String> validTriggers, Map<Integer, MerchantItemForSale> merchantItemForSales, String welcomeMessage) {
+    public Merchant(GameManager gameManager, String name, String colorName, Set<String> validTriggers, List<MerchantItemForSale> merchantItemForSales, String welcomeMessage) {
         this(gameManager, name, colorName, validTriggers, merchantItemForSales, welcomeMessage, MerchantType.BASIC);
     }
 
-    public Merchant(GameManager gameManager, String name, String colorName, Set<String> validTriggers, Map<Integer, MerchantItemForSale> merchantItemForSales, String welcomeMessage, MerchantType merchantType) {
+    public Merchant(GameManager gameManager, String name, String colorName, Set<String> validTriggers, List<MerchantItemForSale> merchantItemForSales, String welcomeMessage, MerchantType merchantType) {
         this.gameManager = gameManager;
         this.name = name;
         this.colorName = colorName;
@@ -44,28 +43,23 @@ public abstract class Merchant extends CreeperEntity {
         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();
-            Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(next.getValue().getInternalItemName());
+        int i = 0;
+        Iterator<MerchantItemForSale> iterator = merchantItemForSales.iterator();
+        while (iterator.hasNext()) {
+            i++;
+            MerchantItemForSale merchantItemForSale = iterator.next();
+            Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(merchantItemForSale.getInternalItemName());
             if (!itemMetadataOptional.isPresent()) {
                 continue;
             }
             ItemMetadata itemMetadata = itemMetadataOptional.get();
-            t.addCell(String.valueOf(next.getKey()));
-            t.addCell(NumberFormat.getNumberInstance(Locale.US).format(next.getValue().getCost()));
+            t.addCell(String.valueOf(i));
+            t.addCell(NumberFormat.getNumberInstance(Locale.US).format(merchantItemForSale.getCost()));
             t.addCell(itemMetadata.getItemDescription());
-            i++;
         }
         return t.render();
     }
 
-    @Override
-    public void run() {
-
-    }
-
     public long getLastPhraseTimestamp() {
         return lastPhraseTimestamp;
     }
@@ -86,7 +80,7 @@ public abstract class Merchant extends CreeperEntity {
         return validTriggers;
     }
 
-    public Map<Integer, MerchantItemForSale> getMerchantItemForSales() {
+    public List<MerchantItemForSale> merchantItemForSales() {
         return merchantItemForSales;
     }
 
@@ -98,6 +92,10 @@ public abstract class Merchant extends CreeperEntity {
         return merchantType;
     }
 
+    public List<MerchantItemForSale> getMerchantItemForSales() {
+        return merchantItemForSales;
+    }
+
     public enum MerchantType {
         BANK,
         LOCKER,
diff --git a/src/main/java/com/comandante/creeper/merchant/MerchantManager.java b/src/main/java/com/comandante/creeper/merchant/MerchantManager.java
index 4eacdf68..927b20db 100644
--- a/src/main/java/com/comandante/creeper/merchant/MerchantManager.java
+++ b/src/main/java/com/comandante/creeper/merchant/MerchantManager.java
@@ -10,8 +10,6 @@ import com.comandante.creeper.items.ItemMetadata;
 import com.comandante.creeper.player.Player;
 import com.comandante.creeper.player.PlayerMetadata;
 
-import java.util.Iterator;
-import java.util.Map;
 import java.util.Optional;
 
 import static com.codahale.metrics.MetricRegistry.name;
@@ -29,11 +27,11 @@ public class MerchantManager {
     public void purchaseItem(Merchant merchant, int itemNo, Player player) {
         final Timer.Context context = responses.time();
         try {
-            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)) {
-                    String internalItemName = next.getValue().getInternalItemName();
+            int i = 0;
+            for (MerchantItemForSale merchantItemForSale : merchant.getMerchantItemForSales()) {
+                i++;
+                if (i == itemNo) {
+                    String internalItemName = merchantItemForSale.getInternalItemName();
                     Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(internalItemName);
                     if (!itemMetadataOptional.isPresent()) {
                         continue;
@@ -44,7 +42,7 @@ public class MerchantManager {
                         gameManager.getChannelUtils().write(player.getPlayerId(), "Your inventory is full, drop some items and come back.\r\n");
                         return;
                     }
-                    int price = next.getValue().getCost();
+                    int price = merchantItemForSale.getCost();
                     Optional<PlayerMetadata> playerMetadataOptional = gameManager.getPlayerManager().getPlayerMetadata(player.getPlayerId());
                     if (!playerMetadataOptional.isPresent()) {
                         continue;
diff --git a/src/main/java/com/comandante/creeper/merchant/MerchantMetadata.java b/src/main/java/com/comandante/creeper/merchant/MerchantMetadata.java
new file mode 100644
index 00000000..ad8401e5
--- /dev/null
+++ b/src/main/java/com/comandante/creeper/merchant/MerchantMetadata.java
@@ -0,0 +1,53 @@
+package com.comandante.creeper.merchant;
+
+import java.util.List;
+import java.util.Set;
+
+public class MerchantMetadata {
+
+    private String name;
+    private String colorName;
+    private Set<String> validTriggers;
+    private List<MerchantItemForSale> merchantItemForSales;
+    private String welcomeMessage;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getColorName() {
+        return colorName;
+    }
+
+    public void setColorName(String colorName) {
+        this.colorName = colorName;
+    }
+
+    public Set<String> getValidTriggers() {
+        return validTriggers;
+    }
+
+    public void setValidTriggers(Set<String> validTriggers) {
+        this.validTriggers = validTriggers;
+    }
+
+    public List<MerchantItemForSale> getMerchantItemForSales() {
+        return merchantItemForSales;
+    }
+
+    public void setMerchantItemForSales(List<MerchantItemForSale> merchantItemForSales) {
+        this.merchantItemForSales = merchantItemForSales;
+    }
+
+    public String getWelcomeMessage() {
+        return welcomeMessage;
+    }
+
+    public void setWelcomeMessage(String welcomeMessage) {
+        this.welcomeMessage = welcomeMessage;
+    }
+}
diff --git a/src/main/java/com/comandante/creeper/merchant/NigelBartender.java b/src/main/java/com/comandante/creeper/merchant/NigelBartender.java
index aae4efe1..772075dd 100644
--- a/src/main/java/com/comandante/creeper/merchant/NigelBartender.java
+++ b/src/main/java/com/comandante/creeper/merchant/NigelBartender.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -21,7 +20,7 @@ public class NigelBartender extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public NigelBartender(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public NigelBartender(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/OldWiseMan.java b/src/main/java/com/comandante/creeper/merchant/OldWiseMan.java
index eed1aefc..bc568491 100644
--- a/src/main/java/com/comandante/creeper/merchant/OldWiseMan.java
+++ b/src/main/java/com/comandante/creeper/merchant/OldWiseMan.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
 import com.comandante.creeper.core_game.GameManager;
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -21,7 +20,7 @@ public class OldWiseMan extends Merchant {
     ));
 
 
-    public OldWiseMan(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public OldWiseMan(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage, MerchantType.PLAYERCLASS_SELECTOR);
     }
 
diff --git a/src/main/java/com/comandante/creeper/merchant/WentworthTailor.java b/src/main/java/com/comandante/creeper/merchant/WentworthTailor.java
index 3183a08a..c38a894f 100644
--- a/src/main/java/com/comandante/creeper/merchant/WentworthTailor.java
+++ b/src/main/java/com/comandante/creeper/merchant/WentworthTailor.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -21,7 +20,7 @@ public class WentworthTailor extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.CYAN + NAME  + Color.RESET ;
 
-    public WentworthTailor(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public WentworthTailor(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/merchant/Wizard.java b/src/main/java/com/comandante/creeper/merchant/Wizard.java
index 14a9fc5d..a98f07ca 100644
--- a/src/main/java/com/comandante/creeper/merchant/Wizard.java
+++ b/src/main/java/com/comandante/creeper/merchant/Wizard.java
@@ -1,12 +1,11 @@
 package com.comandante.creeper.merchant;
 
-import com.comandante.creeper.items.Loot;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.server.player_communication.Color;
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
 import java.util.Set;
 
 import static com.comandante.creeper.server.player_communication.Color.BOLD_ON;
@@ -35,7 +34,7 @@ public class Wizard extends Merchant {
 
     private final static String colorName = BOLD_ON + Color.BLUE + NAME  + Color.RESET ;
 
-    public Wizard(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) {
+    public Wizard(GameManager gameManager, List<MerchantItemForSale> merchantItemForSales) {
         super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage);
     }
 }
diff --git a/src/main/java/com/comandante/creeper/player/PlayerMetadata.java b/src/main/java/com/comandante/creeper/player/PlayerMetadata.java
index 32487d80..7edd8a72 100644
--- a/src/main/java/com/comandante/creeper/player/PlayerMetadata.java
+++ b/src/main/java/com/comandante/creeper/player/PlayerMetadata.java
@@ -298,7 +298,7 @@ public class PlayerMetadata implements Serializable {
     }
 
     public void resetCoolDowns() {
-        Maps.newConcurrentMap();
+        this.coolDowns = Maps.newConcurrentMap();
     }
 
     public String[] getPlayerEquipment() {
diff --git a/src/main/java/com/comandante/creeper/storage/FilebasedJsonStorage.java b/src/main/java/com/comandante/creeper/storage/FilebasedJsonStorage.java
new file mode 100644
index 00000000..259d5678
--- /dev/null
+++ b/src/main/java/com/comandante/creeper/storage/FilebasedJsonStorage.java
@@ -0,0 +1,68 @@
+package com.comandante.creeper.storage;
+
+import com.comandante.creeper.Main;
+import com.google.gson.Gson;
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+public class FilebasedJsonStorage {
+
+
+    private final Gson gson;
+    private static final Logger log = Logger.getLogger(FilebasedJsonStorage.class);
+
+    public FilebasedJsonStorage(Gson gson) {
+        this.gson = gson;
+    }
+
+    public <E> List<E> readAllMetadatas(String storageDirectory, boolean recursive, E a) {
+        List<String> jsonStrings = getAllJsonStrings(storageDirectory, recursive);
+        List<Object> list = jsonStrings.stream()
+                .map(s -> {
+                    try {
+                        return gson.fromJson(s, a.getClass());
+                    } catch (Exception e) {
+                        log.error("Unable to read NpcMetaData from Json!", e);
+                    }
+                    return null;
+                })
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        return (List<E>) list;
+    }
+
+    public void saveMetadata(String name, String storageDirectory, Object metadata) throws IOException {
+        new File(storageDirectory).mkdirs();
+        File file = new File(storageDirectory + name.replaceAll("\\s", "_") + ".json");
+        org.apache.commons.io.FileUtils.writeStringToFile(file, gson.toJson(metadata));
+    }
+
+    private List<String> getAllJsonStrings(String storageDirectory, boolean recursive) {
+        Iterator<File> iterator = FileUtils.iterateFiles(new File(storageDirectory), new String[]{"json"}, recursive);
+        return toListOfJsonStrings(iterator);
+    }
+
+    private List<String> toListOfJsonStrings(final Iterator<File> iterator) {
+        return StreamSupport
+                .stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
+                .map(f -> {
+                    try {
+                        Main.startUpMessage("Reading: " + f.getAbsolutePath());
+                        return new String(Files.readAllBytes(f.toPath()));
+                    } catch (IOException e) {
+                        log.error("Unable to read: " + f.getAbsolutePath(), e);
+                    }
+                    return null;
+                })
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(ArrayList::new));
+    }
+}
diff --git a/src/main/java/com/comandante/creeper/storage/ItemStorage.java b/src/main/java/com/comandante/creeper/storage/ItemStorage.java
index e32b7456..1ad24419 100644
--- a/src/main/java/com/comandante/creeper/storage/ItemStorage.java
+++ b/src/main/java/com/comandante/creeper/storage/ItemStorage.java
@@ -1,84 +1,32 @@
 package com.comandante.creeper.storage;
 
-import com.comandante.creeper.Main;
 import com.comandante.creeper.items.ItemMetadata;
-import com.google.gson.Gson;
-import org.apache.commons.io.FileUtils;
 import org.apache.log4j.Logger;
 
-import java.io.File;
 import java.io.IOException;
-import java.nio.file.Files;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
+import java.util.List;
+import java.util.Optional;
 
 public class ItemStorage {
 
     public final static String LOCAL_ITEM_DIRECTORY = "world/items/";
 
-    private final Gson gson;
     private static final Logger log = Logger.getLogger(NpcStorage.class);
+    private final FilebasedJsonStorage filebasedJsonStorage;
 
     private final List<ItemMetadata> itemMetadatas;
 
-    public ItemStorage(Gson gson) {
-        this.gson = gson;
-        this.itemMetadatas = readAllItemMetadatas();
+    public ItemStorage(FilebasedJsonStorage filebasedJsonStorage) {
+        this.filebasedJsonStorage = filebasedJsonStorage;
+        this.itemMetadatas = filebasedJsonStorage.readAllMetadatas(LOCAL_ITEM_DIRECTORY, true, new ItemMetadata());
     }
 
-    public List<ItemMetadata> getAllItemMetadata()  {
+    public List<ItemMetadata> getAllItemMetadata() {
         return itemMetadatas;
     }
 
-    public void saveItemMetaData(ItemMetadata itemMetadata) throws IOException {
-        new File(LOCAL_ITEM_DIRECTORY).mkdirs();
-        File npcFile = new File(LOCAL_ITEM_DIRECTORY + itemMetadata.getInternalItemName().replaceAll("\\s", "_") + ".json");
-        org.apache.commons.io.FileUtils.writeStringToFile(npcFile, gson.toJson(itemMetadata));
-    }
-
-    protected List<ItemMetadata> readAllItemMetadatas() {
-        return readAllItemMetadatas(getAllJsonStrings());
-    }
-
-    protected List<ItemMetadata> readAllItemMetadatas(List<String> jsonStrings) {
-        List<ItemMetadata> itemMetadata = jsonStrings.stream()
-                .map(s -> {
-                    try {
-                        return gson.fromJson(s, ItemMetadata.class);
-                    } catch (Exception e) {
-                        log.error("Unable to read NpcMetaData from Json!", e);
-                    }
-                    return null;
-                })
-                .filter(Objects::nonNull)
-                .collect(Collectors.toList());
-        return itemMetadata;
-    }
-
-    protected List<String> getAllJsonStrings() {
-        Iterator<File> iterator = FileUtils.iterateFiles(new File(LOCAL_ITEM_DIRECTORY), new String[]{"json"}, false);
-        return toListOfJsonStrings(iterator);
-    }
-
-    protected List<String> toListOfJsonStrings(final Iterator<File> iterator) {
-        return StreamSupport
-                .stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
-                .map(f -> {
-                    try {
-                        Main.startUpMessage("Reading item: " + f.getAbsolutePath());
-                        return new String(Files.readAllBytes(f.toPath()));
-                    } catch (IOException e) {
-                        log.error("Unable to read: " + f.getAbsolutePath(), e);
-                    }
-                    return null;
-                })
-                .filter(Objects::nonNull)
-                .collect(Collectors.toCollection(ArrayList::new));
-    }
-
-    public List<ItemMetadata> getItemMetadatas() {
-        return itemMetadatas;
+    public void saveItemMetadata(ItemMetadata itemMetadata) throws IOException {
+        filebasedJsonStorage.saveMetadata(itemMetadata.getInternalItemName(), LOCAL_ITEM_DIRECTORY, itemMetadata);
     }
 
     public Optional<ItemMetadata> get(String internalItemName) {
diff --git a/src/main/java/com/comandante/creeper/storage/NpcStorage.java b/src/main/java/com/comandante/creeper/storage/NpcStorage.java
index 9f16a497..75c41a95 100644
--- a/src/main/java/com/comandante/creeper/storage/NpcStorage.java
+++ b/src/main/java/com/comandante/creeper/storage/NpcStorage.java
@@ -1,34 +1,28 @@
 package com.comandante.creeper.storage;
 
 
-import com.comandante.creeper.Main;
 import com.comandante.creeper.core_game.GameManager;
 import com.comandante.creeper.npc.Npc;
 import com.comandante.creeper.npc.NpcBuilder;
-import com.google.gson.Gson;
-import org.apache.commons.io.FileUtils;
 import org.apache.log4j.Logger;
 
-import java.io.File;
 import java.io.IOException;
-import java.nio.file.Files;
-import java.util.*;
+import java.util.List;
 import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
 
 public class NpcStorage {
 
     private final GameManager gameManager;
-    private final Gson gson;
     private final static String LOCAL_NPC_DIRECTORY = "world/npcs/";
     private static final Logger log = Logger.getLogger(NpcStorage.class);
+    private final FilebasedJsonStorage filebasedJsonStorage;
 
-    public NpcStorage(GameManager gameManager, Gson gson) {
-        this.gson = gson;
+    public NpcStorage(GameManager gameManager, FilebasedJsonStorage filebasedJsonStorage) {
         this.gameManager = gameManager;
+        this.filebasedJsonStorage = filebasedJsonStorage;
     }
 
-    public List<Npc> getAllNpcs()  {
+    public List<Npc> getAllNpcs() {
         List<NpcMetadata> npcMetadata = readAlLNpcs();
         return npcMetadata.stream()
                 .map(metadata -> new NpcBuilder(metadata).setGameManager(gameManager).createNpc())
@@ -36,49 +30,10 @@ public class NpcStorage {
     }
 
     public void saveNpcMetadata(NpcMetadata npcMetadata) throws IOException {
-        new File(LOCAL_NPC_DIRECTORY).mkdirs();
-        File npcFile = new File(LOCAL_NPC_DIRECTORY + npcMetadata.getName().replaceAll("\\s", "_") + ".json");
-        org.apache.commons.io.FileUtils.writeStringToFile(npcFile, gson.toJson(npcMetadata));
+       filebasedJsonStorage.saveMetadata(npcMetadata.getName(), LOCAL_NPC_DIRECTORY, npcMetadata);
     }
 
-    protected List<NpcMetadata> readAlLNpcs() {
-        return readAlLNpcs(getAllJsonStrings());
+    private List<NpcMetadata> readAlLNpcs() {
+        return filebasedJsonStorage.readAllMetadatas(LOCAL_NPC_DIRECTORY, true, new NpcMetadata());
     }
-
-    protected List<NpcMetadata> readAlLNpcs(List<String> jsonStrings) {
-        List<NpcMetadata> npcMetadatas = jsonStrings.stream()
-                .map(s -> {
-                    try {
-                        return gson.fromJson(s, NpcMetadata.class);
-                    } catch (Exception e) {
-                        log.error("Unable to read NpcMetaData from Json!", e);
-                    }
-                    return null;
-                })
-                .filter(Objects::nonNull)
-                .collect(Collectors.toList());
-        return npcMetadatas;
-    }
-
-    protected List<String> getAllJsonStrings() {
-        Iterator<File> iterator = FileUtils.iterateFiles(new File(LOCAL_NPC_DIRECTORY), new String[]{"json"}, false);
-        return toListOfJsonStrings(iterator);
-    }
-
-    protected List<String> toListOfJsonStrings(final Iterator<File> iterator) {
-        return StreamSupport
-                .stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
-                .map(f -> {
-                    try {
-                        Main.startUpMessage("Reading npc: " + f.getAbsolutePath());
-                        return new String(Files.readAllBytes(f.toPath()));
-                    } catch (IOException e) {
-                        log.error("Unable to read: " + f.getAbsolutePath(), e);
-                    }
-                    return null;
-                })
-                .filter(Objects::nonNull)
-                .collect(Collectors.toCollection(ArrayList::new));
-    }
-
 }
diff --git a/src/test/com/comandante/creeper/items/ItemMetadataTest.java b/src/test/com/comandante/creeper/items/ItemMetadataTest.java
index 354c03f6..c1938ad3 100644
--- a/src/test/com/comandante/creeper/items/ItemMetadataTest.java
+++ b/src/test/com/comandante/creeper/items/ItemMetadataTest.java
@@ -1,38 +1,35 @@
-//package com.comandante.creeper.items;
-//
-//import com.comandante.creeper.server.player_communication.Color;
-//import com.comandante.creeper.spawner.SpawnRule;
-//import com.comandante.creeper.spawner.SpawnRuleBuilder;
-//import com.comandante.creeper.stats.Stats;
-//import com.comandante.creeper.stats.StatsBuilder;
-//import com.comandante.creeper.storage.ItemStorage;
-//import com.comandante.creeper.world.model.Area;
-//import com.google.common.collect.Lists;
-//import com.google.common.collect.Sets;
-//import com.google.gson.Gson;
-//import com.google.gson.GsonBuilder;
-//import org.junit.Test;
-//
-//import java.util.Set;
-//
-//
-//public class ItemMetadataTest {
-//
-//    private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
-//
-//    @Test
-//    public void testSerialization() throws Exception {
-//
-////        private String itemName;
-////        private String itemDescription;
-////        private String restingName;
-////        private int numberOfUses;
-////        private int valueInGold;
-////        private int itemHalfLifeTicks;
-////        private Rarity rarity;
-////        private Equipment equipment;
-////        private Set<Effect> effects;
-////        private List<String> itemTriggers;
+package com.comandante.creeper.items;
+
+import com.comandante.creeper.merchant.MerchantItemForSale;
+import com.comandante.creeper.stats.Stats;
+import com.comandante.creeper.stats.StatsBuilder;
+import com.comandante.creeper.storage.FilebasedJsonStorage;
+import com.comandante.creeper.storage.ItemStorage;
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.junit.Test;
+
+import java.util.List;
+
+
+public class ItemMetadataTest {
+
+    private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+    @Test
+    public void testSerialization() throws Exception {
+//
+//        private String itemName;
+//        private String itemDescription;
+//        private String restingName;
+//        private int numberOfUses;
+//        private int valueInGold;
+//        private int itemHalfLifeTicks;
+//        private Rarity rarity;
+//        private Equipment equipment;
+//        private Set<Effect> effects;
+//        private List<String> itemTriggers;
 //
 //
 //        ItemMetadata itemMetadata = new ItemMetadata();
@@ -45,7 +42,7 @@
 //        itemMetadata.setValueInGold(30);
 //        itemMetadata.setItemHalfLifeTicks(60);
 //        itemMetadata.setRarity(Rarity.BASIC);
-//        // itemMetadata.setValidTimeOfDays(Sets.newHashSet(TimeTracker.TimeOfDay.MORNING, TimeTracker.TimeOfDay.NIGHT));
+//         itemMetadata.setValidTimeOfDays(Sets.newHashSet(TimeTracker.TimeOfDay.MORNING, TimeTracker.TimeOfDay.NIGHT));
 //
 //        SpawnRule spawnRule1 = new SpawnRuleBuilder().setArea(Area.NEWBIE_ZONE).setSpawnIntervalTicks(600).setMaxInstances(100).setMaxPerRoom(5).setRandomPercent(40).createSpawnRule();
 //        SpawnRule spawnRule2 = new SpawnRuleBuilder().setArea(Area.FANCYHOUSE_ZONE).setSpawnIntervalTicks(600).setMaxInstances(12).setMaxPerRoom(2).setRandomPercent(50).createSpawnRule();
@@ -53,9 +50,9 @@
 //        itemMetadata.setSpawnRules(Sets.newHashSet(spawnRule1, spawnRule2, spawnRule3));
 //
 //        Stats stats = new StatsBuilder().setInventorySize(100).createStats();
-//        //  final Equipment equipment = new Equipment(EquipmentSlotType.BAG, stats);
+//          final Equipment equipment = new Equipment(EquipmentSlotType.BAG, stats);
 //
-//        //   itemMetadata.setEquipment(equipment);
+//           itemMetadata.setEquipment(equipment);
 //        itemMetadata.setItemTriggers(Lists.newArrayList("p", "little potion", "potion"));
 //
 //
@@ -72,88 +69,89 @@
 //
 //
 //        ItemStorage itemStorage = new ItemStorage(gson);
-//        itemStorage.saveItemMetaData(itemMetadata);
+//        itemStorage.saveItemMetadata(itemMetadata);
 //
 //
 //        String s = gson.toJson(itemMetadata);
 //        System.out.println(s);
-//
-//    }
-//
-//    @Test
-//    public void generator() throws Exception {
-//
-//        ItemStorage itemStorage = new ItemStorage(gson);
-//
-//        // BERSERKER BOOTS
+
+    }
+
+    @Test
+    public void generator() throws Exception {
+
+        FilebasedJsonStorage filebasedJsonStorage = new FilebasedJsonStorage(new GsonBuilder().setPrettyPrinting().create());
+        ItemStorage itemStorage = new ItemStorage(filebasedJsonStorage);
+//
+//         BERSERKER BOOTS
 //        ItemMetadata itemMetadata = metadataFrom(ItemType.BERSEKER_BOOTS);
 //        Stats stats = new StatsBuilder().setArmorRating(3).createStats();
 //        final Equipment equipment = new Equipment(EquipmentSlotType.FEET, stats);
 //        itemMetadata.setEquipment(equipment);
 //        itemMetadata.setInternalItemName("beserker boots");
-//        itemStorage.saveItemMetaData(itemMetadata);
+//        itemStorage.saveItemMetadata(itemMetadata);
 //
-//        // BERSERKER HELM
+//         BERSERKER HELM
 //        ItemMetadata itemMetadataHelm = metadataFrom(ItemType.BERSEKER_HELM);
 //        Stats statsHelm = new StatsBuilder().setArmorRating(3).createStats();
 //        final Equipment equipmentHeml = new Equipment(EquipmentSlotType.HEAD, statsHelm);
 //        itemMetadataHelm.setEquipment(equipmentHeml);
 //        itemMetadataHelm.setInternalItemName("beserker helm");
-//        itemStorage.saveItemMetaData(itemMetadataHelm);
+//        itemStorage.saveItemMetadata(itemMetadataHelm);
 //
 //
-//        // BERSERKER SHORTS
+//         BERSERKER SHORTS
 //        ItemMetadata itemMetadataShorts = metadataFrom(ItemType.BERSEKER_SHORTS);
 //        Stats statsShorts = new StatsBuilder().setArmorRating(4).createStats();
 //        final Equipment equipmentShorts = new Equipment(EquipmentSlotType.LEGS, statsShorts);
 //        itemMetadataShorts.setEquipment(equipmentShorts);
 //        itemMetadataShorts.setInternalItemName("beserker shorts");
-//        itemStorage.saveItemMetaData(itemMetadataShorts);
+//        itemStorage.saveItemMetadata(itemMetadataShorts);
 //
 //
-//        // BERSERKER BATON
+//         BERSERKER BATON
 //        ItemMetadata itemMetadataBaton = metadataFrom(ItemType.BERSERKER_BATON);
 //        Stats statsBaton = new StatsBuilder().setWeaponRatingMin(4).setWeaponRatingMax(6).createStats();
 //        final Equipment equipmentBaton = new Equipment(EquipmentSlotType.HAND, statsBaton);
 //        itemMetadataBaton.setEquipment(equipmentBaton);
 //        itemMetadataBaton.setInternalItemName("beserker baton");
-//        itemStorage.saveItemMetaData(itemMetadataBaton);
+//        itemStorage.saveItemMetadata(itemMetadataBaton);
 //
-//        // BERSERKER BATON
+//         BERSERKER BATON
 //        ItemMetadata itemMetadataBracers = metadataFrom(ItemType.BERSERKER_BRACERS);
 //        Stats statsBracers = new StatsBuilder().setArmorRating(4).createStats();
 //        final Equipment equipmentBracers = new Equipment(EquipmentSlotType.WRISTS, statsBracers);
 //        itemMetadataBracers.setEquipment(equipmentBracers);
 //        itemMetadataBracers.setInternalItemName("beserker bracers");
-//        itemStorage.saveItemMetaData(itemMetadataBracers);
+//        itemStorage.saveItemMetadata(itemMetadataBracers);
 //
 //
-//        // BERSERKER BATON
+//         BERSERKER BATON
 //        ItemMetadata itemMetadataChest = metadataFrom(ItemType.BERSERKER_CHEST);
 //        Stats statsChest = new StatsBuilder().setArmorRating(6).createStats();
 //        final Equipment equipmentChest = new Equipment(EquipmentSlotType.CHEST, statsChest);
 //        itemMetadataChest.setEquipment(equipmentChest);
 //        itemMetadataChest.setInternalItemName("beserker chest");
-//        itemStorage.saveItemMetaData(itemMetadataChest);
+//        itemStorage.saveItemMetadata(itemMetadataChest);
 //
-//        // BIGGERS SKIN SATCHEL
+//         BIGGERS SKIN SATCHEL
 //        ItemMetadata itemMetadataBiggersSkinSatchel = metadataFrom(ItemType.BIGGERS_SKIN_SATCHEL);
 //        Stats statsBiggersSkinSatchel = new StatsBuilder().setInventorySize(100).createStats();
 //        final Equipment equipmentBiggersSkinSatchel= new Equipment(EquipmentSlotType.BAG, statsBiggersSkinSatchel);
 //        itemMetadataBiggersSkinSatchel.setEquipment(equipmentBiggersSkinSatchel);
 //        itemMetadataBiggersSkinSatchel.setInternalItemName("biggers skin satchel");
-//        itemStorage.saveItemMetaData(itemMetadataBiggersSkinSatchel);
+//        itemStorage.saveItemMetadata(itemMetadataBiggersSkinSatchel);
 //
 //
-//        // Key
+//         Key
 //        ItemMetadata itemMetadataKey = metadataFrom(ItemType.KEY);
 //        itemMetadataKey.setInternalItemName("basic key");
 //        SpawnRule spawnRule = new SpawnRuleBuilder().setArea(Area.LOBBY).setSpawnIntervalTicks(600).setMaxInstances(1).setMaxPerRoom(1).setRandomPercent(5).createSpawnRule();
 //        itemMetadataKey.setSpawnRules(Sets.newHashSet(spawnRule));
-//        itemStorage.saveItemMetaData(itemMetadataKey);
+//        itemStorage.saveItemMetadata(itemMetadataKey);
 //
 //
-//        // Marijuana
+//         Marijuana
 //        ItemMetadata itemMetadataMarijuana = metadataFrom(ItemType.MARIJUANA);
 //        itemMetadataMarijuana.setInternalItemName("marijuana");
 //        ForageBuilder marijuanaForageBuilder = new ForageBuilder();
@@ -164,16 +162,16 @@
 //        marijuanaForageBuilder.setCoolDownTicks(600);
 //        marijuanaForageBuilder.setAreas(Sets.newHashSet(Area.WESTERN9_ZONE, Area.NORTH3_ZONE, Area.BLOODRIDGE2_ZONE, Area.BLOODRIDGE1_ZONE));
 //        itemMetadataMarijuana.setForages(Sets.newHashSet(marijuanaForageBuilder.createForage()));
-//        itemStorage.saveItemMetaData(itemMetadataMarijuana);
+//        itemStorage.saveItemMetadata(itemMetadataMarijuana);
 //
-//        // Drank
+//         Drank
 //        ItemMetadata itemMetadataDrank = metadataFrom(ItemType.PURPLE_DRANK);
 //        itemMetadataDrank.setInternalItemName("purple drank");
 //        Stats statsDrank = new StatsBuilder().setCurrentHealth(50).createStats();
 //        itemMetadataDrank.setItemApplyStats(statsDrank);
-//        itemStorage.saveItemMetaData(itemMetadataDrank);
+//        itemStorage.saveItemMetadata(itemMetadataDrank);
 //
-//        // Smell Health Potion
+//         Smell Health Potion
 //        Set<SpawnRule> spawnRulesHealthPotion = Sets.newHashSet(
 //                new SpawnRuleBuilder().setArea(Area.NEWBIE_ZONE).setSpawnIntervalTicks(600).setMaxInstances(100).setMaxPerRoom(5).setRandomPercent(40).createSpawnRule(),
 //                new SpawnRuleBuilder().setArea(Area.FANCYHOUSE_ZONE).setSpawnIntervalTicks(600).setMaxInstances(12).setMaxPerRoom(2).setRandomPercent(50).createSpawnRule(),
@@ -184,66 +182,77 @@
 //        Stats statsHealthPotion = new StatsBuilder().setCurrentHealth(20).createStats();
 //        itemMetadataHealthPotion.setSpawnRules(spawnRulesHealthPotion);
 //        itemMetadataHealthPotion.setItemApplyStats(statsHealthPotion);
-//        itemStorage.saveItemMetaData(itemMetadataHealthPotion);
+//        itemStorage.saveItemMetadata(itemMetadataHealthPotion);
 //
 //
-//        // BIGGERS SKIN SATCHEL
+//         BIGGERS SKIN SATCHEL
 //        ItemMetadata itemMetadataSpellbook = metadataFrom(ItemType.LIGHTNING_SPELLBOOKNG);
 //        itemMetadataSpellbook.setInternalItemName("lightning spellbook");
-//        itemStorage.saveItemMetaData(itemMetadataSpellbook);
+//        itemStorage.saveItemMetadata(itemMetadataSpellbook);
 //
-//        // Stick OF Justice
+//         Stick OF Justice
 //        ItemMetadata itemMetadataStickOfJustice = metadataFrom(ItemType.STICK_OF_JUSTICE);
 //        itemMetadataStickOfJustice.setInternalItemName("stick of justice");
-//        itemStorage.saveItemMetaData(itemMetadataStickOfJustice);
+//        itemStorage.saveItemMetadata(itemMetadataStickOfJustice);
 //
-//        // RED CLAW BEANIE
+//         RED CLAW BEANIE
 //        ItemMetadata itemMetadataBeanie = metadataFrom(ItemType.RED_CLAW_BEANIE);
 //        Stats statsBeanie = new StatsBuilder().setArmorRating(8).setStrength(4).setMaxHealth(50).createStats();
 //        final Equipment equipmentBeanie = new Equipment(EquipmentSlotType.HEAD, statsBeanie);
 //        itemMetadataBeanie.setEquipment(equipmentBeanie);
 //        itemMetadataBeanie.setInternalItemName("red claw beanie");
-//        itemStorage.saveItemMetaData(itemMetadataBeanie);
+//        itemStorage.saveItemMetadata(itemMetadataBeanie);
 //
 //
-//        // RED CLAW Hoodie
+//         RED CLAW Hoodie
 //        ItemMetadata itemMetadataHoodie = metadataFrom(ItemType.RED_CLAW_HOODIE);
 //        Stats statsHoodie = new StatsBuilder().setArmorRating(15).setStrength(7).createStats();
 //        final Equipment equipmentHoodie = new Equipment(EquipmentSlotType.CHEST, statsHoodie);
 //        itemMetadataHoodie.setEquipment(equipmentHoodie);
 //        itemMetadataHoodie.setInternalItemName("rad claw hoodie");
-//        itemStorage.saveItemMetaData(itemMetadataHoodie);
-//
-//
-//        // RED CLAW PANTS
-//        ItemMetadata itemMetadataPants = metadataFrom(ItemType.RED_CLAW_PANTS);
-//        Stats statsPants = new StatsBuilder().setArmorRating(15).setStrength(7).createStats();
-//        final Equipment equipmentPants = new Equipment(EquipmentSlotType.LEGS, statsPants);
-//        itemMetadataPants.setEquipment(equipmentPants);
-//        itemMetadataPants.setInternalItemName("rad claw pants");
-//        itemStorage.saveItemMetaData(itemMetadataPants);
-//    }
-//
-//
-//    private ItemMetadata metadataFrom(ItemType itemType) {
-//        ItemMetadata itemMetadata = new ItemMetadata();
-//        itemMetadata.setInternalItemName(null);
-//        itemMetadata.setItemName(itemType.getItemName());
-//        itemMetadata.setRestingName(itemType.getRestingName());
-//        itemMetadata.setItemDescription(itemType.getItemDescription());
-//        itemMetadata.setItemHalfLifeTicks(itemType.getItemHalfLifeTicks());
-//        itemMetadata.setItemTriggers(itemType.getItemTriggers());
-//        itemMetadata.setMaxUses(itemType.getMaxUses());
-//        itemMetadata.setRarity(itemType.getRarity());
-//        itemMetadata.setSpawnRules(null);
-//        itemMetadata.setValidTimeOfDays(itemType.getValidTimeOfDays());
-//        itemMetadata.setValueInGold(itemType.getValueInGold());
-//        itemMetadata.setItemApplyStats(null);
-//        itemMetadata.setEquipment(null);
-//        itemMetadata.setEffects(null);
-//        itemMetadata.setDisposable(itemType.isDisposable());
-//        return itemMetadata;
-//    }
-//
-//
-//}
\ No newline at end of file
+//        itemStorage.saveItemMetadata(itemMetadataHoodie);
+//
+//
+       //  RED CLAW PANTS
+        ItemMetadata itemMetadataPants = metadataFrom(ItemType.RED_CLAW_PANTS);
+        Stats statsPants = new StatsBuilder().setArmorRating(15).setStrength(7).createStats();
+        final Equipment equipmentPants = new Equipment(EquipmentSlotType.LEGS, statsPants);
+        itemMetadataPants.setEquipment(equipmentPants);
+        itemMetadataPants.setInternalItemName("rad claw pants1");
+        itemStorage.saveItemMetadata(itemMetadataPants);
+    }
+
+
+    private ItemMetadata metadataFrom(ItemType itemType) {
+        ItemMetadata itemMetadata = new ItemMetadata();
+        itemMetadata.setInternalItemName(null);
+        itemMetadata.setItemName(itemType.getItemName());
+        itemMetadata.setRestingName(itemType.getRestingName());
+        itemMetadata.setItemDescription(itemType.getItemDescription());
+        itemMetadata.setItemHalfLifeTicks(itemType.getItemHalfLifeTicks());
+        itemMetadata.setItemTriggers(itemType.getItemTriggers());
+        itemMetadata.setMaxUses(itemType.getMaxUses());
+        itemMetadata.setRarity(itemType.getRarity());
+        itemMetadata.setSpawnRules(null);
+        itemMetadata.setValidTimeOfDays(itemType.getValidTimeOfDays());
+        itemMetadata.setValueInGold(itemType.getValueInGold());
+        itemMetadata.setItemApplyStats(null);
+        itemMetadata.setEquipment(null);
+        itemMetadata.setEffects(null);
+        itemMetadata.setDisposable(itemType.isDisposable());
+        return itemMetadata;
+    }
+
+
+    @Test
+    public void generateMerchants() throws Exception {
+
+        List<MerchantItemForSale> itemsForSale = Lists.newArrayList();
+        itemsForSale.add(new MerchantItemForSale("small health potion", 8));
+        itemsForSale.add(new MerchantItemForSale("purple drank", 80));
+        itemsForSale.add(new MerchantItemForSale("biggers skin satchel", 25000));
+//
+      //  LloydBartender lloydBartender = new LloydBartender(gameManager, itemsForSale);
+    }
+
+}
-- 
GitLab