Bug Bitmap Load Listeners not working (1.5.0)

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
2,993
Reaction score
2,280
First Language
Portuguese - Br
Primarily Uses
RMMZ
Hi there people!

I just found a problem with the latest core updates.
The Bitmap Load Listeners are not working sometimes. Although most of the time this problem happens when the dev tools are open, it also happened when it was not opened, less frequently though.

To reproduce the bug:
  1. Hit Playtest on the project sent here(or anyone without any plugins).
  2. Start a new game.
  3. On the map scene, open dev tools with F12.
  4. With the dev tools on focus, press F5 to restart the playtest.
  5. Click on the game screen again to restore focus.
  6. Start the new game again on the title screen.
  7. You will notice sometimes the character sprites and even the Menu Button is not showing on the map scene.
  8. But if you enter the menu and leave, they will appear.

Where do I think the problem lies:

JavaScript:
Bitmap.prototype._startLoading = function() {
    this._image = new Image();
    this._image.onload = this._onLoad.bind(this);
    this._image.onerror = this._onError.bind(this);
    this._destroyCanvas();
    this._loadingState = "loading";
    if (Utils.hasEncryptedImages()) {
        this._startDecrypting();
    } else {
        this._image.src = this._url;
        // BETWEEN THESE COMMENTS
        if (this._image.width > 0) {
            this._image.onload = null;
            this._onLoad();
        }
        // BETWEEN THESE COMMENTS
    }
};

Bitmap.prototype._onLoad = function() {
    if (Utils.hasEncryptedImages()) {
        URL.revokeObjectURL(this._image.src);
    }
    this._loadingState = "loaded";
    this._createBaseTexture(this._image);
    this._callLoadListeners();
};
Bitmap.prototype._callLoadListeners = function() {
    while (this._loadListeners.length > 0) {
        const listener = this._loadListeners.shift();
        listener(this);
    }
};

Before 1.5.0, the code inside the comments does not exist. Making the _image always has the _onLoad method attached to it:
this._image.onload = this._onLoad.bind(this);

But now, if the image is not encrypted and the image width is higher than 0, the onLoad will not fire as it should be.
But it will try to fire via the Bitmap instance (this._onLoad()) but not attached to the_image.onload method.

But thinking only from the perspective of the problem related to the Dev Tools, I believe that the changes on the Scene Manager could maybe have some impact?

Before 1.5.0
JavaScript:
SceneManager.terminate = function() {
    window.close();
};

On 1.5.0
JavaScript:
SceneManager.terminate = function() {
    if (Utils.isNwjs()) {
        nw.App.quit();
    }
};

My file is only 2,77 MB, but it is saying that is too large to upload. So here is a One Drive link:
 

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
3,902
Reaction score
2,963
First Language
EN
Primarily Uses
RMMZ
I see this too, though it doesn't seem to have anything to do with Bitmap#_loadListeners (Image or PIXI.Resource listeners, maybe.)

Reverting the method to how it is in v1.4.4 fixes it:
JavaScript:
/*:
 * @target MZ
 * @plugindesc Revert Bitmap#_startLoading to v1.4.4.
 */

Bitmap.prototype._startLoading = function() {
    this._image = new Image();
    this._image.onload = this._onLoad.bind(this);
    this._image.onerror = this._onError.bind(this);
    this._destroyCanvas();
    this._loadingState = "loading";
    if (Utils.hasEncryptedImages()) {
        this._startDecrypting();
    } else {
        this._image.src = this._url;
        // if (this._image.width > 0) {
        //     this._image.onload = null;
        //     this._onLoad();
        // }
    }
};
Notes:
  1. Commenting out only this._image.onload = null; has no apparent effect on the issue.

  2. Commenting out this._onLoad(); makes the game "load" indefinitely on console refresh - probably because the load listeners for resources already in memory aren't getting called, so those images never get marked as "ready".

  3. Performing a "proper" game refresh via SceneManager.reloadGame(); (or by pressing F5 when the game window is active) avoids the problem entirely.
No doubt reverting to v1.4.4 breaks whatever the edit was meant to fix in the first place. :kaoslp:

_onLoad is being called when it should, tested with this to be sure:
JavaScript:
/*:
 * @target MZ
 * @plugindesc Bitmap#_onLoad call detection.
 */
(alias => {
    Bitmap.prototype._onLoad = function() {
        console.log('Bitmap#_onLoad: ' + this._url);
        alias.apply(this, arguments);
    }
})(Bitmap.prototype._onLoad);
I suspect this is something to do with how refreshes work in NWJS. I'd recommend using SceneManager.reloadGame(), or F5 from the game window, to refresh when needed. :kaohi:

Not sure if this counts as a bug if it's only reproducible with dev tools? I've approved it anyway.
 
Last edited:

Anyone

Veteran
Veteran
Joined
Aug 24, 2019
Messages
262
Reaction score
366
First Language
German
Primarily Uses
RMMV
I have the same problem. It seems to primarily emerge whenever the developer console is open.

It also behaves in a weird fashion:
1. If start the game, start a new game, and then I restart the game through the dev console with F5, the title screen loads normally. If I start the game, don't start a new game, but simply restart the game with F5 in the dev console, the title screen bitmap is not loaded.

