mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-10 07:49:57 -04:00
Make the game load required resources asynchronously, instead of rewriting --preload-file (for texture pack) and prerun (for IndexedDB)
This commit is contained in:
parent
e0658edfd5
commit
96551c620e
@ -1574,7 +1574,7 @@ static void TexturePackScreen_FilterFiles(const cc_string* path, void* obj) {
|
||||
}
|
||||
|
||||
static void TexturePackScreen_LoadEntries(struct ListScreen* s) {
|
||||
static const cc_string path = String_FromConst(TEXPACKS_DIR);
|
||||
static const cc_string path = String_FromConst("texpacks");
|
||||
Directory_Enum(&path, &s->entries, TexturePackScreen_FilterFiles);
|
||||
StringsBuffer_Sort(&s->entries);
|
||||
}
|
||||
|
@ -100,7 +100,6 @@ cc_uint64 Stopwatch_Measure(void) {
|
||||
*-----------------------------------------------------Directory/File------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
extern void interop_InitFilesystem(void);
|
||||
extern void interop_LoadIndexedDB(void);
|
||||
cc_result Directory_Create(const cc_string* path) {
|
||||
/* Web filesystem doesn't need directories */
|
||||
return 0;
|
||||
@ -354,10 +353,10 @@ cc_result Process_StartGame(const cc_string* args, int numArgs) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
void Process_Exit(cc_result code) {
|
||||
/* Window isn't implicitly closed when process is exited */
|
||||
/* 'Window' (i.e. the web canvas) isn't implicitly closed when process is exited */
|
||||
if (code) Window_Close();
|
||||
|
||||
exit(code);
|
||||
/* game normally calls exit with code = 0 due to async IndexedDB loading */
|
||||
if (code) exit(code);
|
||||
}
|
||||
|
||||
extern int interop_OpenTab(const char* url);
|
||||
@ -435,13 +434,7 @@ extern void interop_InitModule(void);
|
||||
void Platform_Init(void) {
|
||||
interop_InitModule();
|
||||
interop_InitFilesystem();
|
||||
interop_LoadIndexedDB();
|
||||
interop_InitSockets();
|
||||
|
||||
/* NOTE: You must pre-load IndexedDB before main() */
|
||||
/* (because pre-loading only works asynchronously) */
|
||||
/* If you don't, you'll get errors later trying to sync local to remote */
|
||||
/* See doc/hosting-webclient.md for example preloading IndexedDB code */
|
||||
}
|
||||
void Platform_Free(void) { }
|
||||
|
||||
@ -454,7 +447,7 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { return E
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Configuration-------------------------------------------------------*
|
||||
*------------------------------------------------------Main driver--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) {
|
||||
int i, count;
|
||||
@ -465,9 +458,40 @@ int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* arg
|
||||
return count;
|
||||
}
|
||||
|
||||
extern int interop_DirectorySetWorking(const char* path);
|
||||
cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) {
|
||||
/* returned result is negative for error */
|
||||
return -interop_DirectorySetWorking("/classicube");
|
||||
|
||||
cc_result Platform_SetDefaultCurrentDirectory(int argc, char** argv) { return 0; }
|
||||
static int _argc;
|
||||
static char** _argv;
|
||||
|
||||
extern void interop_FS_Init(void);
|
||||
extern void interop_DirectorySetWorking(const char* path);
|
||||
extern void interop_AsyncDownloadTexturePack(const char* path, const char* url);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
_argc = argc; _argv = argv;
|
||||
|
||||
/* Game loads resources asynchronously, then actually starts itself */
|
||||
/* main
|
||||
/* > texture pack download (async) */
|
||||
/* > load indexedDB (async) */
|
||||
/* > web_main (game actually starts) */
|
||||
|
||||
interop_FS_Init();
|
||||
interop_DirectorySetWorking("/classicube");
|
||||
interop_AsyncDownloadTexturePack("texpacks/default.zip", "static/default.zip");
|
||||
}
|
||||
|
||||
extern void interop_LoadIndexedDB(void);
|
||||
extern void interop_AsyncLoadIndexedDB(void);
|
||||
/* Asynchronous callback after texture pack is downloaded */
|
||||
EMSCRIPTEN_KEEPALIVE void main_phase1(void) {
|
||||
interop_LoadIndexedDB(); /* legacy compatibility */
|
||||
interop_AsyncLoadIndexedDB();
|
||||
}
|
||||
|
||||
extern int web_main(int argc, char** argv);
|
||||
/* Asynchronous callback after IndexedDB is loaded */
|
||||
EMSCRIPTEN_KEEPALIVE void main_phase2(void) {
|
||||
web_main(_argc, _argv);
|
||||
}
|
||||
#endif
|
||||
|
@ -136,8 +136,11 @@ void android_main(void) {
|
||||
/* Normally, the final code produced for "main" is our "main" combined with crt's main */
|
||||
/* (mingw-w64-crt/crt/gccmain.c) - alas this immediately crashes the game on startup. */
|
||||
/* Using main_real instead and setting main_real as the entrypoint fixes the crash. */
|
||||
#ifdef CC_NOMAIN
|
||||
#if defined CC_NOMAIN
|
||||
int main_real(int argc, char** argv) {
|
||||
#elif defined CC_BUILD_WEB
|
||||
/* web does some asynchronous initialisation first, then calls actual main later */
|
||||
int web_main(int argc, char** argv) {
|
||||
#else
|
||||
int main(int argc, char** argv) {
|
||||
#endif
|
||||
|
@ -341,7 +341,7 @@ static cc_result ExtractFromFile(const cc_string* filename) {
|
||||
cc_result res;
|
||||
|
||||
String_InitArray(path, pathBuffer);
|
||||
String_Format1(&path, TEXPACKS_DIR "/%s", filename);
|
||||
String_Format1(&path, "texpacks/%s", filename);
|
||||
|
||||
res = Stream_OpenFile(&stream, &path);
|
||||
if (res) {
|
||||
|
@ -52,12 +52,6 @@ CC_VAR extern struct _Atlas1DData {
|
||||
} Atlas1D;
|
||||
|
||||
extern cc_string TexturePack_Url;
|
||||
#ifdef CC_BUILD_WEB
|
||||
/* texpacks must be read from memory instead of the normal filesystem */
|
||||
#define TEXPACKS_DIR "/texpacks"
|
||||
#else
|
||||
#define TEXPACKS_DIR "texpacks"
|
||||
#endif
|
||||
|
||||
#define Atlas2D_TileX(texLoc) ((texLoc) & ATLAS2D_MASK) /* texLoc % ATLAS2D_TILES_PER_ROW */
|
||||
#define Atlas2D_TileY(texLoc) ((texLoc) >> ATLAS2D_SHIFT) /* texLoc / ATLAS2D_TILES_PER_ROW */
|
||||
|
@ -112,7 +112,37 @@ mergeInto(LibraryManager.library, {
|
||||
// TODO: This is pretty awful and should be rewritten
|
||||
var name = UTF8ToString(path);
|
||||
var data = CCFS.readFile(name);
|
||||
CCFS.writeFile('/texpacks/' + name.substring(1), data);
|
||||
CCFS.writeFile('texpacks/' + name.substring(1), data);
|
||||
},
|
||||
|
||||
|
||||
//########################################################################################################################
|
||||
//-------------------------------------------------------Main driver------------------------------------------------------
|
||||
//########################################################################################################################
|
||||
interop_AsyncDownloadTexturePack: function (rawPath, rawUrl) {
|
||||
var path = UTF8ToString(rawPath);
|
||||
var url = UTF8ToString(rawUrl);
|
||||
Module.setStatus('Downloading textures.. (1/2)');
|
||||
|
||||
Module.readAsync(url,
|
||||
function(buffer) { // onload TODO avoid new UInt8Array
|
||||
CCFS.writeFile(path, new Uint8Array(buffer), { canOwn: true });
|
||||
ccall('main_phase1', 'void');
|
||||
},
|
||||
function() { // onerror
|
||||
ccall('main_phase1', 'void');
|
||||
}
|
||||
);
|
||||
},
|
||||
interop_AsyncLoadIndexedDB__deps: ['IDBFS_loadFS'],
|
||||
interop_AsyncLoadIndexedDB: function() {
|
||||
Module.setStatus('Loading IndexedDB filesystem.. (2/2)');
|
||||
|
||||
_IDBFS_loadFS(function(err) {
|
||||
if (err) window.cc_idbErr = err;
|
||||
Module.setStatus('');
|
||||
ccall('main_phase2', 'void');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -145,14 +175,19 @@ mergeInto(LibraryManager.library, {
|
||||
interop_DirectorySetWorking: function (raw) {
|
||||
var path = UTF8ToString(raw);
|
||||
CCFS.chdir(path);
|
||||
return 0;
|
||||
},
|
||||
interop_DirectoryIter: function(raw) {
|
||||
var path = UTF8ToString(raw);
|
||||
try {
|
||||
var entries = CCFS.readdir(path);
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
ccall('Directory_IterCallback', 'void', ['string'], [entries[i]]);
|
||||
for (var i = 0; i < entries.length; i++)
|
||||
{
|
||||
var path = entries[i];
|
||||
// absolute path to root relative path
|
||||
if (path.indexOf(CCFS.currentPath) === 0) {
|
||||
path = path.substring(CCFS.currentPath.length + 1);
|
||||
}
|
||||
ccall('Directory_IterCallback', 'void', ['string'], [path]);
|
||||
}
|
||||
return 0;
|
||||
} catch (e) {
|
||||
@ -236,18 +271,12 @@ mergeInto(LibraryManager.library, {
|
||||
var msg = 'Error preloading IndexedDB:' + window.cc_idbErr + '\n\nPreviously saved settings/maps will be lost';
|
||||
ccall('Platform_LogError', 'void', ['string'], [msg]);
|
||||
},
|
||||
interop_LoadIndexedDB__deps: ['IDBFS_loadFS', 'FS_Init'],
|
||||
interop_LoadIndexedDB: function() {
|
||||
_FS_Init();
|
||||
// already loaded IndexDB? do nothing then
|
||||
if (CCFS.preloaded) return;
|
||||
CCFS.preloaded = true;
|
||||
|
||||
addRunDependency('load-idb');
|
||||
_IDBFS_loadFS(function(err) {
|
||||
if (err) window.cc_idbErr = err;
|
||||
removeRunDependency('load-idb');
|
||||
});
|
||||
// previously you were required to add interop_LoadIndexedDB to Module.preRun array
|
||||
// to load the indexedDB asynchronously *before* starting ClassiCube, because it
|
||||
// could not load indexedDB asynchronously
|
||||
// however, as ClassiCube now loads IndexedDB asynchronously itself, this is no longer
|
||||
// necessary, but is kept arounf foe backwards compatibility
|
||||
},
|
||||
interop_SaveNode__deps: ['IDBFS_getDB', 'IDBFS_storeRemoteEntry'],
|
||||
interop_SaveNode: function(path) {
|
||||
@ -822,7 +851,7 @@ mergeInto(LibraryManager.library, {
|
||||
|
||||
reader.onload = function(e) {
|
||||
var data = new Uint8Array(e.target.result);
|
||||
CCFS.createDataFile('/' + name, data, true);
|
||||
CCFS.writeFile('/' + name, data, { canOwn: true });
|
||||
ccall('Window_OnFileUploaded', 'void', ['string'], ['/' + name]);
|
||||
CCFS.unlink('/' + name);
|
||||
};
|
||||
@ -1050,10 +1079,10 @@ mergeInto(LibraryManager.library, {
|
||||
//########################################################################################################################
|
||||
//------------------------------------------------------------FS----------------------------------------------------------
|
||||
//########################################################################################################################
|
||||
FS_Init: function() {
|
||||
interop_FS_Init: function() {
|
||||
if (window.CCFS) return;
|
||||
|
||||
window.MEMFS={
|
||||
window.MEMFS={
|
||||
createNode:function(path) {
|
||||
var node = CCFS.createNode(path);
|
||||
node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
|
||||
@ -1171,11 +1200,10 @@ mergeInto(LibraryManager.library, {
|
||||
return (mode & 61440) === CCFS.MODE_TYPE_FILE;
|
||||
},
|
||||
nextfd:function() {
|
||||
// max 4096 open files
|
||||
for (var fd = 0; fd <= 4096; fd++) {
|
||||
if (!CCFS.streams[fd]) {
|
||||
return fd;
|
||||
}
|
||||
// max 4096 open files
|
||||
for (var fd = 0; fd <= 4096; fd++)
|
||||
{
|
||||
if (!CCFS.streams[fd]) return fd;
|
||||
}
|
||||
throw new CCFS.ErrnoError(24);
|
||||
},
|
||||
@ -1367,35 +1395,6 @@ mergeInto(LibraryManager.library, {
|
||||
};
|
||||
CCFS.ErrnoError.prototype = new Error();
|
||||
CCFS.ErrnoError.prototype.constructor = CCFS.ErrnoError;
|
||||
},
|
||||
createDataFile:function(path, data, canOwn) {
|
||||
if (!data) return;
|
||||
|
||||
if (typeof data === 'string') {
|
||||
var arr = new Array(data.length);
|
||||
for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
|
||||
data = arr;
|
||||
}
|
||||
|
||||
var stream = CCFS.open(path, 577); // O_WRONLY | O_CREAT | O_TRUNC
|
||||
CCFS.write(stream, data, 0, data.length, 0, canOwn);
|
||||
CCFS.close(stream);
|
||||
},
|
||||
createPreloadedFile:function(path, url, onload, onerror, canOwn, preFinish) {
|
||||
Browser.init(); // XXX perhaps this method should move onto Browser?
|
||||
var dep = getUniqueRunDependency('cp ' + name);
|
||||
|
||||
function processData(byteArray) {
|
||||
if (preFinish) preFinish();
|
||||
CCFS.createDataFile(path, byteArray, canOwn);
|
||||
if (onload) onload();
|
||||
removeRunDependency(dep)
|
||||
}
|
||||
|
||||
addRunDependency(dep);
|
||||
Browser.asyncLoad(url, function(byteArray) {
|
||||
processData(byteArray);
|
||||
}, onerror);
|
||||
}};
|
||||
|
||||
CCFS.ensureErrnoError();
|
||||
|
Loading…
x
Reference in New Issue
Block a user