driver内LPC联合使用python写efun

ldmud支持用python写efun然后在游戏内调用,python具有丰富的第三方库,这样就使得driver的能力获得了扩展。

下面就实际举个使用python扩展efun的例子

驱动下载

环境配置使用的是LDMud 3.6.5 (3.6.5-5-gf597dee3) 编译时开启了python,windows下我已经编译好了具体的驱动,使用的lib是我移植的风云2005,我已经把驱动和lib打包上传,下载地址如下:

链接: https://pan.baidu.com/s/1ba0iQ-uyFebeeeC4XkRe9Q?pwd=489y 提取码: 489y 复制这段内容后打开百度网盘手机App,操作更方便哦

如果有能力自己配置driver编译的话,也可以自己编译,下载好压缩包后解压缩至c盘根目录下,然后进入C:\mud\

mud目录

下面来看下mud目录的具体构成,mud目录下7个子目录:

  • bin内为可执行程序
  • erq内空目录
  • examples目录为python扩展的脚本例子
  • include为driver所需的各种头文件,这些也存在于lib文件夹的\sys内
  • python目录为driver所需要的python环境
  • share目录是man帮助文件

有的小伙伴可能会讲我不想放在C盘下,可以放在其他目录么,放在其他目录也可以,那样的话:一键运行.bat就无法直接使用,需要你自己配置才能一键启动。有的小伙伴可能会问为什么不编译一个放在D盘下的,那是因为我是在云服务器上编译的,我的云服务器只有一个盘符C。

python环境

今天我要分享的重点是使用python联合编程,那么是一定要加载python的。

在运行driver加载python之前,首先是本机也一定要安装python,可以去python官网下载,这里我是用的版本是:Python 3.9.12 - March 23, 2022,直接选择Download Windows installer (64-bit) 下载安装,下载好运行安装包选择Customize installation可自定义路径(我选这个),你也可以选择默认安装路径,勾选Add Python 3.9.12 to PATH是把Python的安装路径添加到系统环境变量的Path变量中,这步一定要选择。

这样你的本机就安装好了python,本机没有python也无法在driver内使用python。

python efun

下面来看一下C:\mud\bin\一键运行.bat的内容:

C:
cd \mud\bin
set PYTHONHOME=/cygdrive/c/mud/python
set HOME=/cygdrive/c/mud/python
ldmud --python-script C:\mud\examples\startup.py 3333
pause

关键的内容是ldmud --python-script C:\mud\examples\startup.py 3333,解释一下意思就是启动的时候,加载python efun的文件内容为C:\mud\examples\startup.py,同时端口设定为3333,ldmud在启动时候支持很多命令行,参数具体的可以看:https://github.com/ldmud/ldmud/blob/master/doc/driver/invocation

如果不想加载python那么可以去掉--python-script C:\mud\examples\startup.py这样就不使用python了。

下面来看一下C:\mud\examples\startup.py的内容

# This module can be used as a startup script.
#
# It will load all the other modules that offer the ldmud_efun entry point.
# In the configuration file ~/.ldmud-efuns single efuns can be deactivated
# with entries like this:
#
#   [efuns]
#   name_of_the_efun = off

from ldmudefuns.startup import startup
import ldmud
def python_return(val):
    """Return the given value to check the
    type conversion between Python and LPC."""
    return val
def python_abs(arg:int):
    return abs(arg)    

ldmud.register_efun("python_return", python_return)
ldmud.register_efun("abs",python_abs)
startup()

import的部分是必不可少的,然后是在下面我写了两个简单的python efun,一个是python_return,它的做就用是直接返回函数参数,另外一个就是python_abs(arg:int) 这个函数的作用就是返回一个绝对值,这两个简单efun 都是起到测试的作用,函数的下面ldmud.register_efun("python_return", python_return)的意思就是把这两个python的函数注册成lpc的efun名字分别是python_returnpython_abs,这里efun的名字你可以自己指定比如注册成ldmud.register_efun("abs",_abs)那么efun的名字就是_abs。最后一行 startup() 这个不用解释了。

编写好python 文件后保存退出,运行C:\mud\bin\一键运行.bat driver跑起来后能看到

