背景:
阅读文章

从头打造mudlib

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

[日期:2011-03-01] 来源:泥巴创世纪  作者:Akuma [字体: ]
1.存盘和读取的底层机制
2.简单的房间系统和简单的look指令,物件的move
3.指令权限还是没有。。。。
4.登录过程里依然没有密码验证,但是可以区分新老用户了,并且可以存取数据。

现在已经可以这样了:
欢迎来到测试MUD
请输入您的ID:akuma
读取存盘数据成功,开始进入游戏。

世界的中心 -
    这里就是世界的中心。人来人往,车水马龙。
到处都是人,摩肩接踵的。。。。非常热闹。

    这里有:
    akuma
> test连线进入这个世界。
 
目录结构如下:
.
|-- adm
|  |-- daemons
|  |  |-- cmd_d.c
|  |  `-- login_d.c
|  `-- obj
|      |-- master.c
|      `-- simul_efun.c
|-- cmds
|  `-- usr
|      |-- look.c
|      `-- test.c
|-- d
|  `-- wiz
|      `-- center.c
|-- data
|  `-- user
|      |-- a
|      |  `-- akuma.o
|      `-- t
|          |-- test.o
|          `-- test2.o
|-- include
|  `-- globals.h
|-- log
|-- obj
|  `-- user.c
`-- std
    |-- body
    |  |-- move.c
    |  |-- room_dbase.c
    |  |-- user_dbase.c
    |  `-- user_save.c
    `-- room.c
 
0.4.1的目录树:
.
|-- adm
|  |-- daemons
|  |  |-- cmd_d.c
|  |  `-- login_d.c
|  `-- obj
|      |-- master.c
|      `-- simul_efun.c
|-- cmds
|  `-- usr
|      |-- look.c
|      `-- test.c
|-- d
|  `-- wiz
|      `-- center.c
|-- data
|-- include
|  `-- globals.h
|-- log
|-- obj
|  |-- login.c
|  `-- user.c
`-- std
    |-- body
    |  |-- move.c
    |  |-- room_dbase.c
    |  |-- user_dbase.c
    |  `-- user_save.c
    `-- room.c
第四讲:较为完整的登录过程

我直接按照0.4.1的版本来讲。

重点1.存盘与读取数据
这个文件是这次新增的,/std/body/user_save.c
它提供了两个函数,save()和restore()。
具体内容可以读文件,这里只说两个关键:
a. mud中我们用的save()和restore()的核心是save_object()与restore_object(),可以参看具体的efun声明。
  这两个函数是把object身上的“全局”数据(不包括static或者nosave),以类似sprintf的格式存成文件,或者相反:将符合格式的文件读出来并恢复成数据格式,赋予object。
  值得关注的是另外两个efun,save_variable()和restore_variable(),实际上在使用save_object()和restore_object的时候也是在调用这两个函数的内容。

b. 存为什么和读什么文件?
  这个是由具体的ob身上的query_save_file()获得的。
  注意这里我们使用了query("id"),实际上,在真正的系统当中,如果考虑到安全因素(比如wiz可以call xxx->set("id")之类的),一般是通过euid来解决这个问题。
  不过这样我们需要调整的地方太多,就暂时不做处理了,有兴趣的同学可以自行比对其他lib来修改。

重点2.dbase当中增加了tmp一族
如之前所说,我们希望有些时候ob身上的标记是临时的,即不被save()。
因此我们在user_dbase.c当中增加了一个新的mapping
static mapping tmp_dbase = ([]);
并且增加了三个对应的接口函数:query_tmp(),set_tmp(),delete_tmp();
到这里,我们给ob写标记的时候终于比较圆满了(记住:还差一个多重mapping的设计没有实现)

重点3.登录过程
先说明一下,我们这次终于把user_ob和login_ob(/obj/login.c)分开了。。。。

我们稍微整理一下,一次登录,最简单来说,应该处理哪些事情:
a.获取id输入,判断是否有这个用户(有:转到b;没有:转到g)
b.如果有,则载入login数据[密码保存在login_ob的存盘文件里],并获取密码输入,判断是否有存盘的密码相同[注意为了安全,我们应该使用加密存储的密码,范例就不处理这个了](相同:转到c,不同:转到f)
c.寻找是否有连线或者短线的同名用户(有:转到d,没有:转到e)
d.一系列的exec()取代,最终保证新的连线取代老的user_ob,并给予适当的描述【取代登录完成】,进入enter_world()过程
e.创建一个新的user_ob,并restore()玩家数据,进入enter_world()过程
f.(从b过来),密码比对失败,踢出,万事儿。。。
g.(从a过来,没有用户),进入新用户创建过程(获取密码,然后生成user_ob,进入enter_world()过程)

这个过程主要是在login_d.c当中实现。
有一个需要注意的是find_body()。这里之所以不用单纯的find_player(),是因为在某些特殊情况下,find_player()会失效,所以还要尝试一下children()。

重点3. ROOM
room其实就是一个容器(事实上所有的object都是容器)
room本身没有什么特别,我们将一下new(),load_object()和call_other()
a.  new()创建出来的object必然是clonep,也即是形如obj/user#xxx这样带井号的object。
  事实上,任何在内存中的物品,必然都会有一个不带井号的版本,也就是说,如果我们new()了某个file,那么他至少会存在一个file#xxx和file两个ob。为何呢?这是driver的一个机制。
  对应的有clonep(),children()两个函数可以用。
  大家看一般的mudlib,在item里经常会有一个set_default_object(__FILE__);
    这个玩意儿就是给物品设置一个标记,在query的时候,如果“我”身上没有数据,就去default上去找。这个defalt就是我们说到的new()出来的那个不带#的obj了。
  这个做法可以节省内存,但比较浪费时间。我不喜欢它。。。

b. load_object(),如果有物件就返回,否则就创建,这里返回和创建的都是不带#的obj。

c. call_other(),这个是执行某个物件或者文件名身上的函数,如果没有对应的物件存在,就尝试先创建。

所以:
  call_other("file",“???”);
      find_object("file");
      的做法约等于load_object();
     
      call_other()又约等于"fine"->xxx();
象user_ob,npc,item这些,我们往往希望有多个副本,因此我们总是用new()
但是象daemon,room这种,我们通常不希望有副本(比如说,到底是哪个ftpd在起作用?或者我为什么和他进入的不是同一个center?)你看,这种情况,如果不用本体物件,而是new,会产生很多困扰。所以我们这里用load_object()或者call_other。

这是一个大概的解释,有问题我们再继续讨论吧。。。。
增加了对房间的出口的粗糙的处理。
/cmds/usr/look.c里支持了对exits的显示。

增加了指令/cmds/usr/go.c,根据房间的exits可以走方向。

另外user_ob的process_input()又回来了,这次我们用它来解决global alias的问题(即用w west来代替go west)
ok,没有太多可以解释的。

依然没有指令权限,但是在执行指令的地方增加了一个对指令是否能正常编译的判定。所以现在可以正常的看到what?而不是报错了。
/adm/daemons/cmd_d.c的:
int do_cmd(object me,string verb,string arg)
{
        object cmd;
        cmd = load_object("/cmds/usr/"+verb);
        if(objectp(cmd))
                return cmd->main(me,arg);
        else
                return 0;
}


至此,我们有了一个可以看起来很像样子的lib了。他都可以走路了~~

接下来搞点啥?大家~

这是0.4.2的目录树:
.
|-- adm
|  |-- daemons
|  |  |-- cmd_d.c
|  |  `-- login_d.c
|  `-- obj
|      |-- master.c
|      `-- simul_efun.c
|-- cmds
|  `-- usr
|      |-- go.c
|      |-- look.c
|      `-- test.c
|-- d
|  `-- wiz
|      |-- center.c
|      `-- westyard.c
|-- data
|-- include
|  `-- globals.h
|-- log
|-- obj
|  |-- login.c
|  `-- user.c
`-- std
    |-- body
    |  |-- move.c
    |  |-- room_dbase.c
    |  |-- user_dbase.c
    |  `-- user_save.c
    `-- room.c
【内容导航】
第1页:Akuma一起从头打造mudlib--【第零讲】 第2页:与Akuma一起从头打造mudlib--【第一讲】
第3页:与Akuma一起从头打造mudlib--【第二讲】 第4页:与Akuma一起从头打造mudlib--【第三讲】
第5页:与Akuma一起从头打造mudlib--【第四讲】 第6页:与Akuma一起从头打造mudlib--【第五讲】
收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容       mudlib  mud 
本文评论   [发表评论]   全部评论 (3)
第 3 楼
* 匿名 发表于 2013/8/16 3:08:48
老大,文章实在好,可是附件在哪里下载啊?
第 2 楼
* baobao会员 发表于 2011/6/8 10:57:42
你好,我是新来的,请问有问题如何在论坛中提问呢?
先谢谢了就
第 1 楼
* 匿名 发表于 2011/3/8 21:42:30
请问,这篇教程的后序还有吗?去年就是看到这里就没有了。。。
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论
* 匿名 发表于 2013/8/16 3:08:48
老大,文章实在好,可是附件在哪里下载啊?
* baobao会员 发表于 2011/6/8 10:57:42
你好,我是新来的,请问有问题如何在论坛中提问呢?
先谢谢了就
* 匿名 发表于 2011/3/8 21:42:30
请问,这篇教程的后序还有吗?去年就是看到这里就没有了。。。