作者kyoe (习惯,不容易)
看板mud
标题Re: [闲聊] 分散式储存
时间Mon Jan 28 18:07:45 2013
一起来振兴 mud 世界吧!!
我也来聊聊点这方面的心得,但因为我大多是自己研究和看 code 学,
所以有些观念不一定正确,不过我想,分享一些心得应该可以让有兴趣
的人少点弯路,也为 mud 的落没做点努力/_\
分散式的储存系统通常再搭配上虚拟物件产生的效果会比较好
例如:玩家住宅、国家房间、帮派房间、动态装备等
常见的储存系统有:
1. 分散式储存:
将物件资料存入已分门别类好的目录中存入。(就是 laechan 大介绍的方式)
2. 单一档案式储存:
将物件资料存入一个专门的档案阵列或映射变数,再将该档案储存至 .o 档。
好,接下来我们谈谈分散式储存和虚拟物件的应用和心得
大家都知道,在 /adm/obj/
(在 es2 里是 /adm/obj/, nt 里 /adm/single/ 或有些是 /adm/kernel/ )
中有个 master.c,他是做为被 mudos 呼叫的启始主档,在它里面有一段
function 指向了 virtuald.c
mixed compile_object(string file)
{
return load_object(VIRTUAL_D)->compile_object(file);
}
那麽,我们可以想像在一个虚拟物件的产生过程顺序应该是:
玩家或系统触碰要求载入 -> os 找不到实体或已存在物件 -> os 呼叫 master.c ->
master.c 要求 compile_object 判断是否有虚拟物件存在 -> 最後 compile_object 导向
virtuald.c 中的 compile_object 因此我们可以了解到,要对於虚拟物件的判断处理都可
以在 virtuald.c 的 compile_object 中设定,假设我们现在要将玩家住宅系统改造为分
散式储存和使用虚拟物件产生,那麽我们的 compile_object 可以这样写
#define HOUSE_D "/adm/daemons/housed"
#define USR_HOUSE_FILE "/data/room/"
object compile_object(string filename)
{
int t = strsrch(filename, "/", -1);
if( t <= 0 ) return 0; // 传来的 filename 中最少要有一个 / 的存在
if(filename[0..10] == USR_HOUSE_FILE)
return HOUSE_D->get_virtual_room(filename);
// 当 filename 的开头符合 /data/room/ 这段字串的时候
// 转至 HOUSE_D 去处理相关的物件产生
return 0; // 如果都没有符合条件,回报 master 无此物件
}
由於一个站点也许不止会有一个虚拟物件系统,也许玩家住宅使用,帮派房间也使用
,或动态装备系统也使用,因此我们在 virtuald 当作是一个各虚拟物件系统的判断
分水岭,用於导向各不同系统的专用 daemon
再来我们看 HOUSE_D(/adm/daemons/housed.c) 中的
get_virtual_room(string filename) 是如何写的
#define PRIVATE_ROOM "/inherit/room/privateroom"
object get_virtual_room(string filename) {
object room;
if(file_size(filename + ".o") < 0) return 0;
// 如果没有这个档案名称的 .o 档,表示未曾创造过,传回 0 表示无此房间
if(!room = new(PRIVATE_ROOM)) return 0;
// 如果无法载入初始物件则直接回传无此房间或可使用 error() 来报错
return room->restore_room(filename);
// 呼叫初始物件(object room)告诉他可以创造并载入 filename 这个档案
}
其实也可以将用在载入的 restore_room() 这个 function 直接写在 HOUSE_D 中,
其实都是一样的,看每个人的习惯而已,也可以选则将 restore_room() 和 save_room()
都写在 HOUSE_D 中,要使用时就用 HOUSE_D->restore_room(object room, string file)
去呼叫就可以,意义差不多。
PRIVATE_ROOM 中的 restore_room() 大概可以这样写
object restore_room(string file)
{
int res;
res = restore_object(file +".o");
// 找到并载入 file 详情请 more /doc/efuns/restore_object
if(res) return this_object();
// 如果载入成功,restore_object() 会回传大於 1 的数字,回传物件
else return 0;
// 失败一样传回去告知没有这个物件
}
从上可知,即使多个档案互相的引用、呼叫,最终仍是回到 master.c 的
compile_object 去回报 os 给要求载入的对象,对 compile_object 来说,
回传回来的如果是一个物件,那麽他就会照实的回馈载入,如果不是,那麽
就会回报无物件的判断。
如我所在的房间 west 是一个虚拟物件类型的 room,我的房间 exits 可能会是:
set("exits", ([ /* sizeof() == 1 */
"west" : "/d/virtual/virtual_room",
]));
但是我们并没有 /d/virtual/virtual_room.c 这个档案,也许只有用来储存
/d/virtual/virtual_room.o 的档案,所以 os 就开始了本文开头的那一串
动作去寻找,如果 restore_object 的没问题,那麽正常传回的就是一个被模
拟载入房间资料的 /d/virtual/virtual_room.c 档案,我们下达 west 指令
就可以走过去,如果发生错误了,那麽就可能得到的是 os 中预设的错误讯息如:什麽?
再来,与 restore_object 对应的,当然就是 save_object,详情也可 more /doc/efuns/save_object
而在 PRIVATE_ROOM 中的 save_room() 大概可以这样写
int save_room()
{
int res;
if(base_name(this_object())+".c" == __FILE__) return 0;
// 这是做为初始档案的本身,不需要储存
res = save_object(base_name(this_object())+".o");
// 将 room dbase 存入以物件档名为名的 .o 档
return res; // 回报是否储存成功
}
save_room 相对简单,但也可以在其中依各站不同的需要去做不同的判断和细节处理
因为是心得分享,所以大多用简单的物件档名当做储存的 .o 档,更好的应用就是分
门别类为每种不同的玩家群去置放不同的目录,或是依不同的房间种类去储存,其实
都可以,没有一定该如何做
原则上,分散式储存和虚拟物件的简单运用大致上是这样,当然还有更多种不一样更
方便更好的作法,但我只是想说说一种简单的原理,当能贯通的时候就可以繁生出多
样的变化。
这麽做的好处一定是有,但是有什麽好处我懒的想,因为是鹿人教我做的QQ
Kyoe
--
还记得遥远过往被
深藏的回忆吗?
如果您已
经忘了被现实和繁忙淹没的
曾经
那麽就让我们帮助您找回那
份属於青涩年代的纯真吧
用文字幻化出华丽与梦想的彼岸
金庸修真录 telnet://jy.mud.com.tw:6666
盼能带领您找回似曾相识的记忆深处中最美丽的梦幻
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 1.163.29.54
1F:推 neca :你太晚出手了 但是一出手就请不要停 210.66.174.184 01/28 18:41
2F:推 pssjim :鹿人?...感觉好熟悉 =.,= 36.224.28.71 01/28 18:58
3F:推 tawi :这是论文Xd 111.240.44.245 01/28 20:11
4F:→ zcecil :我是觉得後面直接接database就好啦..216.237.113.234 01/28 22:58
5F:→ kruz :mud会这样子搞很多时候都是因为CPU跟 107.3.160.35 01/29 03:52
6F:→ kruz :RAM/HD,现在什麽都不是问题了啊.. 107.3.160.35 01/29 03:56
7F:推 QQmother :原po不是鹿人 是no gg人 123.192.148.71 01/29 06:00
8F:推 laechan :嗯,这样写是更好的,类似user.c用法 1.165.174.117 01/29 07:59