Results 1 comments of 小大圣

您好,无意间逛到这个issue,我是个业余爱好者,用nonebot做个人用的qq机器人也已经很久了,非常感谢各位开发者能让我们这么方便的做qqbot。想从一个业余代码的角度聊聊这段时间用nonebot的感受。 看到这里聊到用nonebot做游戏,我从一开始用的时候到现在,在我的qq机器人上做过好几个小游戏,还写过一个比较简单的多人对战游戏的API。我的qq机器人是指令型的而不是对话型的,很大程度上是因为nonebot本身就是指令型的。nonebot的session确实无法直接用来做多人游戏,所以我一开始写游戏API的时候逻辑是完全和session这个逻辑无关的,就是在插件里自己维护一些Game对象,用户对话时操作Game对象,独立完成判断。用这个API我写过几个多人的或是单人的小游戏,用指令进入/退出游戏,游戏过程中通过on_natural_language装饰的函数处理游戏操作。 ![6V({BUANV1$BW%`A0JRO~(1](https://user-images.githubusercontent.com/17756612/137330794-f7cba778-6660-467c-a2f1-97e20f6d4c63.png) 一段时间前,我看到nonebot 1.8.0更新了CommandSession.aget函数,我惊呼这就是我很久之前就想过但是自己又无法实现的功能,在目前session绑定到用户的情况下,有这个异步暂停的功能可以实现很多复杂的想法。我最近在维护的一个多人游戏就很大程度上受益于这个函数。这个游戏是一个有复杂结算机制的卡牌游戏,诸如摸牌弃牌使用手牌等等都可能会有嵌套结算。使用手牌时可能需要选定对象,或是手牌超出上限需要弃牌这些都是需要借助aget异步暂停才得以实现的。虽然在整个游戏的层面上仍然是类似于之前的逻辑,Game对象本身存在插件中,但是我也对用户交互这里做了一些自己的封装(虽然这一部分是参考了一些我学软件工程的同学的意见)。我先是对session做了一个简单的包装,使它携带一个缓冲区,在需要的时候再进行flush,这是因为游戏结算可能会在同一次用户交互时显示很多次结算信息,这些信息需要打包到一条消息里进行发送。在用户数据这一块,由于这个游戏不是回合制的,不同用户的交互之间会有穿插,而攻击之类的操作也可能会涉及到其他用户,我使用了一个UserData类存数据,对每一个用户绑定同一个UserData,然后User类保有一个UserData对象和一个带缓冲区的session,在每次交互时创建交互结束时删除,这样与同一个用户相关的所有操作结果会输出到同一个缓冲区然后flush。 (当然这是比较specific的idea,更general一点的可能还是session支持多人这个比较现实吧......) 关于其他部分我也有一些个人的想法。虽然比较不好意思,我在使用的时候是对nonebot本身的源码做了一些修改的。我在使用时发现了几个瓶颈。第一个问题是指令的帮助,我将指令帮助文本放在了函数的__doc__里,依靠反射获取帮助文本,那么查找帮助文本的时候就需要从nonebot的Command里去寻找,这本身比较简单。但是我遇到的问题是,假设我有一个指令`play.game1`,一个指令`play.game2`,我想在调用指令`play`时自动发送play的帮助文档。在nonebot 1.8.0以前的时候指令是树状存储的,无法同时创建指令`play`和`play.game1`,我也只能对nonebot的源码做少量的修改来达到这一要求。当然在我现在使用的版本1.8.2里命令的储存方式修改了,这也不再是问题了,但是我仍然需要修改on_command函数来达到自动创建`play`指令(以及一些更复杂的逻辑,比如某些调试用指令需要hide,某些特殊指令不完全依照前缀分类而是应当显示在别的母指令下)的目的。 另一个修改是权限方面的问题。上面也讨论过了,权限控制确实是一个非常复杂的内容,我遇到过有的群的建议是在每天的某些时间开放某些指令,这些也只能用lambda来表示了。目前我自己简单地写了一个类,在我修改后的on_command里传进去,包含“在某些群里可以使用”、“某些群的管理员可用”、额外的lambda限制、是否私聊可用,以及一些储存在文件中的可变项表示“游戏维护中”等。以及还有一点比较重要的是,在某些不可用的情况发送一条消息。比如说在开放时段之外的时间试图调用时会发送提示消息“这个游戏在每天xx点至xx点开放”,甚至更复杂的是这条消息本身也可能包含可变信息需要用lambda来表示等等我觉得都是有可能有需求的。 还有另外一些虽然自己做起来很简单但是也是不可或缺的内容,比如对于复杂游戏可能需要自己维护一个log文件,对于容易抛出error又需要调试的地方需要wrap一下以消息的形式发送error message等等。 再次感谢各位开发者的努力付出。