C:\mud\bin>ldmud  --python-script E:\bank\fengyun_ldmud_with_python\ldmud_with_python\examples\startup.py 3333
2022.07.28 17:31:17 LDMud 3.6.5 (3.6.5-5-gf597dee3) (development)
2022.07.28 17:31:17 Seeding PRNG from /dev/urandom.
2022.07.28 17:31:17 TLS deactivated.
Registering Python efun python_efun_help
Registering Python efun python_reload
Registering Python efun json_parse
Registering Python efun json_serialize
//...此处省略若干
LDMud ready for users.

这说明已driver经成功运行,登陆游戏本机3333端口,使用wiz账号可以做一个测试

eval printf("%O",python_abs(-1))

显示是1说明python efun 运行良好,以上是自带简单的python的例子。

复杂示例

下面我们来一个复杂有点的例子,比如目前游戏里面的时间系统都很简单,我想给游戏增加一些复杂的,比如农历、黄历、二十四节气、节假日、星次、每日凶煞、每日值神、农历建除十二神、农历每日宜忌、彭祖百忌、每日五行、二十八星宿、天干地支、农历生辰八字、时辰凶吉等,甚至可以考虑加入个算卦的npc来卜卦,那么可以怎么办呢?

如果用lpc从头开写工作量是很大的,这时候python的优越性就展现出来了,我直接登陆 https://github.com/ 搜索python 然后我找了一个日历的库 https://github.com/OPN48/cnlunar ,很好这库还可以直接使用pip安装,那就更简单了。

下面开始:

打开cmd命令行,然后运行pip3 install cnlunar直接安装库,安装好之后需要再次运行一次pip3 install cnlunar,这样系统会提示你Requirement already satisfied: cnlunar in c:\python\python39\lib\site-packages (0.0.7) 这里划重点,要记住。

这样你就知道你这个程序包的位置了,这里个位置就是一开始你安装python选的自定义路径有关,比如我的python安装的位置是c:\python\,cnlunar库安装好了,然后呢我们就仿照 https://github.com/OPN48/cnlunar/blob/master/cnlunar/demo.py 写一个可以在driver提lpc调用的efun,这里为了简单起见我直接粘贴我写好的

#coding:utf-8
# This module can be used as a startup script.
#
# It will load all the other modules that offer the ldmud_efun entry point.
# In the configuration file ~/.ldmud-efuns single efuns can be deactivated
# with entries like this:
#
#   [efuns]
#   name_of_the_efun = off

from ldmudefuns.startup import startup
import ldmud
import datetime
import cnlunar

def p_cnlunar():
    a = cnlunar.Lunar() # 为空为当前时间 #
    dic = {
    '日期': str(a.date),
    '农历数字': str((a.lunarYear, a.lunarMonth, a.lunarDay, '闰' if a.isLunarLeapMonth else '')),
    '农历': '%s %s[%s]年 %s%s' % (a.lunarYearCn, a.year8Char, a.chineseYearZodiac, a.lunarMonthCn, a.lunarDayCn),
    '星期': str(a.weekDayCn),
    '今日节日': str((a.get_legalHolidays(), a.get_otherHolidays(), a.get_otherLunarHolidays())),
    '八字': str(' '.join([a.year8Char, a.month8Char, a.day8Char, a.twohour8Char])),
    '今日节气': str(a.todaySolarTerms),
    '下一节气': str((a.nextSolarTerm, a.nextSolarTermDate, a.nextSolarTermYear)),
    '今年节气表': str(a.thisYearSolarTermsDic),
    '季节': str(a.lunarSeason),
    '今日时辰': str(a.twohour8CharList),
    '时辰凶吉': str(a.get_twohourLuckyList()),
    '生肖冲煞': str(a.chineseZodiacClash),
    '星座': str(a.starZodiac),
    '星次': str(a.todayEastZodiac),
    '彭祖百忌': str(a.get_pengTaboo()),
    '彭祖百忌精简': str(a.get_pengTaboo(long=4, delimit='<br>')),
    '十二神': str(a.get_today12DayOfficer()),
    '廿八宿': str(a.get_the28Stars()),
    '今日三合': str(a.zodiacMark3List),
    '今日六合': str(a.zodiacMark6),
    '今日五行': str(a.get_today5Elements()),
    '纳音': str(a.get_nayin()),
    '九宫飞星': str(a.get_the9FlyStar()),
    '吉神方位': str(a.get_luckyGodsDirection()),
    '今日胎神': str(a.get_fetalGod()),
    '神煞宜忌': str(a.angelDemon),
    '今日吉神': str(a.goodGodName),
    '今日凶煞': str(a.badGodName),
    '宜忌等第': str(a.todayLevelName),
    '宜': str(a.goodThing),
    '忌': str(a.badThing),
    '时辰经络': str(a.meridians)
}

    return ldmud.Mapping(dic)

