battle.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. local skynet = require "skynet"
  2. local battleCore = require "battle.battleCore"
  3. local battleLog = require "battle.battleLog"
  4. local battleCode = require "battle.battleCode"
  5. local battleDefine = require "battle.battleDefine"
  6. local nodeMgr = require "nodeMgr"
  7. local httpc = require "http.httpc"
  8. local md5 = require "md5"
  9. local machine = require "machine"
  10. local code = require "code"
  11. local util_user = require "utils.util_user"
  12. local gameConst = require("const.gameConst")
  13. local battleAdapt = require "adapt.battleAdapt"
  14. local sessionData = require("data.session")
  15. local battleData = require("data.battle")
  16. local nodename = skynet.getenv("nodeName")
  17. local root = class("Battle")
  18. function root:ctor(matchInfo, battleParams, settleNodeInfo)
  19. self.matchNodeInfo = {}
  20. self.matchNodeInfo.nodeName = matchInfo.matchNode
  21. self.matchNodeInfo.agent = matchInfo.matchAgent
  22. self.roomId = matchInfo.roomId
  23. self.matchId = matchInfo.matchId
  24. self.battleId = matchInfo.battleId
  25. self.isMatchSettle = matchInfo.isMatchSettle -- 结算经过业务服
  26. self.settleNodeInfo = settleNodeInfo -- 结算节点
  27. self.battleParams = battleParams
  28. local w = battleParams.w
  29. local h = battleParams.h
  30. local debugJsonObj = battleParams.debugJsonObj
  31. self.core = battleCore.new(self, matchInfo.battleReal, matchInfo.battleType, w, h, debugJsonObj)
  32. self.record = {}
  33. self.isActive = true
  34. end
  35. -- 获取战斗标示
  36. function root:get_core_id()
  37. return string.format("%s:%s:%s", self.matchNodeInfo.nodeName, self.matchId, self.battleId)
  38. end
  39. function root:enableRecord()
  40. return true
  41. end
  42. function root:addRecord(protoName, msg)
  43. if self:enableRecord() then
  44. table.insert(self.record, {proto = protoName, data = msg})
  45. end
  46. end
  47. local protos = {
  48. "on_battle_qipan_info",
  49. "on_battle_operate_info",
  50. "on_battle_start",
  51. "on_battle_finish",
  52. "on_battle_attack",
  53. "on_battle_attack_finish",
  54. "on_battle_create_info"
  55. }
  56. function root:notifyPlayer(uid, protoName, msg)
  57. if uid == nil or is_robot(uid) or is_empty(protoName) then
  58. return
  59. end
  60. local uidList = self.core:get_real_uid_list()
  61. if uidList[1] == uid and table.include(protos, protoName) then
  62. self:addRecord(protoName, msg)
  63. end
  64. util_user:user_proto_notify(uid, protoName, msg)
  65. end
  66. -- game节点结算
  67. function root:game_player_settle(uid, msg)
  68. -- 机器人
  69. if uid == nil or is_robot(uid) then
  70. return
  71. end
  72. -- 玩家不在线
  73. local nodeInfo = util_user:user_get_cluster_info(uid, "game")
  74. if not nodeMgr.is_node_info_valid(nodeInfo) then
  75. nodeMgr.send("game1_1", ".settleSrv", "offline_settle", uid, msg)
  76. return
  77. end
  78. util_user:user_send_game_agent(uid, "battle.settleBattle", msg)
  79. end
  80. function root:notifyClientLog(uid, logStr)
  81. if uid == nil or is_robot(uid) or is_empty(logStr) then
  82. return
  83. end
  84. battleLog:logClient(logStr)
  85. -- TODO: Debug 测试代码,上线前修改过来.
  86. util_user:user_notify_client_log(uid, logStr)
  87. end
  88. function root:recordOpenLog(...)
  89. local logUtil = require "utils.serverLogUtil"
  90. logUtil.logOpen(...)
  91. end
  92. function root:logEvent(...)
  93. util_user:log_event(...)
  94. end
  95. function root:getBattleNode()
  96. return nodename
  97. end
  98. function root:getBattleId()
  99. return self.battleId
  100. end
  101. function root:getBattleParams()
  102. return self.battleParams
  103. end
  104. local GAME_SALT_MD5 = "0bdb9a5863c8c9063a42f38a9d5166fe" -- 游戏服加盐 md5
  105. local function sendRecord(battleNode, battleStartTime, battleId, version, record)
  106. local server = machine.get("record_server")
  107. if is_nil(server) then
  108. return
  109. end
  110. local url = "/record/add?sign="
  111. local head = {["Content-Type"] = "application/json"}
  112. local body =
  113. cjson_encode(
  114. {
  115. node = tostring(battleNode),
  116. startTime = tonumber(battleStartTime),
  117. id = tonumber(battleId),
  118. version = tostring(version),
  119. record = cjson_encode(record)
  120. }
  121. )
  122. url = url .. md5.sumhexa(body .. GAME_SALT_MD5)
  123. local ok, errCode, response = pcall(httpc.request, "POST", server, url, nil, head, body)
  124. if not ok then
  125. battleLog:logError(
  126. string.format(
  127. "添加录像失败 battleNode=%s battleStartTime=%s battleId=%s version=%s",
  128. battleNode,
  129. battleStartTime,
  130. battleId,
  131. version
  132. )
  133. )
  134. end
  135. if errCode ~= 200 then
  136. battleLog:logError(
  137. string.format(
  138. "添加录像失败 battleNode=%s battleStartTime=%s battleId=%s version=%s response=%s",
  139. battleNode,
  140. battleStartTime,
  141. battleId,
  142. version,
  143. tostring(response and cjson_decode(response))
  144. )
  145. )
  146. end
  147. end
  148. -- 开始战斗
  149. function root:startBattle(playerList, viewerList)
  150. local battleInfo = {
  151. matchId = self.matchId,
  152. battleId = self.battleId,
  153. nodeName = nodename,
  154. agent = skynet.self()
  155. }
  156. for _, v in ipairs(playerList) do
  157. if not is_robot(v.uid) then
  158. sessionData:user_update_cluster_info(v.uid, "battle", battleInfo)
  159. end
  160. end
  161. self.core:startBattle(playerList, viewerList)
  162. end
  163. -- 结算
  164. function root:settleBattle(result)
  165. -- 测试战斗类型
  166. if battleAdapt:isAiTestBattle(self.core.battleType) then
  167. log.warning(
  168. "settleBattle battleId[%s] settleNodeInfo[%s]",
  169. tostring(self.battleId),
  170. tostring(self.settleNodeInfo)
  171. )
  172. if nodeMgr.is_node_info_valid(self.settleNodeInfo) then
  173. nodeMgr.send_with_node_info(self.settleNodeInfo, "settle", result)
  174. else
  175. nodeMgr.send("test", ".aiSrv", "settle", result)
  176. end
  177. return
  178. end
  179. -- 组队
  180. -- 业务服结算
  181. if self.isMatchSettle then
  182. nodeMgr.send_with_node_info(self.matchNodeInfo, "match_settle", self.roomId, result)
  183. return
  184. end
  185. for _, v in ipairs(self.core:getAllPlayer()) do
  186. self:game_player_settle(v.uid, result)
  187. end
  188. end
  189. -- 消耗战斗
  190. function root:dismissBattle(reason)
  191. self.isActive = false
  192. battleLog:logWarning(string.format("开始销毁对战服务并退出 battleId=%s reason=%s", self.battleId, reason))
  193. nodeMgr.send_with_node_info(self.matchNodeInfo, "destory_battle", self.roomId)
  194. local uidList = self.core:get_real_uid_list()
  195. for _, v in ipairs(uidList) do
  196. -- 清除玩家战斗节点信息
  197. battleData:user_clear_battle_info(v)
  198. self:notifyPlayer(v, "on_battle_finish", {code = battleCode.OK})
  199. end
  200. if self:enableRecord() then
  201. sendRecord(self:getBattleNode(), self.core.battleStartTime, self:getBattleId(), 1.0, self.record)
  202. end
  203. skynet.call(".BattleMgr", "lua", "battleLeave", self.battleId, skynet.self())
  204. end
  205. function root:loginBattle(uid)
  206. battleLog:logInfo(string.format("玩家%d登入对战", uid))
  207. local playerData = self.core:getPlayer(uid)
  208. if not playerData then
  209. -- 围观进入
  210. self.core:viewerLoginBattle(uid)
  211. return
  212. end
  213. self.core:loginBattle(playerData)
  214. -- self:playFinish(uid, self.core:getCurRound())
  215. end
  216. function root:logoutBattle(uid)
  217. battleLog:logInfo(string.format("玩家%d登出对战", uid))
  218. local playerData = self.core:getPlayer(uid)
  219. if not playerData then
  220. return
  221. end
  222. self.core:logoutBattle(playerData)
  223. -- self.core:dismissBattle("force")
  224. end
  225. -- 玩家是否在战斗中
  226. function root:is_user_in_battle(uid)
  227. local playerData = self.core:getPlayer(uid)
  228. if playerData then
  229. return true
  230. end
  231. return false
  232. end
  233. function root:operate(uid, ids, exSkillGridId)
  234. if not ids or #ids < battleDefine.MIN_LINK_BLOCK then
  235. return {code = battleCode.BATTLE_COUNT_LESS}
  236. end
  237. local playerData = self.core:getPlayer(uid)
  238. if not playerData then
  239. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  240. end
  241. if self.core:getNextLinkUid() ~= uid then
  242. return {code = battleCode.BATTLE_ROUND_ERR}
  243. end
  244. if self.core:isPlayerOperated(playerData) then
  245. return {code = battleCode.BATTLE_OPERATED}
  246. end
  247. if not self.core:operate(playerData, ids, exSkillGridId) then
  248. if IS_TEST then
  249. self.core:sendTestGrids(playerData)
  250. end
  251. return {code = battleCode.BATTLE_CANNOT_LINK}
  252. end
  253. return {code = battleCode.OK}
  254. end
  255. function root:playFinish(uid, round)
  256. local playerData = self.core:getPlayer(uid)
  257. if not playerData then
  258. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  259. end
  260. if self.core:getCurRound() ~= round then
  261. return {code = battleCode.BATTLE_ROUND_EXPIRED}
  262. end
  263. self.core:playFinish(playerData, uid, round)
  264. return {code = battleCode.OK}
  265. end
  266. -- 玩家托管
  267. function root:auto_link(uid, isAuto)
  268. local playerData = self.core:getPlayer(uid)
  269. if not playerData then
  270. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  271. end
  272. self.core:updateAutoLink(playerData, isAuto)
  273. return {code = code.OK}
  274. end
  275. function root:info(uid)
  276. local playerData = self.core:getPlayer(uid)
  277. if not playerData then
  278. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  279. end
  280. self.core:info(playerData)
  281. return {code = battleCode.OK}
  282. end
  283. function root:debug(uid, debugType, debugArgs)
  284. local playerData = self.core:getPlayer(uid)
  285. if not playerData then
  286. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  287. end
  288. local errorMsg
  289. if IS_TEST then
  290. errorMsg = self.core:debug(playerData, debugType, debugArgs)
  291. end
  292. return {code = battleCode.OK, errorMsg = errorMsg}
  293. end
  294. function root:chat(uid, id, text)
  295. local playerData = self.core:getPlayer(uid)
  296. if not playerData then
  297. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  298. end
  299. self.core:chat(playerData, id, text)
  300. return {code = battleCode.OK}
  301. end
  302. function root:getOverview(uid)
  303. local playerData = self.core:getPlayer(uid)
  304. if not playerData then
  305. return {code = battleCode.BATTLE_PLAYER_NOT_EXIST}
  306. end
  307. local msg = self.core:getOverview(playerData)
  308. msg.code = battleCode.OK
  309. return msg
  310. end
  311. function root:addViewers(uid)
  312. self.core:addViewers(uid)
  313. end
  314. function root:deleteViewers(uid)
  315. self.core:deleteViewers(uid)
  316. end
  317. -- 测试对战服务是否还在
  318. function root:ping(uid)
  319. local playerData = self.core:getPlayer(uid)
  320. return playerData and true or false
  321. end
  322. function root:fastSettle(uid)
  323. log.info("battle fastSettle uid = %s", tostring(uid))
  324. self.core:settleBattle(2, nil, uid)
  325. end
  326. -- 服务端是否启用AI
  327. function root:isServerBattleAiOpen()
  328. return true
  329. end
  330. return root