tdengine 0.1.2

game server for Rust
Documentation
--room.lua
--Created by wugd
--房间类

--创建类模板
ROOM_TDCLS = tdcls()
ROOM_TDCLS.name = "ROOM_TDCLS"

--构造函数
function ROOM_TDCLS:create(value)
    assert(is_table(value), "room:create para not correct")

    --记录该场景的基本信息
    self.data = value

    --创建存放该场景实体的弱表
    self.room_entity = {}

    self:init_desk_entity()
end

function ROOM_TDCLS:destruct()
    for _,data in pairs(dup(self.room_entity)) do
        self:entity_destruct(data)
    end
    for _,table in pairs(self.desk_entity) do
        destruct_object(table)
    end
end

function ROOM_TDCLS:init_desk_entity()
    --创建该房间的桌子信息
    self.desk_entity = {}
    local desk_num = self.data["desk_num"] or 100
    for i=1,desk_num do
    self.desk_entity[i] = clone_object(self:get_desk_class(), self, i)
    end
end

-- 生成对象的唯一ID
function ROOM_TDCLS:get_ob_id()
    return (string.format("ROOM_TDCLS:%s", save_string(self:get_room_name())))
end

--定义公共接口,按照字母顺序排序

function ROOM_TDCLS:time_update()
    for _,data in pairs(dup(self.room_entity)) do
        self:entity_update(data)
    end

    for _,table in pairs(self.desk_entity) do
        table:time_update()
    end
end

function ROOM_TDCLS:entity_update(entity)
    --正在游戏中的不做析构处理,等游戏先结束
    if entity.last_logout_time and os.time() - entity.last_logout_time > 10 then
        if not self:is_user_playing(entity.user_rid) then
            self:entity_destruct(entity.user_rid)
        end
    end
end

-- 广播消息
function ROOM_TDCLS:broadcast_message(msg, ...)

    local size = sizeof(self.room_entity)
    local config_amount = ROOM_D.get_msg_amount(msg)
    local find_object_by_rid = find_object_by_rid
    local is_object = is_object
    local user
    local msg_buf = pack_message(msg, ...)
    local send_raw_message = get_class_func(USER_TDCLS, "send_raw_message")

    if not msg_buf then
        trace("广播消息(%d)打包消息失败。\n", msg)
        return
    end

    -- 遍历该房间的所有玩家对象
    for rid, info in pairs(self.room_entity) do
        if info.ob_type == OB_TYPE_USER then
            if  math.random(1, size) < config_amount then
                user = find_object_by_rid(rid)
                if is_object(user) then
                    send_raw_message(user, msg_buf)
                else
                    self.room_entity[rid] = nil
                end
            end
        end
    end

    del_message(msg_buf)
end

--玩家进入房间
function ROOM_TDCLS:entity_enter(server_id, user_rid, info)
    local data = self.room_entity[user_rid]
    if data then
        data.server_id = server_id
        data.last_op_time = os.time()
        data.info = info
    else
        --将新实体加该场景
        self.room_entity[user_rid] = {
            user_rid = user_rid,
            --对像连接的服务器id
            server_id = server_id,
            --对像的登出时间
            last_logout_time = nil,
            --玩家的上次操作时间,确定是否超时
            last_op_time = os.time(),
            --进入桌子时间
            enter_desk_time = nil,
            --进入桌子编号
            enter_desk_idx = nil,

            info = info,
        }

    end

    self:send_rid_message(user_rid, {}, MSG_ROOM_MESSAGE, "success_enter_room", {rid = user_rid, room_name = self:get_room_name()})
    if data and data.enter_desk_idx then
        self:send_rid_message(user_rid, {}, MSG_ROOM_MESSAGE, "pre_desk", {rid = user_rid, enter_desk_idx = data.enter_desk_idx})
    end
    return 0
end

function ROOM_TDCLS:is_user_playing(user_rid)
    local entity = self.room_entity[user_rid]
    if not entity then
        return false
    end
    if not entity.enter_desk_idx then
        return false
    end
    local desk = self.desk_entity[entity.enter_desk_idx]
    if not desk then
        return false
    end
    return desk:is_playing(user_rid)
end

--玩家离开房间
function ROOM_TDCLS:entity_leave(user_rid)
    if not self.room_entity[user_rid] then
        LOG.err("Error:对象%s离开房间%s时找不到自己\n", user_rid, self:get_room_name())
    end

    --设置实体的登出时间,如果实体还在游戏中则等待处理,如果实体不在游戏中,则下一秒则析构掉玩家对像
    local entity = self.room_entity[user_rid]
    entity.last_logout_time = os.time()

    if not self:is_user_playing(user_rid) then
        if entity.enter_desk_idx then
            local desk = self.desk_entity[entity.enter_desk_idx]
            if not desk:is_playing() then
                desk:user_leave(user_rid)
            end
        end

        self:entity_destruct(user_rid)
        trace("玩家不在游戏状态,掉线时离开桌子")
        return
    end

    return 0