ldmud.register_efun("p_cnlunar", p_cnlunar)
startup()

下面来看下内容:

from ldmudefuns.startup import startup

import ldmud

这些是必不可少的内容不解释了

import datetime

import cnlunar

从这里开始就是复制了 https://github.com/OPN48/cnlunar/blob/master/cnlunar/demo.py 里面的内容并且定义了一个python函数def p_cnlunar() 为了简单起见这个函数不需要参数直接返回的内容是ldmud.Mapping(dic) 也就是一个lpc mapping格式的数据,需要注意的是这里使用了str()把python dic 里面的内容强制转换成了string,把上述的代码保存为C:\mud\examples\startup.py

然后直接运行C:\mud\bin\一键运行.bat 你会发现 cmd line里面提示

Traceback (most recent call last):
  File "C:\mud\examples\startup.py", line 14, in <module>
    import cnlunar
ModuleNotFoundError: No module named 'cnlunar'

思考下,这说明了什么?这说明没有cnlunar模块,可是刚刚我的确pip3安装了cnlunar了啊,这是因为你是在本机python环境下安装了这个模块,但是ldmud需要的python环境里面没有,那么该怎么办呢?

还记的Requirement already satisfied: cnlunar in c:\python\python39\lib\site-packages (0.0.7) 吗

这就好办了,打开c:\python\python39\lib\site-packages文件夹把这个复制到C:\mud\python\lib\python3.9\里面,替换确认,或者是打开c:\python\python39\lib\site-packages找到cnlunar的安装目录cnlunar和cnlunar-0.0.7.dist-info目录直接复制这两个目录到C:\mud\python\lib\python3.9\site-packages目录内,这样我们ldmud需要的python环境里面就有了cnlunar模块了。

然后关掉cmd重新运行C:\mud\bin\一键运行.bat我们发现这次提示

C:\mud\bin>ldmud  --python-script C:\mud\examples\startup.py 3333
2022.07.28 19:29:49 LDMud 3.6.5 (3.6.5-5-gf597dee3) (development)
2022.07.28 19:29:50 Seeding PRNG from /dev/urandom.
2022.07.28 19:29:50 TLS deactivated.
Registering Python efun python_efun_help
Registering Python efun python_reload
Registering Python efun json_parse
Registering Python efun json_serialize
//...此处省略若干
LDMud ready for users.

这就说明driver已经正确加载python脚本了,登陆游戏使用wiz账号继续做一个测试eval

printf("%O",p_cnlunar())

显示是:

