[lua] 游戏客户端逻辑使用lua协程
我们的游戏有这样一种情景:客户端中角色需要用到一些公会的数据,但服务器不会在玩家(创角后)一进入到游戏里就推送给玩家,而是需要客户端自己在需要的时候向服务器请求公会的数据,之前的实现就是在请求消息的时候加一个回调函数,消息一回来就执行回调函数继续后续的业务!但后面发现存在这样的不足:
1.有时会用到好多个参数,这就需要每次都把一些无关的参数传给消息请求者,然后回调过来再把这些参数原封不动地传回来,很繁琐;
2.这样的回调写法感觉很不符合人类的顺序思维习惯,有点乱;
回调的lua代码写法类似:
--@callbackFunc带的参数可能有(self, p1, p2, ..., [最后还有allianceData, 这个是取到数据后分发时加上的]) function AllianceProxy:requestAllianceData(callbackFunc) --handle send request msg --这里使用一个uniqueKey往一个管理器中注册保存这个回调 end function AllianceProxy:responseAllianceData(allianceData) --handle receive response msg --这里根据上面uniqueKey分发消息,执行回调, 调用类似:callbackFunc(self, p1, p2, ..., allianceData) end --请求公会数据的写法就是这样: function Role:handleAllianceData() local function _callbackFunc(self, p1, p2, allianceData) --使用的到allianceData处理相关的业务逻辑 end AllianceProxy:requestAllianceData(packing(_callbackFunc, self, p1, p2)) --packing返回的仍然是一个function end
上述的参数self, p1, p2, ...等等完全就没必要往requestAllianceData中丢过去的,但就是因为收到回调后需要用到,作为强迫症的我,觉得这种写法很恶心,所以今天想到,这完全可以利用lua提供的协程机制来做这件事,大致思路的代码如下:(注:下面这些代码未经过编译及测试,另外还未考虑协程恢复执行时若其主函数所在table被销毁的情况, 后续会完善下面的代码)
--创建并运行一个协程
--@param mainFunc 协程主函数
function global:createAndRunningCo(mainFunc)
self:assertFmt(type(mainFunc) == 'function', 'func=%s is not function', tostring(mainFunc))
local co = coroutine.create(mainFunc)
local isSuccess, errMsg = coroutine.resume(co, co)
self:assertFmt(isSuccess, 'one error happened in mainFunc:%s', errMsg)
end
function global:checkCoIsRunning(co)
self:assertFmt(type(co) == 'thread')
local curCo = coroutine.running()
self:assertFmt(co == curCo, 'co[%s] is not running, current running coroutine is %s, please sure that co is running', co, curCo)
end
function global:yieldAndSaveCo(key, co)
self:assertFmt(key ~= nil)
self:checkCoIsRunning(co)
if coT[key] == nil then
coT[key] = {}
end
table.insert(coT[key], co)
return coroutine.yield()
end
function global:resumeAndRemoveCo(key, ...)
if coT[key] then
for _, co in ipairs(coT[key]) do
if coroutine.status(co) == 'suspended' then
local isSuccess, errMsg = coroutine.resume(co, ...)
self:assertFmt(isSuccess, 'one error happened in mainFunc:%s', errMsg)
end
end
coT[key] = nil
end
end
local global = require('global')
global:createAndRunningCo(function(co)
local allianceData = Alliance:requestAllianceData(co)
--do something
end)
function AllianceProxy:requestAllianceData(co)
--send msg : request alliance Data
return global:yieldAndSaveCo('allianceData', co)
end
function AllianceProxy:responseAllianceData(allianceData)
--receive msg : response alliance data
global:resumeAndRemoveCo('allianceData', allianceData)
end
需要获取公会数据的用户就使用下面这样的写法则可:
global:createAndRunningCo(function(co)
local allianceData = Alliance:requestAllianceData(co)
--do something
end)
然后在消息收发那里做好相应的处理就行了,这个写法跟前面的对比,很明显,我们顺序的编写相应的逻辑就行了,完全不需要像前面的说等回调过来后反过头来再执行相应的逻辑
[lua] 游戏客户端逻辑使用lua协程的更多相关文章
- lua:写了个基于协程的task调度库
写了一个(不完整的)基于协程的task调度库 sample code如下 my_spawn( function () print('f: 1') local t1 = my_spawn( functi ...
- Cocos2d-x lua游戏开发之安装Lua到mac系统
注意:mac ox .lua version :5.15 下载lua官网的lua, 注意:最好是5.15下面.5.2的lua不支持table的getn()方法,这让我情何以堪.(获取table长度.相 ...
- Openresty Lua协程调度机制
写在前面 OpenResty(后面简称:OR)是一个基于Nginx和Lua的高性能Web平台,它内部集成大量的Lua API以及第三方模块,可以利用它快速搭建支持高并发.极具动态性和扩展性的Web应用 ...
- lua编程之协程介绍
一,lua协程简介 协程(coroutine),意思就是协作的例程,最早由Melvin Conway在1963年提出并实现.跟主流程序语言中的线程不一样,线程属于侵入式组件,线程实现的系统称之为抢占式 ...
- 《Lua游戏开发实践指南》读后感
书籍地址:http://book.douban.com/subject/20392269/ 一句话点评该书:想用Lua作游戏脚本开发的同学值得一读! (一)本书特点 市面专门讲Lua的中文书籍非常少, ...
- python协程--yield和yield from
字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...
- Unity3D中的线程与协程
线程 Unity3D是以生命周期主线程循环进行游戏开发. Unity3D中的子线程无法运行Unity SDK(开发者工具包,软件包.软件框架)跟API(应用程序编程接口,函数库). 限制原因:大多数游 ...
- Kotlin协程解析系列(上):协程调度与挂起
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...
- 45、concurrent.futures模块与协程
concurrent.futures —Launching parallel tasks concurrent.futures模块同时提供了进程池和线程池,它是将来的使用趋势,同样我们之前学习 ...
随机推荐
- #DP# ----- OpenJudge山区建小学
没有记性.到DP不得不写博了,三天后又忘的干干净净.DP是啥 :-) 一道久到不能再久的题了. OpenJudge 7624:山区建小学 总时间限制: 1000ms 内存限制: 65536k ...
- cvc-complex-type.2.4.c: The matching wildcard...
在家里的电脑好好的,在单位的就不行,需要把web app libraties提到 最前面,然后clean一下项目
- JSON在线解析,新版本JSON在线解析
SOJSON,出了新版本的JSON在线解析,真的很好用,可以上下版本.左右版本.效果图如下.它的网址是:http://www.sojson.com/simple_json.html SOJSON集成了 ...
- CodeForces 451B
Sort the Array Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Sub ...
- SDWebImage源码解读之干货大总结
这是我认为的一些重要的知识点进行的总结. 1.图片编码简介 大家都知道,数据在网络中是以二进制流的形式传播的,那么我们该如何把那些1和0解析成我们需要的数据格式呢? 说的简单一点就是,当文件都使用二进 ...
- 爱你不容易 —— Stream详解
作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() ...
- 一次dns缓存引发的惨案
时间2015年的某个周六凌晨5点,公司官方的QQ群有用户反馈官网打不开了,但有的用户反馈可以打开,客服爬起来自己用电脑试了一下没有问题,就给客户反馈说,可能是自己网络的问题,请过会在试试.早点8点,越 ...
- 浅谈时间复杂度- 算法衡量标准Big O
写在前面: 今天有一场考试,考到了Big-O的知识点,考到了一道原题,原题的答案我记住了,但实际题目有一些改动导致答案有所改动,为此作者决定重新整理一下复杂度相关知识点 Efficiency and ...
- Jquery AutoComplete实现搜索自动完成
AutoComplete控件就是指用户在文本框输入前几个字母或是汉字的时候,该控件就能从存放数据的文本或是数据库里将所有以这些字母开头的数据提示给用户,供用户选择,提供方便. 例子: <!doc ...
- LVS的十种调度算法
LVS十种调度算法 1.静态调度: ①rr(Round Robin):轮询调度,轮叫调度 轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重 ...