count = 1;
}
-void ItemStack::serialize(std::ostream &os) const
+void ItemStack::serialize(std::ostream &os, bool serialize_meta) const
{
if (empty())
return;
// Check how many parts of the itemstring are needed
int parts = 1;
- if(count != 1)
- parts = 2;
- if(wear != 0)
- parts = 3;
if (!metadata.empty())
parts = 4;
+ else if (wear != 0)
+ parts = 3;
+ else if (count != 1)
+ parts = 2;
- os<<serializeJsonStringIfNeeded(name);
- if(parts >= 2)
- os<<" "<<count;
- if(parts >= 3)
- os<<" "<<wear;
+ os << serializeJsonStringIfNeeded(name);
+ if (parts >= 2)
+ os << " " << count;
+ if (parts >= 3)
+ os << " " << wear;
if (parts >= 4) {
os << " ";
- metadata.serialize(os);
+ if (serialize_meta)
+ metadata.serialize(os);
+ else
+ os << "<metadata size=" << metadata.size() << ">";
}
}
deSerialize(is, itemdef);
}
-std::string ItemStack::getItemString() const
+std::string ItemStack::getItemString(bool include_meta) const
{
std::ostringstream os(std::ios::binary);
- serialize(os);
+ serialize(os, include_meta);
return os.str();
}
return desc.empty() ? name : desc;
}
+std::string ItemStack::getShortDescription(IItemDefManager *itemdef) const
+{
+ std::string desc = metadata.getString("short_description");
+ if (desc.empty())
+ desc = getDefinition(itemdef).short_description;
+ if (!desc.empty())
+ return desc;
+ // no short_description because of old server version or modified builtin
+ // return first line of description
+ std::stringstream sstr(getDescription(itemdef));
+ std::getline(sstr, desc, '\n');
+ return desc;
+}
+
ItemStack ItemStack::addItem(ItemStack newitem, IItemDefManager *itemdef)
{
for (auto i = m_items.rbegin(); i != m_items.rend(); ++i) {
if (i->name == item.name) {
u32 still_to_remove = item.count - removed.count;
- removed.addItem(i->takeItem(still_to_remove), m_itemdef);
+ ItemStack leftover = removed.addItem(i->takeItem(still_to_remove),
+ m_itemdef);
+ // Allow oversized stacks
+ removed.count += leftover.count;
+
if (removed.count == item.count)
break;
}
}
+ if (!removed.empty())
+ setModified();
return removed;
}
if (item1.empty())
return;
- // Try to add the item to destination list
- u32 dest_size = dest->getSize();
- // First try all the non-empty slots
- for (u32 dest_i = 0; dest_i < dest_size; dest_i++) {
- if (!m_items[dest_i].empty()) {
- item1 = dest->addItem(dest_i, item1);
- if (item1.empty()) return;
- }
- }
+ ItemStack leftover;
+ leftover = dest->addItem(item1);
- // Then try all the empty ones
- for (u32 dest_i = 0; dest_i < dest_size; dest_i++) {
- if (m_items[dest_i].empty()) {
- item1 = dest->addItem(dest_i, item1);
- if (item1.empty()) return;
- }
+ if (!leftover.empty()) {
+ // Add the remaining part back to the source item
+ addItem(i, leftover);
}
-
- // If we reach this, the item was not fully added
- // Add the remaining part back to the source item
- addItem(i, item1);
}
u32 InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i,
u32 count, bool swap_if_needed, bool *did_swap)
{
- if(this == dest && i == dest_i)
+ if (this == dest && i == dest_i)
return count;
// Take item from source list
ItemStack item1;
- if(count == 0)
+ if (count == 0)
item1 = changeItem(i, ItemStack());
else
item1 = takeItem(i, count);
- if(item1.empty())
+ if (item1.empty())
return 0;
// Try to add the item to destination list
item1 = dest->addItem(dest_i, item1);
// If something is returned, the item was not fully added
- if(!item1.empty())
- {
+ if (!item1.empty()) {
// If olditem is returned, nothing was added.
bool nothing_added = (item1.count == oldcount);
void Inventory::clear()
{
- m_dirty = true;
for (auto &m_list : m_lists) {
delete m_list;
}
m_lists.clear();
+ setModified();
}
Inventory::Inventory(IItemDefManager *itemdef)
{
- m_dirty = false;
m_itemdef = itemdef;
+ setModified();
}
Inventory::Inventory(const Inventory &other)
// Gracefully handle self assignment
if(this != &other)
{
- m_dirty = true;
clear();
m_itemdef = other.m_itemdef;
for (InventoryList *list : other.m_lists) {
m_lists.push_back(new InventoryList(*list));
}
+ setModified();
}
return *this;
}
void Inventory::serialize(std::ostream &os, bool incremental) const
{
+ //std::cout << "Serialize " << (int)incremental << ", n=" << m_lists.size() << std::endl;
for (const InventoryList *list : m_lists) {
if (!incremental || list->checkModified()) {
os << "List " << list->getName() << " " << list->getSize() << "\n";
delete list;
list = nullptr;
- m_dirty = true;
+ setModified();
}
m_lists.erase(std::remove(m_lists.begin(), m_lists.end(),
nullptr), m_lists.end());
InventoryList * Inventory::addList(const std::string &name, u32 size)
{
- m_dirty = true;
+ setModified();
s32 i = getListIndex(name);
if(i != -1)
{
{
delete m_lists[i];
m_lists[i] = new InventoryList(name, size, m_itemdef);
+ m_lists[i]->setModified();
}
return m_lists[i];
}
//don't create list with invalid name
- if (name.find(' ') != std::string::npos) return NULL;
+ if (name.find(' ') != std::string::npos)
+ return nullptr;
InventoryList *list = new InventoryList(name, size, m_itemdef);
+ list->setModified();
m_lists.push_back(list);
return list;
}
s32 i = getListIndex(name);
if(i == -1)
return false;
- m_dirty = true;
+
+ setModified();
delete m_lists[i];
m_lists.erase(m_lists.begin() + i);
return true;