mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 00:03:50 +00:00
make a user friendly delete message
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
This commit is contained in:
parent
5b47d034c5
commit
fe1dc5e02b
5 changed files with 62 additions and 10 deletions
|
|
@ -199,7 +199,7 @@ public:
|
||||||
using CharCreateCallback = std::function<void(bool success, const std::string& message)>;
|
using CharCreateCallback = std::function<void(bool success, const std::string& message)>;
|
||||||
void setCharCreateCallback(CharCreateCallback cb) { charCreateCallback_ = std::move(cb); }
|
void setCharCreateCallback(CharCreateCallback cb) { charCreateCallback_ = std::move(cb); }
|
||||||
|
|
||||||
using CharDeleteCallback = std::function<void(bool success)>;
|
using CharDeleteCallback = std::function<void(bool success, const std::string& message)>;
|
||||||
void setCharDeleteCallback(CharDeleteCallback cb) { charDeleteCallback_ = std::move(cb); }
|
void setCharDeleteCallback(CharDeleteCallback cb) { charDeleteCallback_ = std::move(cb); }
|
||||||
uint8_t getLastCharDeleteResult() const { return lastCharDeleteResult_; }
|
uint8_t getLastCharDeleteResult() const { return lastCharDeleteResult_; }
|
||||||
|
|
||||||
|
|
@ -3336,6 +3336,10 @@ private:
|
||||||
CharDeleteCallback charDeleteCallback_;
|
CharDeleteCallback charDeleteCallback_;
|
||||||
CharLoginFailCallback charLoginFailCallback_;
|
CharLoginFailCallback charLoginFailCallback_;
|
||||||
uint8_t lastCharDeleteResult_ = 0xFF;
|
uint8_t lastCharDeleteResult_ = 0xFF;
|
||||||
|
bool pendingCharDeleteResponse_ = false;
|
||||||
|
uint64_t pendingDeleteGuid_ = 0;
|
||||||
|
float pendingDeleteTimer_ = 0.0f;
|
||||||
|
bool pendingDeleteFallbackEnum_ = false;
|
||||||
bool pendingCharCreateResult_ = false;
|
bool pendingCharCreateResult_ = false;
|
||||||
bool pendingCharCreateSuccess_ = false;
|
bool pendingCharCreateSuccess_ = false;
|
||||||
std::string pendingCharCreateMsg_;
|
std::string pendingCharCreateMsg_;
|
||||||
|
|
|
||||||
|
|
@ -166,15 +166,10 @@ void UIScreenCallbackHandler::setupCallbacks() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Character delete result callback
|
// Character delete result callback
|
||||||
gameHandler_.setCharDeleteCallback([this](bool success) {
|
gameHandler_.setCharDeleteCallback([this](bool success, const std::string& message) {
|
||||||
|
uiManager_.getCharacterScreen().setStatus(message, !success);
|
||||||
if (success) {
|
if (success) {
|
||||||
uiManager_.getCharacterScreen().setStatus("Character deleted.");
|
|
||||||
// Refresh character list
|
|
||||||
gameHandler_.requestCharacterList();
|
gameHandler_.requestCharacterList();
|
||||||
} else {
|
|
||||||
uint8_t code = gameHandler_.getLastCharDeleteResult();
|
|
||||||
uiManager_.getCharacterScreen().setStatus(
|
|
||||||
"Delete failed (code " + std::to_string(static_cast<int>(code)) + ").", true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -756,6 +756,43 @@ void GameHandler::update(float deltaTime) {
|
||||||
updateNetworking(deltaTime);
|
updateNetworking(deltaTime);
|
||||||
if (!socket) return; // disconnect() may have been called
|
if (!socket) return; // disconnect() may have been called
|
||||||
|
|
||||||
|
// Fallback for CMSG_CHAR_DELETE with no server response: if the server
|
||||||
|
// doesn't send SMSG_CHAR_DELETE within 3 seconds, re-request the character
|
||||||
|
// list. Some server cores silently process the delete without responding.
|
||||||
|
if (pendingCharDeleteResponse_) {
|
||||||
|
pendingDeleteTimer_ += deltaTime;
|
||||||
|
if (pendingDeleteTimer_ >= 3.0f) {
|
||||||
|
LOG_WARNING("No SMSG_CHAR_DELETE response after 3s — requesting character list to verify");
|
||||||
|
pendingCharDeleteResponse_ = false;
|
||||||
|
pendingDeleteFallbackEnum_ = true;
|
||||||
|
requestCharacterList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After the fallback SMSG_CHAR_ENUM has been processed, check if the
|
||||||
|
// character was actually removed and fire the delete callback.
|
||||||
|
if (pendingDeleteFallbackEnum_ && state == WorldState::CHAR_LIST_RECEIVED) {
|
||||||
|
pendingDeleteFallbackEnum_ = false;
|
||||||
|
uint64_t deletedGuid = pendingDeleteGuid_;
|
||||||
|
pendingDeleteGuid_ = 0;
|
||||||
|
bool found = false;
|
||||||
|
for (const auto& ch : characters) {
|
||||||
|
if (ch.guid == deletedGuid) { found = true; break; }
|
||||||
|
}
|
||||||
|
bool deleted = !found;
|
||||||
|
LOG_INFO("Char delete fallback: GUID 0x", std::hex, deletedGuid, std::dec,
|
||||||
|
deleted ? " was deleted" : " still exists");
|
||||||
|
std::string msg;
|
||||||
|
if (deleted) {
|
||||||
|
msg = "Character deleted.";
|
||||||
|
} else {
|
||||||
|
msg = "Delete failed: the server did not respond. "
|
||||||
|
"This usually happens if you recently logged out — "
|
||||||
|
"wait 20-30 seconds and try again.";
|
||||||
|
}
|
||||||
|
if (charDeleteCallback_) charDeleteCallback_(deleted, msg);
|
||||||
|
}
|
||||||
|
|
||||||
// Validate target still exists
|
// Validate target still exists
|
||||||
if (targetGuid != 0 && !entityController_->getEntityManager().hasEntity(targetGuid)) {
|
if (targetGuid != 0 && !entityController_->getEntityManager().hasEntity(targetGuid)) {
|
||||||
clearTarget();
|
clearTarget();
|
||||||
|
|
|
||||||
|
|
@ -342,13 +342,16 @@ void GameHandler::handleCharCreateResponse(network::Packet& packet) {
|
||||||
|
|
||||||
void GameHandler::deleteCharacter(uint64_t characterGuid) {
|
void GameHandler::deleteCharacter(uint64_t characterGuid) {
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
if (charDeleteCallback_) charDeleteCallback_(false);
|
if (charDeleteCallback_) charDeleteCallback_(false, "Delete failed: not connected to server.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
network::Packet packet(wireOpcode(Opcode::CMSG_CHAR_DELETE));
|
network::Packet packet(wireOpcode(Opcode::CMSG_CHAR_DELETE));
|
||||||
packet.writeUInt64(characterGuid);
|
packet.writeUInt64(characterGuid);
|
||||||
socket->send(packet);
|
socket->send(packet);
|
||||||
|
pendingCharDeleteResponse_ = true;
|
||||||
|
pendingDeleteGuid_ = characterGuid;
|
||||||
|
pendingDeleteTimer_ = 0.0f;
|
||||||
LOG_INFO("CMSG_CHAR_DELETE sent for GUID: 0x", std::hex, characterGuid, std::dec);
|
LOG_INFO("CMSG_CHAR_DELETE sent for GUID: 0x", std::hex, characterGuid, std::dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,10 +151,23 @@ void GameHandler::registerOpcodeHandlers() {
|
||||||
dispatchTable_[Opcode::SMSG_CHAR_DELETE] = [this](network::Packet& packet) {
|
dispatchTable_[Opcode::SMSG_CHAR_DELETE] = [this](network::Packet& packet) {
|
||||||
uint8_t result = packet.readUInt8();
|
uint8_t result = packet.readUInt8();
|
||||||
lastCharDeleteResult_ = result;
|
lastCharDeleteResult_ = result;
|
||||||
|
pendingCharDeleteResponse_ = false;
|
||||||
bool success = (result == 0x00 || result == 0x47);
|
bool success = (result == 0x00 || result == 0x47);
|
||||||
LOG_INFO("SMSG_CHAR_DELETE result: ", static_cast<int>(result), success ? " (success)" : " (failed)");
|
LOG_INFO("SMSG_CHAR_DELETE result: ", static_cast<int>(result), success ? " (success)" : " (failed)");
|
||||||
requestCharacterList();
|
requestCharacterList();
|
||||||
if (charDeleteCallback_) charDeleteCallback_(success);
|
std::string msg;
|
||||||
|
if (success) {
|
||||||
|
msg = "Character deleted.";
|
||||||
|
} else {
|
||||||
|
// Map known CHAR_DELETE_* result codes to user-friendly messages
|
||||||
|
switch (result) {
|
||||||
|
case 0x31: msg = "Delete failed: character is a guild leader. Transfer leadership first."; break;
|
||||||
|
case 0x32: msg = "Delete failed: character is in an arena team."; break;
|
||||||
|
case 0x3A: msg = "Delete failed: character has mail. Check mailbox first."; break;
|
||||||
|
default: msg = "Delete failed (server error code " + std::to_string(static_cast<int>(result)) + ")."; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (charDeleteCallback_) charDeleteCallback_(success, msg);
|
||||||
};
|
};
|
||||||
dispatchTable_[Opcode::SMSG_CHAR_ENUM] = [this](network::Packet& packet) {
|
dispatchTable_[Opcode::SMSG_CHAR_ENUM] = [this](network::Packet& packet) {
|
||||||
if (state == WorldState::CHAR_LIST_REQUESTED)
|
if (state == WorldState::CHAR_LIST_REQUESTED)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue