Fix for losing 2nd and 3rd cursor items after zoning

This commit is contained in:
Uleat 2014-09-05 16:16:56 -04:00
parent da121137e5
commit 1d0a6bdc71
4 changed files with 134 additions and 33 deletions

View File

@ -1,5 +1,8 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 09/05/2014 ==
Uleat: Fix for cursor item loss when zoning. (Thanks to the other devs who traced and fixed the 'macro' issue!)
== 09/03/2014 == == 09/03/2014 ==
Secrets: Identified the routines needed to augment items in RoF. Currently, only Insert and Remove are supported. Swap and Destroy do not work due to missing functions related to the cursor. Secrets: Identified the routines needed to augment items in RoF. Currently, only Insert and Remove are supported. Swap and Destroy do not work due to missing functions related to the cursor.
demonstar55: Added work around command to show numhits on your buffs (#shownumhits) demonstar55: Added work around command to show numhits on your buffs (#shownumhits)

View File

@ -143,19 +143,22 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<ItemInst*>::const_iterator &start, std::list<ItemInst*>::const_iterator &end) bool SharedDatabase::SaveCursor(uint32 char_id, std::list<ItemInst*>::const_iterator &start, std::list<ItemInst*>::const_iterator &end)
{ {
iter_queue it; iter_queue it;
int i; int i;
bool ret=true; bool ret = true;
char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0; char* query = 0;
// Delete cursor items // Delete cursor items
if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND ( (slotid >=8000 and slotid<=8999) or slotid=%i or (slotid>=%i and slotid<=%i))", char_id, MainCursor,EmuConstants::CURSOR_BAG_BEGIN,EmuConstants::CURSOR_BAG_END), errbuf))) { if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid = %i AND ((slotid >= 8000 AND slotid <= 8999) OR slotid = %i OR (slotid >= %i AND slotid <= %i))",
for(it=start,i=8000;it!=end;++it,i++) { char_id, MainCursor, EmuConstants::CURSOR_BAG_BEGIN, EmuConstants::CURSOR_BAG_END), errbuf))) {
ItemInst *inst=*it;
if (!(ret=SaveInventory(char_id,inst,(i==8000) ? MainCursor : i))) for (it = start, i = 8000; it != end; ++it, i++) {
ItemInst *inst = *it;
if (!(ret = SaveInventory(char_id, inst, (i == 8000) ? MainCursor : i)))
break; break;
} }
} else { }
else {
std::cout << "Clearing cursor failed: " << errbuf << std::endl; std::cout << "Clearing cursor failed: " << errbuf << std::endl;
} }
safe_delete_array(query); safe_delete_array(query);

View File

@ -836,8 +836,6 @@ void Client::BulkSendInventoryItems() {
} }
} }
// Where are cursor buffer items processed? They need to be validated as well... -U
bool deletenorent = database.NoRentExpired(GetName()); bool deletenorent = database.NoRentExpired(GetName());
if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items

View File

