I'm creating a MUD and am running into some design issues regarding Items.
Items are stored in an ItemDatabase
after being read from a JSON file.
template <typename ItemType>
static void load(std::string const& filename)
{
PropertyTree propertyTree;
boost::property_tree::read_json(filename, propertyTree);
for (auto& jsonItem : propertyTree)
{
Item *item = new ItemType();
item->fromJson(jsonItem);
database_[item->id()] = item;
}
}
At first, every Database::find() returned a shallow copy of the item, however, this quickly becomes dangerous and erroneous when items have a finite usage, e.g. a life potion that is consumed after one charge.
Therefore, I want to start returning deep copies as std::unique_ptr
s because each Item is unique and is possessed by only one entity. This avoids dangerous dangling pointers, if the Item is not maintained or destroyed by the caller:
template <typename DataType>
std::unique_ptr<DataType> EntityDatabase<DataType>::find(EntityId const& entityId)
{
auto found = std::find_if(std::begin(database_), std::end(database_),
[&entityId](Container::value_type const& candidate)
{
return (candidate.second->id() == entityId);
});
if (found != std::end(database_))
return std::unique_ptr<DataType>(new DataType(*found->second));
else
return nullptr;
}
However, the resulting code is worse than hideous. Consider turning an Item
into a Weapon
:
void Inventory::fromJson(PropertyTree::value_type const& properties)
{
auto jsonInventory = *properties.second.find("Inventory");
auto weaponId = getValue<EntityId>(jsonInventory, "Weapon");
weapon_.reset(static_cast<Weapon*>(ItemDatabase::find(weaponId).release()));
auto armorId = getValue<EntityId>(jsonInventory, "Armor");
armor_.reset(static_cast<Armor*>(ItemDatabase::find(armorId).release()));
money_ = getValue<Money>(jsonInventory, "Money");
for (auto& item : jsonInventory.second.get_child("Items"))
{
auto itemId = boost::lexical_cast<EntityId, std::string>(item.second.data());
inventory_.push_back(std::move(ItemDatabase::find(itemId)));
}
}
How can I improve the code or the design?