从头开发MUDLIB

跟Akuma一起从头打造mudlib--【第一讲】

第一讲:让它跑起来
注:每一讲我都会上传一个相符的lib,有些文件是旧的,有些是新的,我尽可能在lib里写清楚注释。更详细的内容则在每讲的正文里写。

一个最简单的能跑的lib应该长成什么样子?每个基于mudos写lpc的人可能都会给出不同的答案。我记得曾经有个朋友释出过一个不到5k的lib。

我这个则还要小一点,tgz之后是1851个字节。嗯。。。还好。
我们对这个lib基本上不会有什么期待,但是他至少应该完成如下两个事情:
1.能跑起来,并且接受用户的连接(你用zmud也好,telnet也好,总之是可以连到端口上)
2.连接后的用户可以输入,并且lib应该给予一定的反应(那么最简单的做法就是完成一个所谓的echo server了---你输入什么,server就给你返回什么)。

【配合本讲的lib版本为0.1,文件名则是newlib.0.1.tar.gz,见附件】
以下是目录结构:
.
|-- adm
|  `-- obj
|      |-- master.c
|      `-- simul_efun.c
|-- include
|  `-- globals.h
|-- log
`-- obj
    `-- user.c

首先说目录结构,一个好的清晰的目录结构用起来很舒服,我自己一般推崇单层目录结构,但是考虑到习惯问题,我在/adm下采用了和xkx类似的方法,即把master和simul放到了/adm/obj/下。
大致讲一下:
目前我们只创建了四个基本目录:/adm /include /log /obj。
adm放的都是“独一无二”的东西,比如最关键的两个物件master.c和simul_efun.c,还有以后会慢慢出现的各种daemons。
include是所有头文件所在的目录,目前只有一个globals.h。
log是用来存放各种log输出的,这没啥可讲的。
obj是所有lib当中最终被用到的物件的实体文件,也就是会被最终new()或者load_object()出来的东西。暂时只有一个连线物件,也就是user.c。(你看,现在我们连login.c都省掉了,因为我们的当前目标仅仅是能让mud接受连接而已,断线重连、帐号认证等工作要放到以后完成)

这里我们先讲一点基础的东西:mudos如何启动?
我们不讲mudos自己,只说和lib有关的部分。
有人认为,mudos最先载入的是master.c(请注意,这个master.c不是那个可以用来拜师的master),其实这个看法是有点问题的。
一般来说,mudos最先载入的文件是simul_efun.c。
我们知道,要想跑起一个mud,除了lib以外,还需要driver和一个给driver用的配置文件config.cfg。在config.cfg里,有三个文件是要被定义的:simul_efun.c,master.c和globals.h。如果愿意的话,我们当然可以给这三个文件起个其他的名字,比如master.c改名叫core.c,globals.h可以叫做dangzhongyang.h之类的,随意。。。不过大家都习惯了,我就不改了。

重点1.关于simul_efun.c
刚才我们说到,mudos启动之后,会先尝试载入这个simul_efun.c。
这里有一个概念就是所谓的simul。众所周知,mudos为了游戏的目的,提供了大量的函数(efun)来帮助我们完成工作,比如说像判断是否为玩家的userp(),像是对字符串做操作的一系列函数等等。
然而mudos也不是万能的,他不可能为预先想到所有可能的需求,有时候我们必须自己动手封装一些功能(比如说,log_file()这么方便而好用的功能,mudos就没有提供),如果应用范围很窄,我们当然可以直接把他写到代码里,但是像log_file这么大众化而且常用的功能,我们不可能每次用到就c/p到对应的文件里去,一个是不方便,一个也容易出错不是?
于是,mudos提供了一个方法来解决这个问题,这就是simul efun,简单说就是“模拟的efun”,这个功能可以帮助我们封装合心意的函数,并且在lib的任何地方像使用efun一样的使用他(虽然说慢点吧。。。。当然从效率上说,最快的办法是把efun移植到mudos里,真正做成一个efun,然而这是另外一个话题,不是我们讨论的范畴)。
完成这个工作所需要干的事儿不多,也很简单,就是把函数定义和体写到config.cfg指定的simul_efun.c当中就好了。(具体请参考我的lib当中simul_efun.c里的log_file()函数),这样我们就能让他像个efun一样的工作了。
【题外话】很多mudlib经过了很长时间的发展之后,积累了大量的simul,统统塞到simul_efun.c当中也很困扰,不美观也不便于管理,因此他们会采用另外一个做法:继承。
简单说就是把simul_efun.c当作一个入口文件,把所有的simul函数分门别类的写到其他文件当中去,在主文件里只用继承(inherit)的方法来把这些“其他文件”包含进来。(用include貌似也可吧。。。我不是很确定)

============分割线=====题外话2纯熟废话,有兴趣的同学可以自己参考OOP===============
【题外话2】关于lpc的OOP特性。
lpc这门语言出现的时间较早,虽然一般来说我们认为他是面向对象的,但是也并不完全符合面向对象的所有观念。
比方说,他只支持对对象的函数引用,而不支持对对象的元素引用,当我们想获取或者改变一个对象中的变量时,我们只能通过函数来实现;
再比方说,对于封装来讲,LPC并不能完好的实现多态,并且只有限的支持变长参数表(varargs,lpc只支持一个变长参数)。
============分割线=====题外话2纯熟废话,有兴趣的同学可以自己参考OOP===============

重点2.master.c当中的connect()函数
我们本讲开篇就说了,当下最重要的是让mudos能够接受连接。所以这里我们有必要讲讲mudos接受用户连接的机制。
我们知道,LPC最有趣的地方就在于他是OOP的(不完全无所谓,反正了解到lib里所有的东西都是对象就ok了),那么给每个用户连线分配一个object是很正常也是很方便的管理方法。
问题来了,如何让mudos知道“这是一个连线物件”呢?
这里就用到了一个很重要的master_apply(这玩意儿我们下边讲到),master_apply::connect()
他的原型是:
object connect()
这个函数的作用就在于,当mud接受到一个连接之后(不管你是用zmud还是telnet,总之你连上了mudos提供的端口服务),mudos会调用master的connect()函数,并且期望返回一个对象。这个对象就相当于在mudos里挂了号了。mudos会把它当作一个用户连线对象来对待,比如说会认为他是userp()和interactive()之类的(这几个函数有一些细微而且诡异的差别,有空我们再说)。
请看我的lib里的connect():
object connect()
{
        log_file("new_user_login",time()+"\n");
        return new("/obj/user.c");
}
很简单,master.c只要被动的等待mudos的呼叫,并且在合适的时候造一个user_ob就ok了。

这里多讲一句:
一个完整的登录过程,在mudos当中包括两步:
a.调用master apply的connect()获取连线物件;
b.调用这个连线物件身上的另外一个apply函数:logon()
其中第二步是为了给登录验证过程一个合适的调用接口用的。目前我们0.1版的lib还用不到这么牛b的技术,所以他就悬空了。
未来适当的时候我们再补充上。

=======================分割线===============================================
重点3.master的apply
实际上master.c当中除了构造函数create()之外,基本都是apply。
什么是apply呢?
大概说一下,所谓apply,就是那种由mudos隐形调用的函数接口,这些接口是为mudos提供服务的,我们通常在lib当中,只是被动的通过这个接口告诉mudos在某些情况下“可以”或者“不可以”,或者“应该是谁”这样子。
在普通对象身上的这种接口我们就把他叫做apply,在master身上的就是所谓的master apply了。

通常大家见到的比较多的apply包括像 id()(被present()隐含调用),像reset()(被reset机制调用)。
master里更多是跟权限有关的master apply,比如valid_xxx一族~~~
ok,这里我们大概知道有这么个事情就ok了,具体以后碰到需要用的apply,我们再像这次的connect()一样讲解。

=======================分割线===============================================
重点4.globals.h
大家会不会遇到这样的问题,我定义了一个宏,却忘了他在哪个头文件里?或者是写一个.c的时候经常要包含无数的头文件,其实就为了他当中一两个宏而已?
感谢mudos的作者,他通过globals.h帮我们在一定程度上解决了这个问题:
当我们有些宏定义是非常全句化的(比如说对目录的定义,对一些重要ob的定义等等),我们可以把它们丢到globals.h里。
并且,更方便的在这里:我们不需要显性的在程序里include这个globals.h,mudos自动的帮我们在每个.c当中都包含了它。
所以,当你有一些宏很全局的时候,尽管塞给globals.h吧。。。

另外一点,请看现在这个非常简单的globals.h
#ifndef __GLOBALS_H__
#define __GLOBALS_H__

#define LOG_DIR                "/log/"

#endif

发现有什么不一样没有?
我们使用了#ifdnef #define #endif的方式。
这样做的好处是,避免出现由于.h嵌套而导致的redefine(比如说a.c包含了a.h和b.h,不幸的是a.c同时继承了b.c,而b.c自己也包含了b.h,这样就出现了实际上的嵌套)

=======================分割线===============================================
重点5.user.c
我们的user.c现在功能很简单。在正常的lib当中,为了方便登录认证和断线重连,这个文件被分成了两个。即login.c和user.c(也许有人直接是用body.c?我不太确定,总之是这么个意思)。一个负责密码认证,一个负责真正的用户行为和数据。并且通过exec()函数把mudos认为的用户标签在两个之间切换。

现在我们这里非常简单,不认证,所以直接就只有一个user.c,未来再细化这里。

接下来,mudos如何获取用户的指令呢?
在正常的mudlib当中,我们通常通过一系列复杂的行为来实现之,例如通过一个“全时的”的add_action(command_hook)钩子来获取用户输入,并且通过commandd.c之类名字的一个daemon来找到恰当的指令文件,并执行之。
未来我们也会完善这样的一套结构,不过现在么。。。既然我们只想完成一个echo server。我们暂时用一个更简单的方式来处理他:string process_input(string arg)
这又是一个apply,在“正常的”mudlib里,我们通常用这个apply来实现global alias的解析。
这里我们就直接通过
string process_input(string arg)
{
        write(arg+"\n");
}
这样的模式来完成“echo server”的工作了。

这边有个问题,大家有没有发现一个string型的函数我没有return,这直接导致跑起来之后,我们每个指令敲进去都会返回一个>what?
不要紧,反正这个版本我们只是大概的演示,下一次我们修好他。

好了,这次一共就四个文件,我们构建了一个可以跑起来并且有反应的lib了。大家可以跑一下看看(附件里我提供了一个bin文件,包含了driver和config.cfg,是linux版的,由于我在我的服务器上跑的driver非常多,所以我给driver改名叫mud以避免不幸被killall掉。)
如果您想在linux下跑,只要chmod +x mud,并且重新配置一下config.cfg里的mudlib和bin的目录就ok了。
如果您想在win下测试,那么很抱歉,我手头没有合适的mudos.exe版本(哪位好心的老大提供一个)

=================分了又割===================================================
小结和预告:
第一次写这种东西(声明一下,我没写过语言类的书,所以不太会写,可能结构太乱,内容也很分散,抱歉),大家有啥建议和意见欢迎跟帖,我尽量改进。
附件是两个文件:
bin.tar.gz 是linux版的mudos和config
newlib.0.1.tar.gz是和本讲座同步的lib。可能有个问题,就是里边涉及到的中文是utf8格式的,大家用起来可能是乱码,这个倒是可以用uedit转一下码(主要是我习惯了在shell下直接敲代码,也就不改编码了,好在作为一个讲解用的lib,不会有太多中文内容在里边)。
下一讲,我想我会把登录验证和指令系统补全。这样我们就可以有空间做一些实验了(用指令来写测试代码很方便的说)。
另外,如果可能,也许会补一个不那么完善的权限系统,也许不会,我看进度把。。。

时间: 2024-11-08 15:50:08

从头开发MUDLIB的相关文章

Ios 项目从头开发 MVVM模式(一)

1.之前的项目一直用mvc开发ios,发现ios有一个弊端,mvc里,viewcontroller里边有大量的业务逻辑,当不断的修改,会发现只是一个痛苦的过程. 2.之前做wpf,使用过mvvm模式,可以把业务逻辑放到vm模式,vm可以来处理业务逻辑.做过几个ios项目,也想过mvvm模式,但是一直没找到.偶尔看到网上有一个mvvm模式的ios项目,我来尝试从头开始做这个项目,做完之后源码会公开. 3.ok,这个mvvm开源的项目是C-41,有兴趣的可以去网上搜搜. 4.这个项目要关联到一些类

Ios 项目从头开发 MVVM模式(三)

1.话说,本来想做个聚合查询功能,但是我的重点想研究xmpp聊天功能.所以使用mvvm模式做了完全模式51job主界面的页面. 2.首先给大家看我运行起来的界面. 3.界面很简单,做这个界面主要是为了比较mvvm模式和mvc模式之间的区别. 4.这个界面的结构是下边这张图片 与mvc相比,我多了一个viewmodel文件. mvc之前是把业务逻辑和数据放在viewcontroller里边,逻辑复杂的话,别人维护起来很麻烦. 我就不贴viewcontroller的图片了,我把这个代码上传给大家,大

Ios 项目从头开发 MVVM模式(二)

1.这个项目昨天我想了下,有三大部分,第一部分是根据聚合进行在线数据的一个查询功能,第二部分是xmpp的聊天功能,第三部分是更多功能. 2.在线查询功能,主要用到的技术,就是get请求或者是post请求,这个在线查询功能,我们用到的是聚合的SDK,有自己的API,所以我们就需要单独的去做一些请求的类. 3.xmpp聊天功能,主要用到xmpp协议,框架我们用ios的XMPPFramework-master这个开源项目,详细的功能,我会再详细考虑. 4.更多功能,就是每一个app都会有的一些设置等功

使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?(非常稳定、捕获所有异常、非常适合从头开始,但大公司已经有现成的C++框架、所以不会使用)

使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?和C Socket服务器比起来有什么优劣?可行性怎么样? 从2013年起,经朋友推荐开始用Golang编写游戏登陆服务器, 配合C++做第三方平台验证. 到编写独立工具导表工具GitHub - davyxu/tabtoy: 跨平台的高性能便捷电子表格导出器. 以及网络库GitHub - davyxu/cellnet: 简单,方便,高效的Go语言的游戏服务器底层. 最终使用这些工具及库编写整个游戏服务器框架, 我的感受是很不错的 细节看来,

微信公众平台小程序开发教程

? 本文档将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果.这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志.下载源码 1. 获取微信小程序的 AppID 如果你是收邀请的开发者,我们会提供一个帐号,利用提供的帐号,登录 https://mp.weixin.qq.com ,就可以在网站的“设置”-“开发者设置”中,查看到微信小程序的 AppID 了,注意不可直接使用服务号或订阅号的 AppID . 如果是游客模式,

微信小程序开发教程

9月21日晚发布的微信公众平台·小程序内侧邀请,微信应用号(小程序,「应用号」的新称呼)终于来了!目前还处于内测阶段,微信只邀请了部分企业参与封测.想必大家都关心应用号的最终形态到底是什么样子? 怎样将一个「服务号」改造成为「小程序」?相信很多技术人员开始关注,会不会取代APP开发,一些职位会不会被取代. 现在带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果.这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志.下载源码

如何成为优秀的驱动开发工程师

或许这样的标题,应该是由像Linus或Greg KH这样的大师级的高手才有资格写的吧.但是作为我来说,也许我更想把这个标题作为一个疑问句来使用,整理一下自己的认识,用来勉励自己,和大家一起努力实现这个目标.认识肤浅的地方,还请大家见谅. 何谓优秀的驱动开发工程师 首先要定义,我所认为的一个优秀的驱动开发工程师,应该具备什么样的能力,这里列一下按照从易到难的顺序,个人认为应该会有几个方面的要求吧: 能够独立完成驱动的功能开发任务 能够分析和优化驱动的性能,针对特定硬件扬长避短 能够充分了解模块相关

微信应用号开发教程

——第一篇 微信应用号(小程序,「应用号」的新称呼)终于来了! 目前还处于内测阶段,微信只邀请了部分企业参与封测.想必大家都关心应用号的最终形态到底是什么样子?怎样将一个「服务号」改造成为「小程序」? 我们暂时以一款简单的第三方工具的实例,来演示一下开发过程吧.(公司的项目保密还不能分享代码和截图.小白是边加班边偷偷给大家写教程.感谢「名片盒」团队提供他们的服务号来动这个手术,所以小白的教程就用「名片盒」的公众号滚动更新发布吧??) OK,为了让大家尽快看到这份教程,小白注定要熬夜了!今晚开始更

微信小程序开发入门教程

做任何程序开发要首先找到其官方文档,微信小程序目前还在邀请内测阶段,目前官方放出了部分开发文档,经过笔者一天的查看和尝试,感觉文档并不全面,但是通过这些文档已经能够看出其大概面貌了.闲话不多说,我们先来看看其有哪些官方文档. 微信公众平台开发者文档统一入口为:https://mp.weixin.qq.com/wiki,这里面大部分内容都是以前就有的,微信开发都是基于此份文档. 现在的变化是在这份文档的顶部加了一个“微信公众平台.小程序”的入口,这个入口才就是专门针对微信小程序开发的文档,如下图: