replaceScene creates but does not replace the scene

I’m having an object that communicates with a server. I’m trying to make it replace scene with Error scene if an error occurs, but it is not working.

if(json.Parse<0>(resp.c_str()).HasParseError())
    {
        CCLOG("PARSE ERROR HANDLE THIS!!!");
        auto scene = crashScene::createScene();
        Director::getInstance()->replaceScene(scene);
    }

I can confirm scene is created but it wont replace?

I would use the debugger and step over this code. Place a breakpoint on your Director line and then examine the scene variable that was created. Also, post what crashScene::createScene() is doing.

Thanks for helping.
CrashScene is just background and a button for restart so far.

bool crashScene::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    visibleSize = Director::getInstance()->getVisibleSize();
    origin = Director::getInstance()->getVisibleOrigin();
  
    auto crash_screen = Sprite::create("CrashScreen/crash_screen.png");
    if (crash_screen == nullptr)
    {
        CCLOG("Error: 'crash_screen'");
    }
    else
    {
        crash_screen->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
        this->addChild(crash_screen);

        restartButton = Button::create("CrashScreen/restart_button.png", "CrashScreen/restart_button.png");
        restartButton->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type)
                                           {
                                               switch(type)
                                               {
                                                   case Widget::TouchEventType::BEGAN:
                                                       break;
                                                
                                                   case Widget::TouchEventType::ENDED:
                                                   {
                                                       auto scene = splashScreen::createScene();
                                                       Director::getInstance()->replaceScene(scene);
                                                       
                                                       break;
                                                   }
                                                       
                                                   case Widget::TouchEventType::CANCELED:
                                                      
        
                                                       break;
                                                       
                                                 
                                                   default:
                                                       break;
                                               }
                                           });
        restartButton->setPosition(Vec2(200, 120));
        crash_screen->addChild(restartButton);
    }
    CCLOG("START CRASH");
    return true;
}

Code goes to createScene, it finishes the init() and then it goest back to

Director::getInstance()->replaceScene(scene);

but nothing happens… it continues execution of the function that calls that code :confused:
Scene looks valid.
Screenshot 2020-04-08 at 0.36.27
Any ideas?

Director::getInstance()->replaceScene();

requires you pass it a Scene Object. I dont see where you are doing that.

Sorry I was testing with push.
Screenshot 2020-04-08 at 0.42.25


It just continues trough this code and nothing happens?

please show createScene()

Does it hit your CCLOG statement?

Scene* crashScene::createScene()
{
    return crashScene::create();
}


Yes, It hits the CCLOG.

Does it hot your auto line? Add some logs in there to see how far it gets or use the debugger

Document dbManager::validateJson(string resp)
{
    Document json;
    
    if(json.Parse<0>(resp.c_str()).HasParseError())
    {
        CCLOG("PARSE ERROR HANDLE THIS!!!");
        auto scene = crashScene::createScene();
        Director::getInstance()->replaceScene(scene);
        
//        Director::getInstance()->replaceScene(crashScene::createScene());
        
    }
    else
    {
        if(!string(json["status"].GetString()).compare("OK"))
            return json;
        
        
        if(!string(json["status"].GetString()).compare("ERROR"))
        {
            .........
            return json;
        }
    }
    return json; // Just for testing
}
Document dbManager::authUser(std::string u)
{
 ...
    res = sendReqSync(SERVERNAME"user.php?cmd=AUTH&user=" + usr);
    json = this->validateJson(res);
    return json;
}
           json = _dbManager->authUser(userText->getString().c_str());
           this->buttonThinking(false);
                                                               
          _userData->loadUserDataStruct(json);  <--- Crashes first line here when i tries to parse json

It keep going untill it crashes when trying to parse the invalid json

So, I made a quick test. I have 3-4 places in my code that i replaceScene, but it is always at the end of the code flow. So I added some code after the replaceScenes that were working fine and what happens is that the following code is again executed before the actual scene replace occurs. Is there a way to handle this as I need to replace scene only if a condition occurs :confused: ?

Is this running on the main/cocos thread?

It should be. I’m not using threads.

I would have handled the validation a bit differently. Maybe if you have the initial validation function return a bool instead of a Document, you can check against it being valid or not. if (validateJson()) { … continue parsing etc } else { handle error case}… or something of that nature.

in pseudo form:

bool validateJSON(string resp);
Document parseJSON(string resp);
void handleError();



if (validateJSON(resp)) {
 parseJSON(resp);
} else {
 handleError()
}

I will have to change my whole logic here as Im having an object that communicates with the server. So the scene asks this object to get the response json = dbManager->getResponse. So the function will have to return… that leads to the same problem again. Or I will have to add this check to every server call i make from the scene itself :frowning:

Not necessarily, depends how you return the ‘object’… You can create a new object type:

struct ServerResponse {
   bool success;
   Document data;
};

then you return a ServerResponse instead of Document, and just check if (serverResponse.success) { use serverresmonde.data } else {follow error path}

Note this is just an example case to keep existing code structure with a different response object.

Yup, that’s something i was planning as a workaround, just I somehow feel replaceScene should occur right when its called. Thank you for helping with this!

Got answered on Discord that this is the intended behavior.