Direct scene loading (not from JSON file)

Hello there!

We have this issue on our webserver/CMS where we want to deploy our PlayCanvas App - the JSON files are not handled by the webserver and thus PlayCanvas cannot load config.json and scenenumber.json files.

Changing the webserver policies is not an option right now, so I was thinking if could I feed the JSON data directly, but the loading system seems quite complex and intertwined with other parts of PC. Of course I started with the _start_.js where the first occurance of scene loading is handled (app.loadScene(SCENE_PATH, function (err, scene))

Any ideas how to feed the data from these two JSON files directly when loading the App?

Thanks for any tips and hints!

I’ve not tried this before but a base64 string should work here?

Well the problem I encountered is that PC’s loading system needs and uses the URL in several parts of the code. The data themselves are not a problem.

What you mean is instead of using URL like
"/playcanvas/config.json" use something like
"data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=" which is the encoded JSON data instead?

The core JSON files would be config.json that has the asset registry and other data as well as all the various scenes.

It is possible change the path of the config.js and the scene paths in __settings__.js or have those global variables set elsewhere.

The boilerplate __start__.js is where all the config.json is loaded via app.configure.

Customising either/or both the __start__.js and __settings__.js would be where I would start.

It sounds like you’ve done this part already so I’m missing the bit where you are having trouble with.

Are you looking to modify the config.json data? Or is it more that you just want to load the data itself, not a JSON file?

Something like that. As I stated before, I am unable to load JSON files on the server the app will be running on (every other file type is fine). That means I need to load the data in those two JSON files some other way - preferably directly copying the JSON data from the file and using it as a variable inside the loading script.

Right now I am trying to tinker with the loading script inside playcanvas javascript library so that it will use this “hard coded” data directly for those 2 certain loadings (scene and config)

Just to confirm, you can’t serve JSON files. Can you load text files instead? I can’t remember if the engine cares about the extension for scenes and the config file.

Base64 would be my workaround for this

My current solution is that I edited the engine’s scene loading function
(playcanvas-stable.js:68876 _proto.loadScene)

I removed the “loading by URL” part and hard-coded the needed scene data (copied from scene.json and pasted as a new variable)

Not elegant solution, but works for now.

1 Like

Tried with .txt files, but the loading system did not like that

I’ve had a quick look at this, it’s possible to patch the engine to allow for .txt files with a few workarounds.

Rename config.json to config.json.txt and the scene json to end also in .json.txt

Change the URLs in __settings__.js to use .json.txt

Change the scenes property in config.json.txt to use the correct URL:
image

Create a JS file for the patch (eg http-patch.js) with the following code:

(function () {
    pc.Http.prototype._onSuccess = function (method, url, options, xhr) {
        var response;
        var header;
        var contentType;
        var parts;
        header = xhr.getResponseHeader("Content-Type");
        if (header) {
            // Split up header into content type and parameter
            parts = header.split(";");
            contentType = parts[0].trim();
        }
        try {
            // Check the content type to see if we want to parse it
            if (contentType === this.ContentType.JSON || url.split('?')[0].includes(".json")) {
                // It's a JSON response
                response = JSON.parse(xhr.responseText);
            } else if (this._isBinaryContentType(contentType)) {
                response = xhr.response;
            } else {
                if (xhr.responseType === Http.ResponseType.ARRAY_BUFFER) {
                    response = xhr.response;
                } else if (xhr.responseType === Http.ResponseType.BLOB || xhr.responseType === Http.ResponseType.JSON) {
                    response = xhr.response;
                } else {
                    if (xhr.responseType === Http.ResponseType.DOCUMENT || contentType === this.ContentType.XML) {
                        // It's an XML response
                        response = xhr.responseXML;
                    } else {
                        // It's raw data
                        response = xhr.responseText;
                    }
                }
            }

            options.callback(null, response);
        } catch (err) {
            options.callback(err);

        }
    }
})();

And include this in index.html after the engine inclusion:

This worked in my limited test on Flappy Bird, zip file here:
Flappy Bird.zip (810.4 KB)

2 Likes