X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Finventory.cpp;h=f91e2e0b6cd6e433e784d7b1b5ad0a18d757e135;hb=59de7a324cec6ffcb5015b616853d60e74a0c62d;hp=3899c9394186cdf3e5cac86ed81d115c64618c88;hpb=3f5bad938a3fcb601ad41924a4707476b8b87241;p=dragonfireclient.git diff --git a/src/inventory.cpp b/src/inventory.cpp index 3899c9394..f91e2e0b6 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -27,13 +27,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" #include #include "main.h" +#include "serverobject.h" /* InventoryItem */ -InventoryItem::InventoryItem() +InventoryItem::InventoryItem(u16 count) { + m_count = count; } InventoryItem::~InventoryItem() @@ -66,6 +68,22 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is) std::getline(is, inventorystring, '|'); return new MapBlockObjectItem(inventorystring); } + else if(name == "CraftItem") + { + std::string subname; + std::getline(is, subname, ' '); + u16 count; + is>>count; + return new CraftItem(subname, count); + } + else if(name == "ToolItem") + { + std::string toolname; + std::getline(is, toolname, ' '); + u16 wear; + is>>wear; + return new ToolItem(toolname, wear); + } else { dstream<<"Unknown InventoryItem name=\""<getTextureRaw(name); +} +#endif + +ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos) +{ + // Special cases + if(m_subname == "rat") + { + ServerActiveObject *obj = new RatSAO(env, id, pos); + return obj; + } + // Default + else + { + return InventoryItem::createSAO(env, id, pos); + } +} + +u16 CraftItem::getDropCount() +{ + // Special cases + if(m_subname == "rat") + return 1; + // Default + else + return InventoryItem::getDropCount(); +} + +bool CraftItem::isCookable() +{ + if(m_subname == "lump_of_iron") + { + return true; + } + return false; +} + +InventoryItem *CraftItem::createCookResult() +{ + if(m_subname == "lump_of_iron") + { + return new CraftItem("steel_ingot", 1); + } + return NULL; +} + /* MapBlockObjectItem + TODO: Remove */ #ifndef SERVER video::ITexture * MapBlockObjectItem::getImage() { if(m_inventorystring.substr(0,3) == "Rat") - //return g_device->getVideoDriver()->getTexture("../data/rat.png"); - return g_irrlicht->getTexture("../data/rat.png"); + return g_texturesource->getTextureRaw("rat.png"); if(m_inventorystring.substr(0,4) == "Sign") - //return g_device->getVideoDriver()->getTexture("../data/sign.png"); - return g_irrlicht->getTexture("../data/sign.png"); + return g_texturesource->getTextureRaw("sign.png"); return NULL; } @@ -126,6 +259,19 @@ MapBlockObject * MapBlockObjectItem::createObject RatObject *obj = new RatObject(NULL, -1, pos); return obj; } + else if(name == "ItemObj") + { + /* + Now we are an inventory item containing the serialization + string of an object that contains the serialization + string of an inventory item. Fuck this. + */ + //assert(0); + dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj " + <<"because an item-object should never be inside " + <<"an object-item."<clone(); } } + //setDirty(true); return *this; } -u32 Inventory::getSize() +std::string InventoryList::getName() +{ + return m_name; +} + +u32 InventoryList::getSize() { return m_items.size(); } -u32 Inventory::getUsedSlots() +u32 InventoryList::getUsedSlots() { u32 num = 0; for(u32 i=0; i m_items.size() - 1) return NULL; return m_items[i]; } -InventoryItem * Inventory::changeItem(u32 i, InventoryItem *newitem) +InventoryItem * InventoryList::changeItem(u32 i, InventoryItem *newitem) { assert(i < m_items.size()); InventoryItem *olditem = m_items[i]; m_items[i] = newitem; + //setDirty(true); return olditem; } -void Inventory::deleteItem(u32 i) +void InventoryList::deleteItem(u32 i) { assert(i < m_items.size()); InventoryItem *item = changeItem(i, NULL); @@ -280,53 +465,143 @@ void Inventory::deleteItem(u32 i) delete item; } -bool Inventory::addItem(InventoryItem *newitem) +InventoryItem * InventoryList::addItem(InventoryItem *newitem) { - // If it is a MaterialItem, try to find an already existing one - // and just increment the counter - if(std::string("MaterialItem") == newitem->getName()) + if(newitem == NULL) + return NULL; + + /* + First try to find if it could be added to some existing items + */ + for(u32 i=0; igetMaterial(); - u8 count = ((MaterialItem*)newitem)->getCount(); - for(u32 i=0; igetName()) - continue; - // Found one. Check if it is of the right material and has - // free space - MaterialItem *mitem2 = (MaterialItem*)item2; - if(mitem2->getMaterial() != material) - continue; - //TODO: Add all that can be added and add remaining part - // to another place - if(mitem2->freeSpace() < count) - continue; - // Add to the counter - mitem2->add(count); - // Dump the parameter - delete newitem; - return true; - } + // Ignore empty slots + if(m_items[i] == NULL) + continue; + // Try adding + newitem = addItem(i, newitem); + if(newitem == NULL) + return NULL; // All was eaten } - // Else find an empty position + + /* + Then try to add it to empty slots + */ for(u32 i=0; iaddableTo(to_item) == false) + return newitem; + + // If the item fits fully in the slot, add counter and delete it + if(newitem->getCount() <= to_item->freeSpace()) + { + to_item->add(newitem->getCount()); + delete newitem; + return NULL; + } + // Else the item does not fit fully. Add all that fits and return + // the rest. + else + { + u16 freespace = to_item->freeSpace(); + to_item->add(freespace); + newitem->remove(freespace); + return newitem; + } +} + +bool InventoryList::itemFits(u32 i, InventoryItem *newitem) +{ + // If it is an empty position, it's an easy job. + InventoryItem *to_item = m_items[i]; + if(to_item == NULL) + { + return true; + } + + // If not addable, return the item + if(newitem->addableTo(to_item) == false) + return false; + + // If the item fits fully in the slot, add counter and delete it + if(newitem->getCount() <= to_item->freeSpace()) + { return true; } - // Failed + return false; } -void Inventory::print(std::ostream &o) +InventoryItem * InventoryList::takeItem(u32 i, u32 count) +{ + if(count == 0) + return NULL; + + //setDirty(true); + + InventoryItem *item = m_items[i]; + // If it is an empty position, return NULL + if(item == NULL) + return NULL; + + if(count >= item->getCount()) + { + // Get the item by swapping NULL to its place + return changeItem(i, NULL); + } + else + { + InventoryItem *item2 = item->clone(); + item->remove(count); + item2->setCount(count); + return item2; + } + + return false; +} + +void InventoryList::decrementMaterials(u16 count) { - o<<"Player inventory:"<getName()<<" "<getSize()<<"\n"; + list->serialize(os); + } + + os<<"EndInventory\n"; +} + +void Inventory::deSerialize(std::istream &is) +{ + clear(); + + for(;;) + { + std::string line; + std::getline(is, line, '\n'); + + std::istringstream iss(line); + + std::string name; + std::getline(iss, name, ' '); + + if(name == "EndInventory") + { + break; + } + // This is a temporary backwards compatibility fix + else if(name == "end") + { + break; + } + else if(name == "List") + { + std::string listname; + u32 listsize; + + std::getline(iss, listname, ' '); + iss>>listsize; + + InventoryList *list = new InventoryList(listname, listsize); + list->deSerialize(is); + + m_lists.push_back(list); + } + else + { + throw SerializationError("Unknown inventory identifier"); + } + } +} + +InventoryList * Inventory::addList(const std::string &name, u32 size) +{ + s32 i = getListIndex(name); + if(i != -1) + { + if(m_lists[i]->getSize() != size) + { + delete m_lists[i]; + m_lists[i] = new InventoryList(name, size); + } + return m_lists[i]; + } + else + { + m_lists.push_back(new InventoryList(name, size)); + return m_lists.getLast(); + } +} + +InventoryList * Inventory::getList(const std::string &name) +{ + s32 i = getListIndex(name); + if(i == -1) + return NULL; + return m_lists[i]; +} + +s32 Inventory::getListIndex(const std::string &name) +{ + for(u32 i=0; igetName() == name) + return i; + } + return -1; +} + +/* + InventoryAction +*/ + +InventoryAction * InventoryAction::deSerialize(std::istream &is) +{ + std::string type; + std::getline(is, type, ' '); + + InventoryAction *a = NULL; + + if(type == "Move") + { + a = new IMoveAction(is); + } + + return a; +} + +void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr) +{ +#if 1 + + /*dstream<<"from_inv="<getList(from_list); + InventoryList *list_to = inv_to->getList(to_list); + + /*dstream<<"list_from="<getItem(from_i)="<getItem(from_i) + <getItem(to_i)="<getItem(to_i) + <getItem(from_i) == NULL) + { + dstream<<__FUNCTION_NAME<<": Operation not allowed " + <<"(the source item doesn't exist)" + <changeItem(from_i, NULL); + else + item1 = list_from->takeItem(from_i, count); + + // Try to add the item to destination list + InventoryItem *olditem = item1; + item1 = list_to->addItem(to_i, item1); + + // If something is returned, the item was not fully added + if(item1 != NULL) + { + // If olditem is returned, nothing was added. + bool nothing_added = (item1 == olditem); + + // If something else is returned, part of the item was left unadded. + // Add the other part back to the source item + list_from->addItem(from_i, item1); + + // If olditem is returned, nothing was added. + // Swap the items + if(nothing_added) + { + // Take item from source list + item1 = list_from->changeItem(from_i, NULL); + // Adding was not possible, swap the items. + InventoryItem *item2 = list_to->changeItem(to_i, item1); + // Put item from destination list to the source list + list_from->changeItem(from_i, item2); + } + } + + mgr->inventoryModified(c, from_inv); + if(from_inv != to_inv) + mgr->inventoryModified(c, to_inv); +#endif +} + +/* + Craft checking system +*/ + +bool ItemSpec::checkItem(InventoryItem *item) +{ + if(type == ITEM_NONE) + { + // Has to be no item + if(item != NULL) + return false; + return true; + } + + // There should be an item + if(item == NULL) + return false; + + std::string itemname = item->getName(); + + if(type == ITEM_MATERIAL) + { + if(itemname != "MaterialItem") + return false; + MaterialItem *mitem = (MaterialItem*)item; + if(mitem->getMaterial() != num) + return false; + } + else if(type == ITEM_CRAFT) + { + if(itemname != "CraftItem") + return false; + CraftItem *mitem = (CraftItem*)item; + if(mitem->getSubName() != name) + return false; + } + else if(type == ITEM_TOOL) + { + // Not supported yet + assert(0); + } + else if(type == ITEM_MBO) + { + // Not supported yet + assert(0); + } + else + { + // Not supported yet + assert(0); + } + return true; +} + +bool checkItemCombination(InventoryItem **items, ItemSpec *specs) +{ + u16 items_min_x = 100; + u16 items_max_x = 100; + u16 items_min_y = 100; + u16 items_max_y = 100; + for(u16 y=0; y<3; y++) + for(u16 x=0; x<3; x++) + { + if(items[y*3 + x] == NULL) + continue; + if(items_min_x == 100 || x < items_min_x) + items_min_x = x; + if(items_min_y == 100 || y < items_min_y) + items_min_y = y; + if(items_max_x == 100 || x > items_max_x) + items_max_x = x; + if(items_max_y == 100 || y > items_max_y) + items_max_y = y; + } + // No items at all, just return false + if(items_min_x == 100) + return false; + + u16 items_w = items_max_x - items_min_x + 1; + u16 items_h = items_max_y - items_min_y + 1; + + u16 specs_min_x = 100; + u16 specs_max_x = 100; + u16 specs_min_y = 100; + u16 specs_max_y = 100; + for(u16 y=0; y<3; y++) + for(u16 x=0; x<3; x++) + { + if(specs[y*3 + x].type == ITEM_NONE) + continue; + if(specs_min_x == 100 || x < specs_min_x) + specs_min_x = x; + if(specs_min_y == 100 || y < specs_min_y) + specs_min_y = y; + if(specs_max_x == 100 || x > specs_max_x) + specs_max_x = x; + if(specs_max_y == 100 || y > specs_max_y) + specs_max_y = y; + } + // No specs at all, just return false + if(specs_min_x == 100) + return false; + + u16 specs_w = specs_max_x - specs_min_x + 1; + u16 specs_h = specs_max_y - specs_min_y + 1; + + // Different sizes + if(items_w != specs_w || items_h != specs_h) + return false; + + for(u16 y=0; y