diff --git a/extensions/localSave.js b/extensions/localSave.js new file mode 100644 index 00000000..455b36ce --- /dev/null +++ b/extensions/localSave.js @@ -0,0 +1,76 @@ +/** + * 离线游戏使用本地存储扩展。 + * 开启本拓展后,将会把所有存档存至 _saves 目录下。 + * 需配合样板V2.8.2+使用 + */ + +"use strict"; + +(function () { + // 将这一行改成 false 可以禁用本拓展 + var __enabled = true; + + if (window.jsinterface || !window.fs || !__enabled) return; + + function rewrite() { + core.utils._setLocalForage_set = function (name, str, callback) { + var data = LZString.compressToBase64(str); + core.saves.cache[name] = data; + fs.writeFile('_saves/' + name, data, 'utf-8', callback); + } + + core.utils._getLocalForage_get = function (name, callback) { + fs.readFile('_saves/' + name, 'utf-8', function (err, data) { + if (err) return callback(err); + callback(null, data); + }); + } + + core.utils.decompress = function (data) { + try { + return JSON.parse(LZString.decompressFromBase64(data)) + } catch (e) { + return null; + } + } + + core.utils._removeLocalForage_remove = function (name, callback) { + fs.deleteFile('_saves/' + name, callback); + } + + core.utils.clearLocalForage = function (name, callback) { + // Nothing to do + } + + core.utils.iterateLocalForage = function (iter, callback) { + fs.readdir('_saves', function (err, data) { + if (err) callback(err); + else { + data.forEach(function (one) { + iter(null, one, null); + }); + callback(); + } + }); + } + + core.utils.keysLocalForage = function (callback) { + fs.readdir('_saves', callback); + } + + core.utils.lengthLocalForage = function (callback) { + fs.readdir('_saves', function (err, data) { + if (err) callback(err); + else callback(null, data.length); + }); + } + } + + fs.mkdir('_saves', function (err) { + if (err) return; + rewrite(); + core.control.getSaveIndexes(function (indexes) { core.saves.ids = indexes; }); + }); +})(); + + diff --git a/libs/core.js b/libs/core.js index 5be2e626..8cb19316 100644 --- a/libs/core.js +++ b/libs/core.js @@ -125,7 +125,8 @@ function core() { "now": 0, }, "favorite": [], - "favoriteName": {} + "favoriteName": {}, + "cache": {} } this.initStatus = { 'played': false, diff --git a/libs/utils.js b/libs/utils.js index 1601ca05..5814ee78 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -214,18 +214,7 @@ utils.prototype.setLocalStorage = function (key, value) { var str = JSON.stringify(value).replace(/[\u007F-\uFFFF]/g, function (chr) { return "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).substr(-4) }); - var compressed = lzw_encode(str); - - // test if we can save to localStorage - localStorage.setItem("__tmp__", compressed); - if (lzw_decode(localStorage.getItem("__tmp__")) == str) { - localStorage.setItem(core.firstData.name + "_" + key, compressed); - } - else { - // We cannot compress the data - localStorage.setItem(core.firstData.name + "_" + key, str); - } - localStorage.removeItem("__tmp__"); + localStorage.setItem(core.firstData.name + "_" + key, str); if (key == 'autoSave') core.saves.ids[0] = true; else if (/^save\d+$/.test(key)) core.saves.ids[parseInt(key.substring(4))] = true; @@ -240,8 +229,11 @@ utils.prototype.setLocalStorage = function (key, value) { ////// 获得本地存储 ////// utils.prototype.getLocalStorage = function (key, defaultValue) { - var res = this.decompress(localStorage.getItem(core.firstData.name + "_" + key)); - return res == null ? defaultValue : res; + try { + return JSON.parse(localStorage.getItem(core.firstData.name + "_" + key)); + } catch (e) { + return defaultValue; + } } ////// 移除本地存储 ////// @@ -271,13 +263,18 @@ utils.prototype.setLocalForage = function (key, value, successCallback, errorCal if (successCallback) successCallback(); } } + this._setLocalForage_set(name, str, callback); +} +utils.prototype._setLocalForage_set = function (name, str, callback) { if (window.jsinterface && window.jsinterface.setLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; + core.saves.cache[name] = str; window.jsinterface.setLocalForage(id, name, str); } else { var compressed = str.length > 100000 ? LZString.compress(str) : lzw_encode(str); + core.saves.cache[name] = compressed; localforage.setItem(name, compressed, callback); } } @@ -289,6 +286,7 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e if (errorCallback) errorCallback(err); } else { + core.saves.cache[name] = value; if (!successCallback) return; if (value != null) { var res = core.utils.decompress(value); @@ -298,7 +296,13 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e successCallback(defaultValue); } }; + if (core.saves.cache[name] != null) { + return callback(null, core.saves.cache[name]); + } + this._getLocalForage_get(name, callback); +} +utils.prototype._getLocalForage_get = function (name, callback) { if (window.jsinterface && window.jsinterface.getLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; @@ -320,7 +324,11 @@ utils.prototype.removeLocalForage = function (key, successCallback, errorCallbac if (successCallback) successCallback(); } } + delete core.saves.cache[name]; + this._removeLocalForage_remove(name, callback); +} +utils.prototype._removeLocalForage_remove = function (name, callback) { if (window.jsinterface && window.jsinterface.removeLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; @@ -331,6 +339,7 @@ utils.prototype.removeLocalForage = function (key, successCallback, errorCallbac } utils.prototype.clearLocalForage = function (callback) { + core.saves.cache = {}; if (window.jsinterface && window.jsinterface.clearLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; diff --git a/server.py b/server.py index cad5e4a1..0e7d5900 100644 --- a/server.py +++ b/server.py @@ -47,11 +47,12 @@ def get_mimetype(path): def get_file(path): if not os.path.isfile(path): + if path.startswith('_saves/'): + return '' abort(404) return None if not is_sub(path): abort(403) - return None with open(path, 'rb') as f: content = f.read() # str in py2 and bytes in py3 return content @@ -82,6 +83,10 @@ def all_animates(): else: content.append('') return '@@@~~~###~~~@@@'.join(content) +@app.route('/favicon.ico', methods=['GET']) +def favicon(): + return '' + @app.route('/', methods=['GET']) def static_file(path): if os.path.isdir(path): @@ -206,6 +211,10 @@ def deleteFile(): shutil.rmtree(name) return 'Success' +@app.route('/games/upload.php', methods=['POST']) +def upload(): + return '' + def port_used(port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) result = True