From a8f3a108a0d7e705bdedfa65a206fd0fcaf4c6fa Mon Sep 17 00:00:00 2001 From: Sylvain Beucler Date: Mon, 18 Nov 2019 15:56:50 +0100 Subject: [PATCH] Better error handling --- launcher/game/web.rpy | 1 + renpy/display/core.py | 2 +- renpy/loader.py | 49 ++++++++++++++++++++++++++----------------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/launcher/game/web.rpy b/launcher/game/web.rpy index e7acc18328..9ac0f0df9f 100644 --- a/launcher/game/web.rpy +++ b/launcher/game/web.rpy @@ -87,6 +87,7 @@ init python: # Filter out downloadable resources MIN_REMOTE_SIZE=100*1024 # TODO: configurable min_size? use archives to better describe web distribution? + # TODO: predict/include title screen's resources for a smooth start (no black blink) shutil.move( os.path.join(destination, 'game.zip'), os.path.join(destination, 'game-old.zip')) diff --git a/renpy/display/core.py b/renpy/display/core.py index 812dd099e1..b3f4ac8619 100644 --- a/renpy/display/core.py +++ b/renpy/display/core.py @@ -2791,7 +2791,7 @@ def idle_frame(self, can_block, expensive): elif step == 2: if renpy.emscripten or os.environ.get('RENPY_SIMULATE_DOWNLOAD', False): - renpy.loader.ReloadRequest.load_downloaded_resources() + renpy.loader.ReloadRequest.process_downloaded_resources() step += 1 diff --git a/renpy/loader.py b/renpy/loader.py index 233aa81979..4b36ad9c25 100644 --- a/renpy/loader.py +++ b/renpy/loader.py @@ -45,27 +45,34 @@ xhrs: {}, dl_new: function(path) { - var xhr = new XMLHttpRequest(); - xhr.responseType = 'arraybuffer'; - xhr.onload = function() { - // Create file reusing XHR's buffer (no-copy) - try { FS.unlink(path); } catch {} - FS.writeFile(path, new Uint8Array(xhr.response), {canOwn:true}); - } - xhr.open('GET', path); - xhr.send(); - RenPyWeb.xhrs[RenPyWeb.xhr_id] = xhr; - var ret = RenPyWeb.xhr_id; - RenPyWeb.xhr_id++; - return ret; + var xhr = new XMLHttpRequest(); + xhr.responseType = 'arraybuffer'; + xhr.onerror = function() { + console.log("Network error", xhr); + } + xhr.onload = function() { + if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { + // Create file reusing XHR's buffer (no-copy) + try { FS.unlink(path); } catch {} + FS.writeFile(path, new Uint8Array(xhr.response), {canOwn:true}); + } else { + console.log("Download error", xhr); + } + } + xhr.open('GET', path); + xhr.send(); + RenPyWeb.xhrs[RenPyWeb.xhr_id] = xhr; + var ret = RenPyWeb.xhr_id; + RenPyWeb.xhr_id++; + return ret; }, dl_get: function(xhr_id) { - return RenPyWeb.xhrs[xhr_id]; + return RenPyWeb.xhrs[xhr_id]; }, dl_free: function(xhr_id) { - delete RenPyWeb.xhrs[xhr_id]; + delete RenPyWeb.xhrs[xhr_id]; // Note: xhr.response kept alive until file is deleted }, } @@ -145,7 +152,7 @@ def download_completed(self): return self.xhr is not None and self.xhr.readyState == 4 @staticmethod - def load_downloaded_resources(): + def process_downloaded_resources(): postponed = [] reloaded = False @@ -153,13 +160,17 @@ def load_downloaded_resources(): # TODO: support images and sounds if hasattr(rr, 'image'): if rr.download_completed(): - if rr.xhr.status == 0: - raise IOError("Download error: " + rr.xhr.statusText) + fullpath = os.path.join(renpy.config.gamedir,rr.image.filename) + if not os.path.exists(fullpath): + # don't rethrow exception in Ren'Py's error handler + ReloadRequest.all.remove(rr) + # show Ren'Py's error handler + raise IOError("Download error: {}: {}".format( + rr.image.filename, (rr.xhr.statusText or "network error"))) #print("reloading", rr.image.filename) ce = renpy.display.im.cache.cache.get(rr.image) renpy.display.im.cache.kill(ce) renpy.display.im.cache.get(rr.image, render=True) - fullpath = os.path.join(renpy.config.gamedir,rr.image.filename) #print("unlink", fullpath) os.unlink(fullpath) reloaded = True