spawn.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. local skynet = require "skynet"
  2. local util = require "util"
  3. local logger = require "logger"
  4. local packstring = skynet.packstring
  5. local unpack = skynet.unpack
  6. local intmax = math.maxinteger
  7. local clamp = util.clamp
  8. local table_insert = table.insert
  9. local traceback = debug.traceback
  10. local spawn = function(readonly)
  11. -- 首先,定义角色默认的数据结构
  12. local datasource = {
  13. -- TODO: 在下面定义 Number 和 String 类型的字段
  14. uid = nil, -- 角色ID
  15. sid = nil, -- 服务器ID
  16. account = nil, -- 帐号唯一标识(渠道分配)
  17. appid = nil, -- App唯一标识
  18. channel = nil, -- 渠道唯一标识
  19. platform = nil, -- 操作系统(pc,ios,android等)
  20. tourist = nil, -- 游客标识:1:非游客账号 2: 游客账号 -- CDPK3-005 海外SDK
  21. reported = nil, -- 玩家角色数据上报 --PK3-1366 数据统计
  22. createtime = nil, -- 创号时间
  23. lastlogin = nil, -- 最后登录时间
  24. lastlogout = nil, -- 最后下线时间
  25. forbidden = 0, -- 封号标志0是正常,非0解封号时间
  26. silent = 0, -- 禁言标志0是正常,非0解禁言时间
  27. fb = nil, -- 玩家绑定faceboik帐号使用的云帐号
  28. facebook = nil, -- 玩家绑定facebook账号
  29. google = nil, -- 玩家绑定google账号
  30. ios = nil, -- 玩家绑定ios账号
  31. nickname = nil, -- 角色名
  32. rename_time = 0, -- 改变名字的时间
  33. level = 1, -- 队伍等级
  34. exp = 0, -- 队伍经验
  35. avater = 0, -- avater
  36. vip = 0, -- vip等级
  37. updiamond = 0, -- vip经验
  38. money = 0, -- 充值金额
  39. daily_refresh = 0, -- 每日刷新时间
  40. weekly_refresh = 0, -- 每周刷新时间
  41. ban_rank = 0, -- 禁用排行
  42. power = 0, -- 战斗力
  43. -- TODO: 在下面定义二进制类型的字段 (BLOB)
  44. role = nil, -- 角色数据
  45. currency = nil, -- 货币
  46. adventure = nil, -- 冒险
  47. building = nil, -- 建筑
  48. mail = nil, -- 邮件
  49. hero = nil, -- 英雄
  50. embattle = nil, -- 阵容
  51. debris = nil, -- 碎片
  52. skill_card = nil, -- 技能卡牌
  53. equip = nil, -- 装备
  54. talent = nil, -- 天赋
  55. sign_in = nil, -- 签到
  56. stats = nil, -- 任务数据统计
  57. quest = nil, -- 任务
  58. manual = nil, -- 战令
  59. draw = nil, -- 抽奖
  60. grocery = nil, -- 杂货店
  61. time_box = nil, -- 宝箱
  62. activitytimemod = nil, -- 活动时间
  63. }
  64. -- 定义角色数据的只读元表
  65. local mt = {
  66. __index = datasource,
  67. __newindex = function(t, k, v) assert(false, "attempt to update a read-only table") end
  68. }
  69. -- 定义 setter 的基础函数
  70. local tracker = {}
  71. local function setter(k, v)
  72. tracker[k] = v
  73. datasource[k] = v
  74. end
  75. local function n_setter(k, v, low, up)
  76. v = clamp(v, low, up or intmax)
  77. tracker[k] = v
  78. datasource[k] = v
  79. end
  80. -- TODO: 在下面定义字段的 setter
  81. local self = { readonly=readonly }
  82. function self.set_exp(value, up) n_setter('exp', value, 0, up) end
  83. function self.set_avater(value, up) n_setter('avater', value, 0, up) end
  84. function self.set_forbidden(value, up) n_setter('forbidden', value, 0, up) end
  85. function self.set_silent(value, up) n_setter('silent', value, 0, up) end
  86. function self.set_lastlogin(value, up) n_setter('lastlogin', value, 0, up) end
  87. function self.set_lastlogout(value, up) n_setter('lastlogout', value, 0, up) end
  88. function self.set_level(value, up) n_setter('level', value, 1, up) end
  89. function self.set_rename_time(value, up) n_setter('rename_time', value, 1, up) end
  90. function self.set_nickname(value) setter('nickname', value) end
  91. function self.set_vip(value, up) n_setter('vip', value, 0, up) end
  92. function self.set_updiamond(value, up) n_setter('updiamond', value, 0, up) end--累计充值钻石
  93. function self.set_money(value, up) n_setter('money', value, 0, up) end--累计充值的金额
  94. function self.set_daily_refresh(value, up) n_setter('daily_refresh', value, 0, up) end
  95. function self.set_weekly_refresh(value, up) n_setter('weekly_refresh', value, 0, up) end
  96. function self.set_ban_rank(value, up) n_setter('ban_rank', value, 0, up) end
  97. function self.set_power(value, up) n_setter('power', value, 0, up) end
  98. function self.set_currency(value) setter('currency', value) end
  99. function self.set_role(value) setter('role', value) end
  100. function self.set_adventure(value) setter('adventure', value) end
  101. function self.set_building(value) setter('building', value) end
  102. function self.set_mail(value) setter('mail', value) end
  103. function self.set_hero(value) setter('hero', value) end
  104. function self.set_embattle(value) setter('embattle', value) end
  105. function self.set_debris(value) setter('debris', value) end
  106. function self.set_skill_card(value) setter('skill_card', value) end
  107. function self.set_equip(value) setter('equip', value) end
  108. function self.set_talent(value) setter('talent', value) end
  109. function self.set_sign_in(value) setter('sign_in', value) end
  110. function self.set_stats(value) setter('stats', value) end
  111. function self.set_quest(value) setter('quest', value) end
  112. function self.set_manual(value) setter('manual', value) end
  113. function self.set_draw(value) setter('draw', value) end
  114. function self.set_grocery(value) setter('grocery', value) end
  115. function self.set_time_box(value) setter('time_box', value) end
  116. --------------------------------- setter end ---------------------------------
  117. local function loadfrom(metadata)
  118. assert(metadata)
  119. local dest = datasource
  120. for i=1, #metadata, 2 do
  121. local k = metadata[i]
  122. local v = metadata[i+1]
  123. if k == "nickname" then
  124. dest[k] = v
  125. else
  126. dest[k] = tonumber(v) or v
  127. end
  128. end
  129. dest.uid = tostring(dest.uid)
  130. return self
  131. end
  132. local function pack(k)
  133. if next(tracker) then
  134. local pkg = { k }
  135. for field, value in pairs(tracker) do
  136. table_insert(pkg, field)
  137. table_insert(pkg, value)
  138. end
  139. tracker = {} -- Must do it
  140. return pkg
  141. end
  142. end
  143. local function packall(k)
  144. tracker = datasource
  145. return pack(k)
  146. end
  147. -- TODO: 备份抛弃的数据
  148. local backups_discard = {
  149. presence = 'presence',
  150. }
  151. local function backups_all()
  152. local ret = {}
  153. for k, v in pairs(datasource) do
  154. if not backups_discard[k] then
  155. if type(v) == 'number'
  156. or k == 'uid'
  157. or k == 'channel'
  158. or k == 'nickname'
  159. or k == 'account'
  160. or k == 'appid'
  161. or k == 'platform'
  162. then
  163. ret[k] = v
  164. else
  165. ret[k] = unpack(v)
  166. end
  167. end
  168. end
  169. return ret
  170. end
  171. local listener = {}
  172. local function dispatch(signame, ...)
  173. local sigslot = listener[signame] or {}
  174. for i, v in ipairs(sigslot) do
  175. local ok,info = xpcall(v, traceback, self, ...)
  176. if not ok then
  177. logger.trace("dispatch errno %s, errno info %s", signame, info)
  178. end
  179. end
  180. end
  181. local function monitor(signame, f)
  182. listener[signame] = listener[signame] or {}
  183. table_insert(listener[signame], f)
  184. end
  185. local specific = {}
  186. local function getspecific(k) return specific[k] end
  187. local function register_specific(k, alloc)
  188. assert(not specific[k], k)
  189. local d = nil
  190. local v = datasource[k]
  191. if v then
  192. d = unpack(v)
  193. elseif alloc then
  194. d = alloc()
  195. end
  196. local f = rawget(self, 'set_'..k)
  197. local function get() return d end
  198. local function save()
  199. assert(f, string.format("attempt to call a nil value(field 'set_%s')", k))
  200. f(packstring(d))
  201. end
  202. specific[k] = { get=get, save=save, runtime={} }
  203. return d
  204. end
  205. -- Ok, let's go on
  206. self.loadfrom = loadfrom
  207. self.pack = pack
  208. self.packall = packall
  209. self.dispatch = dispatch
  210. self.monitor = monitor
  211. self.getspecific = getspecific
  212. self.register_specific = register_specific
  213. self.backups_all = backups_all
  214. self.__index = self
  215. return setmetatable(self, mt)
  216. end
  217. return spawn