一、Lua脚本功能接口

1. LuaInterface.h/.cpp声明和实现LuaInterface。

LuaInterface成员如下:

//脚本引擎

FoxLuaScriptmLua ;

//注册器

LuaCFuncRegistermFuncRegister;

//场景关联

Scene*mOwner;

//已经读取的脚本表

IDTablem_ScriptTable ;

主要方法:

VOIDInit(Scene* pScene);//完成Lua脚本环境的初始化和C导出函数的注册

Scene* GetOwner();

执行Lua脚本的C++接口,提供多达8个参数支持。

INTExeScript( ScriptID_t scriptid, CHAR* funcname ) ;

INTExeScript_D( ScriptID_t scriptid, CHAR* funcname, INT Param0 ) ;

INTExeScript_DD( ScriptID_t scriptid, CHAR* funcname, INT Param0, INT Param1 ) ;

INTExeScript_DDD( ScriptID_t scriptid, CHAR* funcname, INT Param0, INT Param1, INT Param2 ) ;

INTExeScript_DDDD( ScriptID_t scriptid, CHAR* funcname, INT Param0, INT Param1, INT Param2, INT Param3 ) ;

LuaInterface::Init里面会初始化mLua引擎,注册C++提供给Lua脚本的函数(LuaCFuncRegister),并加载ScriptGlobal.lua脚本。

2. LuaCFuncRegister.cpp里面对所有导出到Lua的C++函数进行注册。

struct _Str2Func functbl[] =

{

{"AddEventList",FuncProto(LuaFnAddNumText)},

{"GetMission", FuncProto(LuaFnGetMission)},

{"GetMissionCount", FuncProto(LuaFnGetMissionCount)},

{"SetMissionByIndex", FuncProto(LuaFnSetMissionByIndex)},

{"AddMission", FuncProto(LuaFnAddMission)},

{"AddMissionEx", FuncProto(LuaFnAddMissionEx)},

{"SetMissionEvent", FuncProto(LuaFnSetMissionEvent)},

...

};

这些C++函数的实现是在下列头文件中进行的:

#include "LuaFnTbl_Mission.h"

#include "LuaFnTbl_Misc.h"

#include "LuaFnTbl_Ability.h"

#include "LuaFnTbl_Attr.h"

#include "LuaFnTbl_Pet.h"

#include "LuaFnTbl_Battle.h"

#include "LuaFnTbl_Shop.h"

#include "LuaFnTbl_PetPlacard.h"

#include "LuaFnTbl_Scene.h"

#include "LuaFnTbl_Team.h"

#include "LuaFnTbl_DoAction.h"

#include "LuaFnTbl_Relation.h"

#include "LuaFnTbl_Guild.h"

#include "LuaFnTbl_City.h"

这些函数并不是功能的真正实现地方,真正的实现代码在Scene、Obj_Human等地方。这里只是集中转调而已。

3. 注册完成后,在Lua脚本中就可以使用类似AddMission接口调用C++里面功能。

二、Lua脚本位置

所有脚本在Bin\Public\Data\Script子目录中。

Bin\Public\Data\Script.dat是索引,里面保存了ScriptID和对应的脚本文件名。如:

888888=\scene.lua

888889=\mail.lua

888890=\player_login.lua

...

脚本ID是6位的。

三、脚本索引的初始化

每个场景都会进行脚本初始化,具体是在Scene::Load里面,在在m_pLuaInterface初始化之后。

m_pLuaInterface->Init(this);

if( !m_pScriptFileMgr->IsInit() )

{

m_pScriptFileMgr->Init( FILE_SCRIPT, FALSE);

}

Log::SaveLog( SERVER_LOGFILE, "Load ../Public/Data/script.dat OK!" );

m_pScriptFileMgr->Init将"888888=\scene.lua"拆开,保存ID和文件名到SFileData里面。所有的SFileData用SFileDataLink串起来。

四、脚本加载和调用

每个脚本的调用都是通过INT LuaFnCallScriptFunction(Lua_State* L);来进行的。该函数是一个C++函数,脚本里面调用名是CallScriptFunction,注册如下:

{"CallScriptFunction", FuncProto(LuaFnCallScriptFunction)},

LuaFnCallScriptFunction的实现在文件LuaFnTbl_Misc.h里。

可以看到在,此函数:

l 把SFileData添加到pScene->GetLuaInterface()->m_ScriptTable表里面;

pSFileData = pScene->GetLuaInterface()->GetOwner()->GetScriptFileMgr()->GetFileData(scriptId);

pScene->GetLuaInterface()->m_ScriptTable.Add( scriptId, pSFileData ) ;

l 然后加载脚本;

pScene->GetLuaInterface()->mLua.Load( const_cast<CHAR*>(filename) ) ;

l 最后调用脚本。

五、典型脚本的结构

见ScriptDef.h,定义了一些脚本接口函数,如OnDefaultEvent,对于脚本805007,就是:

function x805007_OnDefaultEvent( sceneId, selfId,targetId );

有一些调用没有在这里定义宏,直接写在C++代码里面,如OnScenePlayerLogin。

#defineDEF_EVENT_ENTRY_FUNC_NAME("OnDefaultEvent")//脚本进入函数

#defineDEF_ON_KILL_OBJECT_FUNC_NAME("OnKillObject")

#defineDEF_ON_ITEM_CHANGED_FUNC_NAME("OnItemChanged")

#defineDEF_ON_PET_CHANGED_FUNC_NAME("OnPetChanged")

#defineDEF_ON_ENTER_AREA_FUNC_NAME("OnEnterArea")

#defineDEF_ON_LEAVE_AREA_FUNC_NAME("OnLeaveArea")

#defineDEF_EVENT_ON_TIMER("OnTimer")

#defineDEF_MISSION_ACCEPT("OnMissionAccept")//接受任务

#defineDEF_MISSION_ABANDON("OnAbandon")//放弃任务

#defineDEF_MISSION_REFUSE("OnMissionRefuse")// 拒绝接受任务

#defineDEF_MISSION_SUBMIT("OnMissionSubmit")//任务完成后,提交任务

#defineDEF_MISSION_CHECK("OnMissionCheck")//任务完成条件检查

#defineDEF_MISSION_CONTINUE("OnMissionContinue")//任务没完成,继续

六、样例分析

大理NPC赵天师脚本分析

脚本名:Script\obj\dali\odali_xinshoutian.lua,汗,居然叫这个名字,找了半天,一般的命名都是拼音。

--赵天师

--脚本号

x002030_g_scriptId = 002030

--所拥有的事件ID列表

x002030_g_eventList={210200,210204,210205,210208,210210,210212,210213,210214,210216,210217,210220,210223, 210224, 210225, 210229, 210230, 210232, 210238, 210239, 210237, 210240, 200080, 200083, 200086, 200091, 200094,200095,210241,050022}

一般情况,每个event对于一个任务,也是一段脚本实现的。如210200对于:

;大理城新手指导任务

210200=\event\dali\edali_zhidao_0200.lua

--找人任务

--赵天师寻找蒲良

NPC脚本触发接口函数是xxx_OnDefaultEvent,在AI_Human的PushCommand_DefaultEvent里面触发。

ORESULT PushCommand_DefaultEvent( ObjID_t idNPC );

pCharacter->getScene()->GetLuaInterface()->ExeScript_DDD(

idScript,

DEF_EVENT_ENTRY_FUNC_NAME,

(INT)pCharacter->getScene()->SceneID(),

(INT)pCharacter->GetID(),

(INT)pNPC->GetID() ) ;

