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)
-------------------------------------------------------
== 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 ==
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)

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)
{
iter_queue it;
int i;
bool ret=true;
iter_queue it;
int i;
bool ret = true;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
// 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))) {
for(it=start,i=8000;it!=end;++it,i++) {
ItemInst *inst=*it;
if (!(ret=SaveInventory(char_id,inst,(i==8000) ? MainCursor : i)))
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))) {
for (it = start, i = 8000; it != end; ++it, i++) {
ItemInst *inst = *it;
if (!(ret = SaveInventory(char_id, inst, (i == 8000) ? MainCursor : i)))
break;
}
} else {
}
else {
std::cout << "Clearing cursor failed: " << errbuf << std::endl;
}
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());
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) {
int16 slot_id = 0;
int16 slot_id;
// personal
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
// equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_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);
@ -2014,11 +2013,22 @@ 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
const ItemInst* inst = m_inv[MainPowerSource];
if(inst && !inst->GetItem()->NoRent) {
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
if (m_inv[MainPowerSource]) {
const ItemInst* inst = m_inv[MainPowerSource];
if (inst && !inst->GetItem()->NoRent) {
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
}
}
// containers
@ -2065,15 +2075,41 @@ void Client::RemoveNoRent(bool client_update) {
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
void Client::RemoveDuplicateLore(bool client_update) {
// Split-charge stacking may be added at some point -U
int16 slot_id;
int16 slot_id = 0;
// personal
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
// equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
ItemInst* inst = m_inv.PopItem(slot_id);
if(inst) {
if(CheckLoreConflict(inst->GetItem())) {
@ -2087,17 +2123,34 @@ 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
ItemInst* inst = m_inv.PopItem(MainPowerSource);
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, MainPowerSource);
if (m_inv[MainPowerSource]) {
ItemInst* inst = m_inv.PopItem(MainPowerSource);
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, MainPowerSource);
}
else {
m_inv.PutItem(MainPowerSource, *inst);
}
safe_delete(inst);
}
else {
m_inv.PutItem(MainPowerSource, *inst);
}
safe_delete(inst);
}
// containers
@ -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
// 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) {
int16 slot_id;
int16 slot_id = 0;
// equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {