From 5f11a4fef055a4b0477694f550718b065c31153b Mon Sep 17 00:00:00 2001 From: server Date: Tue, 14 Apr 2026 12:48:48 +0200 Subject: [PATCH] db: prepare player delete cleanup flow --- src/db/ClientManagerPlayer.cpp | 91 ++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/src/db/ClientManagerPlayer.cpp b/src/db/ClientManagerPlayer.cpp index 36c21dc..552776f 100644 --- a/src/db/ClientManagerPlayer.cpp +++ b/src/db/ClientManagerPlayer.cpp @@ -175,6 +175,26 @@ bool UpdatePlayerIndexSlot(DWORD accountId, BYTE accountIndex, DWORD playerId) return stmt.GetAffectedRows() != 0; } +bool ArchiveDeletedPlayerById(DWORD playerId) +{ + char query[QUERY_MAX_LEN]; + snprintf(query, sizeof(query), "INSERT INTO player%s_deleted SELECT * FROM player%s WHERE id = ?", + GetTablePostfix(), GetTablePostfix()); + + CStmt stmt; + if (!PreparePlayerStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &playerId)) + return false; + + if (!stmt.Execute()) + return false; + + const unsigned long long affectedRows = stmt.GetAffectedRows(); + return affectedRows != 0 && affectedRows != static_cast(-1); +} + void DeletePlayerById(DWORD playerId) { char query[QUERY_MAX_LEN]; @@ -189,6 +209,51 @@ void DeletePlayerById(DWORD playerId) stmt.Execute(); } + +bool ResetPlayerIndexSlotForDelete(BYTE accountIndex, DWORD playerId) +{ + char query[QUERY_MAX_LEN]; + snprintf(query, sizeof(query), "UPDATE player_index%s SET pid%u = 0 WHERE pid%u = ?", + GetTablePostfix(), accountIndex + 1, accountIndex + 1); + + CStmt stmt; + if (!PreparePlayerStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &playerId)) + return false; + + if (!stmt.Execute()) + return false; + + const unsigned long long affectedRows = stmt.GetAffectedRows(); + return affectedRows != 0 && affectedRows != static_cast(-1); +} + +void DeletePlayerItemsByOwnerId(DWORD playerId) +{ + char query[QUERY_MAX_LEN]; + snprintf(query, sizeof(query), "DELETE FROM item%s WHERE owner_id = ? AND (window < ? OR window = ?)", + GetTablePostfix()); + + int32_t safeboxWindow = SAFEBOX; + int32_t dragonSoulInventory = DRAGON_SOUL_INVENTORY; + + CStmt stmt; + if (!PreparePlayerStmt(stmt, query)) + return; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &playerId)) + return; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &safeboxWindow)) + return; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &dragonSoulInventory)) + return; + + stmt.Execute(); +} } // @@ -1192,11 +1257,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) char queryStr[QUERY_MAX_LEN]; - snprintf(queryStr, sizeof(queryStr), "INSERT INTO player%s_deleted SELECT * FROM player%s WHERE id=%d", - GetTablePostfix(), GetTablePostfix(), pi->player_id); - auto pIns = CDBManager::instance().DirectQuery(queryStr); - - if (pIns->Get()->uiAffectedRows == 0 || pIns->Get()->uiAffectedRows == (uint32_t)-1) + if (!ArchiveDeletedPlayerById(pi->player_id)) { sys_log(0, "PLAYER_DELETE FAILED %u CANNOT INSERT TO player%s_deleted", dwPID, GetTablePostfix()); @@ -1208,10 +1269,6 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) // 삭제 성공 sys_log(0, "PLAYER_DELETE SUCCESS %u", dwPID); - char account_index_string[16]; - - snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index); - // 플레이어 테이블을 캐쉬에서 삭제한다. CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id); @@ -1240,15 +1297,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) m_map_pkItemCacheSetPtr.erase(pi->player_id); } - snprintf(queryStr, sizeof(queryStr), "UPDATE player_index%s SET pid%u=0 WHERE pid%u=%d", - GetTablePostfix(), - pi->account_index + 1, - pi->account_index + 1, - pi->player_id); - - auto pMsg = CDBManager::instance().DirectQuery(queryStr); - - if (pMsg->Get()->uiAffectedRows == 0 || pMsg->Get()->uiAffectedRows == (uint32_t)-1) + if (!ResetPlayerIndexSlotForDelete(pi->account_index, pi->player_id)) { sys_log(0, "PLAYER_DELETE FAIL WHEN UPDATE account table"); peer->EncodeHeader(DG::PLAYER_DELETE_FAILED, pi->dwHandle, 1); @@ -1256,11 +1305,9 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) return; } - snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), pi->player_id); - CDBManager::instance().DirectQuery(queryStr); + DeletePlayerById(pi->player_id); - snprintf(queryStr, sizeof(queryStr), "DELETE FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)", GetTablePostfix(), pi->player_id, SAFEBOX, DRAGON_SOUL_INVENTORY); - CDBManager::instance().DirectQuery(queryStr); + DeletePlayerItemsByOwnerId(pi->player_id); snprintf(queryStr, sizeof(queryStr), "DELETE FROM quest%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id); CDBManager::instance().AsyncQuery(queryStr);