0
\$\begingroup\$

I have a "console" window in-game where I log messages. When starting up, the game checks for updates by way of a Timer.Task. Any messages I try to log in the task are not displayed, but the file logs show that they were recorded at the proper time. I assume it's a rendering problem and the console's screen fails to render during the task execution.

I use Dagger2 for dependency-injection but the Screen is a @Singleton, plus there are logs in the constructor that are only written once, so I'm confident that the instance injected in MyGame and the one passed to StartupTask are the same.

I would like the console to continue displaying messages "in real time" while the update task is running. What am I missing?

Game class:

public class MyGame extends Game {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyGame.class);

    private final Lazy<ConsoleScreen> bootScreen;
    private final Lazy<StartupTaskProvider> startupTaskProvider;

    public MyGame(Lazy<ConsoleScreen> bootScreen, Lazy<StartupTaskProvider> startupTaskProvider) {
        super();
        this.bootScreen = bootScreen;
        this.startupTaskProvider = startupTaskProvider;
    }

    @Override
    public void create() {
        LOGGER.info("Startup phase.");
        final ConsoleScreen console = bootScreen.get();
        this.setScreen(console);
        console.addLog("Initialization"); // <--- Correctly displayed

        // Update when booting.
        Timer.schedule(startupTaskProvider.get().create(), 2);
    }

    @Override
    public void render() {
        super.render();
    }
    
    @Override
    public void dispose() {
    }

Provider for MyGame: (Used as a glue between Dagger2 and the call to new Lwjgl3Application)

@Module
public class GameModule {

    @Provides
    @Singleton
    static MyGame provideGame(Lazy<ConsoleScreen> bootScreen, Lazy<StartupTaskProvider> startupTaskProvider) {
        return new MyGame(bootScreen, startupTaskProvider);
    }

}

Screen class:

@Singleton
public class ConsoleScreen implements Screen {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleScreen.class);

    @Inject
    DebugUtils debugUtils;

    @Inject
    TextUtils textUtils;

    private final Stage stage;
    private final Table table;
    private final List<Label> logs;
    private final int maxSize;

    @Inject
    public ConsoleScreen(DebugUtils debugUtils, TextUtils textUtils) {
        // Creates the Stage and adds the Table to it, works fine. 
    }

    public void addLog(String text) {
        // Adds the text to the Table, works fine.
    }

    @Override
    public void show() {
        Gdx.input.setInputProcessor(stage);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        stage.act();
        stage.draw();
    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {
        stage.dispose();
    }

Startup task:

public class StartupTask extends Timer.Task {

    private final MyGame game;
    private final ConsoleScreen consoleScreen;
    private final MainScreen mainScreen;
    private final UpdateService updateService;

    public StartupTask(ConsoleScreen consoleScreen, MyGame game, MainScreen mainScreen, UpdateService service) {
        this.game = game;
        this.consoleScreen = consoleScreen;
        this.mainScreen = mainScreen;
        this.updateService = service;
    }

    @Override
    public void run() {
        consoleScreen.addLog("Starting update"); // <-- Does not display, at least not before the screen is changed.
        updateService.start().get(); // <-- Executes correctly

        // The screen is then switched and rendered correctly.
        game.setScreen(mainScreen);
        mainScreen.fadeIn();
    }

}

Provider for startup tasks:

@Module
public class StartupTaskProvider {

    @Inject
    MyGame game;

    @Inject
    ConsoleScreen consoleScreen;

    @Inject
    MainScreen mainScreen;

    @Inject
    UpdateService service;

    @Inject
    public StartupTaskProvider() {}

    @Provides
    @Singleton
    public StartupTask create() {
        return new StartupTask(consoleScreen, game, mainScreen, service);
    }

}
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I found it, rookie mistake. UpdateService.start() call runs asynchroneously, but by waiting on it with AsyncTask::get, I effectively tie up the main thread, hence no rendering during the update.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.