[转]天龙八部服务器端Lua脚本系统的更多相关文章

  1. 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  2. Redis进阶实践之十九 Redis如何使用lua脚本

    一.引言               redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入 ...

  3. Redis Lua 脚本使用

    本文转载自Redis Lua 脚本使用 Lua 简介 Lua语言提供了如下几种数据类型:booleans(布尔).numbers(数值).strings(字符串).tables(表格). 下面是一些 ...

  4. redis原子性读写操作之LUA脚本和watch机制

    最近在开发电商平台的子系统--储值卡系统,系统核心业务涉及到金额消费以及库存控制,因此为了解决建立在内存上高并发情况下的事务控制,使用了spring封装的RedisTemplate执行lua脚本进行原 ...

  5. Redis Lua脚本原理

    2.6版本之后支持嵌入Lua脚本,客户端使用Lua脚本,直接在服务器端原子的执行多条命令 Lua脚本执行过程 创建并修改Lua环境 1 创建基础Lua环境 2 载入函数库 3 创建全局表格Lua 4 ...

  6. redis之lua脚本

    背景介绍 redis数据库提供了一些管理功能比如 流水线:打包发送多条命令,并在一个回复里面接收所有被执行命令的结果.事务:一次执行多条命令,被执行的命令要么就全部都被执行,要么就一个也不执行.并且事 ...

  7. Java调用Lua脚本(LuaJava使用、安装及Linux安装编译)

    依赖包(附件有下载): 包名 类型 操作系统 luajava-1.1.jar jar ALL libluajava-1.1.so .so linux luajava-1.1.dll .dll wind ...

  8. Redis学习-LUA脚本

    最近在做K线的项目中,需要计算商品的分时数据.为了保证多台机器对同一商品的计算的有序性,所以在Redis中进行计算,同时为了保证在分时数据计算过程的原子性所以使用了LUA脚本,Redis内置了对LUA ...

  9. 基于Lua脚本解决实时数据处理流程中的关键问题

    摘要 在处理实时数据的过程中需要缓存的参与,由于在更新实时数据时并发处理的特点,因此在更新实时数据时经常产生新老数据相互覆盖的情况,针对这个情况调查了Redis事务和Lua脚本后,发现Redis事务并 ...

随机推荐

  1. [leetcode] Path sum路径之和

    要求给定树,与路径和,判断是否存在从跟到叶子之和为给定值的路径.比如下图中,给定路径之和为22,存在路径<5,4,11,2>,因此返回true;否则返回false. 5 / \ 4 8 / ...

  2. powerdesigner连接数据库 导出数据 生成PDM文件 傻瓜试教程

    也可下载文档:http://download.csdn.net/detail/shutingwang/6378665 

  3. BIND9配置文件详解模板[转载]

    在CU上看到了一篇关于BIND9配置文件详解的文章,感觉不错,现转载了分享一下. //named.conf 注释说明 by shellyxz@163.com// 此文件对bind9的默认配置文件的说明 ...

  4. Linux 线程属性函数总结

    1.初始化一个线程对象的属性 int pthread_attr_init(pthread_attr_t *attr); 返回值:若是成功返回0,否则返回错误的编号 形 参: attr 指向一个线程属性 ...

  5. JEE学习线路

    传智播客:javaEE学习线路以及需要掌握的知识点:http://java.itcast.cn/subject/javastudypath/index.shtml 最近在学JavaEE,没学Java ...

  6. 第六届华为创新杯编程大赛-进阶1第1轮 洞穴逃生 (bfs + 优先队列)

    这个题容易出错想了挺长时间,然后代码不长,1Y.. 做完题,看了一下别人的博客,也可以优先用 闪烁法术, 在闪烁法术不不如跑步的阶段(即魔法恢复的时候)用跑步. 洞穴逃生 描述: 精灵王子爱好冒险,在 ...

  7. poj 2528 Mayor's posters(线段树)

    题目:http://poj.org/problem?id=2528 题意:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意的, 但是必定是单位宽度的整数 ...

  8. QSettings介绍

    简介 QSettings类提供了持久的跨平台应用程序设置. 用户通常期望应用程序记住它的设置(窗口大小.位置等)所有会话.这些信息通常存储在Windows系统注册表,OS X和iOS的属性列表文件中. ...

  9. javascript插件编写小结

    写JS插件,最好是先通过HTML方式将展示结果显示出来,然后再封装成JS插件,将其画出来.JS模板如下: (function($){ $.fn.fnName = function(options){ ...

  10. 装个Redmine真是麻烦啊

    弄个大半天终于看到这个界面出来了,不容易啊