>eval printf("%O",p_cnlunar())
([ /* #1 */
  "农历": "二零二二 壬寅[虎]年 六月大三十",
  "今日凶煞": "['往亡', '伏兵', '天吏', '受死', '破败', '月建转杀', '土王用事', '血支', '制日']",
  "宜忌等第": "中次:凶胜于吉,遇德从宜亦从忌,不遇从忌不从宜。",
  "忌": "['出行', '安床', '上表章', '冠带', '竖柱上梁', '开市', '修置产室', '开渠', '穿井', '安碓硙', '平治道涂', '破屋坏垣', '捕捉',
'畋猎', '栽种', '牧养', '营建', '苫盖', '缮城郭', '解除', '开仓', '选将', '招贤', '上册', '出师', '祈福', '疗目', '颁诏', '求嗣', 
'举正直', '修宫室', '取鱼', '修仓库', '修饰垣墙', '施恩', '宣政事', '安抚边境', '针刺']",
  "星次": "鹑火",
  "吉神方位": "['喜神正南', '财神正南', '福神东南', '阳贵正东', '阴贵东南']",
  "生肖冲煞": "马日冲鼠",
  "农历数字": "(2022, 6, 30, '')",
  "今日胎神": "仓库碓外西北",
  "时辰凶吉": "['吉', '吉', '凶', '吉', '凶', '凶', '吉', '凶', '吉', '吉', '凶', '凶', '凶']",
  "今日节气": "无",
  "十二神": "('闭', '天牢', '黑道日')",
  "今日五行": "['天干', '壬', '属水', '地支', '午', '属火', '纳音', '木', '属木', '廿八宿', '角', '宿', '十二神', '闭', '日']",
  "彭祖百忌": "壬不泱水 更难提防,午不苫盖 屋主更张",
  "星座": "狮子座",
  "今日吉神": "['岁德', '六合', '不将', '大葬', '鸣吠', '不守塚', '官日', '天恩', '天医', '明星', '吉庆']",
  "神煞宜忌": "((['岁德', '六合', '不将', '大葬', '鸣吠', '不守塚', '官日', '天恩', '天医', '明星', '吉庆'], ['往亡', '伏兵', '天吏',
'受死', '破败', '月建转杀', '土王用事', '血支', '制日']), (['经络', '安葬', '诉讼', '恤孤茕', '酝酿', '塞穴', '雪冤', '入宅', '覃恩', 
'赴任'], ['出行', '安床', '上表章', '冠带', '竖柱上梁', '开市', '修置产室', '开渠', '穿井', '安碓硙', '平治道涂', '破屋坏垣', '捕捉', 
'畋猎', '栽种', '牧养', '营建', '苫盖', '缮城郭', '解除', '开仓', '选将', '招贤', '上册', '出师', '祈福', '疗目', '颁诏', '求嗣', 
'举正直', '修宫室', '取鱼', '修仓库', '修饰垣墙', '施恩', '宣政事', '安抚边境', '针刺']))",
  "今年节气表": "{'小寒': (1, 5), '大寒': (1, 20), '立春': (2, 4), '雨水': (2, 19), '惊蛰': (3, 5), '春分': (3, 20),
'清明': (4, 5), '谷雨': (4, 20), '立夏': (5, 5), '小满': (5, 21), '芒种': (6, 6), '夏至': (6, 21), '小暑': (7, 7), 
'大暑': (7, 23), '立秋': (8, 7), '处暑': (8, 23), '白露': (9, 7), '秋分': (9, 23), '寒露': (10, 8), '霜降': (10, 
23), '立冬': (11, 7), '小雪': (11, 22), '大雪': (12, 7), '冬至': (12, 22)}",
  "星期": "星期四",
  "下一节气": "('立秋', (8, 7), 2022)",
  "八字": "壬寅 丁未 壬午 庚戌",
  "宜": "['经络', '安葬', '诉讼', '恤孤茕', '酝酿', '塞穴', '雪冤', '入宅', '覃恩', '赴任']",
  "彭祖百忌精简": "壬不泱水<br>午不苫盖",
  "廿八宿": "角木蛟",
  "今日三合": "['狗', '虎']",
  "今日六合": "羊",
  "九宫飞星": "624579138",
  "今日节日": "('', '', '')",
  "纳音": "杨柳木",
  "今日时辰": "['庚子', '辛丑', '壬寅', '癸卯', '甲辰', '乙巳', '丙午', '丁未', '戊申', '己酉', '庚戌', '辛亥', '壬子']",
  "季节": "季夏",
  "日期": "2022-07-28 19:29:50.168677",
  "时辰经络": "心包"
])
Result = 0

说明python efun 运行正常,想象下自己重新写个农历时间efun得多耗时,就知道直接使用python有多香了。

如果一直使用python来编写efun的话python的水平也会提高,这样对于新手wiz来说等于又学习了python编程,一举 两得。

京ICP备13031296号-4