@ -2002,11 +2002,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
} }
void Client::RemoveNoRent(bool client_update) { void Client::RemoveNoRent(bool client_update) {
int16 slot_id = 0;
int16 slot_id; // equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
// personal
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
const ItemInst* inst = m_inv[slot_id]; const ItemInst* inst = m_inv[slot_id];
if(inst && !inst->GetItem()->NoRent) { if(inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
@ -2014,12 +2013,23 @@ void Client::RemoveNoRent(bool client_update) {
} }
} }
// general
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; slot_id++) {
const ItemInst* inst = m_inv[slot_id];
if (inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
DeleteItemInInventory(slot_id, 0, client_update);
}
}
// power source // power source
if (m_inv[MainPowerSource]) {
const ItemInst* inst = m_inv[MainPowerSource]; const ItemInst* inst = m_inv[MainPowerSource];
if(inst && !inst->GetItem()->NoRent) { if (inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource); mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource);
DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
} }
}
// containers // containers
for(slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; slot_id++) { for(slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; slot_id++) {
@ -2065,15 +2075,41 @@ void Client::RemoveNoRent(bool client_update) {
DeleteItemInInventory(slot_id, 0, false); // Can't delete from client Shared Bank Container slots DeleteItemInInventory(slot_id, 0, false); // Can't delete from client Shared Bank Container slots
} }
} }
// cursor & limbo
if (!m_inv.CursorEmpty()) {
std::list<ItemInst*> local;
ItemInst* inst = nullptr;
while (!m_inv.CursorEmpty()) {
inst = m_inv.PopItem(MainCursor);
if (inst)
local.push_back(inst);
}
std::list<ItemInst*>::iterator iter = local.begin();
while (iter != local.end()) {
inst = *iter;
if (!inst->GetItem()->NoRent)
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from `Limbo`", inst->GetItem()->Name);
else
m_inv.PushCursor(**iter);
safe_delete(*iter);
iter = local.erase(iter);
}
database.SaveCursor(this->character_id, m_inv.cursor_begin(), m_inv.cursor_end());
local.clear();
}
} }
// Two new methods to alleviate perpetual login desyncs // Two new methods to alleviate perpetual login desyncs
void Client::RemoveDuplicateLore(bool client_update) { void Client::RemoveDuplicateLore(bool client_update) {
// Split-charge stacking may be added at some point -U int16 slot_id = 0;
int16 slot_id;
// personal // equipment
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) { for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
ItemInst* inst = m_inv.PopItem(slot_id); ItemInst* inst = m_inv.PopItem(slot_id);
if(inst) { if(inst) {
if(CheckLoreConflict(inst->GetItem())) { if(CheckLoreConflict(inst->GetItem())) {
@ -2087,10 +2123,26 @@ void Client::RemoveDuplicateLore(bool client_update) {
} }
} }
// general
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; slot_id++) {
ItemInst* inst = m_inv.PopItem(slot_id);
if (inst) {
if (CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
database.SaveInventory(character_id, nullptr, slot_id);
}
else {
m_inv.PutItem(slot_id, *inst);
}
safe_delete(inst);
}
}
// power source // power source
if (m_inv[MainPowerSource]) {
ItemInst* inst = m_inv.PopItem(MainPowerSource); ItemInst* inst = m_inv.PopItem(MainPowerSource);
if(inst) { if (inst) {
if(CheckLoreConflict(inst->GetItem())) { if (CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
database.SaveInventory(character_id, nullptr, MainPowerSource); database.SaveInventory(character_id, nullptr, MainPowerSource);
} }
@ -2099,6 +2151,7 @@ void Client::RemoveDuplicateLore(bool client_update) {
} }
safe_delete(inst); safe_delete(inst);
} }
}
// containers // containers
for(slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; slot_id++) { for(slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; slot_id++) {
@ -2146,11 +2199,55 @@ void Client::RemoveDuplicateLore(bool client_update) {
} }
// Shared Bank and Shared Bank Containers are not checked due to their allowing duplicate lore items -U // Shared Bank and Shared Bank Containers are not checked due to their allowing duplicate lore items -U
// cursor & limbo
if (!m_inv.CursorEmpty()) {
std::list<ItemInst*> local;
ItemInst* inst = nullptr;
while (!m_inv.CursorEmpty()) {
inst = m_inv.PopItem(MainCursor);
if (inst)
local.push_back(inst);
}
std::list<ItemInst*>::iterator iter = local.begin();
while (iter != local.end()) {
inst = *iter;
if (CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name);
safe_delete(*iter);
iter = local.erase(iter);
}
else {
++iter;
}
}
iter = local.begin();
while (iter != local.end()) {
inst = *iter;
if (!inst->GetItem()->LoreFlag ||
((inst->GetItem()->LoreGroup == -1) && (m_inv.HasItem(inst->GetID(), 0, invWhereCursor) == INVALID_INDEX)) ||
(inst->GetItem()->LoreGroup && ~inst->GetItem()->LoreGroup && (m_inv.HasItemByLoreGroup(inst->GetItem()->LoreGroup, invWhereCursor) == INVALID_INDEX))) {
m_inv.PushCursor(**iter);
}
else {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name);
}
safe_delete(*iter);
iter = local.erase(iter);
}
database.SaveCursor(this->character_id, m_inv.cursor_begin(), m_inv.cursor_end());
local.clear();
}
} }
void Client::MoveSlotNotAllowed(bool client_update) { void Client::MoveSlotNotAllowed(bool client_update) {
int16 slot_id = 0;
int16 slot_id;
// equipment // equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) { for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {