From 2db690a86642632f87a1899613212bad04f93206 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 5 Feb 2026 14:18:41 -0800 Subject: [PATCH] Fix crash in character creation by deferring callback to next update The charCreateCallback was firing synchronously during ImGui render, causing a state transition before the create screen's ImGui::End() was called. Defer the callback to GameHandler::update() and ensure update() runs during CHARACTER_CREATION and CHARACTER_SELECTION states. --- include/game/game_handler.hpp | 3 +++ src/core/application.cpp | 8 ++++++-- src/game/game_handler.cpp | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 81218c8a..41c9be45 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -525,6 +525,9 @@ private: WorldConnectSuccessCallback onSuccess; WorldConnectFailureCallback onFailure; CharCreateCallback charCreateCallback_; + bool pendingCharCreateResult_ = false; + bool pendingCharCreateSuccess_ = false; + std::string pendingCharCreateMsg_; // ---- XP tracking ---- uint32_t playerXp_ = 0; diff --git a/src/core/application.cpp b/src/core/application.cpp index 7a12d557..02cfdec7 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -344,11 +344,15 @@ void Application::update(float deltaTime) { break; case AppState::CHARACTER_CREATION: - // Character creation update + if (gameHandler) { + gameHandler->update(deltaTime); + } break; case AppState::CHARACTER_SELECTION: - // Character selection update + if (gameHandler) { + gameHandler->update(deltaTime); + } break; case AppState::IN_GAME: diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index c25fab61..8302a33f 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -406,6 +406,14 @@ bool GameHandler::isConnected() const { } void GameHandler::update(float deltaTime) { + // Fire deferred char-create callback (outside ImGui render) + if (pendingCharCreateResult_) { + pendingCharCreateResult_ = false; + if (charCreateCallback_) { + charCreateCallback_(pendingCharCreateSuccess_, pendingCharCreateMsg_); + } + } + if (!socket && !singlePlayerMode_) { return; } @@ -852,9 +860,10 @@ void GameHandler::createCharacter(const CharCreateData& data) { characters.push_back(ch); LOG_INFO("Single-player character created: ", ch.name); - if (charCreateCallback_) { - charCreateCallback_(true, "Character created!"); - } + // Defer callback to next update() so ImGui frame completes first + pendingCharCreateResult_ = true; + pendingCharCreateSuccess_ = true; + pendingCharCreateMsg_ = "Character created!"; return; }