Administrador gutinha 1.286 Postado 5 de Dezembro 2023 Administrador Compartilhar Postado 5 de Dezembro 2023 Salve rapaziada, esse tutorial é pra você que odeia ter que ficar abrindo suas bags toda vez ao relogar no client. Bora lá, na source do server 1° Passo Spoiler No arquivo enums.h, procure por enum itemAttrTypes : uint32_t Dentro dele, no penúltimo item adicione ITEM_ATTRIBUTE_AUTOOPEN = 1 << 25, Vai ficar mais ou menos assim ITEM_ATTRIBUTE_DOORID = 1 << 22, ITEM_ATTRIBUTE_DECAYTO = 1 << 23, ITEM_ATTRIBUTE_WRAPID = 1 << 24, ITEM_ATTRIBUTE_AUTOOPEN = 1 << 25, ITEM_ATTRIBUTE_CUSTOM = 1U << 31 }; 2° Passo Spoiler No arquivo iologindata.cpp, procure pelo método bool IOLoginData::saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream) e altere ele para bool IOLoginData::saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream, std::map<Container*, int>& openContainers) Dentro do método procure por Item* item = it.second; ++runningId; E adicione em baixo if (Container* container = item->getContainer()) { auto it = openContainers.find(container); if (it == openContainers.end()) { container->resetAutoOpen(); } else { container->setAutoOpen(it->second); } queue.emplace_back(container, runningId); } Ficando mais ou menos assim for (const auto& it : itemList) { int32_t pid = it.first; Item* item = it.second; ++runningId; if (Container* container = item->getContainer()) { auto it = openContainers.find(container); if (it == openContainers.end()) { container->resetAutoOpen(); } else { container->setAutoOpen(it->second); } queue.emplace_back(container, runningId); } propWriteStream.clear(); item->serializeAttr(propWriteStream); Agora procure por if (!query_insert.addRow(ss)) { return false; } E em baixo dele remova o seguinte código if (Container* container = item->getContainer()) { queue.emplace_back(container, runningId); } Procure por for (Item* item : container->getItemList()) { ++runningId; Container* subContainer = item->getContainer(); if (subContainer) { E adicione dentro do if esse código auto it = openContainers.find(subContainer); if (it == openContainers.end()) { subContainer->resetAutoOpen(); } else { subContainer->setAutoOpen(it->second); } Ficando mais ou menos assim for (Item* item : container->getItemList()) { ++runningId; Container* subContainer = item->getContainer(); if (subContainer) { auto it = openContainers.find(subContainer); if (it == openContainers.end()) { subContainer->resetAutoOpen(); } else { subContainer->setAutoOpen(it->second); } queue.emplace_back(subContainer, runningId); } Procure por //item saving E adicione em baixo std::map<Container*, int> openContainers; for (auto container : player->getOpenContainers()) { if (!container.second.container) continue; openContainers[container.second.container] = container.first; } Ficando mais ou menos assim //item saving std::map<Container*, int> openContainers; for (auto container : player->getOpenContainers()) { if (!container.second.container) continue; openContainers[container.second.container] = container.first; } query << "DELETE FROM `player_items` WHERE `player_id` = " << player->getGUID(); if (!db.executeQuery(query.str())) { return false; Procure por todos if (!saveItems(player, itemList, itemsQuery, propWriteStream)) { E substitua todos por if (!saveItems(player, itemList, itemsQuery, propWriteStream, openContainers)) { Agora no arquivo iologindata.h, procure por static bool saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream); E substitua por static bool saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream, std::map<Container*, int>& openContainers); 3° Passo Spoiler Agora no arquivo item.cpp, procure por Item::readAttr(AttrTypes_t attr, PropStream& propStream) Dentro do método procure por case ATTR_WRAPID: Em baixo do bloco de código, adicione case ATTR_AUTOOPEN: { int8_t autoOpen; if (!propStream.read<int8_t>(autoOpen)) { return ATTR_READ_ERROR; } setIntAttr(ITEM_ATTRIBUTE_AUTOOPEN, autoOpen); break; } Ficando mais ou menos assim case ATTR_WRAPID: { uint16_t wrapId; if (!propStream.read<uint16_t>(wrapId)) { return ATTR_READ_ERROR; } setIntAttr(ITEM_ATTRIBUTE_WRAPID, wrapId); break; } case ATTR_AUTOOPEN: { int8_t autoOpen; if (!propStream.read<int8_t>(autoOpen)) { return ATTR_READ_ERROR; } setIntAttr(ITEM_ATTRIBUTE_AUTOOPEN, autoOpen); break; } Procure pelo método void Item::serializeAttr(PropWriteStream& propWriteStream) const e dentro do método procure por if (hasAttribute(ITEM_ATTRIBUTE_WRAPID)) { propWriteStream.write<uint8_t>(ATTR_WRAPID); propWriteStream.write<uint16_t>(getIntAttr(ITEM_ATTRIBUTE_WRAPID)); } Em baixo dele adicione if (hasAttribute(ITEM_ATTRIBUTE_AUTOOPEN)) { propWriteStream.write<uint8_t>(ATTR_AUTOOPEN); propWriteStream.write<int8_t>(getIntAttr(ITEM_ATTRIBUTE_AUTOOPEN)); } Agora em item.h procure por enum AttrTypes_t { e no final do enum adicione ATTR_AUTOOPEN = 37 Ficando mais ou menos assim ATTR_DECAYTO = 35, ATTR_WRAPID = 36, ATTR_AUTOOPEN = 37 Procure por const static uint32_t intAttributeTypes E adicione no final | ITEM_ATTRIBUTE_AUTOOPEN; Ficando mais ou menos assim const static uint32_t intAttributeTypes = ITEM_ATTRIBUTE_ACTIONID | ITEM_ATTRIBUTE_UNIQUEID | ITEM_ATTRIBUTE_DATE | ITEM_ATTRIBUTE_WEIGHT | ITEM_ATTRIBUTE_ATTACK | ITEM_ATTRIBUTE_DEFENSE | ITEM_ATTRIBUTE_EXTRADEFENSE | ITEM_ATTRIBUTE_ARMOR | ITEM_ATTRIBUTE_HITCHANCE | ITEM_ATTRIBUTE_SHOOTRANGE | ITEM_ATTRIBUTE_OWNER | ITEM_ATTRIBUTE_DURATION | ITEM_ATTRIBUTE_DECAYSTATE | ITEM_ATTRIBUTE_CORPSEOWNER | ITEM_ATTRIBUTE_CHARGES | ITEM_ATTRIBUTE_FLUIDTYPE | ITEM_ATTRIBUTE_DOORID | ITEM_ATTRIBUTE_DECAYTO | ITEM_ATTRIBUTE_WRAPID | ITEM_ATTRIBUTE_AUTOOPEN; Procure por bool isRemoved() const override { return !parent || parent->isRemoved(); } E adicione em baixo int8_t getAutoOpen() { if (hasAttribute(ITEM_ATTRIBUTE_AUTOOPEN)) { return getIntAttr(ITEM_ATTRIBUTE_AUTOOPEN); } return -1; } void setAutoOpen(int8_t value) { setIntAttr(ITEM_ATTRIBUTE_AUTOOPEN, value); } void resetAutoOpen() { removeAttribute(ITEM_ATTRIBUTE_AUTOOPEN); } 4° Passo Spoiler Agora em player.cpp, no final do arquivo. Adicione void Player::autoOpenContainers() { for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { Item* item = inventory[i]; if (!item) { continue; } if (Container* container = item->getContainer()) { if (container->getAutoOpen() >= 0) { addContainer(container->getAutoOpen(), container); onSendContainer(container); } for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { if (Container* subContainer = (*it)->getContainer()) { if (subContainer->getAutoOpen() >= 0) { addContainer(subContainer->getAutoOpen(), subContainer); onSendContainer(subContainer); } } } } } } Em player.h, procure por void onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, const ItemType& oldType, const Item* newItem, const ItemType& newType) override; Em cima adicione void autoOpenContainers(); Procure por bool hasLearnedInstantSpell(const std::string& spellName) const; Adicione em baixo const std::map<uint8_t, OpenContainer>& getOpenContainers() const { return openContainers; } 5° Passo Spoiler Em protocolgame.cpp procure por void ProtocolGame::login(const std::string& name, uint32_t accountId, OperatingSystem_t operatingSystem) Dentro do método procure por if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { Adicione em cima player->autoOpenContainers(); Procure por void ProtocolGame::connect(uint32_t playerId, OperatingSystem_t operatingSystem) Dentro do método procure por sendAddCreature(player, player->getPosition(), 0, false); E em baixo adicione player->autoOpenContainers(); Feito isso, basta compilar e testar. Código retirado do github do v8 > This is the hidden content, please Entre ou Cadastre-se 21 Link para o comentário https://tibiadevs.com/forums/topic/254-tfs-1x-salvar-backpacks-abertas-e-enviar-ao-logar/ Compartilhar em outros sites Mais opções de compartilhamento...
Posts Recomendados
Crie uma conta ou entre para comentar
Você precisar ser um membro para fazer um comentário
Criar uma conta
Crie uma nova conta em nossa comunidade. É fácil!
Crie uma nova contaEntrar
Já tem uma conta? Faça o login.
Entrar Agora