} } }

    用lua_tinker将lua脚本嵌入到游戏办事器

    添加时间:2013-5-31 点击量:

          忙中偷闲,经过几天的尽力,将lua脚本嵌入到体系中。之前公司的时辰,偌大一个办事器全部应用C++编写,对于新手经常产生一些宕机事务,被主程谴责。在后来接触的一些人中,发明很多公,都已经引入lua来适应多变的景象和急迅开辟!正如一个主程所说的,在n年前网易已经脚本为王了,如今很多公司拿着C++不放,作为开辟人员不苦逼才怪! 想想在广州开辟游戏的日子,每次在群里面看到运维说某某办事器上方有coredump文件时,老是惊出盗汗,赶紧用gdb去查询,是哪行代码引起的宕机;还要应对主程的谴责!其实不仅是法度,就是策划也经常因为设备文件的题目引起宕机!引入lua,不仅是为了法度开辟的便利,更是为了应对尖刻的运营商,新手的逻辑Bug等。在这些方面lua所发挥解析出来的优良,自是不必说。再加上其小巧灵活,嵌入便利,用来嵌入到游戏办事器之中,处理惩罚逻辑其实是太方面了!


         在底层通信方面还是传统的C++ 和 epoll 或者iocp ,在成功接管到客户端的消息之后,遵守和谈将其封装成MessageBlock的布局(关于MessageBlock ,可以参考我之前的博客 http://www.cnblogs.com/archy_yu/archive/2012/09/07/2674909.html ),传递给逻辑线程,逻辑线程,在消息队列里面作废息,然后处理惩罚,引入lua之后,就是要将这个MessageBlock类的对象传递给lua,让lua来处理惩罚!那么好,我们要将须要的接口暴漏给lua,为了便利在lua 和 C++之间调和,我们引入lua_tinker库


         为了将接口暴漏给lua,我们在类MessageBlock 中添加了一个新的成员函数!如下面的代码:



    class MessageBlock
    
    {
    ...
    ///
    int write_char(const char value);
    int write_short(const short value);
    int write_int(const int value);
    int write_string(const char ss);
    char read_char();
    short read_short();
    int read_int();
    char read_string();
    }

    int MessageBlock::write_char(const char value)
    {
    (this) << value;
    return 0;
    }

    int MessageBlock::write_short(const short value)
    {
    (this) << value;
    return 0;
    }

    int MessageBlock::write_int(const int value)
    {
    (this) << value;
    return 0;
    }

    int MessageBlock::write_string(const char ss)
    {
    (this) << ss;
    return 0;
    }

    char MessageBlock::read_char()
    {
    char a;
    (this) >> a;
    return a;
    }

    short MessageBlock::read_short()
    {
    short s=0;
    (this) >> s;
    return s;
    }

    int MessageBlock::read_int()
    {
    int i=0;
    (this) >> i;
    return i;
    }

    char MessageBlock::read_string()
    {
    static char ss[150];
    (this) >> ss;
    return ss;
    }








      之前数据的拼接和取值,我都是重载了操纵符,为了共同lua的调用,这里添加上述接口! 我们经由过程应用lua_tinker将这些接口暴漏给Lua。关于如何引入lua_tinker和lua_tinker的介绍请参考百度,或者接洽作者!



    extern C
    
    {
    #include lua.h
    #include lualib.h
    #include lauxlib.h
    };

    #include lua_tinker.h

    //包含须要的头文件

    int GameMonitor::lua_init()
    {
    this->L = lua_open(); //函数是用于打开Lua中的所有标准库,如io库、string库等。

    luaopen_base(this->L); //
    luaopen_string(this->L);


    return 0;
    }

    int GameMonitor::lua_class()
    {
    //注册MessageBlock 到lua
    lua_tinker::class_add<MessageBlock>(this->L,MessageBlock);

    return 0;
    }

    int GameMonitor::lua_method()
    {
    //注册MessageBlock 的机关函数等
    lua_tinker::class_con<MessageBlock>(this->L,lua_tinker::constructor<MessageBlock,int>);
    lua_tinker::class_def<MessageBlock>(this->L,write_int,&MessageBlock::write_int);
    lua_tinker::class_def<MessageBlock>(this->L,read_int,&MessageBlock::read_int);

    lua_tinker::class_def<MessageBlock>(this->L,write_string,&MessageBlock::write_string);
    lua_tinker::class_def<MessageBlock>(this->L,read_string,&MessageBlock::read_string);

            lua_tinker::def(this->L, peek_msg, peek_msg);
    lua_tinker::def(this->L, respond_to_client,respond_to_client);



    return 0;
    }

    int GameMonitor::lua_member()
    {
    //如须要,注册一些成员
    return 0;
    }

    int GameMonitor::lua_batfile()
    {
    //运行脚本 进入主逻辑轮回
    lua_tinker::dofile(this->L,LuaScript/MsgPrc.lua);
    return 0;
    }


         如此,我们就可以像如许来处理惩罚消息,如下面的代码(MsgPrc.lua):



    --msg = MessageBlock(1024)
    
    --
    --msg:write_int(10)
    --
    --print (msg:read_int())
    --
    --a = sdsdcds
    --
    --msg:write_string(a);
    --
    --print (msg:read_string())

    local s_msghead = {}

    local msg

    --主逻辑,死轮回,用来处理惩罚消息
    local function run_logic()
    while true do
    msg = peek_msg()
    if msg == nil then
    sleep(1)
    else
    process_msg(msg)
    end
    end
    end

    local function process_msg(msg)
    msg_head = msg:read_int()
    if s_msghead[msg_head] then
    s_msghead[msg_head](msg)
    end
    end

    --在此注册消息处理惩罚逻辑
    local function init_msghead()
    s_msghead[10001] = process_10001
    s_msghead[10002] = process_10002
    end

    local function process_10002(msg)
    msg.read_int(a);
    msg.read_string(b);
    --process
    remsg = MessageBlock(50);
    remsg.write_int(100)
    remsg.write_string(ok);
    respond_to_client(remsg);
    end

    --process_10001


    init_msghead()
    run_logic()


       如许就实现了用lua来处理惩罚所有的逻辑!


          我们调剂一下代码逻辑,就可以实现诸如热更新的功能,来应对日益激烈的页游盗窟竞争!之前就有据说过,说为什么搞IT的人看起来都很闲,说运维老是在重启,web前端开辟者老是在上传,C++开辟者老是在编译。因为说话特点,C++开辟者总要面对编译的题目,对于办事器代码,若是满是C++来编写,必定也是要面对这个题目,据说之前公司一个团队的后端代码要编译三个小时才干编译出可履行文件来。用lua来写主逻辑,其他的底层代码用库封装,岂不是又解决了一个题目!


          迎接评论辩论!!!

    我俩之间有着强烈的吸引力。短短几个小时后,我俩已经明白:我们的心是一个整体的两半,我俩的心灵是孪生兄妹,是知己。她让我感到更有活力,更完美,更幸福。即使她不在我身边,我依然还是感到幸福,因为她总是以这样或者那样的方式出现在我心头。——恩里克·巴里奥斯《爱的文明》
    分享到: