From 95a40f07ae4b398ff47a4eb433a388329d2d2f69 Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Freeman <jeffrey.freeman@syncleus.com> Date: Tue, 19 Sep 2017 09:51:54 -0400 Subject: [PATCH] refactor: Migrated ItemStorage over to the graph DAO. --- .../command/commands/DropCommand.java | 4 +- .../command/commands/EquipCommand.java | 6 +- .../command/commands/InventoryCommand.java | 4 +- .../command/commands/LootCommand.java | 11 +- .../command/commands/PickUpCommand.java | 4 +- .../command/commands/ShowCommand.java | 4 +- .../command/commands/UnequipCommand.java | 6 +- .../command/commands/UseCommand.java | 4 +- .../commands/admin/LoadItemCommand.java | 17 +- .../aethermud/configuration/ConfigureNpc.java | 33 +- .../syncleus/aethermud/core/GameManager.java | 22 +- .../aethermud/entity/EntityManager.java | 35 +- .../aethermud/items/ForageManager.java | 23 +- .../com/syncleus/aethermud/items/Item.java | 305 +++++------------- .../syncleus/aethermud/items/ItemBuilder.java | 49 +-- .../aethermud/items/ItemDecayManager.java | 6 +- .../{ItemMetadata.java => ItemImpl.java} | 204 ++++++++---- .../aethermud/items/ItemInstance.java | 64 ++++ .../aethermud/items/ItemInstanceImpl.java | 271 ++++++++++++++++ .../aethermud/items/ItemUseAction.java | 4 +- .../aethermud/items/ItemUseHandler.java | 31 +- .../syncleus/aethermud/items/LootManager.java | 35 +- .../items/use/DefaultApplyEffectsStats.java | 12 +- .../items/use/DirtyBombUseAction.java | 12 +- .../use/LightningSpellBookUseAction.java | 14 +- .../items/use/ResetAllEffectsUseAction.java | 12 +- .../items/use/StickOfJusticeUseAction.java | 14 +- .../syncleus/aethermud/merchant/Merchant.java | 17 +- .../merchant/MerchantCommandHandler.java | 14 +- .../aethermud/merchant/MerchantManager.java | 25 +- .../merchant/lockers/GetCommand.java | 6 +- .../merchant/lockers/PutCommand.java | 4 +- .../com/syncleus/aethermud/npc/NpcSpawn.java | 5 +- .../com/syncleus/aethermud/player/Player.java | 54 ++-- .../aethermud/player/PlayerManagement.java | 32 +- .../aethermud/spawner/ItemSpawner.java | 39 ++- .../aethermud/storage/AetherMudStorage.java | 14 +- .../aethermud/storage/ItemStorage.java | 67 ---- .../graphdb/GraphDbAetherMudStorage.java | 70 +++- .../storage/graphdb/model/ItemData.java | 101 +++--- .../graphdb/model/ItemInstanceData.java | 243 ++++++++++++++ .../storage/graphdb/model/LootData.java | 3 +- .../syncleus/aethermud/world/model/Room.java | 6 +- .../CombatSimulationDetails.java | 8 +- .../combatsimuation/NpcTestHarness.java | 14 +- 45 files changed, 1242 insertions(+), 686 deletions(-) rename src/main/java/com/syncleus/aethermud/items/{ItemMetadata.java => ItemImpl.java} (58%) create mode 100644 src/main/java/com/syncleus/aethermud/items/ItemInstance.java create mode 100644 src/main/java/com/syncleus/aethermud/items/ItemInstanceImpl.java delete mode 100644 src/main/java/com/syncleus/aethermud/storage/ItemStorage.java create mode 100644 src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemInstanceData.java diff --git a/src/main/java/com/syncleus/aethermud/command/commands/DropCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/DropCommand.java index 1e382f17..9558b595 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/DropCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/DropCommand.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.command.commands; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.google.common.base.Joiner; import org.jboss.netty.channel.ChannelHandlerContext; @@ -43,7 +43,7 @@ public class DropCommand extends Command { } originalMessageParts.remove(0); String itemTarget = Joiner.on(" ").join(originalMessageParts); - for (Item item : player.getInventory()) { + for (ItemInstance item : player.getInventory()) { if (item.getItemTriggers().contains(itemTarget)) { item.setWithPlayer(false); gameManager.placeItemInRoom(currentRoom.getRoomId(), item.getItemId()); diff --git a/src/main/java/com/syncleus/aethermud/command/commands/EquipCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/EquipCommand.java index 19ed11e6..34d334dd 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/EquipCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/EquipCommand.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.command.commands; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.google.common.base.Joiner; import org.jboss.netty.channel.ChannelHandlerContext; @@ -43,9 +43,9 @@ public class EquipCommand extends Command { } originalMessageParts.remove(0); String itemTarget = Joiner.on(" ").join(originalMessageParts); - List<Item> inventory = player.getInventory(); + List<ItemInstance> inventory = player.getInventory(); if (inventory != null) { - for (Item item : inventory) { + for (ItemInstance item : inventory) { if (item.getItemTriggers().contains(itemTarget)) { if (item.getEquipment() == null) { write("Item is not equipable."); diff --git a/src/main/java/com/syncleus/aethermud/command/commands/InventoryCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/InventoryCommand.java index 6cc9d39e..bb6ecadc 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/InventoryCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/InventoryCommand.java @@ -16,7 +16,7 @@ package com.syncleus.aethermud.command.commands; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import org.apache.commons.lang.StringUtils; import org.jboss.netty.channel.ChannelHandlerContext; @@ -40,7 +40,7 @@ public class InventoryCommand extends Command { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { this.execCommand(ctx, e, () -> { - List<Item> inventory = player.getInventory(); + List<ItemInstance> inventory = player.getInventory(); if (inventory == null) { write("You aren't carrying anything."); return; diff --git a/src/main/java/com/syncleus/aethermud/command/commands/LootCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/LootCommand.java index e33e6ece..74b456d5 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/LootCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/LootCommand.java @@ -16,7 +16,8 @@ package com.syncleus.aethermud.command.commands; import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.Loot; import com.syncleus.aethermud.server.communication.Color; import org.jboss.netty.channel.ChannelHandlerContext; @@ -42,8 +43,8 @@ public class LootCommand extends Command { public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { execCommand(ctx, e, () -> { if (originalMessageParts.size() > 1) { - for (Item item : player.getInventory()) { - if (item.getInternalItemName().equals(Item.CORPSE_INTENAL_NAME)) { + for (ItemInstance item : player.getInventory()) { + if (item.getInternalItemName().equals(ItemInstance.CORPSE_INTENAL_NAME)) { Loot loot = item.getLoot(); if (loot != null) { int gold = lootManager.lootGoldAmountReturn(loot); @@ -51,8 +52,8 @@ public class LootCommand extends Command { write("You looted " + NumberFormat.getNumberInstance(Locale.US).format(gold) + Color.YELLOW + " gold" + Color.RESET + " from a " + item.getItemName() + ".\r\n"); player.incrementGold(gold); } - Set<Item> items = lootManager.lootItemsReturn(loot); - for (Item i: items) { + Set<ItemInstance> items = lootManager.lootItemsReturn(loot); + for (ItemInstance i: items) { gameManager.acquireItem(player, i.getItemId(), true); write("You looted " + i.getItemName() + " from a " + item.getItemName() + ".\r\n"); } diff --git a/src/main/java/com/syncleus/aethermud/command/commands/PickUpCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/PickUpCommand.java index a94643f4..227f4cb0 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/PickUpCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/PickUpCommand.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.command.commands; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.google.common.base.Joiner; import org.jboss.netty.channel.ChannelHandlerContext; @@ -43,7 +43,7 @@ public class PickUpCommand extends Command { originalMessageParts.remove(0); String desiredPickUpItem = Joiner.on(" ").join(originalMessageParts); for (String next : itemIds) { - Optional<Item> itemEntityOptional = entityManager.getItemEntity(next); + Optional<ItemInstance> itemEntityOptional = entityManager.getItemEntity(next); if (!itemEntityOptional.isPresent()) { continue; } diff --git a/src/main/java/com/syncleus/aethermud/command/commands/ShowCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/ShowCommand.java index 4324607d..5070d2d1 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/ShowCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/ShowCommand.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.command.commands; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.google.common.base.Joiner; import org.jboss.netty.channel.ChannelHandlerContext; @@ -41,7 +41,7 @@ public class ShowCommand extends Command { } originalMessageParts.remove(0); String target = Joiner.on(" ").join(originalMessageParts); - for (Item next : player.getInventory()) { + for (ItemInstance next : player.getInventory()) { for (String s : next.getItemTriggers()) { if (s.equalsIgnoreCase(target)) { writeToRoom(player.getPlayerName() + " whips out " + next.getItemName() + ".\r\n"); diff --git a/src/main/java/com/syncleus/aethermud/command/commands/UnequipCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/UnequipCommand.java index 56dbe5df..5f65c872 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/UnequipCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/UnequipCommand.java @@ -16,7 +16,7 @@ package com.syncleus.aethermud.command.commands; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.google.common.base.Joiner; import org.jboss.netty.channel.ChannelHandlerContext; @@ -44,8 +44,8 @@ public class UnequipCommand extends Command { } originalMessageParts.remove(0); String itemTarget = Joiner.on(" ").join(originalMessageParts); - Set<Item> equipment = player.getEquipment(); - for (Item item : equipment) { + Set<ItemInstance> equipment = player.getEquipment(); + for (ItemInstance item : equipment) { if (item.getItemTriggers().contains(itemTarget)) { player.unEquip(item); return; diff --git a/src/main/java/com/syncleus/aethermud/command/commands/UseCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/UseCommand.java index 4370d81b..d84a32a2 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/UseCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/UseCommand.java @@ -17,7 +17,7 @@ package com.syncleus.aethermud.command.commands; import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.google.common.base.Joiner; import com.google.common.base.Strings; import org.apache.commons.lang.StringUtils; @@ -49,7 +49,7 @@ public class UseCommand extends Command { return; } - Optional<Item> inventoryItemOptional = player.getInventoryItem(useItemOn.getItem()); + Optional<ItemInstance> inventoryItemOptional = player.getInventoryItem(useItemOn.getItem()); if (!inventoryItemOptional.isPresent()) { write("Useable item is not found in your inventory.\r\n"); return; diff --git a/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadItemCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadItemCommand.java index b9e82de0..1b7036fd 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadItemCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadItemCommand.java @@ -17,9 +17,12 @@ package com.syncleus.aethermud.command.commands.admin; import com.syncleus.aethermud.command.commands.Command; import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.items.ItemMetadata; +import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemImpl; import com.syncleus.aethermud.player.PlayerRole; import com.google.common.collect.Sets; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -33,6 +36,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.Set; public class LoadItemCommand extends Command { @@ -79,17 +83,20 @@ public class LoadItemCommand extends Command { String npcJson = EntityUtils.toString(entity); - ItemMetadata itemMetadata = null; + Item item; try { - itemMetadata = gameManager.getGson().fromJson(npcJson, ItemMetadata.class); + item = gameManager.getGson().fromJson(npcJson, ItemImpl.class); } catch (Exception ex) { write("Retrieved JSON file is malformed. " + ex.getLocalizedMessage() + "\r\n"); return; } httpGet.reset(); - gameManager.getItemStorage().saveItemMetadata(itemMetadata); - write("Item Saved. - " + itemMetadata.getInternalItemName() + "\r\n"); + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + tx.getStorage().saveItem(item); + tx.success(); + } + write("Item Saved. - " + item.getInternalItemName() + "\r\n"); }); } diff --git a/src/main/java/com/syncleus/aethermud/configuration/ConfigureNpc.java b/src/main/java/com/syncleus/aethermud/configuration/ConfigureNpc.java index 9aae9c6c..19ee41dc 100644 --- a/src/main/java/com/syncleus/aethermud/configuration/ConfigureNpc.java +++ b/src/main/java/com/syncleus/aethermud/configuration/ConfigureNpc.java @@ -20,13 +20,14 @@ import com.syncleus.aethermud.Main; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.entity.EntityManager; import com.syncleus.aethermud.items.Forage; -import com.syncleus.aethermud.items.ItemMetadata; +import com.syncleus.aethermud.items.Item; import com.syncleus.aethermud.merchant.Merchant; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.spawner.ItemSpawner; import com.syncleus.aethermud.spawner.NpcSpawner; import com.syncleus.aethermud.spawner.SpawnRule; import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import java.io.IOException; import java.util.List; @@ -53,20 +54,24 @@ public class ConfigureNpc { configureAllNpcs(gameManager); - List<ItemMetadata> allItemMetadata = gameManager.getItemStorage().getItemMetadatas(); - - for (ItemMetadata itemMetadata : allItemMetadata) { - for (SpawnRule spawnRule : itemMetadata.getSpawnRules()) { - Main.startUpMessage("Adding item spawn: " + itemMetadata.getInternalItemName()); - ItemSpawner itemSpawner = new ItemSpawner(itemMetadata, spawnRule, gameManager); - entityManager.addEntity(itemSpawner); - } - } + try( GraphStorageFactory.AetherMudTx tx = gameManager.getGraphStorageFactory().beginTransaction() ) { + List<? extends ItemData> allItem = tx.getStorage().getAllItems(); - for (ItemMetadata itemMetadata : allItemMetadata) { - for (Forage forage : itemMetadata.getForages()) { - Main.startUpMessage("Adding forage: " + itemMetadata.getInternalItemName()); - gameManager.getForageManager().addForage(itemMetadata.getInternalItemName(), forage); + for (ItemData itemData : allItem) { + Item item = ItemData.copyItem(itemData); + if( item.getSpawnRules() != null ) { + for (SpawnRule spawnRule : item.getSpawnRules()) { + Main.startUpMessage("Adding item spawn: " + item.getInternalItemName()); + ItemSpawner itemSpawner = new ItemSpawner(item, spawnRule, gameManager); + entityManager.addEntity(itemSpawner); + } + } + if( item.getForages() != null ) { + for (Forage forage : item.getForages()) { + Main.startUpMessage("Adding forage: " + item.getInternalItemName()); + gameManager.getForageManager().addForage(item.getInternalItemName(), forage); + } + } } } diff --git a/src/main/java/com/syncleus/aethermud/core/GameManager.java b/src/main/java/com/syncleus/aethermud/core/GameManager.java index 3c9aac2e..32eca58e 100644 --- a/src/main/java/com/syncleus/aethermud/core/GameManager.java +++ b/src/main/java/com/syncleus/aethermud/core/GameManager.java @@ -102,7 +102,6 @@ public class GameManager { private final Spells spells; private final MultiThreadedEventProcessor eventProcessor = new MultiThreadedEventProcessor(new ArrayBlockingQueue<>(10000)); private final Room detainmentRoom; - private final ItemStorage itemStorage; private final HttpClient httpclient; private final Gson gson; private final FilebasedJsonStorage filebasedJsonStorage; @@ -145,7 +144,6 @@ public class GameManager { this.detainmentRoom = buildDetainmentRoom(); this.gson = new GsonBuilder().setPrettyPrinting().create(); this.filebasedJsonStorage = new FilebasedJsonStorage(gson); - this.itemStorage = new ItemStorage(filebasedJsonStorage); this.merchantStorage = new MerchantStorage(this, filebasedJsonStorage); this.httpclient = httpClient; } @@ -158,10 +156,6 @@ public class GameManager { return gson; } - public ItemStorage getItemStorage() { - return itemStorage; - } - private Room buildDetainmentRoom() { BasicRoomBuilder basicRoomBuilder = new BasicRoomBuilder(this); @@ -343,12 +337,12 @@ public class GameManager { } for (String itemId : playerCurrentRoom.getItemIds()) { - Optional<Item> itemOptional = entityManager.getItemEntity(itemId); + Optional<ItemInstance> itemOptional = entityManager.getItemEntity(itemId); if (!itemOptional.isPresent()) { playerCurrentRoom.removePresentItem(itemId); continue; } - Item item = itemOptional.get(); + ItemInstance item = itemOptional.get(); sb.append(" ").append(item.getRestingName()).append("\r\n"); } @@ -465,11 +459,11 @@ public class GameManager { } public void placeItemInRoom(Integer roomId, String itemId) { - Optional<Item> itemOptional = entityManager.getItemEntity(itemId); + Optional<ItemInstance> itemOptional = entityManager.getItemEntity(itemId); if (!itemOptional.isPresent()) { throw new IllegalArgumentException("itemId not valid."); } - Item item = itemOptional.get(); + ItemInstance item = itemOptional.get(); roomManager.getRoom(roomId).addPresentItem(item.getItemId()); } @@ -494,21 +488,21 @@ public class GameManager { synchronized (interner.intern(itemId)) { Stats playerStatsWithEquipmentAndLevel = player.getPlayerStatsWithEquipmentAndLevel(); if (player.getInventory().size() < playerStatsWithEquipmentAndLevel.getInventorySize()) { - Optional<Item> itemOptional = entityManager.getItemEntity(itemId); + Optional<ItemInstance> itemOptional = entityManager.getItemEntity(itemId); if (!itemOptional.isPresent()) { return false; } - Item itemEntity = itemOptional.get(); + ItemInstance itemEntity = itemOptional.get(); itemEntity.setWithPlayer(true); player.addInventoryId(itemId); entityManager.saveItem(itemEntity); return true; } else { - Optional<Item> itemOptional = entityManager.getItemEntity(itemId); + Optional<ItemInstance> itemOptional = entityManager.getItemEntity(itemId); if (!itemOptional.isPresent()) { return false; } - Item itemEntity = itemOptional.get(); + ItemInstance itemEntity = itemOptional.get(); channelUtils.write(player.getPlayerId(), "Your inventory is full, drop some items to free up room.\r\n"); if (isFromLoot) { player.getCurrentRoom().addPresentItem(itemId); diff --git a/src/main/java/com/syncleus/aethermud/entity/EntityManager.java b/src/main/java/com/syncleus/aethermud/entity/EntityManager.java index 48e6f204..61347dd9 100644 --- a/src/main/java/com/syncleus/aethermud/entity/EntityManager.java +++ b/src/main/java/com/syncleus/aethermud/entity/EntityManager.java @@ -16,16 +16,18 @@ package com.syncleus.aethermud.entity; import com.google.common.base.Function; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; import com.syncleus.aethermud.Main; import com.syncleus.aethermud.core.SentryManager; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.ItemBuilder; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.player.Player; import com.syncleus.aethermud.player.PlayerManager; import com.syncleus.aethermud.storage.graphdb.GraphDbAetherMudStorage; import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; -import com.syncleus.aethermud.storage.graphdb.model.ItemData; +import com.syncleus.aethermud.storage.graphdb.model.ItemInstanceData; import com.syncleus.aethermud.world.RoomManager; import com.syncleus.aethermud.world.model.Room; import org.apache.log4j.Logger; @@ -50,6 +52,7 @@ public class EntityManager { private final Map<String, NpcSpawn> npcs = new ConcurrentHashMap<>(); private final Map<String, AetherMudEntity> entities = new ConcurrentHashMap<>(); private final ExecutorService mainTickExecutorService = Executors.newFixedThreadPool(50); + private final Interner<String> interner = Interners.newWeakInterner(); public EntityManager(GraphStorageFactory graphStorageFactory, RoomManager roomManager, PlayerManager playerManager) { this.graphStorageFactory = graphStorageFactory; @@ -81,23 +84,31 @@ public class EntityManager { } } - public ItemData saveItem(Item item) { - return this.transact(storage -> storage.saveItem(item)); + public void saveItem(ItemInstance item) { + synchronized (interner.intern(item.getItemId())) { + this.transact(storage -> storage.saveItemEntity(item)); + } } - public void removeItem(Item item) { - this.consume(storage -> storage.removeItem(item.getItemId())); + public void removeItem(ItemInstance item) { + synchronized (interner.intern(item.getItemId())) { + this.consume(storage -> storage.removeItemEntity(item.getItemId())); + } } public void removeItem(String itemId) { - this.consume(storage -> storage.removeItem(itemId)); + synchronized (interner.intern(itemId)) { + this.consume(storage -> storage.removeItemEntity(itemId)); + } } - public Optional<Item> getItemEntity(String itemId) { - return this.transactRead(storage -> { - Optional<ItemData> item = storage.getItemEntity(itemId); - return item.map(itemData -> new ItemBuilder().from(ItemData.copyItem(itemData)).create()); - }); + public Optional<ItemInstance> getItemEntity(String itemId) { + synchronized (interner.intern(itemId)) { + return this.transactRead(storage -> { + Optional<ItemInstanceData> item = storage.getItemEntity(itemId); + return item.map(itemData -> new ItemBuilder().from(ItemInstanceData.copyItem(itemData)).create()); + }); + } } public void deleteNpcEntity(String npcId) { diff --git a/src/main/java/com/syncleus/aethermud/items/ForageManager.java b/src/main/java/com/syncleus/aethermud/items/ForageManager.java index 0e919883..0fc82b06 100644 --- a/src/main/java/com/syncleus/aethermud/items/ForageManager.java +++ b/src/main/java/com/syncleus/aethermud/items/ForageManager.java @@ -20,6 +20,8 @@ import com.syncleus.aethermud.player.CoolDownType; import com.syncleus.aethermud.player.Player; import com.syncleus.aethermud.server.communication.Color; import com.syncleus.aethermud.stats.Stats; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import com.syncleus.aethermud.world.model.Area; import com.syncleus.aethermud.world.model.Room; import org.apache.log4j.Logger; @@ -81,24 +83,27 @@ public class ForageManager { //System.out.prlongln("you get a boost of " + pctSuccessBoostForLevel); foragePctOfSuccess = (foragePctOfSuccess * pctSuccessBoostForLevel) + foragePctOfSuccess; //System.out.prlongln("final pct of success for forage: " + foragePctOfSuccess); - Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(forage.getInternalItemName()); - if (!itemMetadataOptional.isPresent()) { - continue; + Item item; + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + Optional<ItemData> itemOptional = tx.getStorage().getItem(forage.getInternalItemName()); + if (!itemOptional.isPresent()) { + continue; + } + item = ItemData.copyItem(itemOptional.get()); } - ItemMetadata itemMetadata = itemMetadataOptional.get(); if (getRandPercent(foragePctOfSuccess)) { player.updatePlayerForageExperience(forage.getForageExperience()); long numberToHarvest = randInt(forage.getMinAmt(), forage.getMaxAmt()); totalForageXp += forage.getForageExperience(); for (long i = 0; i < numberToHarvest; i++) { countOfForagesFound++; - Item item = new ItemBuilder().from(itemMetadata).create(); - gameManager.getEntityManager().saveItem(item); - gameManager.acquireItem(player, item.getItemId()); + ItemInstance itemInstance = new ItemBuilder().from(item).create(); + gameManager.getEntityManager().saveItem(itemInstance); + gameManager.acquireItem(player, itemInstance.getItemId()); } - gameManager.writeToRoom(room.getRoomId(), player.getPlayerName() + " foraged (" + numberToHarvest + ") " + itemMetadata.getItemName() + "\r\n"); + gameManager.writeToRoom(room.getRoomId(), player.getPlayerName() + " foraged (" + numberToHarvest + ") " + item.getItemName() + "\r\n"); } else { - gameManager.getChannelUtils().write(player.getPlayerId(), "Attempt to forage " + itemMetadata.getItemName() + " failed.\r\n"); + gameManager.getChannelUtils().write(player.getPlayerId(), "Attempt to forage " + item.getItemName() + " failed.\r\n"); //System.out.prlongln("failed to obtain forage, random pctsuccess failed."); } } diff --git a/src/main/java/com/syncleus/aethermud/items/Item.java b/src/main/java/com/syncleus/aethermud/items/Item.java index d12c09b9..30ed0410 100644 --- a/src/main/java/com/syncleus/aethermud/items/Item.java +++ b/src/main/java/com/syncleus/aethermud/items/Item.java @@ -15,242 +15,81 @@ */ package com.syncleus.aethermud.items; - import com.syncleus.aethermud.core.service.TimeTracker; +import com.syncleus.aethermud.spawner.SpawnRule; import com.syncleus.aethermud.stats.Stats; -import com.google.common.collect.Lists; -import java.io.Serializable; import java.util.List; import java.util.Set; -import java.util.UUID; - -public class Item implements Serializable { - - private String itemName; - private String itemDescription; - private String internalItemName; - private List<String> itemTriggers; - private String restingName; - private String itemId; - private int numberOfUses; - private boolean isWithPlayer; - private Loot loot; - private int itemHalfLifeTicks; - private Equipment equipment; - private Rarity rarity; - private int valueInGold; - private Set<Effect> effects; - private boolean hasBeenWithPlayer; - private int maxUses; - private boolean isDisposable; - private List<TimeTracker.TimeOfDay> validTimeOfDays; - private Stats itemApplyStats; - - public static final String CORPSE_INTENAL_NAME = "corpse"; - - public Item() { - } - - protected Item(String itemName, String itemDescription, String internalItemName, List<String> itemTriggers, String restingName, String itemId, int numberOfUses, boolean isWithPlayer, Loot loot, int itemHalfLifeTicks, Equipment equipment, Rarity rarity, int valueInGold, Set<Effect> effects, boolean hasBeenWithPlayer, int maxUses, boolean isDisposable, Set<TimeTracker.TimeOfDay> validTimeOfDays, Stats itemApplyStats) { - this.itemName = itemName; - this.itemDescription = itemDescription; - this.internalItemName = internalItemName; - this.itemTriggers = itemTriggers; - this.restingName = restingName; - this.itemId = itemId; - this.numberOfUses = numberOfUses; - this.isWithPlayer = isWithPlayer; - this.loot = loot; - this.itemHalfLifeTicks = itemHalfLifeTicks; - this.equipment = equipment; - this.rarity = rarity; - this.valueInGold = valueInGold; - this.effects = effects; - this.hasBeenWithPlayer = hasBeenWithPlayer; - this.maxUses = maxUses; - this.isDisposable = isDisposable; - this.validTimeOfDays = ( validTimeOfDays == null ? Lists.newArrayList() : Lists.newArrayList(validTimeOfDays)); - this.itemApplyStats = itemApplyStats; - } - - public Stats getItemApplyStats() { - return itemApplyStats; - } - - public List<TimeTracker.TimeOfDay> getValidTimeOfDays() { - return validTimeOfDays; - } - - public void setValidTimeOfDays(Set<TimeTracker.TimeOfDay> validTimeOfDays) { - this.validTimeOfDays = Lists.newArrayList(validTimeOfDays); - } - - public void setValidTimeOfDays(List<TimeTracker.TimeOfDay> validTimeOfDays) { - this.validTimeOfDays = Lists.newArrayList(validTimeOfDays); - } - - public boolean isDisposable() { - return isDisposable; - } - - public int getMaxUses() { - return maxUses; - } - - public boolean isWithPlayer() { - return isWithPlayer; - } - - public void setWithPlayer(boolean isWithPlayer) { - if (isWithPlayer) { - setHasBeenWithPlayer(true); - } - this.isWithPlayer = isWithPlayer; - } - - public int getNumberOfUses() { - return numberOfUses; - } - - public void setNumberOfUses(int numberOfUses) { - this.numberOfUses = numberOfUses; - } - - public String getItemId() { - return itemId; - } - - - public String getInternalItemName() { - return internalItemName; - } - - public String getItemName() { - return itemName; - } - - public String getItemDescription() { - return itemDescription; - } - - public List<String> getItemTriggers() { - return itemTriggers; - } - - public String getRestingName() { - return restingName; - } - - public int getItemHalfLifeTicks() { - return itemHalfLifeTicks; - } - - public Loot getLoot() { - return loot; - } - - public void setEquipment(Equipment equipment) { - this.equipment = equipment; - } - - public void setHasBeenWithPlayer(boolean hasBeenWithPlayer) { - this.hasBeenWithPlayer = hasBeenWithPlayer; - } - - public Equipment getEquipment() { - return equipment; - } - - public Rarity getRarity() { - return rarity; - } - - public int getValueInGold() { - return valueInGold; - } - - public void setEffects(Set<Effect> effects) { - this.effects = effects; - } - - public Set<Effect> getEffects() { - return effects; - } - - public void setItemName(String itemName) { - this.itemName = itemName; - } - - public void setItemDescription(String itemDescription) { - this.itemDescription = itemDescription; - } - - public void setInternalItemName(String internalItemName) { - this.internalItemName = internalItemName; - } - - public void setItemTriggers(List<String> itemTriggers) { - this.itemTriggers = itemTriggers; - } - - public void setRestingName(String restingName) { - this.restingName = restingName; - } - - public void setItemId(String itemId) { - this.itemId = itemId; - } - - public void setLoot(Loot loot) { - this.loot = loot; - } - - public void setItemHalfLifeTicks(int itemHalfLifeTicks) { - this.itemHalfLifeTicks = itemHalfLifeTicks; - } - - public void setRarity(Rarity rarity) { - this.rarity = rarity; - } - - public void setValueInGold(int valueInGold) { - this.valueInGold = valueInGold; - } - - public void setMaxUses(int maxUses) { - this.maxUses = maxUses; - } - - public void setDisposable(boolean disposable) { - isDisposable = disposable; - } - - public void setItemApplyStats(Stats itemApplyStats) { - this.itemApplyStats = itemApplyStats; - } - - public boolean isHasBeenWithPlayer() { - return hasBeenWithPlayer; - } - - public static Item createCorpseItem(String name, Loot loot) { - - Item item = new ItemBuilder() - .internalItemName(Item.CORPSE_INTENAL_NAME) - .itemName(name + " corpse") - .itemDescription("a bloody corpse") - .itemTriggers(Lists.newArrayList("corpse", "c", name, name + " corpse")) - .itemId(UUID.randomUUID().toString()) - .itemHalfLifeTicks(120) - .rarity(Rarity.BASIC) - .valueInGold(5) - .isDisposable(false) - .restingName("a corpse lies on the ground.") - .loot(loot) - .create(); - - return item; - - } + +public interface Item { + Stats getItemApplyStats(); + + List<TimeTracker.TimeOfDay> getValidTimeOfDays(); + + void setValidTimeOfDays(Set<TimeTracker.TimeOfDay> validTimeOfDays); + + void setValidTimeOfDays(List<TimeTracker.TimeOfDay> validTimeOfDays); + + boolean isDisposable(); + + int getMaxUses(); + + String getInternalItemName(); + + String getItemName(); + + String getItemDescription(); + + List<String> getItemTriggers(); + + String getRestingName(); + + int getItemHalfLifeTicks(); + + Loot getLoot(); + + void setEquipment(Equipment equipment); + + Equipment getEquipment(); + + Rarity getRarity(); + + int getValueInGold(); + + void setEffects(Set<Effect> effects); + + Set<Effect> getEffects(); + + void setItemName(String itemName); + + void setItemDescription(String itemDescription); + + void setInternalItemName(String internalItemName); + + void setItemTriggers(List<String> itemTriggers); + + void setRestingName(String restingName); + + void setLoot(Loot loot); + + void setItemHalfLifeTicks(int itemHalfLifeTicks); + + void setRarity(Rarity rarity); + + void setValueInGold(int valueInGold); + + void setMaxUses(int maxUses); + + void setDisposable(boolean disposable); + + void setItemApplyStats(Stats itemApplyStats); + + Set<SpawnRule> getSpawnRules(); + + void setSpawnRules(Set<SpawnRule> spawnRules); + + Set<Forage> getForages(); + + void setForages(Set<Forage> forages); } diff --git a/src/main/java/com/syncleus/aethermud/items/ItemBuilder.java b/src/main/java/com/syncleus/aethermud/items/ItemBuilder.java index 03299fa9..5d7d49d4 100644 --- a/src/main/java/com/syncleus/aethermud/items/ItemBuilder.java +++ b/src/main/java/com/syncleus/aethermud/items/ItemBuilder.java @@ -18,8 +18,10 @@ package com.syncleus.aethermud.items; import com.google.common.collect.Sets; import com.syncleus.aethermud.core.service.TimeTracker; +import com.syncleus.aethermud.spawner.SpawnRule; import com.syncleus.aethermud.stats.Stats; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; @@ -45,32 +47,36 @@ public class ItemBuilder { private boolean isDisposable; private Set<TimeTracker.TimeOfDay> validTimeOfDays; private Stats itemApplyStats; - - public ItemBuilder from(ItemMetadata itemMetadata) { - this.internalItemName = itemMetadata.getInternalItemName(); - this.itemName = itemMetadata.getItemName(); - this.itemDescription = itemMetadata.getItemDescription(); - this.itemTriggers = itemMetadata.getItemTriggers(); - this.restingName = itemMetadata.getRestingName(); + private Set<SpawnRule> spawnRules; + private Set<Forage> forages; + + public ItemBuilder from(Item item) { + this.internalItemName = item.getInternalItemName(); + this.itemName = item.getItemName(); + this.itemDescription = item.getItemDescription(); + this.itemTriggers = item.getItemTriggers(); + this.restingName = item.getRestingName(); this.itemId = UUID.randomUUID().toString(); // zero uses, its new. this.numberOfUses = 0; this.isWithPlayer = false; - this.itemHalfLifeTicks = itemMetadata.getItemHalfLifeTicks(); - this.rarity = itemMetadata.getRarity(); - this.valueInGold = itemMetadata.getValueInGold(); - this.maxUses = itemMetadata.getMaxUses(); + this.itemHalfLifeTicks = item.getItemHalfLifeTicks(); + this.rarity = item.getRarity(); + this.valueInGold = item.getValueInGold(); + this.maxUses = item.getMaxUses(); this.loot = null; - this.isDisposable = itemMetadata.isDisposable(); - this.equipment = itemMetadata.getEquipment(); - this.validTimeOfDays = itemMetadata.getValidTimeOfDays(); - Set<Effect> effects = itemMetadata.getEffects(); - this.effects = (effects != null ? Sets.newHashSet(itemMetadata.getEffects()) : null ); - this.itemApplyStats = itemMetadata.getItemApplyStats(); + this.isDisposable = item.isDisposable(); + this.equipment = item.getEquipment(); + this.validTimeOfDays = new HashSet<>(item.getValidTimeOfDays()); + Set<Effect> effects = item.getEffects(); + this.effects = (effects != null ? Sets.newHashSet(item.getEffects()) : null ); + this.itemApplyStats = item.getItemApplyStats(); + this.spawnRules = (spawnRules != null ? Sets.newHashSet(item.getSpawnRules()) : null); + this.forages = (forages != null ? Sets.newHashSet(item.getForages()) : null); return this; } - public ItemBuilder from(Item origItem) { + public ItemBuilder from(ItemInstance origItem) { this.internalItemName = origItem.getInternalItemName(); this.itemName = origItem.getItemName(); this.itemDescription = origItem.getItemDescription(); @@ -92,6 +98,8 @@ public class ItemBuilder { this.isDisposable = origItem.isDisposable(); this.validTimeOfDays = Sets.newHashSet(origItem.getValidTimeOfDays()); this.itemApplyStats = origItem.getItemApplyStats(); + this.spawnRules = (spawnRules != null ? Sets.newHashSet(origItem.getSpawnRules()) : null); + this.forages = (forages != null ? Sets.newHashSet(origItem.getForages()) : null); return this; } @@ -190,8 +198,9 @@ public class ItemBuilder { return this; } - public Item create() { - return new Item(itemName, itemDescription, internalItemName, itemTriggers, restingName, itemId, numberOfUses, isWithPlayer, loot, itemHalfLifeTicks, equipment, rarity, valueInGold, effects, hasBeenWithPlayer, maxUses, isDisposable, validTimeOfDays, itemApplyStats); + public ItemInstance create() { + Item item = new ItemImpl(itemName, itemDescription, internalItemName, itemTriggers, restingName, loot, itemHalfLifeTicks, equipment, rarity, valueInGold, effects, maxUses, isDisposable, validTimeOfDays, itemApplyStats, spawnRules, forages); + return new ItemInstanceImpl(item, itemId, numberOfUses, isWithPlayer, hasBeenWithPlayer); } diff --git a/src/main/java/com/syncleus/aethermud/items/ItemDecayManager.java b/src/main/java/com/syncleus/aethermud/items/ItemDecayManager.java index e4a46875..c854e08e 100644 --- a/src/main/java/com/syncleus/aethermud/items/ItemDecayManager.java +++ b/src/main/java/com/syncleus/aethermud/items/ItemDecayManager.java @@ -38,7 +38,7 @@ public class ItemDecayManager extends AetherMudEntity { this.gameManager = gameManager; } - public void addItem(Item item) { + public void addItem(ItemInstance item) { item.setWithPlayer(false); itemDecayTracker.put(item.getItemId(), new DecayProgress(item.getItemHalfLifeTicks())); } @@ -58,12 +58,12 @@ public class ItemDecayManager extends AetherMudEntity { ConcurrentHashMap<String, DecayProgress> itemDecayTracker1 = getItemDecayTracker(); for (Map.Entry<String, DecayProgress> next : itemDecayTracker1.entrySet()) { DecayProgress decayProgress = next.getValue(); - Optional<Item> itemOptional = entityManager.getItemEntity(next.getKey()); + Optional<ItemInstance> itemOptional = entityManager.getItemEntity(next.getKey()); if (!itemOptional.isPresent()) { removeItemFromDecayManager(next.getKey()); continue; } - Item item = itemOptional.get(); + ItemInstance item = itemOptional.get(); if (item.isWithPlayer()) { removeItemFromDecayManager(item.getItemId()); continue; diff --git a/src/main/java/com/syncleus/aethermud/items/ItemMetadata.java b/src/main/java/com/syncleus/aethermud/items/ItemImpl.java similarity index 58% rename from src/main/java/com/syncleus/aethermud/items/ItemMetadata.java rename to src/main/java/com/syncleus/aethermud/items/ItemImpl.java index 375e2b29..18d60ec8 100644 --- a/src/main/java/com/syncleus/aethermud/items/ItemMetadata.java +++ b/src/main/java/com/syncleus/aethermud/items/ItemImpl.java @@ -16,169 +16,233 @@ package com.syncleus.aethermud.items; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.syncleus.aethermud.common.ColorizedTextTemplate; import com.syncleus.aethermud.core.service.TimeTracker; import com.syncleus.aethermud.spawner.SpawnRule; import com.syncleus.aethermud.stats.Stats; -import com.google.common.collect.Sets; import java.util.List; import java.util.Set; -public class ItemMetadata { +public class ItemImpl implements Item { - // Used for persisting to disk (file-name) - // Spaces become underscores. - // Needs to be unique across all itemmetadata's. - // is essentially serving as the item "type". - private String internalItemName; - // This is the unique identifier to represent this itemmetadata (which drives itemtype) private String itemName; private String itemDescription; + private String internalItemName; + private List<String> itemTriggers; private String restingName; - private int valueInGold; + private Loot loot; private int itemHalfLifeTicks; - private Rarity rarity; private Equipment equipment; + private Rarity rarity; + private int valueInGold; private Set<Effect> effects; - private List<String> itemTriggers; - private Set<TimeTracker.TimeOfDay> validTimeOfDays; - private boolean isDisposable; private int maxUses; - private Set<SpawnRule> spawnRules; + private boolean isDisposable; + private List<TimeTracker.TimeOfDay> validTimeOfDays; private Stats itemApplyStats; + private Set<SpawnRule> spawnRules; private Set<Forage> forages; - public Set<Forage> getForages() { - if (forages == null) { - return Sets.newHashSet(); - } - return forages; + public ItemImpl() { } - public void setForages(Set<Forage> forages) { - this.forages = forages; + public ItemImpl(String itemName, String itemDescription, String internalItemName, List<String> itemTriggers, String restingName, Loot loot, int itemHalfLifeTicks, Equipment equipment, Rarity rarity, int valueInGold, Set<Effect> effects, int maxUses, boolean isDisposable, Set<TimeTracker.TimeOfDay> validTimeOfDays, Stats itemApplyStats, Set<SpawnRule> spawnRules, Set<Forage> forages) { + this.itemName = itemName; + this.itemDescription = itemDescription; + this.internalItemName = internalItemName; + this.itemTriggers = Lists.newArrayList(itemTriggers); + this.restingName = restingName; + this.loot = loot; + this.itemHalfLifeTicks = itemHalfLifeTicks; + this.equipment = equipment; + this.rarity = rarity; + this.valueInGold = valueInGold; + this.effects = Sets.newHashSet(effects); + this.maxUses = maxUses; + this.isDisposable = isDisposable; + this.validTimeOfDays = (validTimeOfDays == null ? Lists.newArrayList() : Lists.newArrayList(validTimeOfDays)); + this.itemApplyStats = itemApplyStats; + this.spawnRules = (spawnRules == null ? Sets.newHashSet() : Sets.newHashSet(spawnRules)); + this.forages = (forages == null ? Sets.newHashSet() : Sets.newHashSet(forages)); } + @Override public Stats getItemApplyStats() { return itemApplyStats; } - public void setItemApplyStats(Stats itemApplyStats) { - this.itemApplyStats = itemApplyStats; + @Override + public List<TimeTracker.TimeOfDay> getValidTimeOfDays() { + return validTimeOfDays; } - public String getItemName() { - return itemName; + @Override + public void setValidTimeOfDays(Set<TimeTracker.TimeOfDay> validTimeOfDays) { + this.validTimeOfDays = Lists.newArrayList(validTimeOfDays); } - public void setItemName(String itemName) { - this.itemName = itemName; + @Override + public void setValidTimeOfDays(List<TimeTracker.TimeOfDay> validTimeOfDays) { + this.validTimeOfDays = Lists.newArrayList(validTimeOfDays); } - public String getItemDescription() { - return itemDescription; + @Override + public boolean isDisposable() { + return isDisposable; } - public void setItemDescription(String itemDescription) { - this.itemDescription = itemDescription; + @Override + public int getMaxUses() { + return maxUses; } - public String getRestingName() { - return restingName; + + @Override + public String getInternalItemName() { + return internalItemName; } - public void setRestingName(String restingName) { - this.restingName = restingName; + @Override + public String getItemName() { + return ColorizedTextTemplate.renderFromTemplateLanguage(itemName); } - public int getValueInGold() { - return valueInGold; + @Override + public void setItemName(String itemName) { + this.itemName = ColorizedTextTemplate.renderToTemplateLanguage(itemName); } - public void setValueInGold(int valueInGold) { - this.valueInGold = valueInGold; + @Override + public String getItemDescription() { + return ColorizedTextTemplate.renderFromTemplateLanguage(itemDescription); } - public int getItemHalfLifeTicks() { - return itemHalfLifeTicks; + @Override + public List<String> getItemTriggers() { + return itemTriggers; } - public void setItemHalfLifeTicks(int itemHalfLifeTicks) { - this.itemHalfLifeTicks = itemHalfLifeTicks; + @Override + public String getRestingName() { + return ColorizedTextTemplate.renderFromTemplateLanguage(restingName); + } - public Rarity getRarity() { - return rarity; + @Override + public int getItemHalfLifeTicks() { + return itemHalfLifeTicks; } - public void setRarity(Rarity rarity) { - this.rarity = rarity; + @Override + public Loot getLoot() { + return loot; + } + + @Override + public void setEquipment(Equipment equipment) { + this.equipment = equipment; } + @Override public Equipment getEquipment() { return equipment; } - public void setEquipment(Equipment equipment) { - this.equipment = equipment; + @Override + public Rarity getRarity() { + return rarity; } - public Set<Effect> getEffects() { - return effects; + @Override + public int getValueInGold() { + return valueInGold; } + @Override public void setEffects(Set<Effect> effects) { this.effects = effects; } - public String getInternalItemName() { - return internalItemName; + @Override + public Set<Effect> getEffects() { + return effects; } - public List<String> getItemTriggers() { - return itemTriggers; + @Override + public void setItemDescription(String itemDescription) { + this.itemDescription = ColorizedTextTemplate.renderToTemplateLanguage(itemDescription); } + @Override + public void setInternalItemName(String internalItemName) { + this.internalItemName = internalItemName; + } + + @Override public void setItemTriggers(List<String> itemTriggers) { this.itemTriggers = itemTriggers; } - public void setInternalItemName(String internalItemName) { - this.internalItemName = internalItemName; + @Override + public void setRestingName(String restingName) { + this.restingName = ColorizedTextTemplate.renderToTemplateLanguage(restingName); } - public Set<TimeTracker.TimeOfDay> getValidTimeOfDays() { - return validTimeOfDays; + @Override + public void setLoot(Loot loot) { + this.loot = loot; } - public void setValidTimeOfDays(Set<TimeTracker.TimeOfDay> validTimeOfDays) { - this.validTimeOfDays = validTimeOfDays; + @Override + public void setItemHalfLifeTicks(int itemHalfLifeTicks) { + this.itemHalfLifeTicks = itemHalfLifeTicks; } - public int getMaxUses() { - return maxUses; + @Override + public void setRarity(Rarity rarity) { + this.rarity = rarity; } - public boolean isDisposable() { - return isDisposable; + @Override + public void setValueInGold(int valueInGold) { + this.valueInGold = valueInGold; + } + + @Override + public void setMaxUses(int maxUses) { + this.maxUses = maxUses; } + @Override public void setDisposable(boolean disposable) { isDisposable = disposable; } + @Override + public void setItemApplyStats(Stats itemApplyStats) { + this.itemApplyStats = itemApplyStats; + } + + @Override public Set<SpawnRule> getSpawnRules() { - if (spawnRules == null) { - return Sets.newHashSet(); - } return spawnRules; } + @Override public void setSpawnRules(Set<SpawnRule> spawnRules) { this.spawnRules = spawnRules; } - public void setMaxUses(int maxUses) { - this.maxUses = maxUses; + @Override + public Set<Forage> getForages() { + return forages; + } + + @Override + public void setForages(Set<Forage> forages) { + this.forages = forages; } } diff --git a/src/main/java/com/syncleus/aethermud/items/ItemInstance.java b/src/main/java/com/syncleus/aethermud/items/ItemInstance.java new file mode 100644 index 00000000..3562264b --- /dev/null +++ b/src/main/java/com/syncleus/aethermud/items/ItemInstance.java @@ -0,0 +1,64 @@ +/** + * Copyright 2017 Syncleus, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.syncleus.aethermud.items; + +import com.google.common.collect.Lists; + +import java.util.UUID; + +public interface ItemInstance extends Item { + String CORPSE_INTENAL_NAME = "corpse"; + + Item getItem(); + + void setItem(Item item); + + boolean isWithPlayer(); + + void setWithPlayer(boolean isWithPlayer); + + int getNumberOfUses(); + + void setNumberOfUses(int numberOfUses); + + String getItemId(); + + void setHasBeenWithPlayer(boolean hasBeenWithPlayer); + + void setItemId(String itemId); + + boolean isHasBeenWithPlayer(); + + static ItemInstance createCorpseItem(String name, Loot loot) { + + ItemInstance item = new ItemBuilder() + .internalItemName(CORPSE_INTENAL_NAME) + .itemName(name + " corpse") + .itemDescription("a bloody corpse") + .itemTriggers(Lists.newArrayList("corpse", "c", name, name + " corpse")) + .itemId(UUID.randomUUID().toString()) + .itemHalfLifeTicks(120) + .rarity(Rarity.BASIC) + .valueInGold(5) + .isDisposable(false) + .restingName("a corpse lies on the ground.") + .loot(loot) + .create(); + + return item; + + } +} diff --git a/src/main/java/com/syncleus/aethermud/items/ItemInstanceImpl.java b/src/main/java/com/syncleus/aethermud/items/ItemInstanceImpl.java new file mode 100644 index 00000000..b672f04a --- /dev/null +++ b/src/main/java/com/syncleus/aethermud/items/ItemInstanceImpl.java @@ -0,0 +1,271 @@ +/** + * Copyright 2017 Syncleus, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.syncleus.aethermud.items; + +import com.syncleus.aethermud.core.service.TimeTracker; +import com.syncleus.aethermud.spawner.SpawnRule; +import com.syncleus.aethermud.stats.Stats; + +import java.util.List; +import java.util.Set; + +public class ItemInstanceImpl implements ItemInstance { + + private Item item; + private String itemId; + private int numberOfUses; + private boolean isWithPlayer; + private boolean hasBeenWithPlayer; + + public ItemInstanceImpl() { + } + + public ItemInstanceImpl(Item item, String itemId, int numberOfUses, boolean isWithPlayer, boolean hasBeenWithPlayer) { + this.item = item; + this.itemId = itemId; + this.numberOfUses = numberOfUses; + this.isWithPlayer = isWithPlayer; + this.hasBeenWithPlayer = hasBeenWithPlayer; + } + + @Override + public Item getItem() { + return item; + } + + @Override + public void setItem(Item item) { + this.item = item; + } + + @Override + public Set<SpawnRule> getSpawnRules() { + return item.getSpawnRules(); + } + + @Override + public void setSpawnRules(Set<SpawnRule> spawnRules) { + item.setSpawnRules(spawnRules); + } + + @Override + public Set<Forage> getForages() { + return item.getForages(); + } + + @Override + public void setForages(Set<Forage> forages) { + item.setForages(forages); + } + + @Override + public boolean isWithPlayer() { + return isWithPlayer; + } + + @Override + public void setWithPlayer(boolean isWithPlayer) { + if (isWithPlayer) { + setHasBeenWithPlayer(true); + } + this.isWithPlayer = isWithPlayer; + } + + @Override + public int getNumberOfUses() { + return numberOfUses; + } + + @Override + public void setNumberOfUses(int numberOfUses) { + this.numberOfUses = numberOfUses; + } + + @Override + public String getItemId() { + return itemId; + } + + @Override + public void setHasBeenWithPlayer(boolean hasBeenWithPlayer) { + this.hasBeenWithPlayer = hasBeenWithPlayer; + } + + @Override + public void setItemId(String itemId) { + this.itemId = itemId; + } + + @Override + public boolean isHasBeenWithPlayer() { + return hasBeenWithPlayer; + } + + @Override + public Stats getItemApplyStats() { + return item.getItemApplyStats(); + } + + @Override + public List<TimeTracker.TimeOfDay> getValidTimeOfDays() { + return item.getValidTimeOfDays(); + } + + @Override + public void setValidTimeOfDays(Set<TimeTracker.TimeOfDay> validTimeOfDays) { + item.setValidTimeOfDays(validTimeOfDays); + } + + @Override + public void setValidTimeOfDays(List<TimeTracker.TimeOfDay> validTimeOfDays) { + item.setValidTimeOfDays(validTimeOfDays); + } + + @Override + public boolean isDisposable() { + return item.isDisposable(); + } + + @Override + public int getMaxUses() { + return item.getMaxUses(); + } + + @Override + public String getInternalItemName() { + return item.getInternalItemName(); + } + + @Override + public String getItemName() { + return item.getItemName(); + } + + @Override + public String getItemDescription() { + return item.getItemDescription(); + } + + @Override + public List<String> getItemTriggers() { + return item.getItemTriggers(); + } + + @Override + public String getRestingName() { + return item.getRestingName(); + } + + @Override + public int getItemHalfLifeTicks() { + return item.getItemHalfLifeTicks(); + } + + @Override + public Loot getLoot() { + return item.getLoot(); + } + + @Override + public void setEquipment(Equipment equipment) { + item.setEquipment(equipment); + } + + @Override + public Equipment getEquipment() { + return item.getEquipment(); + } + + @Override + public Rarity getRarity() { + return item.getRarity(); + } + + @Override + public int getValueInGold() { + return item.getValueInGold(); + } + + @Override + public void setEffects(Set<Effect> effects) { + item.setEffects(effects); + } + + @Override + public Set<Effect> getEffects() { + return item.getEffects(); + } + + @Override + public void setItemName(String itemName) { + item.setItemName(itemName); + } + + @Override + public void setItemDescription(String itemDescription) { + item.setItemDescription(itemDescription); + } + + @Override + public void setInternalItemName(String internalItemName) { + item.setInternalItemName(internalItemName); + } + + @Override + public void setItemTriggers(List<String> itemTriggers) { + item.setItemTriggers(itemTriggers); + } + + @Override + public void setRestingName(String restingName) { + item.setRestingName(restingName); + } + + @Override + public void setLoot(Loot loot) { + item.setLoot(loot); + } + + @Override + public void setItemHalfLifeTicks(int itemHalfLifeTicks) { + item.setItemHalfLifeTicks(itemHalfLifeTicks); + } + + @Override + public void setRarity(Rarity rarity) { + item.setRarity(rarity); + } + + @Override + public void setValueInGold(int valueInGold) { + item.setValueInGold(valueInGold); + } + + @Override + public void setMaxUses(int maxUses) { + item.setMaxUses(maxUses); + } + + @Override + public void setDisposable(boolean disposable) { + item.setDisposable(disposable); + } + + @Override + public void setItemApplyStats(Stats itemApplyStats) { + item.setItemApplyStats(itemApplyStats); + } +} diff --git a/src/main/java/com/syncleus/aethermud/items/ItemUseAction.java b/src/main/java/com/syncleus/aethermud/items/ItemUseAction.java index ec3ebe0e..378d3c69 100644 --- a/src/main/java/com/syncleus/aethermud/items/ItemUseAction.java +++ b/src/main/java/com/syncleus/aethermud/items/ItemUseAction.java @@ -24,9 +24,9 @@ import java.util.Set; public interface ItemUseAction { String getInternalItemName(); - void executeAction(GameManager gameManager, Player player, Item item, UseCommand.UseItemOn useItemOn); + void executeAction(GameManager gameManager, Player player, ItemInstance item, UseCommand.UseItemOn useItemOn); - void postExecuteAction(GameManager gameManager, Player player, Item item); + void postExecuteAction(GameManager gameManager, Player player, ItemInstance item); Set<Effect> getEffects(); diff --git a/src/main/java/com/syncleus/aethermud/items/ItemUseHandler.java b/src/main/java/com/syncleus/aethermud/items/ItemUseHandler.java index ce88b311..5546a149 100644 --- a/src/main/java/com/syncleus/aethermud/items/ItemUseHandler.java +++ b/src/main/java/com/syncleus/aethermud/items/ItemUseHandler.java @@ -22,6 +22,8 @@ import com.syncleus.aethermud.items.use.DefaultApplyEffectsStats; import com.syncleus.aethermud.items.use.LightningSpellBookUseAction; import com.syncleus.aethermud.items.use.StickOfJusticeUseAction; import com.syncleus.aethermud.player.Player; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import org.apache.log4j.Logger; import java.util.Optional; @@ -35,33 +37,36 @@ public class ItemUseHandler { this.gameManager = gameManager; } - public void handle(Player player, Item item, UseCommand.UseItemOn useItemOn) { + public void handle(Player player, ItemInstance itemInstance, UseCommand.UseItemOn useItemOn) { ItemUseAction itemUseAction = null; - Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(item.getInternalItemName()); - if (!itemMetadataOptional.isPresent()) { - return; + Item item; + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + Optional<ItemData> itemOptional = tx.getStorage().getItem(itemInstance.getInternalItemName()); + if (!itemOptional.isPresent()) { + return; + } + item = ItemData.copyItem(itemOptional.get()); } - ItemMetadata itemMetadata = itemMetadataOptional.get(); - switch (itemMetadata.getInternalItemName()) { + switch (item.getInternalItemName()) { case "lightning spellbook": - itemUseAction = new LightningSpellBookUseAction(itemMetadata); + itemUseAction = new LightningSpellBookUseAction(item); break; case "stick of justice": - itemUseAction = new StickOfJusticeUseAction(itemMetadata); + itemUseAction = new StickOfJusticeUseAction(item); break; default: - if ((item.getEffects() != null && item.getEffects().size() > 0) || (item.getItemApplyStats() != null)) { - itemUseAction = new DefaultApplyEffectsStats(itemMetadata); + if ((itemInstance.getEffects() != null && itemInstance.getEffects().size() > 0) || (itemInstance.getItemApplyStats() != null)) { + itemUseAction = new DefaultApplyEffectsStats(item); } break; } if (itemUseAction != null) { - itemUseAction.executeAction(gameManager, player, item, useItemOn); - itemUseAction.postExecuteAction(gameManager, player, item); + itemUseAction.executeAction(gameManager, player, itemInstance, useItemOn); + itemUseAction.postExecuteAction(gameManager, player, itemInstance); } } - public static void incrementUses(Item item) { + public static void incrementUses(ItemInstance item) { item.setNumberOfUses(item.getNumberOfUses() + 1); } } diff --git a/src/main/java/com/syncleus/aethermud/items/LootManager.java b/src/main/java/com/syncleus/aethermud/items/LootManager.java index ac9705af..176fdd87 100644 --- a/src/main/java/com/syncleus/aethermud/items/LootManager.java +++ b/src/main/java/com/syncleus/aethermud/items/LootManager.java @@ -15,8 +15,12 @@ */ package com.syncleus.aethermud.items; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; import com.syncleus.aethermud.core.GameManager; import com.google.common.collect.Sets; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import org.apache.commons.lang.math.JVMRandom; import java.util.Optional; @@ -24,14 +28,12 @@ import java.util.Random; import java.util.Set; public class LootManager { - private final GameManager gameManager; - public LootManager(GameManager gameManager) { this.gameManager = gameManager; } - private final Random random = new Random(); + private final Interner<String> interner = Interners.newWeakInterner(); private int randInt(int min, int max) { return (int) JVMRandom.nextLong((max - min) + 1) + min; @@ -48,18 +50,23 @@ public class LootManager { return randInt(loot.getLootGoldMin(), loot.getLootGoldMax()); } - public Set<Item> lootItemsReturn(Loot loot) { - Set<Item> lootItems = Sets.newHashSet(); + public Set<ItemInstance> lootItemsReturn(Loot loot) { + Set<ItemInstance> lootItems = Sets.newHashSet(); for (String internalItemName: loot.getInternalItemNames()) { - Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(internalItemName); - if (!itemMetadataOptional.isPresent()) { - continue; - } - ItemMetadata itemMetadata = itemMetadataOptional.get(); - if (lootDropSuccess(itemMetadata.getRarity().getPercentToLoot())) { - Item i = new ItemBuilder().from(itemMetadata).create(); - gameManager.getEntityManager().saveItem(i); - lootItems.add(i); + synchronized (interner.intern(internalItemName)) { + try (GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction()) { + Optional<ItemData> itemOptional = tx.getStorage().getItem(internalItemName); + if (!itemOptional.isPresent()) { + continue; + } + ItemData item = itemOptional.get(); + if (lootDropSuccess(item.getRarity().getPercentToLoot())) { + ItemInstance i = new ItemBuilder().from(ItemData.copyItem(item)).create(); + tx.getStorage().saveItemEntity(i); + lootItems.add(i); + } + tx.success(); + } } } return lootItems; diff --git a/src/main/java/com/syncleus/aethermud/items/use/DefaultApplyEffectsStats.java b/src/main/java/com/syncleus/aethermud/items/use/DefaultApplyEffectsStats.java index 8fb81477..b9a13a2f 100644 --- a/src/main/java/com/syncleus/aethermud/items/use/DefaultApplyEffectsStats.java +++ b/src/main/java/com/syncleus/aethermud/items/use/DefaultApplyEffectsStats.java @@ -31,10 +31,10 @@ public class DefaultApplyEffectsStats implements ItemUseAction { private final Stats itemApplyStats; private static final Logger log = Logger.getLogger(DefaultApplyEffectsStats.class); - public DefaultApplyEffectsStats(ItemMetadata itemMetadata) { - this.internalItemName = itemMetadata.getInternalItemName(); - this.effectSet = itemMetadata.getEffects(); - this.itemApplyStats = itemMetadata.getItemApplyStats(); + public DefaultApplyEffectsStats(Item item) { + this.internalItemName = item.getInternalItemName(); + this.effectSet = item.getEffects(); + this.itemApplyStats = item.getItemApplyStats(); } @Override @@ -43,7 +43,7 @@ public class DefaultApplyEffectsStats implements ItemUseAction { } @Override - public void executeAction(GameManager gameManager, Player player, Item item, UseCommand.UseItemOn useItemOn) { + public void executeAction(GameManager gameManager, Player player, ItemInstance item, UseCommand.UseItemOn useItemOn) { String playerName = player.getPlayerName(); gameManager.writeToPlayerCurrentRoom(player.getPlayerId(), playerName + " uses " + item.getItemName() + ".\r\n"); @@ -60,7 +60,7 @@ public class DefaultApplyEffectsStats implements ItemUseAction { } @Override - public void postExecuteAction(GameManager gameManager, Player player, Item item) { + public void postExecuteAction(GameManager gameManager, Player player, ItemInstance item) { ItemUseHandler.incrementUses(item); if (item.isDisposable()) { if (item.getNumberOfUses() < item.getMaxUses()) { diff --git a/src/main/java/com/syncleus/aethermud/items/use/DirtyBombUseAction.java b/src/main/java/com/syncleus/aethermud/items/use/DirtyBombUseAction.java index 9ce835a8..44a11d32 100644 --- a/src/main/java/com/syncleus/aethermud/items/use/DirtyBombUseAction.java +++ b/src/main/java/com/syncleus/aethermud/items/use/DirtyBombUseAction.java @@ -32,19 +32,19 @@ import java.util.Set; public class DirtyBombUseAction implements ItemUseAction { - private final ItemMetadata itemMetadata; + private final Item item; - public DirtyBombUseAction(ItemMetadata itemMetadata) { - this.itemMetadata = itemMetadata; + public DirtyBombUseAction(Item item) { + this.item = item; } @Override public String getInternalItemName() { - return itemMetadata.getInternalItemName(); + return item.getInternalItemName(); } @Override - public void executeAction(GameManager gameManager, Player player, Item item, UseCommand.UseItemOn useItemOn) { + public void executeAction(GameManager gameManager, Player player, ItemInstance item, UseCommand.UseItemOn useItemOn) { Room currentRoom = player.getCurrentRoom(); if (currentRoom.getRoomId().equals(1)) { gameManager.writeToPlayerCurrentRoom(player.getPlayerId(), player.getPlayerName() + " tried to detonate a " + item.getItemName() + "!"); @@ -74,7 +74,7 @@ public class DirtyBombUseAction implements ItemUseAction { } @Override - public void postExecuteAction(GameManager gameManager, Player player, Item item) { + public void postExecuteAction(GameManager gameManager, Player player, ItemInstance item) { ItemUseHandler.incrementUses(item); if (item.isDisposable()) { if (item.getNumberOfUses() < item.getMaxUses()) { diff --git a/src/main/java/com/syncleus/aethermud/items/use/LightningSpellBookUseAction.java b/src/main/java/com/syncleus/aethermud/items/use/LightningSpellBookUseAction.java index 614692c8..11dff6b1 100644 --- a/src/main/java/com/syncleus/aethermud/items/use/LightningSpellBookUseAction.java +++ b/src/main/java/com/syncleus/aethermud/items/use/LightningSpellBookUseAction.java @@ -19,7 +19,7 @@ import com.syncleus.aethermud.command.commands.UseCommand; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.items.Effect; import com.syncleus.aethermud.items.Item; -import com.syncleus.aethermud.items.ItemMetadata; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.ItemUseAction; import com.syncleus.aethermud.player.Player; import com.syncleus.aethermud.spells.LightningSpell; @@ -28,21 +28,21 @@ import java.util.Set; public class LightningSpellBookUseAction implements ItemUseAction { - private final ItemMetadata itemMetadata; + private final Item item; - public LightningSpellBookUseAction(ItemMetadata itemMetadata) { - this.itemMetadata = itemMetadata; + public LightningSpellBookUseAction(Item item) { + this.item = item; } private Boolean dontDelete = Boolean.FALSE; @Override public String getInternalItemName() { - return itemMetadata.getInternalItemName(); + return item.getInternalItemName(); } @Override - public void executeAction(GameManager gameManager, Player player, Item item, UseCommand.UseItemOn useItemOn) { + public void executeAction(GameManager gameManager, Player player, ItemInstance item, UseCommand.UseItemOn useItemOn) { if (player.getLearnedSpells().contains(LightningSpell.name)) { gameManager.getChannelUtils().write(player.getPlayerId(), "You already know how to use " + LightningSpell.name); dontDelete = true; @@ -53,7 +53,7 @@ public class LightningSpellBookUseAction implements ItemUseAction { } @Override - public void postExecuteAction(GameManager gameManager, Player player, Item item) { + public void postExecuteAction(GameManager gameManager, Player player, ItemInstance item) { if (!dontDelete) { player.removeInventoryId(item.getItemId()); gameManager.getEntityManager().removeItem(item); diff --git a/src/main/java/com/syncleus/aethermud/items/use/ResetAllEffectsUseAction.java b/src/main/java/com/syncleus/aethermud/items/use/ResetAllEffectsUseAction.java index e5fe47c0..5a49a9a1 100644 --- a/src/main/java/com/syncleus/aethermud/items/use/ResetAllEffectsUseAction.java +++ b/src/main/java/com/syncleus/aethermud/items/use/ResetAllEffectsUseAction.java @@ -24,25 +24,25 @@ import java.util.Set; public class ResetAllEffectsUseAction implements ItemUseAction { - private final ItemMetadata itemMetadata; + private final Item item; - public ResetAllEffectsUseAction(ItemMetadata itemMetadata) { - this.itemMetadata = itemMetadata; + public ResetAllEffectsUseAction(Item item) { + this.item = item; } @Override public String getInternalItemName() { - return itemMetadata.getInternalItemName(); + return item.getInternalItemName(); } @Override - public void executeAction(GameManager gameManager, Player player, Item item, UseCommand.UseItemOn useItemOn) { + public void executeAction(GameManager gameManager, Player player, ItemInstance item, UseCommand.UseItemOn useItemOn) { player.resetEffects(); gameManager.getChannelUtils().write(player.getPlayerId(), "All Effects are removed." + "\r\n"); } @Override - public void postExecuteAction(GameManager gameManager, Player player, Item item) { + public void postExecuteAction(GameManager gameManager, Player player, ItemInstance item) { ItemUseHandler.incrementUses(item); if (item.isDisposable()) { if (item.getNumberOfUses() < item.getMaxUses()) { diff --git a/src/main/java/com/syncleus/aethermud/items/use/StickOfJusticeUseAction.java b/src/main/java/com/syncleus/aethermud/items/use/StickOfJusticeUseAction.java index de9251ab..e34a9b77 100644 --- a/src/main/java/com/syncleus/aethermud/items/use/StickOfJusticeUseAction.java +++ b/src/main/java/com/syncleus/aethermud/items/use/StickOfJusticeUseAction.java @@ -19,7 +19,7 @@ import com.syncleus.aethermud.command.commands.UseCommand; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.items.Effect; import com.syncleus.aethermud.items.Item; -import com.syncleus.aethermud.items.ItemMetadata; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.ItemUseAction; import com.syncleus.aethermud.player.Player; @@ -28,20 +28,20 @@ import java.util.Set; public class StickOfJusticeUseAction implements ItemUseAction { - private final ItemMetadata itemMetadata; + private final Item item; - public StickOfJusticeUseAction(ItemMetadata itemMetadata) { - this.itemMetadata = itemMetadata; + public StickOfJusticeUseAction(Item item) { + this.item = item; } @Override public String getInternalItemName() { - return itemMetadata.getInternalItemName(); + return item.getInternalItemName(); } @Override - public void executeAction(GameManager gameManager, Player player, Item item, UseCommand.UseItemOn useItemOn) { + public void executeAction(GameManager gameManager, Player player, ItemInstance item, UseCommand.UseItemOn useItemOn) { if (!useItemOn.getTarget().isPresent()) { gameManager.getChannelUtils().write(player.getPlayerId(), "You must use the Stick Of Justice on someone who deserves it."); @@ -60,7 +60,7 @@ public class StickOfJusticeUseAction implements ItemUseAction { } @Override - public void postExecuteAction(GameManager gameManager, Player player, Item item) { + public void postExecuteAction(GameManager gameManager, Player player, ItemInstance item) { } @Override diff --git a/src/main/java/com/syncleus/aethermud/merchant/Merchant.java b/src/main/java/com/syncleus/aethermud/merchant/Merchant.java index 93177bb4..3dc9ff8e 100644 --- a/src/main/java/com/syncleus/aethermud/merchant/Merchant.java +++ b/src/main/java/com/syncleus/aethermud/merchant/Merchant.java @@ -16,7 +16,9 @@ package com.syncleus.aethermud.merchant; import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.items.ItemMetadata; +import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import org.nocrala.tools.texttablefmt.BorderStyle; import org.nocrala.tools.texttablefmt.ShownBorders; import org.nocrala.tools.texttablefmt.Table; @@ -71,14 +73,17 @@ public class Merchant { while (iterator.hasNext()) { i++; MerchantItemForSale merchantItemForSale = iterator.next(); - Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(merchantItemForSale.getInternalItemName()); - if (!itemMetadataOptional.isPresent()) { - continue; + Item item; + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + Optional<ItemData> itemOptional = tx.getStorage().getItem(merchantItemForSale.getInternalItemName()); + if (!itemOptional.isPresent()) { + continue; + } + item = ItemData.copyItem(itemOptional.get()); } - ItemMetadata itemMetadata = itemMetadataOptional.get(); t.addCell(String.valueOf(i)); t.addCell(NumberFormat.getNumberInstance(Locale.US).format(merchantItemForSale.getCost())); - t.addCell(itemMetadata.getItemDescription()); + t.addCell(item.getItemDescription()); } return t.render(); } diff --git a/src/main/java/com/syncleus/aethermud/merchant/MerchantCommandHandler.java b/src/main/java/com/syncleus/aethermud/merchant/MerchantCommandHandler.java index 9fb9802b..65cbfb84 100644 --- a/src/main/java/com/syncleus/aethermud/merchant/MerchantCommandHandler.java +++ b/src/main/java/com/syncleus/aethermud/merchant/MerchantCommandHandler.java @@ -17,7 +17,7 @@ package com.syncleus.aethermud.merchant; import com.syncleus.aethermud.command.commands.CommandAuditLog; import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.player.Player; import com.syncleus.aethermud.server.model.AetherMudSession; import com.syncleus.aethermud.server.communication.Color; @@ -70,7 +70,7 @@ public class MerchantCommandHandler extends SimpleChannelUpstreamHandler { Integer desiredItem = Integer.parseInt(split[1]); if (inventoryMenu.containsKey(desiredItem)) { InventoryItemForSale inventoryItemForSale = inventoryMenu.get(desiredItem); - Item item = inventoryItemForSale.getItem(); + ItemInstance item = inventoryItemForSale.getItem(); playerByUsername.incrementGold(inventoryItemForSale.getCost()); gameManager.getChannelUtils().write(playerByUsername.getPlayerId(), "You have received: " + inventoryItemForSale.getCost() + Color.YELLOW + " gold" + Color.RESET + " for " + item.getItemName() + "\r\n"); playerByUsername.removeInventoryId(item.getItemId()); @@ -103,9 +103,9 @@ public class MerchantCommandHandler extends SimpleChannelUpstreamHandler { public Map<Integer, InventoryItemForSale> getInventoryMenu(Player player) { Map<Integer, InventoryItemForSale> inventoryItemsForSale = Maps.newHashMap(); - List<Item> inventory = player.getInventory(); + List<ItemInstance> inventory = player.getInventory(); int inv = 1; - for (Item itemEntity : inventory) { + for (ItemInstance itemEntity : inventory) { int valueInGold = itemEntity.getValueInGold(); if (valueInGold == 0) { valueInGold = itemEntity.getValueInGold(); @@ -150,10 +150,10 @@ public class MerchantCommandHandler extends SimpleChannelUpstreamHandler { } class InventoryItemForSale { - private final Item item; + private final ItemInstance item; private final Integer cost; - public InventoryItemForSale(Integer cost, Item item) { + public InventoryItemForSale(Integer cost, ItemInstance item) { this.cost = cost; this.item = item; } @@ -162,7 +162,7 @@ public class MerchantCommandHandler extends SimpleChannelUpstreamHandler { return cost; } - public Item getItem() { + public ItemInstance getItem() { return item; } } diff --git a/src/main/java/com/syncleus/aethermud/merchant/MerchantManager.java b/src/main/java/com/syncleus/aethermud/merchant/MerchantManager.java index 18d46243..554c19de 100644 --- a/src/main/java/com/syncleus/aethermud/merchant/MerchantManager.java +++ b/src/main/java/com/syncleus/aethermud/merchant/MerchantManager.java @@ -20,10 +20,12 @@ import com.codahale.metrics.Timer; import com.syncleus.aethermud.Main; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.ItemBuilder; -import com.syncleus.aethermud.items.ItemMetadata; import com.syncleus.aethermud.player.Player; import com.syncleus.aethermud.player.PlayerUtil; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import java.util.Optional; @@ -47,11 +49,14 @@ public class MerchantManager { i++; if (i == itemNo) { String internalItemName = merchantItemForSale.getInternalItemName(); - Optional<ItemMetadata> itemMetadataOptional = gameManager.getItemStorage().get(internalItemName); - if (!itemMetadataOptional.isPresent()) { - continue; + Item item; + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + Optional<ItemData> itemOptional = tx.getStorage().getItem(internalItemName); + if (!itemOptional.isPresent()) { + continue; + } + item = ItemData.copyItem(itemOptional.get()); } - ItemMetadata itemMetadata = itemMetadataOptional.get(); long maxInventorySize = player.getPlayerStatsWithEquipmentAndLevel().getInventorySize(); if (player.getInventory().size() >= maxInventorySize) { gameManager.getChannelUtils().write(player.getPlayerId(), "Your inventory is full, drop some items and come back.\r\n"); @@ -61,13 +66,13 @@ public class MerchantManager { PlayerUtil.consume(gameManager, player.getPlayerId(), playerData -> { long availableGold = playerData.getGold(); if (availableGold >= price) { - Item item = new ItemBuilder().from(itemMetadata).create(); - gameManager.getEntityManager().saveItem(item); - gameManager.acquireItem(player, item.getItemId()); + ItemInstance itemInstance = new ItemBuilder().from(item).create(); + gameManager.getEntityManager().saveItem(itemInstance); + gameManager.acquireItem(player, itemInstance.getItemId()); player.incrementGold(-price); - gameManager.getChannelUtils().write(player.getPlayerId(), "You have purchased: " + item.getItemName() + "\r\n"); + gameManager.getChannelUtils().write(player.getPlayerId(), "You have purchased: " + itemInstance.getItemName() + "\r\n"); } else { - gameManager.getChannelUtils().write(player.getPlayerId(), "You can't afford: " + itemMetadata.getItemName() + "\r\n"); + gameManager.getChannelUtils().write(player.getPlayerId(), "You can't afford: " + item.getItemName() + "\r\n"); } }); } diff --git a/src/main/java/com/syncleus/aethermud/merchant/lockers/GetCommand.java b/src/main/java/com/syncleus/aethermud/merchant/lockers/GetCommand.java index cfd3723e..a97dc283 100644 --- a/src/main/java/com/syncleus/aethermud/merchant/lockers/GetCommand.java +++ b/src/main/java/com/syncleus/aethermud/merchant/lockers/GetCommand.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.merchant.lockers; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; import com.syncleus.aethermud.storage.graphdb.model.PlayerData; @@ -50,11 +50,11 @@ public class GetCommand extends LockerCommand { } PlayerData playerData = playerMetadataOptional.get(); for (String entityId : playerData.getLockerInventory()) { - Optional<Item> itemEntityOptional = gameManager.getEntityManager().getItemEntity(entityId); + Optional<ItemInstance> itemEntityOptional = gameManager.getEntityManager().getItemEntity(entityId); if (!itemEntityOptional.isPresent()) { continue; } - Item itemEntity = itemEntityOptional.get(); + ItemInstance itemEntity = itemEntityOptional.get(); if (itemEntity.getItemTriggers().contains(desiredRetrieveOption)) { player.transferItemFromLocker(entityId); write(itemEntity.getItemName() + " retrieved from locker.\r\n"); diff --git a/src/main/java/com/syncleus/aethermud/merchant/lockers/PutCommand.java b/src/main/java/com/syncleus/aethermud/merchant/lockers/PutCommand.java index fac19012..04d5b62a 100644 --- a/src/main/java/com/syncleus/aethermud/merchant/lockers/PutCommand.java +++ b/src/main/java/com/syncleus/aethermud/merchant/lockers/PutCommand.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.merchant.lockers; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.core.GameManager; import com.google.common.base.Joiner; import org.jboss.netty.channel.ChannelHandlerContext; @@ -39,7 +39,7 @@ public class PutCommand extends LockerCommand { configure(e); originalMessageParts.remove(0); String desiredDropOffItem = Joiner.on(" ").join(originalMessageParts); - for (Item item : player.getInventory()) { + for (ItemInstance item : player.getInventory()) { if (item.getItemTriggers().contains(desiredDropOffItem)) { item.setWithPlayer(false); player.transferItemToLocker(item.getItemId()); diff --git a/src/main/java/com/syncleus/aethermud/npc/NpcSpawn.java b/src/main/java/com/syncleus/aethermud/npc/NpcSpawn.java index 6bde9d21..20878b95 100644 --- a/src/main/java/com/syncleus/aethermud/npc/NpcSpawn.java +++ b/src/main/java/com/syncleus/aethermud/npc/NpcSpawn.java @@ -22,7 +22,8 @@ import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.core.SentryManager; import com.syncleus.aethermud.entity.AetherMudEntity; import com.syncleus.aethermud.items.Effect; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.Loot; import com.syncleus.aethermud.player.CoolDown; import com.syncleus.aethermud.player.CoolDownType; @@ -278,7 +279,7 @@ public class NpcSpawn extends AetherMudEntity { isAlive.set(false); player.removeActiveAlertStatus(this); Map<String, Double> damagePercents; - Item corpse = Item.createCorpseItem(getName(), getLoot()); + ItemInstance corpse = ItemInstance.createCorpseItem(getName(), getLoot()); if (!player.isActive(CoolDownType.DEATH)) { gameManager.writeToPlayerCurrentRoom(player.getPlayerId(), getDieMessage() + "\r\n"); } diff --git a/src/main/java/com/syncleus/aethermud/player/Player.java b/src/main/java/com/syncleus/aethermud/player/Player.java index 8569237c..cfe8f576 100644 --- a/src/main/java/com/syncleus/aethermud/player/Player.java +++ b/src/main/java/com/syncleus/aethermud/player/Player.java @@ -698,16 +698,16 @@ public class Player extends AetherMudEntity { } } - public Optional<Item> getInventoryItem(String itemKeyword) { + public Optional<ItemInstance> getInventoryItem(String itemKeyword) { synchronized (interner.intern(playerId)) { final List<String> inventory = new ArrayList<>(); this.consumeRead(playerData -> inventory.addAll(playerData.getInventory())); for (String itemId : inventory) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemOptional.isPresent()) { continue; } - Item itemEntity = itemOptional.get(); + ItemInstance itemEntity = itemOptional.get(); if (itemEntity.getItemTriggers().contains(itemKeyword)) { return Optional.of(itemEntity); } @@ -723,10 +723,10 @@ public class Player extends AetherMudEntity { public List<String> getRolledUpLockerInventory() { synchronized (interner.intern(playerId)) { List<String> rolledUp = Lists.newArrayList(); - List<Item> inventory = getLockerInventory(); + List<ItemInstance> inventory = getLockerInventory(); Map<String, Integer> itemAndCounts = Maps.newHashMap(); if (inventory != null) { - for (Item item : inventory) { + for (ItemInstance item : inventory) { StringBuilder invItem = new StringBuilder(); invItem.append(item.getItemName()); int maxUses = item.getMaxUses(); @@ -761,14 +761,14 @@ public class Player extends AetherMudEntity { } } - public List<Item> getLockerInventory() { + public List<ItemInstance> getLockerInventory() { synchronized (interner.intern(playerId)) { return this.transactRead(playerData -> { - List<Item> inventoryItems = Lists.newArrayList(); + List<ItemInstance> inventoryItems = Lists.newArrayList(); List<String> inventory = playerData.getLockerInventory(); if (inventory != null) { for (String itemId : inventory) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemOptional.isPresent()) { log.info("Orphaned inventoryId:" + itemId + " player: " + getPlayerName()); continue; @@ -776,7 +776,7 @@ public class Player extends AetherMudEntity { inventoryItems.add(itemOptional.get()); } } - inventoryItems.sort(Comparator.comparing(Item::getItemName)); + inventoryItems.sort(Comparator.comparing(ItemInstance::getItemName)); return inventoryItems; }); } @@ -785,10 +785,10 @@ public class Player extends AetherMudEntity { public List<String> getRolledUpIntentory() { synchronized (interner.intern(playerId)) { List<String> rolledUp = Lists.newArrayList(); - List<Item> inventory = getInventory(); + List<ItemInstance> inventory = getInventory(); Map<String, Integer> itemAndCounts = Maps.newHashMap(); if (inventory != null) { - for (Item item : inventory) { + for (ItemInstance item : inventory) { StringBuilder invItem = new StringBuilder(); invItem.append(item.getItemName()); int maxUses = item.getMaxUses(); @@ -823,14 +823,14 @@ public class Player extends AetherMudEntity { } } - public List<Item> getInventory() { + public List<ItemInstance> getInventory() { synchronized (interner.intern(playerId)) { return this.transactRead(playerData -> { - List<Item> inventoryItems = Lists.newArrayList(); + List<ItemInstance> inventoryItems = Lists.newArrayList(); List<String> inventory = playerData.getInventory(); if (inventory != null) { for (String itemId : inventory) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemOptional.isPresent()) { log.info("Orphaned inventoryId:" + itemId + " player: " + getPlayerName()); continue; @@ -838,20 +838,20 @@ public class Player extends AetherMudEntity { inventoryItems.add(itemOptional.get()); } } - inventoryItems.sort(Comparator.comparing(Item::getItemName)); + inventoryItems.sort(Comparator.comparing(ItemInstance::getItemName)); return inventoryItems; }); } } - public Set<Item> getEquipment() { + public Set<ItemInstance> getEquipment() { synchronized (interner.intern(playerId)) { return this.transactRead(playerData -> { - Set<Item> equipmentItems = Sets.newHashSet(); + Set<ItemInstance> equipmentItems = Sets.newHashSet(); List<String> equipment = playerData.getPlayerEquipment(); if (equipment != null) { for (String itemId : equipment) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemOptional.isPresent()) { log.info("Orphaned equipmentId:" + itemId + " player: " + getPlayerName()); continue; @@ -864,14 +864,14 @@ public class Player extends AetherMudEntity { } } - public void equip(Item item) { + public void equip(ItemInstance item) { synchronized (interner.intern(playerId)) { if (item.getEquipment() == null) { return; } Equipment equipment = item.getEquipment(); EquipmentSlotType equipmentSlotType = equipment.getEquipmentSlotType(); - Optional<Item> slotItemOptional = getSlotItem(equipmentSlotType); + Optional<ItemInstance> slotItemOptional = getSlotItem(equipmentSlotType); if (slotItemOptional.isPresent()) { if (!unEquip(slotItemOptional.get())) { return; @@ -883,17 +883,17 @@ public class Player extends AetherMudEntity { } } - public Optional<Item> getSlotItem(EquipmentSlotType slot) { + public Optional<ItemInstance> getSlotItem(EquipmentSlotType slot) { return this.transactRead(playerData -> { if (playerData.getPlayerEquipment() == null) { return Optional.empty(); } for (String item : playerData.getPlayerEquipment()) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(item); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(item); if (!itemOptional.isPresent()) { continue; } - Item itemEntity = itemOptional.get(); + ItemInstance itemEntity = itemOptional.get(); EquipmentSlotType equipmentSlotType = itemEntity.getEquipment().getEquipmentSlotType(); if (equipmentSlotType.equals(slot)) { return Optional.of(itemEntity); @@ -903,7 +903,7 @@ public class Player extends AetherMudEntity { }); } - public boolean unEquip(Item item) { + public boolean unEquip(ItemInstance item) { synchronized (interner.intern(playerId)) { gameManager.getChannelUtils().write(playerId, "Un-equipping " + item.getItemName() + "\r\n"); if (gameManager.acquireItem(this, item.getItemId())) { @@ -966,11 +966,11 @@ public class Player extends AetherMudEntity { return playerStats; } for (String equipId : playerEquipment) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(equipId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(equipId); if (!itemOptional.isPresent()) { continue; } - Item itemEntity = itemOptional.get(); + ItemInstance itemEntity = itemOptional.get(); Equipment equipment = itemEntity.getEquipment(); Stats stats = equipment.getStats(); StatsHelper.combineStats(newStats, stats); @@ -1011,7 +1011,7 @@ public class Player extends AetherMudEntity { List<EquipmentSlotType> all = EquipmentSlotType.getAll(); for (EquipmentSlotType slot : all) { t.addCell(capitalize(slot.getName())); - Optional<Item> slotItemOptional = getSlotItem(slot); + Optional<ItemInstance> slotItemOptional = getSlotItem(slot); if (slotItemOptional.isPresent()) { t.addCell(slotItemOptional.get().getItemName()); } else { diff --git a/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java b/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java index beec826e..15748f1d 100644 --- a/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java +++ b/src/main/java/com/syncleus/aethermud/player/PlayerManagement.java @@ -18,15 +18,17 @@ package com.syncleus.aethermud.player; import com.google.common.base.Function; import com.google.common.collect.Sets; import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.ItemBuilder; -import com.syncleus.aethermud.items.ItemMetadata; +import com.syncleus.aethermud.items.Item; import com.syncleus.aethermud.server.communication.Color; import com.google.api.client.util.Lists; import com.google.api.client.util.Maps; import com.google.common.base.Joiner; import com.google.common.collect.Interner; import com.google.common.collect.Interners; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.ItemData; import com.syncleus.aethermud.storage.graphdb.model.PlayerData; import java.util.*; @@ -175,11 +177,11 @@ public class PlayerManagement implements PlayerManagementMBean { Map<String, String> inventoryContents = Maps.newHashMap(); List<String> inventory = playerData.getInventory(); for (String itemId : inventory) { - Optional<Item> itemEntityOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemEntityOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemEntityOptional.isPresent()) { continue; } - Item itemEntity = itemEntityOptional.get(); + ItemInstance itemEntity = itemEntityOptional.get(); String itemName = itemEntity.getItemName(); final String msgWithoutColorCodes = itemName.replaceAll("\u001B\\[[;\\d]*m", ""); @@ -195,11 +197,11 @@ public class PlayerManagement implements PlayerManagementMBean { Map<String, String> inventoryContents = Maps.newHashMap(); List<String> inventory = playerData.getLockerInventory(); for (String itemId : inventory) { - Optional<Item> itemEntityOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemEntityOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemEntityOptional.isPresent()) { continue; } - Item itemEntity = itemEntityOptional.get(); + ItemInstance itemEntity = itemEntityOptional.get(); String itemName = itemEntity.getItemName(); final String msgWithoutColorCodes = itemName.replaceAll("\u001B\\[[;\\d]*m", ""); @@ -211,16 +213,20 @@ public class PlayerManagement implements PlayerManagementMBean { @Override public String createItemInInventory(String internalItemName){ - Optional<ItemMetadata> itemMetadata = gameManager.getItemStorage().get(internalItemName); - if (!itemMetadata.isPresent()) { - return "No such item exists with internal name: " + internalItemName; + Item item; + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + Optional<ItemData> itemOptional = tx.getStorage().getItem(internalItemName); + if (!itemOptional.isPresent()) { + return "No such item exists with internal name: " + internalItemName; + } + item = ItemData.copyItem(itemOptional.get()); } - Item item = new ItemBuilder().from(itemMetadata.get()).create(); - gameManager.getEntityManager().saveItem(item); + ItemInstance itemInstance = new ItemBuilder().from(item).create(); + gameManager.getEntityManager().saveItem(itemInstance); synchronized (findInterner().intern(playerId)) { - this.consume(playerData -> playerData.addInventoryEntityId(item.getItemId())); + this.consume(playerData -> playerData.addInventoryEntityId(itemInstance.getItemId())); } - final String msgWithoutColorCodes = item.getItemName().replaceAll("\u001B\\[[;\\d]*m", ""); + final String msgWithoutColorCodes = itemInstance.getItemName().replaceAll("\u001B\\[[;\\d]*m", ""); return msgWithoutColorCodes + " created."; } diff --git a/src/main/java/com/syncleus/aethermud/spawner/ItemSpawner.java b/src/main/java/com/syncleus/aethermud/spawner/ItemSpawner.java index bfd8a0ea..b2cdec87 100644 --- a/src/main/java/com/syncleus/aethermud/spawner/ItemSpawner.java +++ b/src/main/java/com/syncleus/aethermud/spawner/ItemSpawner.java @@ -16,14 +16,16 @@ package com.syncleus.aethermud.spawner; import com.codahale.metrics.MetricRegistry; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; import com.syncleus.aethermud.Main; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.core.SentryManager; import com.syncleus.aethermud.entity.AetherMudEntity; import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.items.ItemBuilder; -import com.syncleus.aethermud.items.ItemMetadata; -import com.syncleus.aethermud.storage.graphdb.model.ItemData; +import com.syncleus.aethermud.storage.graphdb.model.ItemInstanceData; import com.syncleus.aethermud.world.model.Area; import com.syncleus.aethermud.world.model.Room; import com.google.common.base.Predicate; @@ -38,17 +40,18 @@ import java.util.Set; public class ItemSpawner extends AetherMudEntity { private static final Logger LOGGER = Logger.getLogger(ItemSpawner.class); - private final ItemMetadata itemMetadata; + private final Item item; private final SpawnRule spawnRule; private final GameManager gameManager; private Integer roomId; private int noTicks = 0; private final Random random = new Random(); private final Area spawnArea; + private final Interner<String> interner = Interners.newWeakInterner(); - public ItemSpawner(ItemMetadata itemMetadata, SpawnRule spawnRule, GameManager gameManager) { - this.itemMetadata = itemMetadata; + public ItemSpawner(Item item, SpawnRule spawnRule, GameManager gameManager) { + this.item = item; this.spawnRule = spawnRule; this.gameManager = gameManager; this.noTicks = spawnRule.getSpawnIntervalTicks(); @@ -68,8 +71,8 @@ public class ItemSpawner extends AetherMudEntity { int numberOfAttempts = spawnRule.getMaxInstances() - counterNumberInArea(); for (int i = 0; i < numberOfAttempts; i++) { if (random.nextInt(100) < randomPercentage || randomPercentage == 100) { - if (itemMetadata.getValidTimeOfDays() != null && itemMetadata.getValidTimeOfDays().size() > 0) { - if (itemMetadata.getValidTimeOfDays().contains(gameManager.getTimeTracker().getTimeOfDay())) { + if (item.getValidTimeOfDays() != null && item.getValidTimeOfDays().size() > 0) { + if (item.getValidTimeOfDays().contains(gameManager.getTimeTracker().getTimeOfDay())) { createAndAddItem(); } } else { @@ -88,10 +91,12 @@ public class ItemSpawner extends AetherMudEntity { private void createAndAddItem() { ArrayList<Room> rooms = Lists.newArrayList(Iterators.filter(gameManager.getRoomManager().getRoomsByArea(spawnArea).iterator(), getRoomsWithRoom())); Room room = rooms.get(random.nextInt(rooms.size())); - Item item = new ItemBuilder().from(itemMetadata).create(); - ItemData itemData = gameManager.getEntityManager().saveItem(item); - gameManager.placeItemInRoom(room.getRoomId(), item.getItemId()); - Main.metrics.counter(MetricRegistry.name(ItemSpawner.class, item.getItemName() + "-spawn")).inc(); + synchronized (interner.intern(this.item.getInternalItemName())) { + ItemInstance itemInstance = new ItemBuilder().from(this.item).create(); + gameManager.getEntityManager().saveItem(itemInstance); + gameManager.placeItemInRoom(room.getRoomId(), itemInstance.getItemId()); + Main.metrics.counter(MetricRegistry.name(ItemSpawner.class, itemInstance.getItemName() + "-spawn")).inc(); + } } private int counterNumberInArea() { @@ -100,12 +105,12 @@ public class ItemSpawner extends AetherMudEntity { for (Room room : roomsByArea) { if (room.getAreas().contains(spawnArea)) { for (String i : room.getItemIds()) { - Optional<Item> currentItemOptional = gameManager.getEntityManager().getItemEntity(i); + Optional<ItemInstance> currentItemOptional = gameManager.getEntityManager().getItemEntity(i); if (!currentItemOptional.isPresent()) { continue; } - Item currentItem = currentItemOptional.get(); - if (currentItem.getInternalItemName().equals(itemMetadata.getInternalItemName())) { + ItemInstance currentItem = currentItemOptional.get(); + if (currentItem.getInternalItemName().equals(item.getInternalItemName())) { numberCurrentlyInArea++; } } @@ -121,12 +126,12 @@ public class ItemSpawner extends AetherMudEntity { int count = 0; Set<String> itemIds = room.getItemIds(); for (String itemId : itemIds) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemOptional.isPresent()) { continue; } - Item item = itemOptional.get(); - if (item.getInternalItemName().equals(itemMetadata.getInternalItemName())) { + ItemInstance item = itemOptional.get(); + if (item.getInternalItemName().equals(ItemSpawner.this.item.getInternalItemName())) { count++; } } diff --git a/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java b/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java index 316d7fa0..ce33fa66 100644 --- a/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java +++ b/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java @@ -18,8 +18,10 @@ package com.syncleus.aethermud.storage; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.storage.graphdb.model.ItemData; +import com.syncleus.aethermud.storage.graphdb.model.ItemInstanceData; import com.syncleus.aethermud.storage.graphdb.model.NpcData; import com.syncleus.aethermud.storage.graphdb.model.PlayerData; @@ -35,11 +37,19 @@ public interface AetherMudStorage { Map<String, PlayerData> getAllPlayerMetadata(); + ItemInstanceData saveItemEntity(ItemInstance item); + + Optional<ItemInstanceData> getItemEntity(String itemId); + + void removeItemEntity(String itemId); + ItemData saveItem(Item item); - Optional<ItemData> getItemEntity(String itemId); + Optional<ItemData> getItem(String internalName); + + void removeItem(String internalName); - void removeItem(String itemId); + public List<? extends ItemData> getAllItems(); List<? extends NpcSpawn> getAllNpcs(GameManager gameManager); diff --git a/src/main/java/com/syncleus/aethermud/storage/ItemStorage.java b/src/main/java/com/syncleus/aethermud/storage/ItemStorage.java deleted file mode 100644 index 74a1149a..00000000 --- a/src/main/java/com/syncleus/aethermud/storage/ItemStorage.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright 2017 Syncleus, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.syncleus.aethermud.storage; - -import com.syncleus.aethermud.common.ColorizedTextTemplate; -import com.syncleus.aethermud.items.ItemMetadata; -import org.apache.log4j.Logger; - -import java.io.IOException; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -public class ItemStorage { - - public final static String LOCAL_ITEM_DIRECTORY = "world/items/"; - - private static final Logger log = Logger.getLogger(ItemStorage.class); - private final FilebasedJsonStorage filebasedJsonStorage; - - private final List<ItemMetadata> itemMetadatas; - - public ItemStorage(FilebasedJsonStorage filebasedJsonStorage) { - this.filebasedJsonStorage = filebasedJsonStorage; - this.itemMetadatas = getAllItemMetadata(); - } - - private List<ItemMetadata> getAllItemMetadata() { - return filebasedJsonStorage.readAllMetadatas(LOCAL_ITEM_DIRECTORY, true, new ItemMetadata()).stream() - .map(itemMetadata -> { - itemMetadata.setItemDescription(ColorizedTextTemplate.renderFromTemplateLanguage(itemMetadata.getItemDescription())); - itemMetadata.setItemName(ColorizedTextTemplate.renderFromTemplateLanguage(itemMetadata.getItemName())); - itemMetadata.setRestingName(ColorizedTextTemplate.renderFromTemplateLanguage(itemMetadata.getRestingName())); - return itemMetadata; - }).collect(Collectors.toList()); - } - - public List<ItemMetadata> getItemMetadatas() { - return itemMetadatas; - } - - public void saveItemMetadata(ItemMetadata itemMetadata) throws IOException { - itemMetadata.setItemName(ColorizedTextTemplate.renderToTemplateLanguage(itemMetadata.getItemName())); - itemMetadata.setItemDescription(ColorizedTextTemplate.renderToTemplateLanguage(itemMetadata.getItemDescription())); - itemMetadata.setRestingName(ColorizedTextTemplate.renderToTemplateLanguage(itemMetadata.getRestingName())); - filebasedJsonStorage.saveMetadata(itemMetadata.getInternalItemName(), LOCAL_ITEM_DIRECTORY, itemMetadata); - } - - public Optional<ItemMetadata> get(String internalItemName) { - return itemMetadatas.stream() - .filter(itemMetadata -> itemMetadata.getInternalItemName().equals(internalItemName)) - .findFirst(); - } -} diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java index 3d516ec5..1c32b022 100644 --- a/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java +++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java @@ -15,26 +15,29 @@ */ package com.syncleus.aethermud.storage.graphdb; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.npc.NpcBuilder; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.storage.AetherMudStorage; import com.syncleus.aethermud.storage.graphdb.model.ItemData; +import com.syncleus.aethermud.storage.graphdb.model.ItemInstanceData; import com.syncleus.aethermud.storage.graphdb.model.NpcData; import com.syncleus.aethermud.storage.graphdb.model.PlayerData; import com.syncleus.ferma.WrappedFramedGraph; -import org.apache.commons.beanutils.PropertyUtils; import org.apache.log4j.Logger; import org.apache.tinkerpop.gremlin.structure.Graph; -import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.stream.Collectors; public class GraphDbAetherMudStorage implements AetherMudStorage { private static final Logger LOGGER = Logger.getLogger(GraphDbAetherMudStorage.class); private final WrappedFramedGraph<? extends Graph> framedGraph; + private final Interner<String> interner = Interners.newWeakInterner(); public GraphDbAetherMudStorage(WrappedFramedGraph<? extends Graph> framedGraph) { @@ -63,26 +66,65 @@ public class GraphDbAetherMudStorage implements AetherMudStorage { } @Override - public Optional<ItemData> getItemEntity(String itemId) { - return Optional.ofNullable(framedGraph.traverse((g) -> framedGraph.getTypeResolver().hasType(g.V(), ItemData.class).has("itemId", itemId)).nextOrDefault(ItemData.class, null)); + public Optional<ItemInstanceData> getItemEntity(String itemId) { + synchronized (interner.intern(itemId)) { + return Optional.ofNullable(framedGraph.traverse((g) -> framedGraph.getTypeResolver().hasType(g.V(), ItemInstanceData.class).has("itemId", itemId)).nextOrDefault(ItemInstanceData.class, null)); + } } @Override - public void removeItem(String itemId) { - this.getItemEntity(itemId).ifPresent((i) -> i.remove()); + public void removeItemEntity(String itemId) { + synchronized (interner.intern(itemId)) { + this.getItemEntity(itemId).ifPresent((i) -> i.remove()); + } + } + @Override + public ItemInstanceData saveItemEntity(ItemInstance itemInstance) { + synchronized (interner.intern(itemInstance.getItemId())) { + Optional<ItemInstanceData> existing = this.getItemEntity(itemInstance.getItemId()); + ItemInstanceData itemInstanceData; + if (existing.isPresent()) + itemInstanceData = existing.get(); + else + itemInstanceData = framedGraph.addFramedVertex(ItemInstanceData.class); + ItemInstanceData.copyItem(itemInstanceData, itemInstance, this.getItem(itemInstance.getItem().getInternalItemName()).get()); + return itemInstanceData; + } } @Override public ItemData saveItem(Item item) { - Optional<ItemData> existing = this.getItemEntity(item.getItemId()); - ItemData itemData; - if(existing.isPresent()) - itemData = existing.get(); - else - itemData = framedGraph.addFramedVertex(ItemData.class); - ItemData.copyItem(itemData, item); - return itemData; + synchronized (interner.intern(item.getInternalItemName())) { + Optional<ItemData> existing = this.getItem(item.getInternalItemName()); + ItemData itemData; + if (existing.isPresent()) + itemData = existing.get(); + else + itemData = framedGraph.addFramedVertex(ItemData.class); + ItemData.copyItem(itemData, item); + return itemData; + } + } + + @Override + public Optional<ItemData> getItem(String internalName) { + synchronized (interner.intern(internalName)) { + return Optional.ofNullable(framedGraph.traverse((g) -> framedGraph.getTypeResolver().hasType(g.V(), ItemData.class).has("internalItemName", internalName)).nextOrDefault(ItemData.class, null)); + } + } + + @Override + public List<? extends ItemData> getAllItems() { + return framedGraph.traverse((g) -> framedGraph.getTypeResolver().hasType(g.V(), ItemData.class)).toList(ItemData.class); + } + + @Override + public void removeItem(String internalName) { + synchronized (interner.intern(internalName)) { + // TODO : recursively remove all instances + this.getItem(internalName).ifPresent((i) -> i.remove()); + } } public List<? extends NpcSpawn> getAllNpcs(GameManager gameManager) { 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 2c5f7eea..c666982e 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 @@ -15,12 +15,13 @@ */ package com.syncleus.aethermud.storage.graphdb.model; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.syncleus.aethermud.common.ColorizedTextTemplate; import com.syncleus.aethermud.core.service.TimeTracker; import com.syncleus.aethermud.items.*; +import com.syncleus.aethermud.spawner.SpawnRule; import com.syncleus.aethermud.storage.graphdb.DataUtils; -import com.syncleus.ferma.TEdge; -import com.syncleus.ferma.VertexFrame; import com.syncleus.ferma.annotations.Adjacency; import com.syncleus.ferma.annotations.GraphElement; import com.syncleus.ferma.annotations.Property; @@ -48,29 +49,20 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame { @Property("maxUses") public abstract int getMaxUses(); - @Property("withPlayer") - public abstract boolean isWithPlayer(); - - @Property("withPlayer") - public abstract void setWithPlayer(boolean isWithPlayer); - - @Property("numberOfUses") - public abstract int getNumberOfUses(); - - @Property("numberOfUses") - public abstract void setNumberOfUses(int numberOfUses); - - @Property("itemId") - public abstract String getItemId(); - @Property("internalItemName") public abstract String getInternalItemName(); - @Property("itemName") - public abstract String getItemName(); + public String getItemName() { + return ColorizedTextTemplate.renderFromTemplateLanguage(this.getProperty("itemName")); + } + + public void setItemName(String itemName) { + this.setProperty("itemName", ColorizedTextTemplate.renderToTemplateLanguage(itemName)); + } - @Property("itemDescription") - public abstract String getItemDescription(); + public String getItemDescription() { + return ColorizedTextTemplate.renderFromTemplateLanguage(this.getProperty("itemDescription")); + } @Property("itemTriggers") public abstract List<String> getItemTriggers(); @@ -78,15 +70,13 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame { @Property("itemTriggers") public abstract void setItemTriggers(List<String> itemTriggers); - @Property("restingName") - public abstract String getRestingName(); + public String getRestingName() { + return ColorizedTextTemplate.renderFromTemplateLanguage(this.getProperty("restingName")); + } @Property("itemHalfLifeTicks") public abstract int getItemHalfLifeTicks(); - @Property("hasBeenWithPlayer") - public abstract void setHasBeenWithPlayer(boolean hasBeenWithPlayer); - @Property("rarity") public abstract Rarity getRarity(); @@ -96,20 +86,16 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame { @Property("valueInGold") public abstract int getValueInGold(); - @Property("itemName") - public abstract void setItemName(String itemName); - - @Property("itemDescription") - public abstract void setItemDescription(String itemDescription); + public void setItemDescription(String itemDescription) { + this.setProperty("itemDescription", ColorizedTextTemplate.renderToTemplateLanguage(itemDescription)); + } @Property("internalItemName") public abstract void setInternalItemName(String internalItemName); - @Property("restingName") - public abstract void setRestingName(String restingName); - - @Property("itemId") - public abstract void setItemId(String itemId); + public void setRestingName(String restingName) { + this.setProperty("restingName", ColorizedTextTemplate.renderToTemplateLanguage(restingName)); + } @Property("itemHalfLifeTicks") public abstract void setItemHalfLifeTicks(int itemHalfLifeTicks); @@ -123,8 +109,34 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame { @Property("disposable") public abstract void setDisposable(boolean disposable); - @Property("hasBeenWithPlayer") - public abstract boolean isHasBeenWithPlayer(); + @Property("forage") + public abstract Set<Forage> getForages(); + + @Property("forage") + public abstract void setForages(Set<Forage> forages); + + @Adjacency(label = "spawnRule", direction = Direction.OUT) + public abstract <N extends SpawnRuleData> Iterator<? extends N> getSpawnRulesDataIterator(Class<? extends N> type); + + public List<SpawnRuleData> getSpawnRuleDatas() { + return Collections.unmodifiableList(Lists.newArrayList(this.getSpawnRulesDataIterator(SpawnRuleData.class))); + } + + @Adjacency(label = "spawnRule", direction = Direction.OUT) + public abstract void addSpawnRuleData(SpawnRuleData spawnRule); + + @Adjacency(label = "spawnRule", direction = Direction.OUT) + public abstract void removeSpawnRuleData(SpawnRuleData spawnRule); + + public void setSpawnRulesDatas(List<SpawnRuleData> spawnRules) { + DataUtils.setAllElements(spawnRules, () -> this.getSpawnRulesDataIterator(SpawnRuleData.class), ruleData -> this.addSpawnRuleData(ruleData), () -> {} ); + } + + public SpawnRuleData createSpawnRuleData() { + final SpawnRuleData rule = this.getGraph().addFramedVertex(SpawnRuleData.class); + this.addSpawnRuleData(rule); + return rule; + } @Adjacency(label = "equipment", direction = Direction.OUT) public abstract <N extends EquipmentData> Iterator<? extends N> getEquipmentDataIterator(Class<? extends N> type); @@ -259,6 +271,12 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame { public static void copyItem(ItemData dest, Item src) { try { PropertyUtils.copyProperties(dest, src); + + for(SpawnRuleData data : dest.getSpawnRuleDatas()) + data.remove(); + for(SpawnRule spawnRule : src.getSpawnRules()) + SpawnRuleData.copySpawnRule(dest.createSpawnRuleData(), spawnRule); + if( src.getItemApplyStats() != null ) StatData.copyStats((dest.getItemApplyStatData() != null ? dest.getItemApplyStatData() : dest.createItemApplyStatData()), src.getItemApplyStats()); if(src.getLoot() != null ) @@ -277,10 +295,15 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame { } public static Item copyItem(ItemData src) { - Item retVal = new Item(); + Item retVal = new ItemImpl(); try { PropertyUtils.copyProperties(retVal, src); + Set<SpawnRule> rules = new HashSet<>(); + for(SpawnRuleData spawnRuleData : src.getSpawnRuleDatas()) + rules.add(SpawnRuleData.copySpawnRule(spawnRuleData)); + retVal.setSpawnRules(Collections.unmodifiableSet(rules)); + EquipmentData equipmentData = src.getEquipmentData(); if(equipmentData != null) retVal.setEquipment(EquipmentData.copyEquipment(equipmentData)); diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemInstanceData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemInstanceData.java new file mode 100644 index 00000000..9f78bae0 --- /dev/null +++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemInstanceData.java @@ -0,0 +1,243 @@ +/** + * Copyright 2017 Syncleus, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.syncleus.aethermud.storage.graphdb.model; + +import com.syncleus.aethermud.core.service.TimeTracker; +import com.syncleus.aethermud.items.ItemInstance; +import com.syncleus.aethermud.items.ItemInstanceImpl; +import com.syncleus.aethermud.items.Rarity; +import com.syncleus.aethermud.storage.graphdb.DataUtils; +import com.syncleus.ferma.annotations.Adjacency; +import com.syncleus.ferma.annotations.GraphElement; +import com.syncleus.ferma.annotations.Property; +import com.syncleus.ferma.ext.AbstractInterceptingVertexFrame; +import org.apache.tinkerpop.gremlin.structure.Direction; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +@GraphElement +public abstract class ItemInstanceData extends AbstractInterceptingVertexFrame { + @Property("withPlayer") + public abstract boolean isWithPlayer(); + + @Property("withPlayer") + public abstract void setWithPlayer(boolean isWithPlayer); + + @Property("numberOfUses") + public abstract int getNumberOfUses(); + + @Property("numberOfUses") + public abstract void setNumberOfUses(int numberOfUses); + + @Property("itemId") + public abstract String getItemId(); + + @Property("hasBeenWithPlayer") + public abstract void setHasBeenWithPlayer(boolean hasBeenWithPlayer); + + @Property("itemId") + public abstract void setItemId(String itemId); + + @Property("hasBeenWithPlayer") + public abstract boolean isHasBeenWithPlayer(); + + @Adjacency(label = "item", direction = Direction.OUT) + public abstract <N extends ItemData> Iterator<? extends N> getItemDatasIterator(Class<? extends N> type); + + public ItemData getItemData() { + Iterator<? extends ItemData> allItems = this.getItemDatasIterator(ItemData.class); + if (allItems.hasNext()) + return allItems.next(); + else + return null; + } + + @Adjacency(label = "item", direction = Direction.OUT) + public abstract ItemData addItemData(ItemData item); + + @Adjacency(label = "item", direction = Direction.OUT) + public abstract void removeItemData(ItemData item); + + public void setItemData(ItemData item) { + DataUtils.setAllElements(Collections.singletonList(item), () -> this.getItemDatasIterator(ItemData.class), itemData -> this.addItemData(itemData), () -> {}); + } + + public List<TimeTracker.TimeOfDay> getValidTimeOfDays() { + return getItemData().getValidTimeOfDays(); + } + + public void setValidTimeOfDays(List<TimeTracker.TimeOfDay> validTimeOfDays) { + getItemData().setValidTimeOfDays(validTimeOfDays); + } + + public void setValidTimeOfDays(Set<TimeTracker.TimeOfDay> validTimeOfDays) { + getItemData().setValidTimeOfDays(validTimeOfDays); + } + + public boolean isDisposable() { + return getItemData().isDisposable(); + } + + public int getMaxUses() { + return getItemData().getMaxUses(); + } + + public String getInternalItemName() { + return getItemData().getInternalItemName(); + } + + public String getItemName() { + return getItemData().getItemName(); + } + + public String getItemDescription() { + return getItemData().getItemDescription(); + } + + public List<String> getItemTriggers() { + return getItemData().getItemTriggers(); + } + + public void setItemTriggers(List<String> itemTriggers) { + getItemData().setItemTriggers(itemTriggers); + } + + public String getRestingName() { + return getItemData().getRestingName(); + } + + public int getItemHalfLifeTicks() { + return getItemData().getItemHalfLifeTicks(); + } + + public Rarity getRarity() { + return getItemData().getRarity(); + } + + public void setRarity(Rarity rarity) { + getItemData().setRarity(rarity); + } + + public int getValueInGold() { + return getItemData().getValueInGold(); + } + + public void setItemName(String itemName) { + getItemData().setItemName(itemName); + } + + public void setItemDescription(String itemDescription) { + getItemData().setItemDescription(itemDescription); + } + + public void setInternalItemName(String internalItemName) { + getItemData().setInternalItemName(internalItemName); + } + + public void setRestingName(String restingName) { + getItemData().setRestingName(restingName); + } + + public void setItemHalfLifeTicks(int itemHalfLifeTicks) { + getItemData().setItemHalfLifeTicks(itemHalfLifeTicks); + } + + public void setValueInGold(int valueInGold) { + getItemData().setValueInGold(valueInGold); + } + + public void setMaxUses(int maxUses) { + getItemData().setMaxUses(maxUses); + } + + public void setDisposable(boolean disposable) { + getItemData().setDisposable(disposable); + } + + public EquipmentData getEquipmentData() { + return getItemData().getEquipmentData(); + } + + public void setEquipmentData(EquipmentData equipment) { + getItemData().setEquipmentData(equipment); + } + + public EquipmentData createEquipmentData() { + return getItemData().createEquipmentData(); + } + + public Set<EffectData> getEffectDatas() { + return getItemData().getEffectDatas(); + } + + public void setEffectDatas(Set<EffectData> effects) { + getItemData().setEffectDatas(effects); + } + + public EffectData createEffectData() { + return getItemData().createEffectData(); + } + + public StatData getItemApplyStatData() { + return getItemData().getItemApplyStatData(); + } + + public void setItemApplyStatData(StatData stats) { + getItemData().setItemApplyStatData(stats); + } + + public StatData createItemApplyStatData() { + return getItemData().createItemApplyStatData(); + } + + public LootData getLootData() { + return getItemData().getLootData(); + } + + public void setLootData(LootData loot) { + getItemData().setLootData(loot); + } + + public LootData createLootData() { + return getItemData().createLootData(); + } + + public static void copyItem(ItemInstanceData dest, ItemInstance src, ItemData itemData) { + dest.setWithPlayer(src.isWithPlayer()); + dest.setNumberOfUses(src.getNumberOfUses()); + dest.setHasBeenWithPlayer(src.isHasBeenWithPlayer()); + dest.setItemId(src.getItemId()); + if(dest.getItemData() == null ) + dest.setItemData(itemData); + else if(!dest.getItemData().getInternalItemName().equals(itemData.getInternalItemName())) { + dest.removeItemData(dest.getItemData()); + dest.setItemData(itemData); + } + } + + public static ItemInstance copyItem(ItemInstanceData src) { + ItemInstance itemInstance = new ItemInstanceImpl(); + itemInstance.setWithPlayer(src.isWithPlayer()); + itemInstance.setNumberOfUses(src.getNumberOfUses()); + itemInstance.setHasBeenWithPlayer(src.isHasBeenWithPlayer()); + itemInstance.setItemId(src.getItemId()); + itemInstance.setItem(ItemData.copyItem(src.getItemData())); + return itemInstance; + } +} diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java index 71f12f73..759ea869 100644 --- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java +++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java @@ -14,8 +14,8 @@ * limitations under the License. */ package com.syncleus.aethermud.storage.graphdb.model; +import com.google.common.collect.Lists; -import com.syncleus.aethermud.items.Item; import com.syncleus.aethermud.items.Loot; import com.syncleus.ferma.annotations.GraphElement; import com.syncleus.ferma.annotations.Property; @@ -55,6 +55,7 @@ public abstract class LootData extends AbstractInterceptingVertexFrame { public static Loot copyLoot(LootData src) { Loot retVal = new Loot(); + try { PropertyUtils.copyProperties(retVal, src); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { diff --git a/src/main/java/com/syncleus/aethermud/world/model/Room.java b/src/main/java/com/syncleus/aethermud/world/model/Room.java index 54e6f8c1..f1cef466 100644 --- a/src/main/java/com/syncleus/aethermud/world/model/Room.java +++ b/src/main/java/com/syncleus/aethermud/world/model/Room.java @@ -19,7 +19,7 @@ import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.core.service.TimeTracker; import com.syncleus.aethermud.entity.AetherMudEntity; import com.syncleus.aethermud.items.Forage; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.merchant.Merchant; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.player.Player; @@ -290,12 +290,12 @@ public abstract class Room extends AetherMudEntity { @Override public void run() { for (String itemId : itemIds) { - Optional<Item> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); + Optional<ItemInstance> itemOptional = gameManager.getEntityManager().getItemEntity(itemId); if (!itemOptional.isPresent()) { removePresentItem(itemId); continue; } - Item itemEntity = itemOptional.get(); + ItemInstance itemEntity = itemOptional.get(); if (itemEntity.isHasBeenWithPlayer()) { continue; } diff --git a/src/test/java/com/syncleus/aethermud/player/combatsimuation/CombatSimulationDetails.java b/src/test/java/com/syncleus/aethermud/player/combatsimuation/CombatSimulationDetails.java index 194fdeee..8349c94a 100644 --- a/src/test/java/com/syncleus/aethermud/player/combatsimuation/CombatSimulationDetails.java +++ b/src/test/java/com/syncleus/aethermud/player/combatsimuation/CombatSimulationDetails.java @@ -15,7 +15,7 @@ */ package com.syncleus.aethermud.player.combatsimuation; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.npc.NpcSpawn; import java.util.Set; @@ -24,10 +24,10 @@ public class CombatSimulationDetails { private final int level; private final int totalIterations; - private final Set<Item> equipmentSet; + private final Set<ItemInstance> equipmentSet; private final NpcSpawn npcSpawn; - public CombatSimulationDetails(int level, Set<Item> equipmentSet, NpcSpawn npcSpawn) { + public CombatSimulationDetails(int level, Set<ItemInstance> equipmentSet, NpcSpawn npcSpawn) { this.level = level; this.totalIterations = 1000; this.equipmentSet = equipmentSet; @@ -46,7 +46,7 @@ public class CombatSimulationDetails { return npcSpawn; } - public Set<Item> getEquipmentSet() { + public Set<ItemInstance> getEquipmentSet() { return equipmentSet; } } 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 df6d0d85..af786999 100644 --- a/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java +++ b/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java @@ -21,7 +21,7 @@ import com.syncleus.aethermud.configuration.AetherMudConfiguration; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.core.SessionManager; import com.syncleus.aethermud.entity.EntityManager; -import com.syncleus.aethermud.items.Item; +import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.npc.NpcBuilder; import com.syncleus.aethermud.player.*; @@ -137,18 +137,18 @@ public class NpcTestHarness { } } - private Set<Item> getEarlyLevelArmorSet() { + private Set<ItemInstance> getEarlyLevelArmorSet() { // return Sets.newHashSet(ItemType.BERSERKER_BATON.create(), ItemType.BERSEKER_BOOTS.create(), ItemType.BERSEKER_SHORTS.create()); return Sets.newConcurrentHashSet(); } - private Set<Item> getMidLevelArmorSet() { - Set<Item> armorSet = getEarlyLevelArmorSet(); + private Set<ItemInstance> getMidLevelArmorSet() { + Set<ItemInstance> armorSet = getEarlyLevelArmorSet(); // armorSet.addAll(Sets.newHashSet(ItemType.BERSERKER_BRACERS.create(), ItemType.BERSERKER_CHEST.create())); return armorSet; } - private void processRunAndVerify(NpcSpawn testNpcSpawn, int desiredLevel, Set<Item> equipment, float winPctMax, float winPctMin, int maxRounds, int minRounds, int maxAvgGold, int minAvgGold) throws Exception { + private void processRunAndVerify(NpcSpawn testNpcSpawn, int desiredLevel, Set<ItemInstance> equipment, float winPctMax, float winPctMin, int maxRounds, int minRounds, int maxAvgGold, int minAvgGold) throws Exception { CombatSimulationDetails combatSimulationDetailsLevel = new CombatSimulationDetails(desiredLevel, equipment, testNpcSpawn); CombatSimulationResult combatSimulationResultLevel = executeCombat(combatSimulationDetailsLevel); printCombatResults(combatSimulationDetailsLevel, combatSimulationResultLevel); @@ -182,7 +182,7 @@ public class NpcTestHarness { playerWins++; int gold = (int) gameManager.getLootManager().lootGoldAmountReturn(npcSpawn.getLoot()); totalGold += gold; - Set<Item> items = gameManager.getLootManager().lootItemsReturn(npcSpawn.getLoot()); + Set<ItemInstance> items = gameManager.getLootManager().lootItemsReturn(npcSpawn.getLoot()); items.forEach(item -> { if (!drops.containsKey(item.getItemName())) { drops.put(item.getItemName(), new AtomicInteger(1)); @@ -254,7 +254,7 @@ public class NpcTestHarness { return player; } - private void equipArmor(Player player, Set<Item> equipment) { + private void equipArmor(Player player, Set<ItemInstance> equipment) { equipment.forEach(item -> { entityManager.saveItem(item); gameManager.acquireItem(player, item.getItemId()); -- GitLab