123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- --[[
- Descripttion:战斗房间
- version:
- Author: Neo,Huang
- Date: 2023-11-16 23:24:42
- LastEditors: Neo,Huang
- LastEditTime: 2023-11-16 23:25:34
- --]]
- local lib_battle_redis = require("lib_battle_redis")
- local timeUtil = require("utils.timeUtil")
- local redisBattleUtil = require("redisBattleUtil")
- local util_player = require("utils.util_player")
- local util_box = require("utils.util_box")
- local gameConst = require("const.gameConst")
- local util_user = require("utils.util_user")
- local nodeMgr = require("nodeMgr")
- local util_battle = require("utils.util_battle")
- local battleData = require("data.battle")
- local bagData = require("data.bag")
- local boxAdapt = require("adapt.boxAdapt")
- local resAdapt = require("adapt.resAdapt")
- local root = {}
- local function _get_global_room_key()
- return "global:room"
- end
- local function _get_room_key(id)
- return string.format("room:%s", tostring(id))
- end
- local function _get_active_room_id_key()
- return "active:rooms"
- end
- -- 分配房间ID
- function root:gen_room_id()
- local key = _get_global_room_key()
- local subKey = "max:room:id"
- local id = lib_battle_redis:hincrby(key, subKey, 1)
- if id > 200000000 then
- id = 1
- lib_battle_redis:hset(key, subKey, id)
- end
- return id
- end
- -- 获取当前活跃房间ID列表
- function root:get_active_room_id_list()
- local key = _get_active_room_id_key()
- return lib_battle_redis:smembers(key)
- end
- -- 打包房间玩家信息
- function root:pack_room_player_info(roomId, uid)
- local info = self:get_room_player_info(roomId, uid)
- if is_empty(info) then
- return
- end
- info.playerInfo = util_player:get_base_info(uid)
- return info
- end
- -- 打包房间玩家信息列表
- function root:pack_room_player_info_list(playerList)
- if is_empty(playerList) then
- return
- end
- local infoList = {}
- for _, v in ipairs(playerList) do
- local info = {
- playerInfo = util_player:get_base_info(v.uid),
- seatId = v.seatId,
- status = v.status
- }
- table.insert(infoList, info)
- end
- return infoList
- end
- -- 打包房间信息
- function root:pack_room_info(roomId)
- if is_empty(roomId) then
- return
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return
- end
- local info = {
- roomId = roomId,
- playCount = redisBattleUtil.hget_int(key, "playCount"),
- battleBoxList = redisBattleUtil.hget_json(key, "boxIdList"),
- status = redisBattleUtil.hget_int(key, "status"),
- createTime = redisBattleUtil.hget_int(key, "createTime")
- }
- -- 玩家信息列表
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- info.playerList = self:pack_room_player_info_list(playerList)
- return info
- end
- -- 打包所有房间信息
- function root:pack_room_info_list()
- local roomIdList = self:get_active_room_id_list()
- if is_empty(roomIdList) then
- return
- end
- local roomInfoList = {}
- for _, v in ipairs(roomIdList) do
- local roomId = tonumber(v)
- local info = self:pack_room_info(roomId)
- if not is_empty(info) then
- table.insert(roomInfoList, info)
- end
- end
- return roomInfoList
- end
- -- 打包玩家房间信息
- function root:pack_player_room_info(uid)
- if is_empty(uid) then
- return
- end
- local roomId = battleData:get_room_id(uid)
- if is_empty(roomId) then
- return
- end
- return self:pack_room_info(roomId)
- end
- -- 创建房间
- function root:create_room(uid, playCount, boxIdList)
- if is_empty(uid) then
- return false
- end
- if is_empty(playCount) or playCount < 2 or playCount > 3 then
- return false
- end
- if is_empty(boxIdList) or #boxIdList < 1 then
- return false
- end
- local roomId = self:gen_room_id()
- -- 设置房间信息
- local playerList = {{uid = uid, seatId = 1, status = 1}}
- local key = _get_room_key(roomId)
- redisBattleUtil.hset(key, "createTime", timeUtil.now()) -- 创建时间
- redisBattleUtil.hset(key, "hostUid", uid) -- 房主
- redisBattleUtil.hset(key, "playCount", playCount) -- 战斗人数
- redisBattleUtil.hset(key, "boxIdList", boxIdList) -- 战斗箱子ID列表
- redisBattleUtil.hset(key, "playerList", playerList) -- 玩家列表
- redisBattleUtil.hset(key, "status", 0) -- 战斗状态
- -- 房间进入准备战斗集合
- key = _get_active_room_id_key()
- lib_battle_redis:sadd(key, roomId)
- return true, roomId
- end
- -- 房间是否存在
- function root:is_room_exist(roomId)
- local key = _get_room_key(roomId)
- -- 房间是否存在
- return lib_battle_redis:exists(key)
- end
- -- 座位是否已被占
- function root:get_seat_player(roomId, seatId)
- if is_empty(roomId) or is_empty(seatId) then
- return
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return
- end
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for _, v in ipairs(playerList) do
- if v.seatId and v.seatId == seatId then
- return v.uid
- end
- end
- end
- -- 进入房间
- function root:enter_room(uid, roomId)
- if is_empty(uid) or is_empty(roomId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return false
- end
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for _, v in ipairs(playerList) do
- if v.uid == uid then
- -- 玩家已进入房间
- return false
- end
- end
- table.insert(playerList, {uid = uid, status = 0})
- redisBattleUtil.hset(key, "playerList", playerList)
- return true
- end
- -- 坐下
- function root:seat_down(uid, roomId, seatId)
- if is_empty(uid) or is_empty(roomId) or is_empty(seatId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return false
- end
- local isMatch = false
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for _, v in ipairs(playerList) do
- if v.uid == uid then
- v.seatId = seatId
- v.status = 1
- isMatch = true
- break
- end
- end
- if not isMatch then
- table.insert(playerList, {uid = uid, seatId = seatId, status = 1})
- end
- redisBattleUtil.hset(key, "playerList", playerList)
- return true
- end
- -- 站起
- function root:stand_up(uid, roomId)
- if is_empty(uid) or is_empty(roomId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return false
- end
- local isMatch = false
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for _, v in ipairs(playerList) do
- if v.uid == uid then
- if v.seatId == nil or v.seatId == 0 then
- return false
- end
- v.seatId = nil
- v.status = 0
- isMatch = true
- break
- end
- end
- if not isMatch then
- return false
- end
- redisBattleUtil.hset(key, "playerList", playerList)
- return true
- end
- -- 离开房间
- function root:leave(uid, roomId)
- if is_empty(uid) or is_empty(roomId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return false
- end
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for k, v in ipairs(playerList) do
- if v.uid == uid then
- table.remove(playerList, k)
- break
- end
- end
- redisBattleUtil.hset(key, "playerList", playerList)
- return true
- end
- -- 获取房间玩家信息
- function root:get_room_player_info(roomId, uid)
- if is_empty(roomId) or is_empty(uid) then
- return
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return
- end
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for _, v in ipairs(playerList) do
- if v.uid == uid then
- return v
- end
- end
- end
- -- 获取房间消耗价格
- function root:get_room_price(roomId)
- local key = _get_room_key(roomId)
- local boxIdList = redisBattleUtil.hget_json(key, "boxIdList")
- if is_empty(boxIdList) then
- return
- end
- return boxAdapt:battle_get_box_price(boxIdList)
- end
- -- 获取房间状态
- -- 0:等待 1:进行中 2:结算 3:销毁
- function root:get_room_status(roomId)
- if is_empty(roomId) then
- return 3
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return 3
- end
- local status = redisBattleUtil.hget_int(key, "status")
- return status
- end
- -- 销毁房间
- function root:destroy_room(roomId)
- if is_empty(roomId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- -- 从活跃房间集合删除
- lib_battle_redis:sismember(_get_active_room_id_key(), roomId)
- return false
- end
- local status = redisBattleUtil.hget_int(key, "status")
- if status >= 0 then
- -- 战斗已开始
- return false
- end
- -- 删除房间信息
- lib_battle_redis:del(key)
- -- 从活跃房间集合删除
- lib_battle_redis:sismember(_get_active_room_id_key(), roomId)
- return true
- end
- -- 是否等待开战结束
- function root:is_wait_battle_end(roomId)
- if is_empty(roomId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- return true
- end
- local currTime = timeUtil.now()
- local createTime = redisBattleUtil.hget_int(key, "createTime")
- local waitSeconds = boxAdapt:battle_const("no_full_close_room_time") or 10
- if currTime < createTime + waitSeconds then
- return false
- end
- return true
- end
- ----------------------------------------
- -- 战斗
- ---------------------------------------
- -- 房间是否开始战斗
- function root:is_room_start_battle(roomId)
- local status = self:get_room_status(roomId)
- if status > 0 then
- return false
- end
- local seatCount = 0
- local key = _get_room_key(roomId)
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- for _, v in ipairs(playerList) do
- if v.seatId and v.seatId > 0 then
- seatCount = seatCount + 1
- end
- end
- local playCount = redisBattleUtil.hget_int(key, "playCount")
- return seatCount >= playCount
- end
- -- 生成战斗编号
- function root:gen_battle_id(roomId)
- local currTime = timeUtil.now()
- return string.format("BT%s%08d", os.date("%Y%m%d", currTime), roomId)
- end
- -- 战斗
- function root:start_battle(roomId)
- if is_empty(roomId) then
- return false
- end
- local key = _get_room_key(roomId)
- -- 房间是否存在
- local isExist = lib_battle_redis:exists(key)
- if not isExist then
- -- 从活跃房间集合删除
- lib_battle_redis:sismember(_get_active_room_id_key(), roomId)
- return false
- end
- -- 更新状态
- redisBattleUtil.hset(key, "status", 1)
- local battleId = self:gen_battle_id(roomId)
- local battleBoxList = redisBattleUtil.hget_json(key, "boxIdList")
- local playerList = redisBattleUtil.hget_json(key, "playerList")
- -- 射击轮次
- local rounds = {}
- local totalPrice = 0
- for k, v in ipairs(battleBoxList) do
- local roundInfo = {round = k, shotList = {}}
- for _, _v in ipairs(playerList) do
- if _v.seatId and _v.seatId > 0 then
- local itemId = util_box:battle_get_box_drop_item_and_count(v)
- local price = resAdapt:get_item_price(itemId)
- local shotInfo = {
- uid = _v.uid,
- itemId = itemId,
- price = price
- }
- table.insert(roundInfo.shotList, shotInfo)
- totalPrice = totalPrice + price
- end
- end
- table.insert(rounds, roundInfo)
- end
- -- 胜利玩家
- local mapUidPrice = {}
- for _, v in ipairs(rounds) do
- for _, _v in ipairs(v.shotList) do
- mapUidPrice[_v.uid] = (mapUidPrice[_v.uid] or 0) + _v.price
- end
- end
- local winUid = nil
- local maxPrice = nil
- for uid, price in pairs(mapUidPrice) do
- if maxPrice == nil or price > maxPrice then
- winUid = uid
- end
- end
- -- 战斗玩家列表
- local n1Price = resAdapt:get_item_price(gameConst.ITEM_ID.N1)
- local battlePlayerList = {}
- for _, v in ipairs(playerList) do
- if v.seatId and v.seatId > 0 then
- if v.uid == winUid then
- -- 收集所有玩家射击
- local info = {uid = v.uid, seatId = v.seatId, shotList = {}}
- for _, _v in ipairs(rounds) do
- for _, __v in ipairs(_v.shotList) do
- table.insert(info.shotList, {itemId = __v.itemId, price = __v.price})
- end
- end
- table.insert(battlePlayerList, info)
- else
- -- 安慰奖
- local info = {
- uid = v.uid,
- seatId = v.seatId,
- shotList = {{itemId = gameConst.ITEM_ID.N1, price = n1Price}}
- }
- table.insert(battlePlayerList, info)
- end
- end
- end
- -- 发放奖励
- for _, v in ipairs(battleBoxList) do
- local items = {}
- for _, _v in ipairs(v.shotList) do
- table.insert(items, {id = v.itemId, count = 1})
- end
- local keyEvent = string.format("battle-settle-%s-%s", battleId, tostring(v.uid == winUid and 1 or 0))
- bagData:add_items(v.uid, items, keyEvent)
- end
- redisBattleUtil.hset(key, "status", 2)
- local settle = {
- roomInfo = self:pack_room_info(roomId),
- winUid = winUid,
- battleId = battleId,
- rounds = rounds,
- battlePlayerList = battlePlayerList
- }
- -- 通知所有房间玩家
- for _, v in ipairs(playerList) do
- util_user:user_proto_notify(v.uid, "on_room_battle_settle", {settle = settle})
- end
- -- 新增战斗记录
- util_battle:add_battle_record(settle, totalPrice)
- -- 关闭房间
- -- 删除房间信息
- lib_battle_redis:del(key)
- -- 从活跃房间集合删除
- lib_battle_redis:sismember(_get_active_room_id_key(), roomId)
- -- 通知在线玩家 - 销毁房间
- nodeMgr.broadcast_proto_notify("on_room_destroy", {roomId = roomId})
- end
- ----------------------------------------
- -- 玩家战斗信息
- ----------------------------------------
- local bagData = require("data.bag")
- -- 绑定房间
- function root:band_room(uid, roomId, costItems)
- if is_empty(uid) or is_empty(costItems) then
- return
- end
- battleData:band_room(uid, roomId, costItems)
- -- 消耗道具
- local keyEvent = string.format("battle-seat-down-%s", tostring(roomId))
- bagData:consume_items(uid, costItems, keyEvent)
- end
- -- 解绑房间
- -- ty - 解绑类型: leave:离开 dismiss:解散 seat:更换座位 settle:结算
- function root:unband_room(uid, ty)
- if is_empty(uid) then
- return
- end
- local costItems = battleData:get_room_cost_items(uid)
- if (ty == "leave" or ty == "dismiss" or ty == "seat") and not is_empty(costItems) then
- -- 返回物品
- local keyEvent = string.format("battle-%s", ty)
- bagData:add_items(uid, costItems, keyEvent)
- end
- battleData:band_room(uid)
- return true
- end
- return root
|