Re: [閒聊] 分散式儲存

看板mud作者 (習慣,不容易)時間11年前 (2013/01/28 18:08), 編輯推噓5(503)
留言8則, 7人參與, 最新討論串2/4 (看更多)
一起來振興 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
這是論文Xd
01/28 20:11, 3F

01/28 22:58, , 4F
我是覺得後面直接接database就好啦..
01/28 22:58, 4F

01/29 03:52, , 5F
mud會這樣子搞很多時候都是因為CPU跟
01/29 03:52, 5F

01/29 03:56, , 6F
RAM/HD,現在什麼都不是問題了啊..
01/29 03:56, 6F

01/29 06:00, , 7F
原po不是鹿人 是no gg人
01/29 06:00, 7F

01/29 07:59, , 8F
嗯,這樣寫是更好的,類似user.c用法
01/29 07:59, 8F
文章代碼(AID): #1H1au50A (mud)
文章代碼(AID): #1H1au50A (mud)