unity是C#+lua,lua有很多插件xlua 和slua等等。
UE4是C++配合unlua。
网易服务器是自研服务端引擎,一般是lpc、python或者luaRedis 本身已经提供了丰富的命令,但是直接用来处理一些复杂业务时可能还不够方便,会有一定的局限性。因此,在 Redis26 版本开始提供了对 Lua 脚本的支持,Lua 脚本的使用还是比较广泛的,比如商品秒杀、分布式锁等,使用 Lua 脚本可以带来以下的好处:
为了让例子更加的贴近实际应用,这里实现一个简单版的分布式锁。这里先用 Jedis *** 作。
上边详细的介绍了分布式锁的实现过程,以及可能出现的问题,最终,我们决定删除锁的 *** 作使用 Lua 脚本实现,对应的脚本如下:
Lua 脚本中执行具体的 Redis 命令,需要使用 rediscall() 方法, KEYS 表示客户端发起脚本执行命令时携带的 Redis key 的一个集合, ARGV 则是其它参数的一个集合,主意下标从1开始。结合我们的业务,这里的 KEYS[1] 则表示 lock , ARGV[1] 则是一个随机字符串。整个脚本的含义就是,如果客户端传递的 lock 的 value 和 Redis 中存储的一致,就删除 lock 。
Lua 脚本的语法还是比较简单的,具体内容可以自行学习。
前边的准备工作基本结束了,文章开始说过执行脚本有两种途径,下边我们具体来看:
这里使用 jediseval() 发送脚本到 Redis 服务器执行,后两个参数分别是 key 的集合,以及 value 参数的集合。
先将脚本以文件形式放到 Redis 里,例如这样:
然后通过如下命令让 Redis 服务器缓存脚本:
script load 命令会在 Redis 服务器缓存 Lua 脚本,并且脚本内容经过 SHA-1 签名算法处理后,会返回脚本内容的 SHA1 校验和的编码,然后在端调用时,传入编码字符串作为参数,这样 Redis 服务器就会执行对应缓存的脚本了,就不用了每次发送具体的脚本内容了。
还有两个比较有用的命令:
除了使用上边的命令缓存脚本、生成脚本的 SHA1 校验和的编码,还可以使用 Jedis 实现,但最终的 SHA1 编码内容是不同的:
实际的项目中,可能更多的会在 SpringBoot 项目中整合 Redis,此时执行 Lua 脚本的基本流程如下:
核心的类就是 DefaultRedisScript ,它实现了 RedisScript 接口。 execute() 方法最后一个参数是可变类型的,用来传递多个 value 参数。初次执行 execute() 方法时,其内部会自动缓存 Lua 脚本到 Redis 服务器;同时每次执行脚本时会根据脚本内容自动计算出对应的 SHA1 校验和的编码,去匹配、执行缓存的脚本。
具体的 SHA1 校验和的编码,可以在 execute() 方法执行后,使用 redisScriptgetSha1() 查看。使用 SpringBoot 方式 执行 Lua 脚本生成的 SHA1 校验和的编码和前边直接使用 Jedis 生成的一致。
无论用那种方式在 Redis 中使用 Lua 脚本,其中的原理都是类似的。protobuf Google的一个很好用的传输数据的封装 说实话Google的东西确实比较好用 所以我们前后端数据交换就用他了 不过Google没有对lua进行支持 还好社区有开源的大侠们贡献 找了所有关于lua protobuf 我只找到 云风的 pbc 修改相关cocos2d-x中的类可以正常使用。protoc-gen-lua 我在使用的时候 总是报截断数据 在修改后cocs2d-x中的类之后没有对protoc-gen-lua 进行测试是否是这个问题导致
1)集成 云风 云大侠的(博客)lua-pbc 标准c写的protobuf 具体看pbc的帮助很轻松集成
2) 生成pb文件(我自己写了个mac中批处理生成所有proto文件为pb文件)把pb 和proto文件都加入到项目资源中
[objc] view plaincopy在CODE上查看代码片派生到我的代码片
#!/bin/sh
#pb = "pb"
for i in proto
do
#echo $i
#echo ${i%}"pb"
#echo ${i%}
#pbn = $i | cut -d
pbname=${i%}"pb"
#echo $pbn
#echo $pbname
protoc --descriptor_set_out $pbname $i
done
echo "finish"
也可以用命令行手动生成
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
protoc --descriptor_set_out aaapb aaaproto
3)本步骤可以忽略了,可以直接用io进行读取(Android是路径问题请看本文最下面解释)在lua中使用如下代码(我用的是cocos2d-x中绑定的CCFileUtils中的获取文件的方式,不过要手动用tolua++进行绑定到lua,可以参考我上个文章中的绑定方式,云大侠中的 用lua io形式获取在相关了解中不能跨平台所有就用这个了)
[javascript] view plaincopy在CODE上查看代码片派生到我的代码片
local protobuf = require "protobuf"
local buffer = CCFileUtils:sharedFileUtils():getFileData("entity/p_resultpb","r",0)
-- print(buffer)
protobufregister(buffer)
4)本步骤可以忽略了,可以直接用io进行读取(Android是路径问题请看本文最下面解释) 上一步完成后我们要对提到的CCFileUtilscpp中的类进行修改 如果不修改读文件pb文件会时好时坏 原因是 读文件的时候结束总是添加多余字节我也不清楚这个问题 进行修改cocos2d-x中CCFileUtilscpp的下面方法中的读取数据后处理并在tolua++ 中添加下面方法绑定到lua层
修改CCFileUtilscp getFileData(const char pszFileName, const char pszMode,unsignedlong pSize)方法(在最后添加\0,保证字节不多余)如下代码
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
unsigned char CCFileUtils::getFileData(const char pszFileName, const char pszMode, unsigned long pSize)
{
unsigned char pBuffer = NULL;
CCAssert(pszFileName != NULL && pSize != NULL && pszMode != NULL, "Invalid parameters");
pSize = 0;
do
{
// read the file from hardware
std::string fullPath = fullPathForFilename(pszFileName);
FILE fp = fopen(fullPathc_str(), pszMode);
CC_BREAK_IF(!fp);
fseek(fp,0,SEEK_END);
pSize = ftell(fp);
fseek(fp,0,SEEK_SET);
pBuffer = new unsigned char[pSize];
pSize = fread(pBuffer,sizeof(unsigned char), pSize,fp);
fclose(fp);
} while (0);
if (pSize >0 && pBuffer[pSize] != '\0')
pBuffer[pSize] = '\0';
if (! pBuffer)
{
std::string msg = "Get data from file(";
msgappend(pszFileName)append(") failed!");
CCLOG("%s", msgc_str());
}
return pBuffer;
}
5)经过上一步骤lua层基本搞定可以创建本地的数据并encode成传输数据到服务器端了 如下代码
[javascript] view plaincopy在CODE上查看代码片派生到我的代码片
local major = {
majorId = "795f94a9-3466-41b4-bf16-043ba8081fab"
}
local buffer = protobufencode("comsjwebprotoMajor", major)
6)我们客户端数据传输到服务器端 服务器端会返回数据给我们 同样我们接收的数据肯定也是protobuf数据了 用 protobufdecode进行解数据
[javascript] view plaincopy在CODE上查看代码片派生到我的代码片
local t = protobufdecode("comsjwebprotoResult", request:getResponseString())--toluacast(eventdataCString))--toluacast(eventdataCString,"CCString"):getCString())
cclog(t)
print(tmajorgender)
print(tmajormajorId)
print(tuserusername)
7)上一步中的数据是服务器端过来的数据,不过在>主要用途是:
(1)描述界面:WOW和剑网三的界面都是用LUA写的;
(2)沟通引擎:游戏图形引擎提供了一些接口库,可以在LUA中调用;
(3)服务器端:有些游戏,例如剑网三,在服务器端也会大量使用LUA。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)