diff --git a/src/main/java/com/syncleus/aethermud/command/commands/WhoCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/WhoCommand.java
index 984d8c5be4e090df207077a0d95aed79c44dbd05..9972df4825c9650eaeb7ceb082653da995389c65 100644
--- a/src/main/java/com/syncleus/aethermud/command/commands/WhoCommand.java
+++ b/src/main/java/com/syncleus/aethermud/command/commands/WhoCommand.java
@@ -62,8 +62,8 @@ public class WhoCommand extends Command {
                         continue;
                     }
                     PlayerData playerData = playerMetadataOptional.get();
-                    t.addCell(Long.toString(Levels.getLevel(playerData.getStats().getExperience())));
-                    t.addCell(NumberFormat.getNumberInstance(Locale.US).format((playerData.getStats().getExperience())));
+                    t.addCell(Long.toString(Levels.getLevel(playerData.getStatData().getExperience())));
+                    t.addCell(NumberFormat.getNumberInstance(Locale.US).format((playerData.getStatData().getExperience())));
                     t.addCell(roomManager.getPlayerCurrentRoom(allPlayer).get().getRoomTitle());
                 }
             }
diff --git a/src/main/java/com/syncleus/aethermud/command/commands/XpCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/XpCommand.java
index c99554ada67f331c27a268cd6b595cfcc72735f7..87030cbbc1469cd7be7837712decb2188f4c3b1f 100644
--- a/src/main/java/com/syncleus/aethermud/command/commands/XpCommand.java
+++ b/src/main/java/com/syncleus/aethermud/command/commands/XpCommand.java
@@ -50,8 +50,8 @@ public class XpCommand extends Command {
     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
         execCommand(ctx, e, () -> {
             PlayerUtil.consume(gameManager, playerId, playerData -> {
-                int nextLevel = Levels.getLevel(playerData.getStats().getExperience()) + 1;
-                int expToNextLevel = Levels.getXp(nextLevel) - playerData.getStats().getExperience();
+                int nextLevel = Levels.getLevel(playerData.getStatData().getExperience()) + 1;
+                int expToNextLevel = Levels.getXp(nextLevel) - playerData.getStatData().getExperience();
                 Meter meter = Main.metrics.meter("experience-" + player.getPlayerName());
 
                 Table table = new Table(2, BorderStyle.CLASSIC_COMPATIBLE, ShownBorders.NONE);
diff --git a/src/main/java/com/syncleus/aethermud/core/NewUserRegistrationManager.java b/src/main/java/com/syncleus/aethermud/core/NewUserRegistrationManager.java
index ab63162c1be5319221607b7fdbef79ab854696fa..bd7c04f696c2abc1512ef14f879e2948c1d0e663 100644
--- a/src/main/java/com/syncleus/aethermud/core/NewUserRegistrationManager.java
+++ b/src/main/java/com/syncleus/aethermud/core/NewUserRegistrationManager.java
@@ -123,7 +123,7 @@ public class NewUserRegistrationManager {
             playerData.setPlayerRoles(Sets.newHashSet(PlayerRole.MORTAL, PlayerRole.ADMIN, PlayerRole.GOD, PlayerRole.TELEPORTER));
             playerData.setPlayerSettings(new HashMap<>());
             try {
-                PropertyUtils.copyProperties(playerData.createStats(), DefaultStats.DEFAULT_PLAYER.createStats());
+                PropertyUtils.copyProperties(playerData.createStatData(), DefaultStats.DEFAULT_PLAYER.createStats());
             } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
                 throw new IllegalStateException("Could not copy properties for stats", e);
             }
diff --git a/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java b/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java
index e9c1513eaa216d26f853554d5e4b6b59f4fbce87..972d3f1cf661c13c69daa5c43667196a7df0be4a 100644
--- a/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java
+++ b/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java
@@ -21,15 +21,12 @@ import com.syncleus.aethermud.core.GameManager;
 import com.syncleus.aethermud.items.Loot;
 import com.syncleus.aethermud.spawner.SpawnRule;
 import com.syncleus.aethermud.stats.Stats;
-import com.syncleus.aethermud.storage.graphdb.model.StatsData;
-import com.syncleus.aethermud.storage.graphdb.model.NpcData;
 import com.syncleus.aethermud.world.model.Area;
 import org.apache.commons.beanutils.PropertyUtils;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.HashSet;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
diff --git a/src/main/java/com/syncleus/aethermud/player/Player.java b/src/main/java/com/syncleus/aethermud/player/Player.java
index 941021654578002800da9069d5455d4113c19be6..83c741db3d03d9f0f911dd77856097d8b9ca6682 100644
--- a/src/main/java/com/syncleus/aethermud/player/Player.java
+++ b/src/main/java/com/syncleus/aethermud/player/Player.java
@@ -30,7 +30,7 @@ import com.syncleus.aethermud.server.communication.Color;
 import com.syncleus.aethermud.stats.*;
 import com.syncleus.aethermud.storage.graphdb.model.CoolDownData;
 import com.syncleus.aethermud.storage.graphdb.model.EffectData;
-import com.syncleus.aethermud.storage.graphdb.model.StatsData;
+import com.syncleus.aethermud.storage.graphdb.model.StatData;
 import com.syncleus.aethermud.storage.graphdb.model.PlayerData;
 import com.syncleus.aethermud.world.model.Room;
 import com.google.common.collect.*;
@@ -149,10 +149,10 @@ public class Player extends AetherMudEntity {
             }
             int maxHealth = stats.getMaxHealth();
             this.consumeRead((p) -> {
-                if (p.getStats().getCurrentHealth() < maxHealth) {
+                if (p.getStatData().getCurrentHealth() < maxHealth) {
                     updatePlayerHealth((int) (maxHealth * .05), null);
                 }
-                if (p.getStats().getCurrentMana() < maxHealth) {
+                if (p.getStatData().getCurrentMana() < maxHealth) {
                     addMana((int) (maxHealth * .03));
                 }
             });
@@ -204,7 +204,8 @@ public class Player extends AetherMudEntity {
     public boolean updatePlayerHealth(int amount, NpcSpawn npcSpawn) {
         synchronized (interner.intern(playerId)) {
             if (amount > 0) {
-                int currentHealth = this.transactRead(playerData -> playerData.getStats().getCurrentHealth());
+                // TODO : make this one large transaction
+                int currentHealth = this.transactRead(playerData -> playerData.getStatData().getCurrentHealth());
                 Stats statsModifier = getPlayerStatsWithEquipmentAndLevel();
                 int maxHealth = statsModifier.getMaxHealth();
                 int proposedNewAmt = currentHealth + amount;
@@ -218,15 +219,15 @@ public class Player extends AetherMudEntity {
                 }
                 else
                     finalNewAmount = proposedNewAmt;
-                this.consume(playerData -> playerData.getStats().setCurrentHealth(finalNewAmount));
+                this.consume(playerData -> playerData.getStatData().setCurrentHealth(finalNewAmount));
                 return false;
             } else {
-                if ((this.transactRead(playerData -> playerData.getStats().getCurrentHealth()) + amount) < 0) {
-                    this.consume(playerData -> playerData.getStats().setCurrentHealth(0));
+                if ((this.transactRead(playerData -> playerData.getStatData().getCurrentHealth()) + amount) < 0) {
+                    this.consume(playerData -> playerData.getStatData().setCurrentHealth(0));
                 } else {
-                    this.consume(playerData -> playerData.getStats().setCurrentHealth(playerData.getStats().getCurrentHealth() + amount));
+                    this.consume(playerData -> playerData.getStatData().setCurrentHealth(playerData.getStatData().getCurrentHealth() + amount));
                 }
-                if (this.transactRead(playerData -> playerData.getStats().getCurrentHealth()) == 0) {
+                if (this.transactRead(playerData -> playerData.getStatData().getCurrentHealth()) == 0) {
                     killPlayer(npcSpawn);
                     return true;
                 }
@@ -257,7 +258,8 @@ public class Player extends AetherMudEntity {
 
     public void addMana(int addAmt) {
         synchronized (interner.intern(playerId)) {
-            int currentMana = this.transactRead(playerData -> playerData.getStats().getCurrentMana());
+            //TODO : Make this one large transaction
+            int currentMana = this.transactRead(playerData -> playerData.getStatData().getCurrentMana());
             Stats statsModifier = getPlayerStatsWithEquipmentAndLevel();
             int maxMana = statsModifier.getMaxMana();
             int proposedNewAmt = currentMana + addAmt;
@@ -271,7 +273,7 @@ public class Player extends AetherMudEntity {
             }
             else
                 finalNewAmount = proposedNewAmt;
-            this.consume(playerData -> playerData.getStats().setCurrentMana(finalNewAmount));
+            this.consume(playerData -> playerData.getStatData().setCurrentMana(finalNewAmount));
         }
     }
 
@@ -279,11 +281,11 @@ public class Player extends AetherMudEntity {
         synchronized (interner.intern(playerId)) {
             final Meter requests = Main.metrics.meter("experience-" + playerName);
             this.consume(playerData -> {
-                int currentExperience = playerData.getStats().getExperience();
+                int currentExperience = playerData.getStatData().getExperience();
                 int currentLevel = Levels.getLevel(currentExperience);
-                playerData.getStats().setExperience(currentExperience + exp);
+                playerData.getStatData().setExperience(currentExperience + exp);
                 requests.mark(exp);
-                int newLevel = Levels.getLevel(playerData.getStats().getExperience());
+                int newLevel = Levels.getLevel(playerData.getStatData().getExperience());
                 if (newLevel > currentLevel) {
                     gameManager.announceLevelUp(playerName, currentLevel, newLevel);
                 }
@@ -292,18 +294,18 @@ public class Player extends AetherMudEntity {
     }
 
     public int getLevel() {
-        return this.transactRead(playerData -> Levels.getLevel(playerData.getStats().getExperience()));
+        return this.transactRead(playerData -> Levels.getLevel(playerData.getStatData().getExperience()));
     }
 
     public int getCurrentHealth() {
         synchronized (interner.intern(playerId)) {
-            return this.transactRead(playerData -> playerData.getStats().getCurrentHealth());
+            return this.transactRead(playerData -> playerData.getStatData().getCurrentHealth());
         }
     }
 
     public void setCurrentHealth(int health) {
         synchronized (interner.intern(playerId)) {
-            this.consume(playerData -> playerData.getStats().setCurrentHealth(health));
+            this.consume(playerData -> playerData.getStatData().setCurrentHealth(health));
         }
     }
 
@@ -328,7 +330,7 @@ public class Player extends AetherMudEntity {
     public boolean addEffect(Effect effect) {
         synchronized (interner.intern(playerId)) {
             return this.transact(playerData -> {
-                if (playerData.getEffects() != null && (playerData.getEffects().size() >= playerData.getStats().getMaxEffects())) {
+                if (playerData.getEffects() != null && (playerData.getEffects().size() >= playerData.getStatData().getMaxEffects())) {
                     return false;
                 }
 
@@ -462,13 +464,13 @@ public class Player extends AetherMudEntity {
 
     public void updatePlayerMana(int amount) {
         synchronized (interner.intern(playerId)) {
-            this.consume(playerData -> playerData.getStats().setCurrentMana(playerData.getStats().getCurrentMana() + amount));
+            this.consume(playerData -> playerData.getStatData().setCurrentMana(playerData.getStatData().getCurrentMana() + amount));
         }
     }
 
     public void updatePlayerForageExperience(int amount) {
         synchronized (interner.intern(playerId)) {
-            this.consume(playerData -> playerData.getStats().setForaging(playerData.getStats().getForaging() + amount));
+            this.consume(playerData -> playerData.getStatData().setForaging(playerData.getStatData().getForaging() + amount));
         }
     }
 
@@ -975,7 +977,7 @@ public class Player extends AetherMudEntity {
                 }
                 if (playerData.getEffects() != null) {
                     for (EffectData effect : playerData.getEffects()) {
-                        StatsHelper.combineStats(newStats, StatsData.copyStats(effect.getDurationStats()));
+                        StatsHelper.combineStats(newStats, StatData.copyStats(effect.getDurationStats()));
                     }
                 }
                 return newStats;
@@ -1260,7 +1262,7 @@ public class Player extends AetherMudEntity {
     }
 
     public Stats getStats() {
-        return this.transactRead(playerData -> StatsData.copyStats(playerData.getStats()));
+        return this.transactRead(playerData -> StatData.copyStats(playerData.getStatData()));
     }
 
     private <T> T transact(Function<PlayerData, T> func) {
diff --git a/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java b/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java
index 0d58d3e323117c7ea1de4eebd4c02c03edd7cfd4..beec826e84d12339a5202c1e3b08f254462ede72 100644
--- a/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java
+++ b/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java
@@ -83,7 +83,7 @@ public class PlayerManagement implements PlayerManagementMBean {
     @Override
     public void setHealth(int amt) {
         synchronized (findInterner().intern(playerId)) {
-            this.consume(playerData -> playerData.getStats().setCurrentHealth(amt));
+            this.consume(playerData -> playerData.getStatData().setCurrentHealth(amt));
         }
     }
 
@@ -109,13 +109,13 @@ public class PlayerManagement implements PlayerManagementMBean {
     @Override
     public void setMana(int amt) {
         synchronized (findInterner().intern(playerId)) {
-            this.consume(playerData -> playerData.getStats().setCurrentMana(amt));
+            this.consume(playerData -> playerData.getStatData().setCurrentMana(amt));
         }
     }
 
     @Override
     public int getHealth() {
-        return this.transactRead(playerData -> playerData.getStats().getCurrentHealth());
+        return this.transactRead(playerData -> playerData.getStatData().getCurrentHealth());
     }
 
     @Override
@@ -125,19 +125,19 @@ public class PlayerManagement implements PlayerManagementMBean {
 
     @Override
     public int getMana() {
-        return this.transactRead(playerData -> playerData.getStats().getCurrentMana());
+        return this.transactRead(playerData -> playerData.getStatData().getCurrentMana());
     }
 
     @Override
     public void setExperience(int amt) {
         synchronized (findInterner().intern(playerId)) {
-            this.consume(playerData -> playerData.getStats().setExperience(amt));
+            this.consume(playerData -> playerData.getStatData().setExperience(amt));
         }
     }
 
     @Override
     public int getExperience() {
-        return this.transactRead(playerData -> playerData.getStats().getExperience());
+        return this.transactRead(playerData -> playerData.getStatData().getExperience());
     }
 
     @Override
diff --git a/src/main/java/com/syncleus/aethermud/player/PlayerManager.java b/src/main/java/com/syncleus/aethermud/player/PlayerManager.java
index 10f623ee869cff89abe0ea63b4c5b19b3d4884e3..ce463d778ab2c53a2ab5ccd63c9fda8a5b799183 100644
--- a/src/main/java/com/syncleus/aethermud/player/PlayerManager.java
+++ b/src/main/java/com/syncleus/aethermud/player/PlayerManager.java
@@ -17,12 +17,10 @@ package com.syncleus.aethermud.player;
 
 
 import com.codahale.metrics.Gauge;
-import com.google.common.collect.Sets;
 import com.syncleus.aethermud.Main;
 import com.syncleus.aethermud.core.SessionManager;
 import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory;
-import com.syncleus.aethermud.storage.graphdb.model.StatsData;
-import com.syncleus.aethermud.storage.AetherMudStorage;
+import com.syncleus.aethermud.storage.graphdb.model.StatData;
 import com.syncleus.aethermud.storage.graphdb.model.PlayerData;
 import com.syncleus.aethermud.world.model.Room;
 import org.apache.commons.codec.binary.Base64;
@@ -122,7 +120,7 @@ public class PlayerManager {
                 Main.metrics.register(name(PlayerManager.class, playerData.getPlayerName(), "current-health"),
                     (Gauge<Integer>) () -> {
                         Optional<PlayerData> playerMetadataOpt = tx.getStorage().getPlayerMetadata(playerId);
-                        return playerMetadataOpt.map(PlayerData::getStats).map(StatsData::getCurrentHealth).orElse(0);
+                        return playerMetadataOpt.map(PlayerData::getStatData).map(StatData::getCurrentHealth).orElse(0);
                     });
             }
 
@@ -131,7 +129,7 @@ public class PlayerManager {
                 Main.metrics.register(name(PlayerManager.class, playerData.getPlayerName(), "xp"),
                     (Gauge<Integer>) () -> {
                         Optional<PlayerData> playerMetadataOpt = tx.getStorage().getPlayerMetadata(playerId);
-                        return playerMetadataOpt.map(PlayerData::getStats).map(StatsData::getExperience).orElse(0);
+                        return playerMetadataOpt.map(PlayerData::getStatData).map(StatData::getExperience).orElse(0);
                     });
             }
         }
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/EffectData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/EffectData.java
index 2fc2dd555fec634df103ef392bd57b5a07be5138..c5ad8669a863ad03422dc58b876febb29f2ff5ec 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/EffectData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/EffectData.java
@@ -73,27 +73,27 @@ public abstract class EffectData extends AbstractInterceptingVertexFrame {
     public abstract void setFrozenMovement(boolean frozenMovement);
 
     @Adjacency(label = "ApplyStatsOnTick", direction = Direction.OUT)
-    public abstract <N extends StatsData> Iterator<? extends N> getAllApplyStatsOnTick(Class<? extends N> type);
+    public abstract <N extends StatData> Iterator<? extends N> getAllApplyStatsOnTick(Class<? extends N> type);
 
     public Stats getApplyStatsOnTick() {
-        Iterator<? extends StatsData> allStats = this.getAllApplyStatsOnTick(StatsData.class);
+        Iterator<? extends StatData> allStats = this.getAllApplyStatsOnTick(StatData.class);
         if (allStats.hasNext())
-            return StatsData.copyStats(allStats.next());
+            return StatData.copyStats(allStats.next());
         else
             return null;
     }
 
     @Adjacency(label = "ApplyStatsOnTick", direction = Direction.OUT)
-    public abstract StatsData addApplyStatsOnTick(StatsData stats);
+    public abstract StatData addApplyStatsOnTick(StatData stats);
 
     @Adjacency(label = "ApplyStatsOnTick", direction = Direction.OUT)
-    public abstract void removeApplyStatsOnTick(StatsData stats);
+    public abstract void removeApplyStatsOnTick(StatData stats);
 
     public void setApplyStatsOnTick(Stats stats) {
-        Iterator<? extends StatsData> existingAll = this.getAllApplyStatsOnTick(StatsData.class);
+        Iterator<? extends StatData> existingAll = this.getAllApplyStatsOnTick(StatData.class);
         if (existingAll != null) {
             while (existingAll.hasNext()) {
-                StatsData existing = existingAll.next();
+                StatData existing = existingAll.next();
                 this.removeApplyStatsOnTick(existing);
                 existing.remove();
             }
@@ -103,7 +103,7 @@ public abstract class EffectData extends AbstractInterceptingVertexFrame {
             return;
         }
 
-        StatsData createdData = this.createOrphanStats();
+        StatData createdData = this.createOrphanStats();
         try {
             PropertyUtils.copyProperties(createdData, stats);
         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
@@ -113,10 +113,10 @@ public abstract class EffectData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "DurationStats", direction = Direction.OUT)
-    public abstract <N extends StatsData> Iterator<? extends N> getAllDurationStats(Class<? extends N> type);
+    public abstract <N extends StatData> Iterator<? extends N> getAllDurationStats(Class<? extends N> type);
 
-    public StatsData getDurationStats() {
-        Iterator<? extends StatsData> allStats = this.getAllDurationStats(StatsData.class);
+    public StatData getDurationStats() {
+        Iterator<? extends StatData> allStats = this.getAllDurationStats(StatData.class);
         if (allStats.hasNext())
             return allStats.next();
         else
@@ -124,16 +124,16 @@ public abstract class EffectData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "DurationStats", direction = Direction.OUT)
-    public abstract StatsData addDurationStats(StatsData stats);
+    public abstract StatData addDurationStats(StatData stats);
 
     @Adjacency(label = "DurationStats", direction = Direction.OUT)
-    public abstract void removeDurationStats(StatsData stats);
+    public abstract void removeDurationStats(StatData stats);
 
     public void setDurationStats(Stats stats) {
-        Iterator<? extends StatsData> existingAll = this.getAllDurationStats(StatsData.class);
+        Iterator<? extends StatData> existingAll = this.getAllDurationStats(StatData.class);
         if (existingAll != null) {
             while (existingAll.hasNext()) {
-                StatsData existing = existingAll.next();
+                StatData existing = existingAll.next();
                 this.removeDurationStats(existing);
                 existing.remove();
             }
@@ -143,7 +143,7 @@ public abstract class EffectData extends AbstractInterceptingVertexFrame {
             return;
         }
 
-        StatsData createdData = this.createOrphanStats();
+        StatData createdData = this.createOrphanStats();
         try {
             PropertyUtils.copyProperties(createdData, stats);
         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
@@ -152,10 +152,10 @@ public abstract class EffectData extends AbstractInterceptingVertexFrame {
         this.addDurationStats(createdData);
     }
 
-    private StatsData createOrphanStats() {
+    private StatData createOrphanStats() {
         if (this.getDurationStats() != null)
             throw new IllegalStateException("Already has stats, can't create another");
-        final StatsData stats = this.getGraph().addFramedVertex(StatsData.class);
+        final StatData stats = this.getGraph().addFramedVertex(StatData.class);
         stats.setAgile(0);
         stats.setAim(0);
         stats.setArmorRating(0);
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java
index f2df118838797833e85024ae1edfb7955f55f766..94777f7494beb26d7ba6d861f1123df44ee35501 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java
@@ -16,11 +16,8 @@
 package com.syncleus.aethermud.storage.graphdb.model;
 
 import com.google.common.collect.Sets;
-import com.syncleus.aethermud.common.AetherMudMessage;
 import com.syncleus.aethermud.core.service.TimeTracker;
 import com.syncleus.aethermud.items.*;
-import com.syncleus.aethermud.spawner.SpawnRule;
-import com.syncleus.aethermud.stats.Stats;
 import com.syncleus.aethermud.storage.graphdb.DataUtils;
 import com.syncleus.ferma.annotations.Adjacency;
 import com.syncleus.ferma.annotations.GraphElement;
@@ -157,10 +154,10 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "ItemApplyStats", direction = Direction.OUT)
-    public abstract <N extends StatsData> Iterator<? extends N> getItemApplyStatDatasIterator(Class<? extends N> type);
+    public abstract <N extends StatData> Iterator<? extends N> getItemApplyStatDatasIterator(Class<? extends N> type);
 
-    public StatsData getItemApplyStatData() {
-        Iterator<? extends StatsData> allStats = this.getItemApplyStatDatasIterator(StatsData.class);
+    public StatData getItemApplyStatData() {
+        Iterator<? extends StatData> allStats = this.getItemApplyStatDatasIterator(StatData.class);
         if( allStats.hasNext() )
             return allStats.next();
         else
@@ -168,19 +165,19 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "ItemApplyStats", direction = Direction.OUT)
-    public abstract StatsData addStatData(StatsData stats);
+    public abstract StatData addStatData(StatData stats);
 
     @Adjacency(label = "ItemApplyStats", direction = Direction.OUT)
-    public abstract void removeStatData(StatsData stats);
+    public abstract void removeStatData(StatData stats);
 
-    public void setItemApplyStatData(StatsData stats) {
-        DataUtils.setAllElements(Collections.singletonList(stats), () -> this.getItemApplyStatDatasIterator(StatsData.class), statsData -> this.addStatData(statsData), () -> createItemApplyStatData() );
+    public void setItemApplyStatData(StatData stats) {
+        DataUtils.setAllElements(Collections.singletonList(stats), () -> this.getItemApplyStatDatasIterator(StatData.class), statsData -> this.addStatData(statsData), () -> createItemApplyStatData() );
     }
 
-    public StatsData createItemApplyStatData() {
+    public StatData createItemApplyStatData() {
         if( this.getItemApplyStatData() != null )
             throw new IllegalStateException("Already has stats, can't create another");
-        final StatsData stats = this.getGraph().addFramedVertex(StatsData.class);
+        final StatData stats = this.getGraph().addFramedVertex(StatData.class);
         stats.setAgile(0);
         stats.setAim(0);
         stats.setArmorRating(0);
@@ -237,7 +234,7 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
     public static void copyItem(ItemData dest, Item src) {
         try {
             PropertyUtils.copyProperties(dest, src);
-            StatsData.copyStats(dest.createItemApplyStatData(), src.getItemApplyStats());
+            StatData.copyStats(dest.createItemApplyStatData(), src.getItemApplyStats());
             LootData.copyLoot(dest.createLoottData(), src.getLoot());
             for(Effect effect : src.getEffects())
                 EffectData.copyEffect(dest.createEffectData(), effect);
@@ -255,9 +252,9 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
             if(lootData != null)
                 retVal.setLoot(LootData.copyLoot(lootData));
 
-            StatsData applyStats = src.getItemApplyStatData();
+            StatData applyStats = src.getItemApplyStatData();
             if( applyStats != null )
-                retVal.setItemApplyStats(StatsData.copyStats(applyStats));
+                retVal.setItemApplyStats(StatData.copyStats(applyStats));
 
             Set<Effect> effects = new HashSet<>();
             for(EffectData effect : src.getEffectDatas())
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java
index 8b41374a81c584a3814fc36f780ad5c749047564..ba0b58c3787aa4f74de63e3274ba3776572a7930 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java
@@ -134,10 +134,10 @@ public abstract class NpcData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "stats", direction = Direction.OUT)
-    public abstract <N extends StatsData> Iterator<? extends N> getAllStatsData(Class<? extends N> type);
+    public abstract <N extends StatData> Iterator<? extends N> getAllStatsData(Class<? extends N> type);
 
-    public StatsData getStatsData() {
-        Iterator<? extends StatsData> allStats = this.getAllStatsData(StatsData.class);
+    public StatData getStatsData() {
+        Iterator<? extends StatData> allStats = this.getAllStatsData(StatData.class);
         if( allStats.hasNext() )
             return allStats.next();
         else
@@ -145,19 +145,19 @@ public abstract class NpcData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "stats", direction = Direction.OUT)
-    public abstract StatsData addStatsData(StatsData stats);
+    public abstract StatData addStatsData(StatData stats);
 
     @Adjacency(label = "stats", direction = Direction.OUT)
-    public abstract void removeStatsData(StatsData stats);
+    public abstract void removeStatsData(StatData stats);
 
-    public void setStatsData(StatsData stats) {
-        DataUtils.setAllElements(Collections.singletonList(stats), () -> this.getAllStatsData(StatsData.class), statsData -> this.addStatsData(statsData), () -> this.createStatsData() );
+    public void setStatsData(StatData stats) {
+        DataUtils.setAllElements(Collections.singletonList(stats), () -> this.getAllStatsData(StatData.class), statsData -> this.addStatsData(statsData), () -> this.createStatsData() );
     }
 
-    public StatsData createStatsData() {
+    public StatData createStatsData() {
         if( this.getStatsData() != null )
             throw new IllegalStateException("Already has stats, can't create another");
-        final StatsData stats = this.getGraph().addFramedVertex(StatsData.class);
+        final StatData stats = this.getGraph().addFramedVertex(StatData.class);
         stats.setAgile(0);
         stats.setAim(0);
         stats.setArmorRating(0);
@@ -283,7 +283,7 @@ public abstract class NpcData extends AbstractInterceptingVertexFrame {
         try {
             PropertyUtils.copyProperties(dest, src);
             LootData.copyLoot(dest.createLootData(), src.getLoot());
-            StatsData.copyStats(dest.createStatsData(), src.getStats());
+            StatData.copyStats(dest.createStatsData(), src.getStats());
             for(SpawnRule spawnRule : src.getSpawnRules())
                 SpawnRuleData.copySpawnRule(dest.createSpawnRuleData(), spawnRule);
             for(AetherMudMessage message : src.getAttackMessages())
@@ -304,7 +304,7 @@ public abstract class NpcData extends AbstractInterceptingVertexFrame {
         try {
             PropertyUtils.copyProperties(retVal, src);
             retVal.setLoot(LootData.copyLoot(src.getLootData()));
-            retVal.setStats(StatsData.copyStats(src.getStatsData()));
+            retVal.setStats(StatData.copyStats(src.getStatsData()));
 
             List<SpawnRule> rules = new ArrayList<>();
             for(SpawnRuleData spawnRuleData : src.getSpawnRuleDatas())
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/PlayerData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/PlayerData.java
index 01d21c70bbf793b1eb7203975d3905623b24039a..17c6f4853bd771d77359d8512bb2ce894ec3b716 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/PlayerData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/PlayerData.java
@@ -16,9 +16,9 @@
 package com.syncleus.aethermud.storage.graphdb.model;
 
 
-import com.syncleus.aethermud.items.Effect;
 import com.syncleus.aethermud.player.*;
 import com.google.common.collect.Sets;
+import com.syncleus.aethermud.storage.graphdb.DataUtils;
 import com.syncleus.ferma.ClassInitializer;
 import com.syncleus.ferma.DefaultClassInitializer;
 import com.syncleus.ferma.annotations.Adjacency;
@@ -256,10 +256,10 @@ public abstract class PlayerData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "stats", direction = Direction.OUT)
-    public abstract <N extends StatsData> Iterator<? extends N> getAllStats(Class<? extends N> type);
+    public abstract <N extends StatData> Iterator<? extends N> getStatDataIterator(Class<? extends N> type);
 
-    public StatsData getStats() {
-        Iterator<? extends StatsData> allStats = this.getAllStats(StatsData.class);
+    public StatData getStatData() {
+        Iterator<? extends StatData> allStats = this.getStatDataIterator(StatData.class);
         if( allStats.hasNext() )
             return allStats.next();
         else
@@ -267,44 +267,19 @@ public abstract class PlayerData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "stats", direction = Direction.OUT)
-    public abstract StatsData addStats(StatsData stats);
+    public abstract StatData addStatData(StatData stats);
 
     @Adjacency(label = "stats", direction = Direction.OUT)
-    public abstract void removeStats(StatsData stats);
+    public abstract void removeStatData(StatData stats);
 
-    public void setStats(StatsData stats) {
-        Iterator<? extends StatsData> existingAll = this.getAllStats(StatsData.class);
-        if( existingAll != null ) {
-            while( existingAll.hasNext() ) {
-                StatsData existing = existingAll.next();
-                this.removeStats(existing);
-                existing.remove();
-            }
-
-        }
-
-        if( stats == null ) {
-            this.createStats();
-            return;
-        }
-
-        StatsData statsData;
-        if( stats instanceof StatsData ) {
-            this.addStats((StatsData) stats);
-        }
-        else {
-            try {
-                PropertyUtils.copyProperties(this.createStats(), stats);
-            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-                throw new IllegalStateException("Could not copy properties");
-            }
-        }
+    public void setStats(StatData stats) {
+        DataUtils.setAllElements(Collections.singletonList(stats), () -> this.getStatDataIterator(StatData.class), statsData -> this.addStatData(statsData), () -> createStatData() );
     }
 
-    public StatsData createStats() {
-        if( this.getStats() != null )
+    public StatData createStatData() {
+        if( this.getStatData() != null )
             throw new IllegalStateException("Already has stats, can't create another");
-        final StatsData stats = this.getGraph().addFramedVertex(StatsData.class);
+        final StatData stats = this.getGraph().addFramedVertex(StatData.class);
         stats.setAgile(0);
         stats.setAim(0);
         stats.setArmorRating(0);
@@ -323,7 +298,7 @@ public abstract class PlayerData extends AbstractInterceptingVertexFrame {
         stats.setWeaponRatingMax(0);
         stats.setWeaponRatingMin(0);
         stats.setWillpower(0);
-        this.addStats(stats);
+        this.addStatData(stats);
         return stats;
     }
 
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/StatsData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/StatData.java
similarity index 96%
rename from src/main/java/com/syncleus/aethermud/storage/graphdb/model/StatsData.java
rename to src/main/java/com/syncleus/aethermud/storage/graphdb/model/StatData.java
index e1cc61ac31bbbecb91e60ceda621febbfb63a935..4970f5fbf3a4c86a96e8d4ded494ebac4eed95f5 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/StatsData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/StatData.java
@@ -26,7 +26,7 @@ import java.lang.reflect.InvocationTargetException;
 import static java.lang.StrictMath.sqrt;
 
 @GraphElement
-public abstract class StatsData extends AbstractInterceptingVertexFrame {
+public abstract class StatData extends AbstractInterceptingVertexFrame {
     @Property("intelligence")
     public abstract Integer getIntelligence();
 
@@ -135,7 +135,7 @@ public abstract class StatsData extends AbstractInterceptingVertexFrame {
     @Property("inventorySize")
     public abstract void setInventorySize(Integer inventorySize);
 
-    public static void copyStats(StatsData dest, Stats src) {
+    public static void copyStats(StatData dest, Stats src) {
         try {
             PropertyUtils.copyProperties(dest, src);
         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
@@ -143,7 +143,7 @@ public abstract class StatsData extends AbstractInterceptingVertexFrame {
         }
     }
 
-    public static Stats copyStats(StatsData src) {
+    public static Stats copyStats(StatData src) {
         Stats retVal = new Stats();
         try {
             PropertyUtils.copyProperties(retVal, src);
diff --git a/src/test/java/com/syncleus/aethermud/AetherMudUtilsTest.java b/src/test/java/com/syncleus/aethermud/AetherMudUtilsTest.java
index 510c5712bd42e4b6f5307201061db500e53d8d50..1fe2f64b0614eb35a7a2690ed27e4dba1d04edc6 100644
--- a/src/test/java/com/syncleus/aethermud/AetherMudUtilsTest.java
+++ b/src/test/java/com/syncleus/aethermud/AetherMudUtilsTest.java
@@ -26,11 +26,10 @@ import com.syncleus.aethermud.stats.DefaultStats;
 import com.syncleus.aethermud.stats.modifier.StatsModifierFactory;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import com.syncleus.aethermud.storage.AetherMudStorage;
 import com.syncleus.aethermud.storage.graphdb.GraphDbAetherMudStorage;
 import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory;
 import com.syncleus.aethermud.storage.graphdb.model.PlayerData;
-import com.syncleus.aethermud.storage.graphdb.model.StatsData;
+import com.syncleus.aethermud.storage.graphdb.model.StatData;
 import org.apache.commons.beanutils.PropertyUtils;
 import org.junit.Assert;
 import org.junit.Test;
@@ -71,13 +70,13 @@ public class AetherMudUtilsTest {
         playerData.setPlayerId(Main.createPlayerId("usertest"));
         playerData.setPlayerRoles(Sets.newHashSet(PlayerRole.MORTAL));
         playerData.setPlayerSettings(new HashMap<>());
-        StatsData statsData = mock(StatsData.class);
+        StatData statData = mock(StatData.class);
         try {
-            PropertyUtils.copyProperties(statsData, DefaultStats.DEFAULT_PLAYER.createStats());
+            PropertyUtils.copyProperties(statData, DefaultStats.DEFAULT_PLAYER.createStats());
         } catch (IllegalAccessException | InvocationTargetException e) {
             throw new IllegalStateException("Could not create a stats object", e);
         }
-        when(playerData.getStats()).thenReturn(statsData);
+        when(playerData.getStatData()).thenReturn(statData);
 
         GameManager gameManager = mock(GameManager.class);
         StatsModifierFactory statsModifierFactory = mock(StatsModifierFactory.class);
diff --git a/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java b/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java
index fd4c6fb5b3aaa9b719b2d3f2c662004b252c7d5a..df6d0d85e4e67c7d4ca1a531aaca31dbf4e1ae86 100644
--- a/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java
+++ b/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java
@@ -318,7 +318,7 @@ public class NpcTestHarness {
             playerData.setPlayerRoles(Sets.newHashSet(PlayerRole.MORTAL));
             playerData.setPlayerSettings(new HashMap<>());
             try {
-                PropertyUtils.copyProperties(playerData.createStats(), DefaultStats.DEFAULT_PLAYER.createStats());
+                PropertyUtils.copyProperties(playerData.createStatData(), DefaultStats.DEFAULT_PLAYER.createStats());
             } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                 throw new IllegalStateException("Could not create a stats object", e);
             }