用lua_tinker将lua脚本嵌入到游戏服务器

      忙中偷闲,经过几天的努力,将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;
}

<br>

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

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

#include "lua_tinker.h"

<span style="color: rgb(255, 0, 0);">//包含必要的头文件</span>

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

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

    return 0;
}

int GameMonitor::lua_class()
{
       //注册MessageBlock 到lua
    <span style="color: rgb(255, 0, 0);">lua_tinker::class_add<MessageBlock>(this->L,"MessageBlock");</span>

    return 0;
}

int GameMonitor::lua_method()
{
        <span style="color: rgb(255, 0, 0);">//注册MessageBlock 的构造函数等</span>
    <span style="color: rgb(136, 136, 136);">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);</span>

   如此,我们就可以像这样来处理消息,如下面的代码(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
<br>--主逻辑,死循环,用来处理消息
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
<br>--在此注册消息处理逻辑
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来写主逻辑,其他的底层代码用库封装,岂不是又解决了一个问题!

      欢迎讨论!!!

时间: 2024-09-20 17:09:28

用lua_tinker将lua脚本嵌入到游戏服务器的相关文章

阿里云Redis LUA脚本功能上线——轻量嵌入,极速扩展,业务轻松跨平台

    阿里云Redis云数据库,全面支持LUA脚本功能,助力企业轻松迁移自建Redis数据库的业务逻辑,实现业务的跨平台复用,快速驱动业务上云.LUA语言作为目前最流行的轻量级嵌入式脚本语言,凭借其语法简单.高效稳定.支持复杂数据结构以及自动内存管理等特点,已经在众多著名的游戏程序中大量被使用,如:愤怒的小鸟.星际争霸.魔兽世界等. 了解Redis详细配置及价格>> Redis支持LUA脚本的主要优势      LUA脚本的融合将使Redis数据库产生更多的使用场景,迸发更多新的优势: 高效

Redis脚本插件之————执行Lua脚本示例

Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行.使用脚本的好处如下: 1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成.使用脚本,减少了网络往返时延. 2.原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入. 3.复用:客户端发送的脚本会永久存储在Redis中,意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑. 实现一个访问频率控制,某个ip在短时间内频繁访问页面

【COCOS2DX-LUA 脚本开发之一】LUA语言基础在COCOS2DX游戏中使用LUA脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2dx/681.html 对于游戏公司而言,采用游戏脚本lua.python等进行开发也很常见,但是很多童鞋对脚本并没有很熟悉的概念,本篇则向大家简单介绍脚本的用途以及在Cocos2dx基础用法: Lua和python这些详细介绍的话,请不太熟悉的童鞋自行百度百科哈,那么对于lua和python则是两个常用的脚本语言,

《Lua游戏开发实践指南》一3.1脚本语言和游戏

3.1脚本语言和游戏 脚本语言可以让美术师直接开始界面设计,让设计师和初级程序员(脚本语言是一种让新手快速进入游戏开发的很好的方式)立即着手游戏流程和逻辑的开发,让关卡设计师能迅速掌控游戏环境和游戏体验.脚本语言不是非常高效--它们没有原生代码的运行效率,因此不适合作为开发高性能需求处理的工具.但易整合语言能够利用原生语言编写的模块扩展功能,比如Lua,可以作为控制机制来调用原生代码编写的高性能处理组件.(Lua是运行效率最高的脚本语言之一,因此大部分性能方面的问题都可以不用担心.)C函数可以利

Lua教程(一):在C++中嵌入Lua脚本_Lua

本系列教程主要介绍如何在C/C++程序里面嵌入Lua脚本,我打算从以下几个方面来介绍: 1.如何在C/C++里面嵌入Lua脚本 2.Lua访问C/C++数据结构(这里面要介绍类,结构体,函数,变量,枚举等数据类型在lua里面如何访问) 3.C/C++访问Lua的数据,主要是基本数据类型,函数和Table 4.Cocos2D-X里面的Lua绑定(含自动绑定与手动绑定) 5.Cocos2D-x里面Lua和C/C++相互调用 6.Cocos2D-x里面Lua和Java相互调用 7.Cocos2D-x里

GopherLua —— Go 程序中嵌入 Lua 脚本

GopherLua 是用 Go 语言编写的 Lua 5.1 的虚拟机和编译器.GopherLua 的目标和 Lua 相同 -- 成为一个支持可扩展语义的脚本语言,提供 Go API 可方便在 Go 应用中植入 Lua 脚本语言功能. 实际测试表明 GopherLua 的性能是其他同类实现的 20 倍. 示例代码: import ( "github.com/yuin/gopher-lua" ) L := lua.NewState() defer L.Close() if err := L

《Lua游戏AI开发指南》一2.7 创建一个沙箱Lua脚本

2.7 创建一个沙箱Lua脚本 基本的沙箱程序就位之后,我们就可以新建沙箱的创建Lua脚本了.首先在脚本文件夹中新建一个Sandbox.lua脚本. 像下面这样创建一个Lua文件: src/my_sandbox/script/Sandbox.lua 沙箱Lua脚本必须实现4个全局函数供C++代码调用,它们分别是Sandbox_Cleanup. Sandbox_HandleEvent. Sandbox_Initialize和Sandbox_Update: Sandbox.lua: function

《Lua游戏AI开发指南》一2.9 创建智能体Lua脚本

2.9 创建智能体Lua脚本 为了创建一个新的智能体,我们需要创建另一个Lua脚本并实现Agent_Cleanup. Agent_HandleEvent. Agent_Initialize和Agent_Update函数. 创建一个Lua文件如下: src/my_sandbox/script/Agent.lua Agent.lua: function Agent_Cleanup(agent) end function Agent_HandleEvent(agent, event) end func

Lua脚本语言概述_Lua

Lua是什么 Lua是一中嵌入式的脚本语言. Lua语言可以独立进行编程,但这不是其主要的使用方式.Lua虽然有动态.灵活的语法提供强大的功能,但并不像 Java.Python 等一样有一个完善的库(但仍存在一定数量的第三方库),这不是缺陷,而是和其定位有关. Lua最典型的用法,是作为一个库,嵌入 到其他大型语言(称之为宿主语言 )的应用程序之中,为应用程序提供参数配置或逻辑描述等功能,带来前所未有的灵活性. Lua常见的宿主语言有:C/C++,Java,.NET,甚至脚本语言如PHP,Rub