AppServer.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php
  2. namespace loyalsoft;
  3. include_once __DIR__ . '/../main.php'; # 导入主要工具库
  4. /**
  5. * API入口
  6. * @author gwang (mail@wanggangzero.cn)
  7. */
  8. class AppServer {
  9. /**
  10. * The Main Entrance of App
  11. * @return Resp
  12. */
  13. public function api() {
  14. $uniq = uniqid(); # 自己生成一个唯一串,作为此次处理过程的标记。
  15. $GLOBALS['deal-uid'] = $uniq; # 写入日志的时候带上,方便辨认同一个处理过程.
  16. $GLOBALS['zoneid'] = req()->zoneid; # 暂时未想到更好的方案
  17. $err = self::BeforeProc(); # 预处理
  18. my_Assert(ErrCode::ok == $err, $err); # 如果tk校验未通过
  19. $retry = 0;
  20. do {
  21. $retry++;
  22. if ($retry > 1) {
  23. new Req(req()->toString()); # 如果是重试,需要重新刷新下req的数据
  24. Resp::$ext_events = array(); # fix:客户端发现event播放2次的情况.
  25. }
  26. $resp = self::Route(); # 分发逻辑
  27. if ($retry > 12) { # 最大重试次数
  28. Err(ErrCode::err_retry, "数据写入失败, 重试{$retry}次");
  29. break;
  30. }
  31. } while (!self::AfterProc($resp)); # 执行后处理逻辑
  32. return $resp;
  33. }
  34. /**
  35. * 预处理逻辑
  36. */
  37. private static function BeforeProc() {
  38. my_Assert(!config::Inst()->isBaned(req()->uid), ErrCode::err_server_updating); # 检查封号
  39. if (self::isUpdating()) { # 检查是否处于更新阶段,暂停对玩家请求的响应。
  40. if (req()->uid && !config::Inst()->isTester(req()->uid)) { # 排除测试号
  41. return ErrCode::err_server_updating;
  42. }
  43. }
  44. $ssd = GameConfig::service_schedule_getItem(1); # 服务计划(固定只有1条)
  45. if (now() > $ssd->startts && now() < $ssd->endts) { # 在维护期间
  46. Err(ErrCode::err_server_maintaining, $ssd->reason);
  47. }
  48. // if (!Index::$isDebugging && abs(now() - req()->ts) > OFFSET_MSGTIME) { # 如果服务端客户端时间戳超过规定误差,则消息非法
  49. // return ErrCode::err_outtime;
  50. // }
  51. // todo: 检查clientVersion 判断是否应该强制升级
  52. return self::checkVersion(); # 最后检查下客户端版本
  53. }
  54. /**
  55. * 后处理逻辑
  56. * @param Resp $resp
  57. */
  58. static function AfterProc(&$resp) {
  59. if (req()->cmd != CmdCode::cmd_user_delUserUid) {
  60. if (req()->userInfoChanged || (null != ctx() && ctx()->NeedSave())) { # 回写玩家数据
  61. if (!UserProc::setUserInfo(ctx())) { # 失败, 改写返回值
  62. return false;
  63. }
  64. }
  65. }
  66. if (null != $resp) { # resp后处理
  67. $resp->AfterProc();
  68. }
  69. self::LogCmdMongo($resp); # 向MongoDB写入操作日志
  70. // CLog::flush(); # flush日志
  71. return true;
  72. }
  73. /**
  74. * 新版: 使用pdo_mysql+dao版本
  75. * @param Resp $resp
  76. */
  77. private static function LogCmd($resp) {
  78. $tablename = 'tab_op_log' . date('Ymd'); # 今天的表名
  79. $old_tablename = 'tab_op_log' . date('Ymd', now(-86400 * 21)); # 待删除的表名 日志保留21天
  80. $sql = sprintf('create table if not exists %s like `tpl_op_log_tab`;', $tablename); # 创建今天的表
  81. $sql .= sprintf('drop table if exists %s;', $old_tablename); # 循环删除以前的表
  82. $sql .= sprintf("insert into %s (`uid`,`zoneid`,`cmd`,`days`,`param`,`ret`) values ('%s', %d, %d, %d, '%s', '%s');", #
  83. $tablename, req()->uid, req()->zoneid, req()->cmd, # # Uid, zoneid, cmd
  84. (null != ctx() ? (totalDays() - totalDays(ctx()->baseInfo->firstLogin)) : 0), # # ps.留存天数
  85. JsonUtil::encode(req()->paras), # # req->paras
  86. JsonUtil::encode($resp->result)); # # resp->result
  87. daoInst()->exec($sql); # 执行sql
  88. }
  89. /**
  90. * 新版: MongoDB版本
  91. * @param Resp $resp
  92. */
  93. private static function LogCmdMongo($resp) {
  94. $tablename = 'tab_op_log' . date('Ym'); # 当月的日志表名
  95. $arr = array(
  96. 'uid' => req()->uid,
  97. 'req' => req()->storage(),
  98. 'ret' => $resp,
  99. 'ts' => TimeUtil::dtCurrent(),
  100. );
  101. gMongo()->insert($tablename, $arr);
  102. }
  103. /**
  104. * 路由方法
  105. */
  106. private static function Route() {
  107. $opc = substr(req()->cmd, 0, 2);
  108. $proc = OpeCode::getProc($opc); # 映射处理模块.
  109. // DebugHelper::print_stack_trace();
  110. my_Assert($proc != "err", ErrCode::ope_err); # 未能找到对应的处理模块
  111. try {
  112. $resp = call_user_func(array($proc, 'procMain'), req()); # 调用对应的处理逻辑
  113. if (!($resp instanceof Resp)) { # 异常返回值
  114. Err(ErrCode::err_innerfault, JsonUtil::encode($resp));
  115. }
  116. return $resp; # 返回值
  117. } catch (\Exception $ex) { # 异常信息写入日志
  118. $msg = CommUtil::str2UTF8($ex->getMessage()); # 异常信息转下码
  119. Err(ErrCode::err_unknownn, "call_user_func got Exception: $msg"); # 返回给客户端
  120. }
  121. }
  122. /**
  123. * 返回是否处于更新中
  124. * @return boolean
  125. */
  126. private static function isUpdating() {
  127. $ts = now();
  128. if ($ts > glc()->updatingBeginTs && $ts < glc()->updatingEndTs) {
  129. return true;
  130. }
  131. return false;
  132. }
  133. /**
  134. * 检查客户端版本是否需要强制更新
  135. * @return int/ErrCode
  136. */
  137. private static function checkVersion() {
  138. $ret = ErrCode::ok;
  139. if (req()->CV == "unityEditor" || req()->CV == "unity") {
  140. return $ret;
  141. }
  142. if (req()->CV == "nil") {
  143. return ErrCode::clientversionlow_err;
  144. }
  145. $limit_Ver = "1.0.3"; # 限制客户端最低版本
  146. $clientArr = CommUtil::split(req()->CV, ".");
  147. $serverArr = CommUtil::split($limit_Ver, ".");
  148. $client = $clientArr[0] * 1000 * 1000 + $clientArr[1] * 1000 + $clientArr[2];
  149. $server = $serverArr[0] * 1000 * 1000 + $serverArr[1] * 1000 + $serverArr[2];
  150. if ($server > $client) { # 更新游戏状态
  151. if ($clientArr[0] < $serverArr[0] # 主版本号小
  152. || $clientArr[1] < $serverArr[1]) { # 或者次版本号小
  153. $ret = ErrCode::clientversionlow_err; # 返回错误码,强制更新1
  154. req()->updateInfo = "请更新游戏后再继续!";
  155. } else if ($clientArr[2] < $serverArr[2] # 小版本号不一致
  156. && req()->cmd == CmdCode::cmd_user_getzonelist) { # 只有在请求分区列表的时候提示下, 其他消息不强制更新
  157. req()->updateInfo = "游戏有更新!"; # 提示更新,可以咱不更新
  158. $ret = ErrCode::clientversionlow_err; # 返回错误码,强制更新1
  159. }
  160. }
  161. return $ret;
  162. }
  163. }