GameStateDB.lua
quick-cocos2d-x3.3版本中,framework/cc/utils/GameState.lua已经提供了GameStateDB.lua中的方法
--本地存储的加密文件 local m = class( "GameStateDB" ) m.ERROR_INVALID_FILE_CONTENTS = -1 m.ERROR_HASH_MISS_MATCH = -2 m.ERROR_STATE_FILE_NOT_FOUND = -3 local crypto = require(cc.PACKAGE_NAME .. ".crypto") local json = require(cc.PACKAGE_NAME .. ".json") function m:ctor() self.encodeSign = "=GS=" self._fileName = "GameStateDB.txt" self._cbHandle = nil self.secretKey = nil end function m:init(_cbHandle,fileName,secretKey_) if type(_cbHandle) ~= "function" then print("m:init() - invalid self._cbHandle") return false end self._cbHandle = _cbHandle if type(fileName) == "string" then self._fileName = fileName end if type(secretKey_) == "string" then self.secretKey = secretKey_ end self._cbHandle({ eventName = "init",filename = self:getGameStateDBPath(),isEncrypt = type(self.secretKey) == "string" }) return true end --返回保存是否成功结果及保存存档字符串 function m:save(newValues) local function encode_(values) local strValues = json.encode(values) local md5 = crypto.md5(strValues..self.secretKey) --md5码,用于校验数据的完整性,安全性 local contents = json.encode({md5 = md5,strValues = strValues}) return crypto.encodeBase64(self.encodeSign..contents) --数据加密 end local values = self._cbHandle({ eventName = "save",values = newValues,isEncrypt = type(self.secretKey) == "string" }) if type(values) ~= "table" then print("m:save() - listener return invalid data") return false end local filename = self:getGameStateDBPath() local ret = false local saveStr = "" if self.secretKey then saveStr = encode_(values) ret = io.writefile(filename,saveStr) else saveStr = json.encode(values) if type(saveStr) == "string" then ret = io.writefile(filename,saveStr) end end printf("m:save() - update file \"%s\"",filename) return ret,saveStr end function m:load(_strData) local function isEncodedContents_(contents) return string.sub(contents,1,string.len(self.encodeSign)) == self.encodeSign end local function decode_(fileContents) local contents = string.sub(fileContents,string.len(self.encodeSign) + 1) local j = json.decode(contents) if type(j) ~= "table" then print("m:decode_() - invalid contents") return {errorCode = m.ERROR_INVALID_FILE_CONTENTS} end local hash,strValues = j.md5,j.strValues local testHash = crypto.md5(strValues..self.secretKey) if testHash ~= hash then print("m:decode_() - hash miss match") return {errorCode = m.ERROR_HASH_MISS_MATCH} end local values = json.decode(strValues) if type(values) ~= "table" then print("m:decode_() - invalid state data") return {errorCode = m.ERROR_INVALID_FILE_CONTENTS} end return {values = values} end local contents = nil if _strData == nil then local filename = self:getGameStateDBPath() if not io.exists(filename) then printf("m:load() - file \"%s\" not found",filename) return self._cbHandle({eventName = "load",errorCode = m.ERROR_STATE_FILE_NOT_FOUND}) end contents = io.readfile(filename) printf("m:load() - get values from \"%s\"",filename) else printf("m:load() with function!!!") contents = _strData end --解密 contents = crypto.decodeBase64(contents) local values local isEncrypt = false if self.secretKey and isEncodedContents_(contents) then local d = decode_(contents) if d.errorCode then return self._cbHandle({eventName = "load",errorCode = d.errorCode}) end values = d.values isEncrypt = true else values = json.decode(contents) if type(values) ~= "table" then print("m:load() - invalid data") return self._cbHandle({eventName = "load",errorCode = m.ERROR_INVALID_FILE_CONTENTS}) end end return self._cbHandle({ eventName = "load",values = values,isEncrypt = isEncrypt,time = os.time() }) end function m:getGameStateDBPath() return string.gsub(device.writablePath,"[\\\\/]+$","") .. "/" .. self._fileName end return mLocalDBMgr.lua
--[[ LocalDBMgr.lua 存储本地数据 数据编码格式: local data = { a=1,b=2,c=3} local secretKey = "123" 1.先将data转换成json串s,然后s 和 secretKey 连接成字符串 c 2.再将c计算md5得到值hash 3.再次以格式 { h = hash,s = s } 编码json 形成 contents 4.将contents进行base64加密 ]] local LocalDBMgr = class( "LocalDBMgr" ) local GameStateDB = require("app.core.GameStateDB").new() --换成GameStateDB的真实路径 --数据文件秘钥(不变化) local DATA_SER_KEY = "2k7x2023r49mvpus2t616e13c7965b1" --构造函数 function LocalDBMgr:ctor() self:init() local function GameStateCallBackHandle(params) return params end GameStateDB:init( GameStateCallBackHandle,"LocalDBMgr",DATA_SER_KEY ) local path = GameStateDB:getGameStateDBPath() if not io.exists( path ) then print("[[ 创建LocalDBMgr ]]") GameStateDB:save( self.db ) else self:load() end end --初始化config表 function LocalDBMgr:init() self.db = { clientVersion = "1.0.0",-- 客户端版本号 accessToken = "",--微信token openID = "",--openid bgState = 1,--背景音乐是否打开 bgValume = 100,--背景音乐大小 soundState = 1,--音效是否打开 soundValume = 100,--音效大小 actImgList = {},--活动图片列表 } end --数据存储 function LocalDBMgr:save(_key,_value) if not _key or not _value then assert( nil,"LocalDBMgr save key or value is nil! ") return end self.db[ _key .. '' ] = _value print( "LocalDBMgr save:",_key,_value ) GameStateDB:save( self.db ) end --数据读取 function LocalDBMgr:read(_key) if not _key then assert( nil,"LocalDBMgr read key is nil!" ) return end return self.db[ _key .. '' ] end --数据加载 function LocalDBMgr:load() self:init()--只维护self.db中的数据 local data = GameStateDB:load().values.values for k,v in pairs(self.db) do if data[k] then self.db[k] = data[k] --本地数据重置到缓存数据, end end GameStateDB:save( self.db ) end return LocalDBMgr