If I manually force the backsprite1 to refresh, it refreshes correctly. Something is preventing the image from actually being loaded properly, as Eliaquim pointed out.

2. This also affects in-game events in the weirdest way. My event sprites are modified by my plugin to update dynamically based on character tags to automatically change appearance. All my events with a sprite that do that work fine.
Every default sprite that does NOT use my dynamic sprite simply no longer loads until interacted with.

In both cases, 1 & 2, the image seems to not be loaded in time. My dynamic sprites that use loadlisteners seem to work correct out of the box - but the default sprites that don't seem to fail to load correctly.

When closing the dev console and restarting normally, these issues do not seem to appear so far.

But getting bugs when using the dev console is a BIG DEAL for plugin developers. We need to use it to track down bugs & test our plugins. Not find bugs that don't exist without the dev console.
 

Synrec

Veteran
Veteran
Joined
Nov 6, 2019
Messages
271
Reaction score
159
First Language
English
Primarily Uses
RMMV
Yeah, this bug is really annoying tbh.

Having to constantly re-open the console is seriously clipping my speed.

(ノ`Д´)ノ彡┻━┻

Anyone know how this affects exported games?
 

Anyone

Veteran
Veteran
Joined
Aug 24, 2019
Messages
262
Reaction score
366
First Language
German
Primarily Uses
RMMV
The Problem is still persisting and - under the hood- even more annoying than I originally thought.

I've spent 6 hours today, trying fix a problem when trying to design a new object type that would allow smooth, complex, multilayered images acting as one image, including allowing opacity without all the countless issues that you usually get.

Only to realize, after endless testing, that the reason why all the loadListeners weren't working even though they seemed to be, was due to the dev console being open.

Please realize the impossibly neutral and calm tone with which I write this. I deserve a statue built in my name. A place in the pantheon of gods as the god of patience and tranquility.
Fortunately, no one can see the teeth imprints in my table.

Right now, a plugin designer creating a plugin, can literally not rely on anything he sees while the dev console is open.

How are you supposed to design plugins when the moment you start testing for errors, you're literally creating them?

Can this please get fixed?
 

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
2,993
Reaction score
2,280
First Language
Portuguese - Br
Primarily Uses
RMMZ
@Anyone I know it's painful, but you can use this workaround while they don't fix it. Just overwrite these functions to this:

JavaScript:
Bitmap.prototype._startLoading = function() {
    this._image = new Image();
    this._image.onload = this._onLoad.bind(this);
    this._image.onerror = this._onError.bind(this);
    this._destroyCanvas();
    this._loadingState = "loading";
    if (Utils.hasEncryptedImages()) {
        this._startDecrypting();
    } else {
        this._image.src = this._url;
        // if (this._image.width > 0) {
        //     this._image.onload = null;
        //     this._onLoad();
        // }
    }
};

// This will speed up the F5/restart while the game is open.
SceneManager.reloadGame = function() {
    if (Utils.isNwjs()) {
        //chrome.runtime.reload();
        location.reload()
    }
};

// Optionally, if you set this to always return true, the game will be active even without the window focus.
SceneManager.isGameActive = function() {
    // [Note] We use "window.top" to support an iframe.
    //try {
    //    return window.top.document.hasFocus();
    //} catch (e) {
        // SecurityError
        return true;
    //}
};
 

Anyone

Veteran
Veteran
Joined
Aug 24, 2019
Messages
262
Reaction score
366
First Language
German
Primarily Uses
RMMV
@Anyone I know it's painful, but you can use this workaround while they don't fix it. Just overwrite these functions to this:

JavaScript:
Bitmap.prototype._startLoading = function() {
    this._image = new Image();
    this._image.onload = this._onLoad.bind(this);
    this._image.onerror = this._onError.bind(this);
    this._destroyCanvas();
    this._loadingState = "loading";
    if (Utils.hasEncryptedImages()) {
        this._startDecrypting();
    } else {
        this._image.src = this._url;
        // if (this._image.width > 0) {
        //     this._image.onload = null;
        //     this._onLoad();
        // }
    }
};

// This will speed up the F5/restart while the game is open.
SceneManager.reloadGame = function() {
    if (Utils.isNwjs()) {
        //chrome.runtime.reload();
        location.reload()
    }
};

// Optionally, if you set this to always return true, the game will be active even without the window focus.
SceneManager.isGameActive = function() {
    // [Note] We use "window.top" to support an iframe.
    //try {
    //    return window.top.document.hasFocus();
    //} catch (e) {
        // SecurityError
        return true;
    //}
};
Thanks, tested it for the loadListener and it seems to be working.

Not ideal to have to hand-import a fix into dozens of plugin projects, but it's a lot better than nothing, which is what RPGMZ currently offers. At least I can now actually see what works & what doesn't.
 

Latest Threads

Latest Posts

Latest Profile Posts


Clarn Hold
(No storylines)
There was a tutorial on how to draw anime eyes. Just draw Among Us. So I tried.
Screenshot_107.jpg
DamageActor3_7.png added!
index.php

Making a "characters first appearance" drawing for my game. Now I just have to finish the sprite art animation for her grand entrance.​
ScreenShot_9_24_2022_7_56_24.png
New area being started today. It leads to one of the games 2 optional bosses.

Forum statistics

Threads
125,540
Messages
1,171,818
Members
164,614
Latest member
guymelul
Top