zoneid; # 暂时未想到更好的方案 $err = self::BeforeProc(); # 预处理 my_Assert(ErrCode::ok == $err, $err); # 如果tk校验未通过 $retry = 0; do { $retry++; if ($retry > 1) { new Req(req()->toString()); # 如果是重试,需要重新刷新下req的数据 Resp::$ext_events = array(); # fix:客户端发现event播放2次的情况. } $resp = self::Route(); # 分发逻辑 if ($retry > 12) { # 最大重试次数 Err(ErrCode::err_retry, "数据写入失败, 重试{$retry}次"); break; } } while (!self::AfterProc($resp)); # 执行后处理逻辑 return $resp; } /** * 预处理逻辑 */ private static function BeforeProc() { my_Assert(!config::Inst()->isBaned(req()->uid), ErrCode::err_server_updating); # 检查封号 if (self::isUpdating()) { # 检查是否处于更新阶段,暂停对玩家请求的响应。 if (req()->uid && !config::Inst()->isTester(req()->uid)) { # 排除测试号 return ErrCode::err_server_updating; } } $ssd = GameConfig::service_schedule_getItem(1); # 服务计划(固定只有1条) if (now() > $ssd->startts && now() < $ssd->endts) { # 在维护期间 Err(ErrCode::err_server_maintaining, $ssd->reason); } // if (!Index::$isDebugging && abs(now() - req()->ts) > OFFSET_MSGTIME) { # 如果服务端客户端时间戳超过规定误差,则消息非法 // return ErrCode::err_outtime; // } // todo: 检查clientVersion 判断是否应该强制升级 return self::checkVersion(); # 最后检查下客户端版本 } /** * 后处理逻辑 * @param Resp $resp */ private static function AfterProc(&$resp) { if (req()->userInfoChanged) { # 回写玩家数据 if (!UserProc::setUserInfo(ctx())) { # 失败, 改写返回值 return false; } } $resp->AfterProc(); // self::LogCmd($resp); # 向MySQL记录操作日志 self::LogCmdMongo($resp); # 向MongoDB写入操作日志 CLog::flush(); # flush日志 //UserProc::CollectUserLevelParam(); //UserProc::CollectHeroLevelParam(); return true; } /** * 新版: 使用pdo_mysql+dao版本 * @param Resp $resp */ private static function LogCmd($resp) { $tablename = 'tab_op_log' . date('Ymd'); # 今天的表名 $old_tablename = 'tab_op_log' . date('Ymd', now(-86400 * 21)); # 待删除的表名 日志保留21天 $sql = sprintf('create table if not exists %s like `tpl_op_log_tab`;', $tablename); # 创建今天的表 $sql .= sprintf('drop table if exists %s;', $old_tablename); # 循环删除以前的表 $sql .= sprintf("insert into %s (`uid`,`zoneid`,`cmd`,`days`,`param`,`ret`) values ('%s', %d, %d, %d, '%s', '%s');", # $tablename, req()->uid, req()->zoneid, req()->cmd, # # Uid, zoneid, cmd (null != ctx() ? (totalDays() - totalDays(ctx()->baseInfo->firstLogin)) : 0), # # ps.留存天数 JsonUtil::encode(req()->paras), # # req->paras JsonUtil::encode($resp->result)); # # resp->result daoInst()->exec($sql); # 执行sql } /** * 新版: MongoDB版本 * @param Resp $resp */ private static function LogCmdMongo($resp) { $tablename = 'tab_op_log' . date('Ym'); # 当月的日志表名 $arr = array( 'uid' => req()->uid, 'req' => req()->storage(), 'ret' => $resp, 'ts' => TimeUtil::dtCurrent(), ); gMongo()->insert($tablename, $arr); } /** * 路由方法 */ private static function Route() { $proc = OpeCode::getProc(req()->ope); # 映射处理模块. // DebugHelper::print_stack_trace(); my_Assert($proc != "err", ErrCode::ope_err); # 未能找到对应的处理模块 try { $resp = call_user_func(array($proc, 'procMain'), req()); # 调用对应的处理逻辑 if (!($resp instanceof Resp)) { # 异常返回值 Err(ErrCode::err_innerfault, JsonUtil::encode($resp)); } return $resp; # 返回值 } catch (\Exception $ex) { # 异常信息写入日志 $msg = CommUtil::str2UTF8($ex->getMessage()); # 异常信息转下码 Err(ErrCode::err_unknownn, "call_user_func got Exception: $msg"); # 返回给客户端 } } /** * 返回是否处于更新中 * @return boolean */ private static function isUpdating() { $ts = now(); if ($ts > glc()->updatingBeginTs && $ts < glc()->updatingEndTs) { return true; } return false; } /** * 检查客户端版本是否需要强制更新 * @return int/ErrCode */ private static function checkVersion() { $ret = ErrCode::ok; if (req()->CV == "unityEditor" || req()->CV == "unity") { return $ret; } if (req()->CV == "nil") { return ErrCode::clientversionlow_err; } $limit_Ver = "1.1.8"; # 限制客户端最低版本 $clientArr = CommUtil::split(req()->CV, "."); $serverArr = CommUtil::split($limit_Ver, "."); $client = $clientArr[0] * 1000 * 1000 + $clientArr[1] * 1000 + $clientArr[2]; $server = $serverArr[0] * 1000 * 1000 + $serverArr[1] * 1000 + $serverArr[2]; if ($server > $client) { # 更新游戏状态 if ($clientArr[0] < $serverArr[0] # 主版本号小 || $clientArr[1] < $serverArr[1]) { # 或者次版本号小 $ret = ErrCode::clientversionlow_err; # 返回错误码,强制更新1 req()->updateInfo = "请更新游戏后再继续!"; } else if ($clientArr[2] < $serverArr[2] # 小版本号不一致 && req()->cmd == CmdCode::cmd_user_getzonelist) { # 只有在请求分区列表的时候提示下, 其他消息不强制更新 req()->updateInfo = "游戏有更新!"; # 提示更新,可以咱不更新 $ret = ErrCode::clientversionlow_err; # 返回错误码,强制更新1 } } return $ret; } }