tdengine 0.1.2

game server for Rust
Documentation
-- accountd.lua
-- Created by wugd
-- 负责玩家相关的功能模块

-- 声明模块名
ACCOUNT_D = {}
setmetatable(ACCOUNT_D, {__index = _G})
local _ENV = ACCOUNT_D

-- 创建弱引用表
local account_list = {}
setmetatable(account_list, { __mode = "v" })

-- 冻结玩家数据,在保存数据的过程中不允许用户登陆
local account_freeze_list = {}

-- 所有的账号登陆的信息情况
local account_online_list = {}

-- 所有的等待登陆的信息情况
local account_wait_list = {}

-- 创建玩家
function create_account(dbase)
    local account = ACCOUNT_TDCLS.new(dbase)
    account_list[#account_list + 1] = account
    return account
end

-- 新增玩家记录的回调
local function create_new_account_callback(info, ret, result_list)
    local account_ob = info["account_ob"]
    if ret ~= 0 then
        do return end
    end

    login(account_ob, info["rid"], info)
end

function login(agent, account_rid, account_dbase)
    assert(account_rid == account_dbase["rid"])
    local account = create_account(account_dbase)
    account:accept_relay(agent)
    account:send_message(MSG_LOGIN_NOTIFY_STATUS, {ret = 0})
    success_login(account, false)
end

function success_login(account, is_reconnect)
    if not account:get_user_ob() then
        is_reconnect = false
    end
    account:set_server_type(SERVER_TYPE_CLIENT)
    account:set_authed(true)

    if is_reconnect then
        account:set_login_user(account:get_user_ob(), is_reconnect)
    elseif IS_SINGLE then
        ACCOUNT_D.get_user_list(account)
    end
end

-- 创建 user 表记录
function create_new_account(login_info)
    local agent = login_info["agent"]
    local device_id = login_info["device_id"]

    if not is_object(agent) then
        return
    end

    -- 检查信息是否合法
    if not is_string(device_id) then
        trace("创建新角色信息不合法。\n")
        return
    end

    local user_rid = NEW_RID()

    -- 记录其它必备的玩家属性
    local account_dbase = {
        rid         = user_rid,
        name        = login_info["name"],
        create_time = os.time(),
        account     = login_info["account"],
        device_id   = device_id,
        password    = login_info["password"],
        switch_time = 0,
        device_md5  = calc_str_md5(device_id),
    }
    local sql = SQL_D.insert_sql("account", account_dbase)
    account_dbase["account_ob"] = agent
    DB_D.execute_db("account", sql, create_new_account_callback, account_dbase)
end

function get_account_list()
    return account_list
end

function account_logout(account)
    if not is_object(account) then
        return
    end
    destruct_object(account)
end

local function callback_get_user_list(account, ret, result_list)
    account:send_message(MSG_USER_LIST, result_list or {})

    local user_list = {}
    for _,value in ipairs(result_list) do
        user_list[value["rid"]] = value
    end
    account:set("user_list", user_list)
    if IS_SINGLE then
        local rid, value = get_first_key_value(user_list)
        if value and value.ban_flag and value.ban_flag ~= 0 then
            account:send_message(MSG_LOGIN_NOTIFY_STATUS, {ret = -1, err_msg = "账号被冻结"})
            account:connection_lost(true)
            return
        end
        if rid then
            request_select_user(account, rid)
        else
            local user_rid = NEW_RID()
            request_create_user(account, {
                name = "auto_" .. user_rid, --RANDOM_NAMED.generate_random_name(), --"auto_" .. user_rid,
                rid  = user_rid,
            })
        end
    end
end

function get_user_list(account)
    local sql = SQL_D.select_sql("user", {_WHERE={account_rid=account:query("rid")}})
    DB_D.read_db("user", sql, callback_get_user_list, account)
end

local function create_new_user_callback(info, ret, result_list)
    local account_ob = info["account_ob"]
    info["account_ob"] = nil
    if ret ~= 0 then
        account_ob:send_message(MSG_CREATE_USER, {status=1})
        destruct_object(account_ob)
        do return end
    end
    account_ob:send_message(MSG_CREATE_USER, {status=0})
    info["status"] = 0
    local user_list = account_ob:query("user_list")
    if not user_list then
        user_list = {}
        account_ob:set("user_list", user_list)
    end

    local table_data= {rid=info.rid, name = info.name, fight= info.fight,
        watch_rids = info.watch_rids, zone = info.zone, ban_flag = info.ban_flag, vip= info.vip ,
        lv= info.lv, head_icon= info.head_icon, head_photo_frame= info.head_photo_frame,
        last_login_time= info.last_login_time, last_logout_time= info.last_logout_time }
    USER_D.publish_user_attr_update(table_data)

    user_list[info.rid] = info
    LOG_D.to_log(LOG_TYPE_CREATE_NEW_USER, info.rid, account_ob:query("name"), "", "")

    raise_issue(EVENT_NEW_USER_CREATE, info)
    request_select_user(account_ob, info.rid)
end

function request_create_user(account, info)
    local user_dbase = {
        rid         = info.rid or NEW_RID(),
        name        = info.name,
        ban_flag    = 0,
        sp          = 50,
        gold        = 0,
        stone       = 0,
        sex         = math.random(0, 1),
        create_time = os.time(),
        account_rid = account:query("rid"), 
        vip= 0,
        lv= 1, 
        last_login_time= os.time(),
        last_logout_time= 0,
    }

    local sql = SQL_D.insert_sql("user", user_dbase)
    user_dbase["account_ob"] = account
    DB_D.execute_db("account", sql, create_new_user_callback, user_dbase)
end


local function read_user_callback(info, args)
    local rid, account = args["rid"], args["account"]
    assert(rid ~= nil, "rid must not nil")
    -- local user = find_object_by_rid(rid)
    -- assert(user ~= nil, "user must not nil")
    if info.failed then
        return
    end

    local user = remove_get(info, "user")
    local item = remove_get(info, "item")
    local equip = remove_get(info, "equip")
    local ddz_info = remove_get(info, "ddz_info")
    for key, value in pairs(user or {}) do
        info[key] = value
    end

    local user_ob = find_object_by_rid(rid)
    if user_ob then
        user_ob:close_agent()
    else
        user_ob = USER_D.create_user(info)
    end

    for _,v in pairs(item) do
        user_ob:get_container():init_property(v)
    end
    
    for _,v in pairs(equip) do
        user_ob:get_container():init_property(v)
    end
    user_ob:set_ddz_dbase(ddz_info)
    account:set_login_user(user_ob)
end

function request_select_user(account, rid)
    local user_list = account:query("user_list") or {}
    if user_list[rid] == nil then
        return
    end

    local user_ob = find_object_by_rid(rid)
    --断线重连
    if user_ob then
        account:set_login_user(user_ob)
    else
        CACHE_D.get_user_data(rid, read_user_callback, {rid = rid, account = account})
    end
end

function add_account_freeze(account_rid)
    account_freeze_list[account_rid] = {time=os.time()}
end

function remove_account_freeze(account_rid)
    account_freeze_list[account_rid] = nil
    raise_issue(EVENT_SUCCESS_ACCOUNT_END_HIBERNATE, account_rid)
end

function is_account_freeze(account_rid)
    local data = account_freeze_list[account_rid]
    if not data then
        return false
    end
    return os.time() - (data.time or 0) < 100
end

function add_account_online(account_rid)
    account_online_list[account_rid] = {time=os.time()}
    remove_account_wait_login(account_rid)
end

function remove_account_online(account_rid)
    account_online_list[account_rid] = nil
    raise_issue(EVENT_SUCCESS_ACCOUNT_OBJECT_DESTRUCT, account_rid)
end

function is_account_online(account_rid)
    local data = account_online_list[account_rid]
    if not data then
        return false
    end
    return os.time() - (data.time or 0) < 10000
end

function add_account_wait_login(account_rid)
    account_wait_list[account_rid] = {time=os.time()}
end

function remove_account_wait_login(account_rid)
    account_wait_list[account_rid] = nil
end

function is_account_wait(account_rid)
    local data = account_wait_list[account_rid]
    if not data then
        return false
    end
    return os.time() - (data.time or 0) < 100
end

local function init()
end

function create()
    register_as_audience("ACCOUNT_D", {EVENT_ACCOUNT_START_HIBERNATE = add_account_freeze})
    register_as_audience("ACCOUNT_D", {EVENT_ACCOUNT_END_HIBERNATE = remove_account_freeze})
    register_as_audience("ACCOUNT_D", {EVENT_ACCOUNT_WAIT_LOGIN = add_account_wait_login})
    register_as_audience("ACCOUNT_D", {EVENT_ACCOUNT_CANCEL_WAIT_LOGIN = remove_account_wait_login})
    register_as_audience("ACCOUNT_D", {EVENT_ACCOUNT_OBJECT_CONSTRUCT = add_account_online})
    register_as_audience("ACCOUNT_D", {EVENT_ACCOUNT_OBJECT_DESTRUCT = remove_account_online})
    register_as_audience("ACCOUNT_D", {EVENT_NOTIFY_ACCOUNT_OBJECT_DESTRUCT = function(rid)
        local ob = find_object_by_rid(rid)
        if not is_object(ob) then
            return
        end
        ob:connection_lost(true)   
    end})
end

create()
register_post_init(init)