end

--玩家离开房间
function ROOM_TDCLS:entity_destruct(user_rid)
    if not self.room_entity[user_rid] then
        LOG.err("Error:对象%s析构时找不到自己\n", user_rid)
    end

    --将该实体从场景中删除,并发送离开场景消息
    local entity = remove_get(self.room_entity, user_rid)
    return 0
end

--TODO优先填取桌子人多但并未满的桌子 
function ROOM_TDCLS:get_can_enter_desk()
    for idx, t in ipairs(self.desk_entity) do
        if not t:is_full_user() then
            return idx
        end
    end
    return nil
end

function ROOM_TDCLS:enter_desk(user_rid, idx, enter_method)
    local data = self.room_entity[user_rid]
    if not data then
        LOG.err("Error:%s进入桌子时找不到自己\n", user_rid)
        return -1
    end
    if idx and idx == data.enter_desk_idx then
        data.enter_desk_idx = nil
    elseif idx == nil then
        if data.enter_desk_idx then
            idx = data.enter_desk_idx
            data.enter_desk_idx = nil
        else
            idx = self:get_can_enter_desk()
        end
    end

    if data.enter_desk_idx then
        LOG.err("Error:%s已在%d桌,无法进入\n", user_rid, data.enter_desk_idx)
        return -1
    end
    if not idx then
        LOG.err("桌子已用完,无可用桌子")
        return -1
    end

    local desk = self.desk_entity[idx]
    if not desk then
        LOG.err("Error:%o桌号不存在\n", idx)
        return -1
    end

    desk:user_enter(user_rid)
    data.enter_desk_idx = idx
    return 0
end

function ROOM_TDCLS:send_rid_message(user_rid, record, msg, ...)
    local msg_buf = pack_message(msg, ...)
    if not msg_buf then
        trace("广播消息(%s)打包消息失败。\n", msg)
        return
    end
    self:send_rid_raw_message(user_rid, record, msg_buf)
    del_message(msg_buf)
end

function ROOM_TDCLS:send_rid_raw_message(user_rid, record, msg_buf)
    local data = self:get_data_by_rid(user_rid)
    if not data or not data.server_id then
        trace("获取用户%s数据失败", user_rid)
        return
    end
    INTERNAL_COMM_D.send_server_raw_message(data.server_id, user_rid, record or {}, msg_buf:get_data())
end

function ROOM_TDCLS:desk_op(user_rid, info)
    local data = self.room_entity[user_rid]
    if not data then
        return -1
    end
    local desk = self.desk_entity[data.enter_desk_idx or 0]
    if not desk then
        return -1
    end

    desk:op_info(user_rid, info)
end

--获取房间名称
function ROOM_TDCLS:get_room_name()
    return self.data["room_name"]
end

--获取房间类型
function ROOM_TDCLS:get_game_type()
    return self.data["game_type"]
end

-- 返回房间中的玩家信息
function ROOM_TDCLS:get_room_entity()
    return self.room_entity
end

-- 返回房间中的玩家信息
function ROOM_TDCLS:get_data_by_rid(user_rid)
    return self.room_entity[user_rid]
end

-- 返回房间中的玩家信息
function ROOM_TDCLS:get_base_info_by_rid(user_rid)
    local data = self.room_entity[user_rid]
    if not data then
        return nil
    end
    return data.info
end

--判断是否是vip场景
function ROOM_TDCLS:is_vip()
    if self.data["is_vip"] == 1 then
        return true
    else
        return nil
    end
end

function ROOM_TDCLS:get_level()
    return self.data["level"]
end

function ROOM_TDCLS:get_desk_class()
    return DESK_TDCLS
end

-- 判断是否为房间对象
function ROOM_TDCLS:is_room()
    return true
end

--更新实体外观信息
function ROOM_TDCLS:update_entity(rid, pkg_info)
    if self.room_entity[rid] and
       self.room_entity[rid]["packet"] then

        self.room_entity[rid]["packet"] = pkg_info
    end
end

function ROOM_TDCLS:get_listen_channel()
    return string.format(REDIS_ROOM_MSG_CHANNEL_USER, self:get_room_name())
end

function ROOM_TDCLS:get_respone_channel()
    return string.format(REDIS_RESPONE_ROOM_INFO, self:get_room_name())
end