tdengine 0.1.2

game server for Rust
Documentation
--roomd.lua
--Created by wugd
--负责房间相关的功能模块

--创建模块声明
ROOM_D = {}
setmetatable(ROOM_D, {__index = _G})
local _ENV = ROOM_D

--场景列表
local room_list  = {}
local room_table = {}
local freq_table = {}

local all_room_details = {}

--定义内部接口,按照字母顺序排序
local function clear_doing_enter_room(entity)
    if entity:is_user() then
        entity:delete_temp("doing_enter_room")
    end
end

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

-- 广播消息
function broadcast_message(room_name, msg, ...)
    -- 取得该房间编号对应的房间对象
    local room = room_list[room_name]
    if not room then
        return
    end

    -- 广播消息
    room:broadcast_message(msg, ...)
end

--创建全部场景
function create_allroom(filename)
    room_table = IMPORT_D.readcsv_to_tables(filename)
    for k, v in pairs(room_table) do
        create_room(v)
    end
end

-- 获取csv表信息
function get_room_table()
    return room_table
end

--创建一个场景
function create_room(roomdata)
    local room_tdcls = _G[roomdata.room_tdcls]
    assert(room_tdcls ~= nil, "场景配置必须存在")
    local room = clone_object(room_tdcls, roomdata)
    assert(room_list[room:get_room_name()] == nil, "重复配置房间")
    room_list[room:get_room_name()] = room
    REDIS_D.add_subscribe_channel(room:get_listen_channel())
    REDIS_D.add_subscribe_channel(room:get_respone_channel())
    return room
end

function enter_room(entity, room_name)
    
end

--获取房间对象
function get_room_list()
    return room_list
end

function get_room(room_name)
    return room_list[room_name]
end

--离开一个场景
function leave_room(entity, room_name)
    local room = room_list[room_name]

    if room then
        room:entity_leave(entity)
    end

    -- 删除玩家的位置信息
    entity:delete_temp("room")
end

-- 根据rid获取room_name
function get_room_name_by_rid(rid)
    local rid_ob = find_object_by_rid(rid)
    if not is_object(rid_ob) then
        return
    end
    return (rid_ob:query_temp("room"))
end

-- 获取某个房间玩家列表
function get_room_entity_list(room_name)
    local peo_list = {}
    local room = room_list[room_name]
    if room then
        local room_peoples = room:get_room_entity()
        local user
        local find_object_by_rid = find_object_by_rid
        local name, account, result
        local query_func
        for rid, info in pairs(room_peoples) do

            if info.ob_type == OB_TYPE_USER then
                user = find_object_by_rid(rid)
                if is_object(user) then
                    if not query_func then
                        query_func = user.query
                    end

                    name    = query_func(user, "name")
                    account = query_func(user, "account")
                    level   = query_func(user, "level")
                    result  = {
                        rid     = rid,
                        name = name,
                        account = account,
                        level = level
                    }

                    peo_list[#peo_list+1] = result
                else
                    room_peoples[rid] = nil
                end
            end
        end
    end

    return {
        ret         = #peo_list,
        result_list = peo_list,
    }
end

function update_room_entity(room_name, rid, pkg_info)

    local room = room_list[room_name]

    if not room then
        return
    end

    room:update_entity(rid, pkg_info)
end

function get_detail_room(room_name)
    local room = all_room_details[room_name or ""]
    if not room then
        return
    end

    if os.time() - (room.time or 0) > 180 then
        all_room_details[room_name] = nil
        room = nil
    end

    return room
end

function redis_room_detail(detail)
    for name,value in pairs(detail) do
        value["time"] = os.time()
        value["room_name"] = name
        all_room_details[name] = value
    end
end

function get_room_detail()
    return all_room_details
end

function cmd_room_message(room_name, user_rid, cookie, oper, info)
    local room = room_list[room_name]
    if not room then
        trace("房间:%o不存在", room_name)
        return
    end
    local data = room:get_data_by_rid(user_rid)
    local ret = 0
    local server_id = remove_get(info, "server_id")
    if oper == "enter_room" then
        assert(is_int(server_id), "server_id must exist")
        ret = room:entity_enter(server_id, user_rid, info)
    elseif oper == "leave_room" then
        ret = room:entity_leave(user_rid, info)
    elseif oper == "enter_desk" then
        if not data then
            ret = -1
        else
            ret = room:enter_desk(user_rid, info.idx, info.enter_method)
        end
    elseif oper == "desk_op" then
        if not data then
            ret = -1
        else
            ret = room:desk_op(user_rid, info)
        end
    elseif oper == "detail_info" then
        if not data then
            ret = -1
        else
            merge(data, info)
        end
    end

    if data then
        server_id = data.server_id
    end
    cookie = tonumber(cookie)
    if server_id and cookie and cookie ~= 0 then
        local channel = string.format(CREATE_RESPONE_SERVER_INFO, server_id, cookie)
        REDIS_D.run_publish(channel, encode_json({ret = ret}))
    end
end

function redis_dispatch_message(room_name, user_rid, cookie, msg_buf)
    local room = room_list[room_name]
    if not is_object(room) then
        LOG.err("房间'%s'信息不存在", room_name)
        return
    end
    local name, net_msg = pack_raw_message(msg_buf)
    if not net_msg then
        LOG.err("发送给房间:'%s',用户:'%s',消息失败", room_name, user_rid)
        return
    end

    local name, args = net_msg:msg_to_table()
    if name and args and ROOM_D[name] then
        ROOM_D[name](room_name, user_rid, cookie, unpack(args))
    end
    del_message(net_msg)
end

function room_detail_update(detail)

end

local function logic_cmd_room_message(user, buffer)
    local room_name = user:query_temp("room_name")
    if sizeof(room_name) == 0 then
        return
    end

    INTERNAL_COMM_D.send_room_raw_message(room_name, get_ob_rid(user), {}, buffer:get_data())
end

local function publish_room_detail()
    local result = {}
    for room_name,room in pairs(room_list) do
        local room_entity = room:get_room_entity()
        result[room_name] = { amount = sizeof(room_entity), game_type = room:get_game_type() }
    end
    REDIS_D.run_publish(SUBSCRIBE_ROOM_DETAIL_RECEIVE, encode_json(result))
end

local function user_login(user_rid, server_id)
    for room_name,room in pairs(room_list) do
        local data = room:get_data_by_rid(user_rid)
        if data then
            data.server_id = server_id
            data.last_logout_time = nil
            data.last_op_time = os.time()
            INTERNAL_COMM_D.send_server_message(server_id, user_rid, {}, RESPONE_ROOM_MESSAGE, "reconnect_user", {room_name = room_name, rid = user_rid})
        end
    end
end

local function user_logout(user_rid)
    trace("玩家登出 %o", user_rid)
    for _, room in pairs(room_list) do
        local data = room:get_data_by_rid(user_rid)
        if data then
            room:entity_leave(user_rid)
            -- INTERNAL_COMM_D.send_server_message(server_id, user_rid, {}, RESPONE_ROOM_MESSAGE, "reconnect_user", {room_name = room_name, rid = user_rid})
        end
    end
end

local function time_update()
    for _,room in pairs(room_list) do
        room:time_update()
    end
end

-- 模块的入口执行
function create()
    if ENABLE_ROOM then
        create_allroom("data/txt/room.txt")
        register_as_audience("ROOM_D", {EVENT_USER_OBJECT_CONSTRUCT = user_login})
        register_as_audience("ROOM_D", {EVENT_USER_CONNECTION_LOST = user_logout})
        set_timer(1000, time_update, nil, true)
    end
    
    register_msg_filter("cmd_room_message", logic_cmd_room_message)

    if SERVER_TYPE == SERVER_LOGIC or STANDALONE then
        REDIS_D.add_subscribe_channel(SUBSCRIBE_ROOM_DETAIL_RECEIVE)
    end
end

local function init()
    if ENABLE_ROOM then
        publish_room_detail()
        set_timer(60000, publish_room_detail, nil, true)
    end
end

create()
register_post_init(init)