mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Add mailbox system and fix logging performance stutter
Implement full mail send/receive: SMSG_SHOW_MAILBOX, CMSG_GET_MAIL_LIST, SMSG_MAIL_LIST_RESULT, CMSG_SEND_MAIL, SMSG_SEND_MAIL_RESULT, mail take money/item/delete/mark-as-read, and inbox/compose UI windows. Fix periodic stuttering in Stormwind caused by synchronous per-line disk flushes in the logger — remove fileStream.flush() and std::endl, downgrade high-volume per-packet/per-model/per-texture LOG_INFO to LOG_DEBUG.
This commit is contained in:
parent
9bc8c5c85a
commit
8a468e9533
14 changed files with 782 additions and 22 deletions
|
|
@ -252,6 +252,8 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
renderVendorWindow(gameHandler);
|
||||
renderTrainerWindow(gameHandler);
|
||||
renderTaxiWindow(gameHandler);
|
||||
renderMailWindow(gameHandler);
|
||||
renderMailComposeWindow(gameHandler);
|
||||
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
|
||||
renderMinimapMarkers(gameHandler);
|
||||
renderDeathScreen(gameHandler);
|
||||
|
|
@ -6028,4 +6030,262 @@ void GameScreen::loadSettings() {
|
|||
LOG_INFO("Settings loaded from ", path);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Mail Window
|
||||
// ============================================================
|
||||
|
||||
void GameScreen::renderMailWindow(game::GameHandler& gameHandler) {
|
||||
if (!gameHandler.isMailboxOpen()) return;
|
||||
|
||||
auto* window = core::Application::getInstance().getWindow();
|
||||
float screenW = window ? static_cast<float>(window->getWidth()) : 1280.0f;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screenW / 2 - 250, 80), ImGuiCond_Appearing);
|
||||
ImGui::SetNextWindowSize(ImVec2(600, 500), ImGuiCond_Appearing);
|
||||
|
||||
bool open = true;
|
||||
if (ImGui::Begin("Mailbox", &open)) {
|
||||
const auto& inbox = gameHandler.getMailInbox();
|
||||
|
||||
// Top bar: money + compose button
|
||||
uint64_t money = gameHandler.getMoneyCopper();
|
||||
uint32_t mg = static_cast<uint32_t>(money / 10000);
|
||||
uint32_t ms = static_cast<uint32_t>((money / 100) % 100);
|
||||
uint32_t mc = static_cast<uint32_t>(money % 100);
|
||||
ImGui::Text("Your money: %ug %us %uc", mg, ms, mc);
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - 100);
|
||||
if (ImGui::Button("Compose")) {
|
||||
mailRecipientBuffer_[0] = '\0';
|
||||
mailSubjectBuffer_[0] = '\0';
|
||||
mailBodyBuffer_[0] = '\0';
|
||||
mailComposeMoney_[0] = 0;
|
||||
mailComposeMoney_[1] = 0;
|
||||
mailComposeMoney_[2] = 0;
|
||||
gameHandler.openMailCompose();
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
if (inbox.empty()) {
|
||||
ImGui::TextDisabled("No mail.");
|
||||
} else {
|
||||
// Two-panel layout: left = mail list, right = selected mail detail
|
||||
float listWidth = 220.0f;
|
||||
|
||||
// Left panel - mail list
|
||||
ImGui::BeginChild("MailList", ImVec2(listWidth, 0), true);
|
||||
for (size_t i = 0; i < inbox.size(); ++i) {
|
||||
const auto& mail = inbox[i];
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
|
||||
bool selected = (gameHandler.getSelectedMailIndex() == static_cast<int>(i));
|
||||
std::string label = mail.subject.empty() ? "(No Subject)" : mail.subject;
|
||||
|
||||
// Unread indicator
|
||||
if (!mail.read) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.5f, 1.0f));
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(label.c_str(), selected)) {
|
||||
gameHandler.setSelectedMailIndex(static_cast<int>(i));
|
||||
// Mark as read
|
||||
if (!mail.read) {
|
||||
gameHandler.mailMarkAsRead(mail.messageId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mail.read) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
// Sub-info line
|
||||
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), " From: %s", mail.senderName.c_str());
|
||||
if (mail.money > 0) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.84f, 0.0f, 1.0f), " [G]");
|
||||
}
|
||||
if (!mail.attachments.empty()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(0.5f, 0.8f, 1.0f, 1.0f), " [A]");
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// Right panel - selected mail detail
|
||||
ImGui::BeginChild("MailDetail", ImVec2(0, 0), true);
|
||||
int sel = gameHandler.getSelectedMailIndex();
|
||||
if (sel >= 0 && sel < static_cast<int>(inbox.size())) {
|
||||
const auto& mail = inbox[sel];
|
||||
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.84f, 0.0f, 1.0f), "%s",
|
||||
mail.subject.empty() ? "(No Subject)" : mail.subject.c_str());
|
||||
ImGui::Text("From: %s", mail.senderName.c_str());
|
||||
|
||||
if (mail.messageType == 2) {
|
||||
ImGui::TextColored(ImVec4(0.8f, 0.6f, 0.2f, 1.0f), "[Auction House]");
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
// Body text
|
||||
if (!mail.body.empty()) {
|
||||
ImGui::TextWrapped("%s", mail.body.c_str());
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
// Money
|
||||
if (mail.money > 0) {
|
||||
uint32_t g = mail.money / 10000;
|
||||
uint32_t s = (mail.money / 100) % 100;
|
||||
uint32_t c = mail.money % 100;
|
||||
ImGui::Text("Money: %ug %us %uc", g, s, c);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("Take Money")) {
|
||||
gameHandler.mailTakeMoney(mail.messageId);
|
||||
}
|
||||
}
|
||||
|
||||
// COD warning
|
||||
if (mail.cod > 0) {
|
||||
uint32_t g = mail.cod / 10000;
|
||||
uint32_t s = (mail.cod / 100) % 100;
|
||||
uint32_t c = mail.cod % 100;
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
|
||||
"COD: %ug %us %uc (you pay this to take items)", g, s, c);
|
||||
}
|
||||
|
||||
// Attachments
|
||||
if (!mail.attachments.empty()) {
|
||||
ImGui::Text("Attachments: %zu", mail.attachments.size());
|
||||
for (size_t j = 0; j < mail.attachments.size(); ++j) {
|
||||
const auto& att = mail.attachments[j];
|
||||
ImGui::PushID(static_cast<int>(j));
|
||||
|
||||
auto* info = gameHandler.getItemInfo(att.itemId);
|
||||
if (info && info->valid) {
|
||||
ImGui::BulletText("%s x%u", info->name.c_str(), att.stackCount);
|
||||
} else {
|
||||
ImGui::BulletText("Item %u x%u", att.itemId, att.stackCount);
|
||||
gameHandler.ensureItemInfo(att.itemId);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("Take")) {
|
||||
gameHandler.mailTakeItem(mail.messageId, att.slot);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
|
||||
// Action buttons
|
||||
if (ImGui::Button("Delete")) {
|
||||
gameHandler.mailDelete(mail.messageId);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (mail.messageType == 0 && ImGui::Button("Reply")) {
|
||||
// Pre-fill compose with sender as recipient
|
||||
strncpy(mailRecipientBuffer_, mail.senderName.c_str(), sizeof(mailRecipientBuffer_) - 1);
|
||||
mailRecipientBuffer_[sizeof(mailRecipientBuffer_) - 1] = '\0';
|
||||
std::string reSubject = "Re: " + mail.subject;
|
||||
strncpy(mailSubjectBuffer_, reSubject.c_str(), sizeof(mailSubjectBuffer_) - 1);
|
||||
mailSubjectBuffer_[sizeof(mailSubjectBuffer_) - 1] = '\0';
|
||||
mailBodyBuffer_[0] = '\0';
|
||||
mailComposeMoney_[0] = 0;
|
||||
mailComposeMoney_[1] = 0;
|
||||
mailComposeMoney_[2] = 0;
|
||||
gameHandler.openMailCompose();
|
||||
}
|
||||
} else {
|
||||
ImGui::TextDisabled("Select a mail to read.");
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (!open) {
|
||||
gameHandler.closeMailbox();
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::renderMailComposeWindow(game::GameHandler& gameHandler) {
|
||||
if (!gameHandler.isMailComposeOpen()) return;
|
||||
|
||||
auto* window = core::Application::getInstance().getWindow();
|
||||
float screenW = window ? static_cast<float>(window->getWidth()) : 1280.0f;
|
||||
float screenH = window ? static_cast<float>(window->getHeight()) : 720.0f;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screenW / 2 - 175, screenH / 2 - 200), ImGuiCond_Appearing);
|
||||
ImGui::SetNextWindowSize(ImVec2(380, 400), ImGuiCond_Appearing);
|
||||
|
||||
bool open = true;
|
||||
if (ImGui::Begin("Send Mail", &open)) {
|
||||
ImGui::Text("To:");
|
||||
ImGui::SameLine(60);
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::InputText("##MailTo", mailRecipientBuffer_, sizeof(mailRecipientBuffer_));
|
||||
|
||||
ImGui::Text("Subject:");
|
||||
ImGui::SameLine(60);
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::InputText("##MailSubject", mailSubjectBuffer_, sizeof(mailSubjectBuffer_));
|
||||
|
||||
ImGui::Text("Body:");
|
||||
ImGui::InputTextMultiline("##MailBody", mailBodyBuffer_, sizeof(mailBodyBuffer_),
|
||||
ImVec2(-1, 150));
|
||||
|
||||
ImGui::Text("Money:");
|
||||
ImGui::SameLine(60);
|
||||
ImGui::SetNextItemWidth(60);
|
||||
ImGui::InputInt("##MailGold", &mailComposeMoney_[0], 0, 0);
|
||||
if (mailComposeMoney_[0] < 0) mailComposeMoney_[0] = 0;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("g");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(40);
|
||||
ImGui::InputInt("##MailSilver", &mailComposeMoney_[1], 0, 0);
|
||||
if (mailComposeMoney_[1] < 0) mailComposeMoney_[1] = 0;
|
||||
if (mailComposeMoney_[1] > 99) mailComposeMoney_[1] = 99;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("s");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(40);
|
||||
ImGui::InputInt("##MailCopper", &mailComposeMoney_[2], 0, 0);
|
||||
if (mailComposeMoney_[2] < 0) mailComposeMoney_[2] = 0;
|
||||
if (mailComposeMoney_[2] > 99) mailComposeMoney_[2] = 99;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("c");
|
||||
|
||||
uint32_t totalMoney = static_cast<uint32_t>(mailComposeMoney_[0]) * 10000 +
|
||||
static_cast<uint32_t>(mailComposeMoney_[1]) * 100 +
|
||||
static_cast<uint32_t>(mailComposeMoney_[2]);
|
||||
|
||||
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Sending cost: 30c");
|
||||
|
||||
ImGui::Spacing();
|
||||
bool canSend = (strlen(mailRecipientBuffer_) > 0);
|
||||
if (!canSend) ImGui::BeginDisabled();
|
||||
if (ImGui::Button("Send", ImVec2(80, 0))) {
|
||||
gameHandler.sendMail(mailRecipientBuffer_, mailSubjectBuffer_,
|
||||
mailBodyBuffer_, totalMoney);
|
||||
}
|
||||
if (!canSend) ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel", ImVec2(80, 0))) {
|
||||
gameHandler.closeMailCompose();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (!open) {
|
||||
gameHandler.closeMailCompose();
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace wowee::ui
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue