Re: [閒聊] 分散式儲存
一起來振興 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
推
01/28 18:41, , 1F
01/28 18:41, 1F
推
01/28 18:58, , 2F
01/28 18:58, 2F
推
01/28 20:11, , 3F
01/28 20:11, 3F
→
01/28 22:58, , 4F
01/28 22:58, 4F
→
01/29 03:52, , 5F
01/29 03:52, 5F
→
01/29 03:56, , 6F
01/29 03:56, 6F
推
01/29 06:00, , 7F
01/29 06:00, 7F
推
01/29 07:59, , 8F
01/29 07:59, 8F
討論串 (同標題文章)