mud mud系統重新整理與記憶體清除分析

2021-09-26 21:13:06 字數 4039 閱讀 3438

有關系統更新一直是玩家乃至於新巫師們關心的問題。比如,為何每隔15分鐘大多數房間裡殺死的npc會重生?跑到別處或被玩家背到別處的npc怎麼會跑回去?為什麼有的npc跑不回去?什麼有的東西會重生?為什麼又有的東西只要別的玩家放在身上?等等。

目前主流mudlib都是es系列的。從es系列沿襲下來的更新都是通過room的更新實現的。而room的更新則是由mudos裡的設定每隔一定時間(一般是15分鐘)呼叫一次所有的有reset()函式的房間。而這個reset()函式則寫在room的標準繼承檔案裡面。下面我們則來看看room是如何實現房間裡的生物、物品的重生或更新:

在寫這篇文章之前,正好在網上看到darks兄寫的《room的結構》,於是我這篇文章的不少地方也就寫得很順暢了,有些直接引用了《room》一文的一些內容。為了尊重原作者,凡是引用或出自darks兄的原文內容我都用「」與綠色標出:

room的標準檔案由於mudlib的不同,放在目錄路徑也不同,但大多情況下也就是/inherit/room/下或者與/obj/room/下兩種可能而已。反正不檢查一下在/include/下的globals.h,看這個檔案裡room是定義在**就可以了,下面來看一看room.c的程式詳解:

inherit f_dbase;

//「這個是繼承dbase標準繼承,有了它,你才可使用set等函式為這個物件設定變數」(此問題日後做專題說明)。

inherit f_clean_up;

//「這個用來定時清除很久沒被訪問的room」,這個概念我們要在後面談到。

object make_inventory(string file)

//這個函式用來產生乙個房間裡的物品。首先它需要別的函式在呼叫它的時候要傳遞給它乙個需要產生的物件的路徑。然後用new()複製出來,接著move到這個房間裡,再接著給它設上startroom這個標記,這個標記就可以在這個房間定時呼叫自己房間裡產生的npc可以使用return_home()這個函式時,正確回到原來的地方。

set("no_clean_up", 0);

//「這個標記為零,即允許系統到了規定時間將這個檔案掃出記憶體,那麼這個檔案內的所有東西都會消失。由於room標準繼承有這句,似乎發現只要繼承它的房間檔案無論寫為0/1都是無效的,因為都會在這裡被清除成零。」

ob_list = query("objects");

//先取出乙個這個房間初始設定的objects的對映集

list = keys(ob_list);

//從ob_list對映中取出關鍵字組成乙個新陣列。

for(i=0; i 1 )

ob[list[i]] = allocate(ob_list[list[i]]);

//如果房間裡曾經定義了要產生物品,並且數量不止乙個的話,就要進行ob[list[i]]這個物件陣列的記憶體分配

switch(ob_list[list[i]])

break;

default:

//除此之外,也就是物件不止乙個的話,舉例相當於檔案裡:set("objects",(["/d/city/npc/bing":2]))或者3,4....這類的情況

for(j=0; jis_character()

&&!ob[list[i]][j]->return_home(this_object()) )

add("no_clean_up", 1);}}

//這裡其實與物件只有乙個是一樣的,只是因為相同的物品不止乙個,需要進行幾次的迴圈判斷而已。}}

set_temp("objects", ob);

//看到這裡,知道這個函式裡ob對映集是如何來的了吧,實際上ob_list就是代表的這個房間裡的的query("objects"),是乙個字串內容的對映集,而ob就是代表的這個房間裡的query_temp("objects")它實際上乙個object型的對映集。

}reset()函式結束了,其實在room裡,除了這兩個函式,還有乙個在一開始編譯進記憶體後進行首次呼叫reset()函式的setup()函式之外,其它的函式都是有關門的,都是可以去掉並影響房間的主要功能的,room標準繼承的最主要功能就是定時檢查自己房間裡的物品是否還在?是否需要更新等等。而這個定時則就是由mudos定義並按時呼叫房間裡的reset(),這個時間絕大多數被定義為十五分鐘。

我們通過上面的程式詳解可以看出,當乙個房間被編譯成功進入記憶體之後,那麼這個房間就將自身產生出來的各個物體(假如它有的話)記入乙個query_temp("objects")的物件對映變數中,這個變數與我們寫程式裡的query("objects")是一一對應的,只不過query("objects")裡記的是這此物件的

檔案路徑,而query_temp("objects")裡記的是這些具體的物件。關於這兩個對映的區別,有興趣的新巫師可以找乙個有很多npc的房間按下面分別call兩次,看看區別:

call here->query("objects")

call here->query_temp("objects")

在reset()被呼叫時,程式就會迴圈地乙個個地查詢這些物件是否還在mud中?如果這些物件都已經不存在了,那麼,reset()函式就會通過呼叫make_inventory()函式將其再次製造出來,也就是我們看到了,更新時間一到,很多被殺死的npc,用掉的東西都會在原處產生出來。

而如果這些物件都還在mud中,就會檢查它們是否還在原處?如果不在的話,只要是生物,就呼叫它的return_home()函式(這個函式在所有npc的標準繼承

/inherit/char/npc.c裡),叫它回來。並且要把這個房間作為引數傳遞過去,否則npc會回不來。如果不是生物只得作罷(這就是房間產生出的物品如果被某一玩家放在身上,就再也不能重生的原因)。那麼下面我們就來看一下npc.c裡的return_home()函式:

int return_home(object home)

//注意,括號裡的home就是呼叫它回家的那個房間,當時是叫this_object()

談到這裡,大家可以發現,所謂房間的更新,實際上只是房間裡的物體進行更新,這個房間沒有任的變化。也就是說,如果在房間更新的時候,我們站在這個房間裡,或者我們扔了乙個不屬於任何房的物品在這個房間裡,都不會受到影響,這些物品與我們在更新前後都不會消失。這個與我們巫師進update here是本質性的兩回事(updata here就是更新了房間)。

那麼,有時有的玩家就會說,我曾得到乙個很好的寶物,離線不能儲存,我就把它扔在乙個很少有去的地方,結果,每次再去連線再去找的時候,大多數時候都找不到,不會是被別人撿去吧?這裡就及到另乙個概念:mud裡的資源清除。

大家知道,在lpmud裡,所有的程式都必須裝載進記憶體裡才會工作。因此,mud的記憶體資源便就是最主要的資源。更合理地分配和使用記憶體便成為乙個mud效率高低的體現。

mudos為了節約記憶體的耗用,對於每乙個占用記憶體的物件,包括是房間、物品、人物、指令等等,如果相當長的時間內沒有被其它程式參考到(參考的含義:就是包括別人進入、看到、或者使用到這個房間、物品、或指令,還包括各個程式等等)的話,也就是這個物件很長時間沒有活動了,mudos就會呼叫這個物件的clean_up()函式(由於大多數的程式都會繼承這個函式標準檔案),如果該函式返回1,則下次同樣情況還會呼叫該物件的clean_up;如果返回0,則永遠不再呼叫。那麼,我們就來看一下/feature/下面的clean_up.c檔案,這個檔案只有乙個函式:

int clean_up()

我們再次複習一下clean_up()函式返回1的含義,如果clean_up()函式返回1,則mudos在這一次的呼叫時不會做其的任何舉動,但到了下一次想呼叫的時間裡,還將再次呼叫這個物件的clean_up()函式。那麼從這可以看出,有以下四種情況不會將其清除出記憶體:

一、非clone出來並且有no_clean_up引數的物件;

二、玩家永遠不會

三、處於乙個還存在的環境裡

四、自己裡面存在著玩家

也就是mudos定時摧毀記憶體不需要的物件是由外向內的,比如乙個房間,系統只要檢查這個房間裡沒有no_clean_up引數、裡面沒有玩家就可清除它,而房間裡的物品、npc都會因環境的不存在而消失。這個清除的定時時間一般都為兩個小時。當然要視不同的mudos裡的設定而看的。

再說一點題外話,如果乙個房間長時間沒有玩家走進來,當然會被mudos清出記憶體,而突然又有玩家進來呢?很簡單,它會在一瞬間被編譯進記憶體,進入乙個已經存在在記憶體裡的房間與進入乙個剛剛編譯出來進入記憶體的房間對於我們的玩家來說,是察覺不出它們之間的差異的。 

ms sql server快取清除與記憶體釋放

ms sql server快取清除與記憶體釋放 sql server系統記憶體管理在沒有配置記憶體最大值,很多時候我們會發現執行sql server的系統記憶體往往居高不下。這是由於他對於記憶體使用的策略是有多少閒置的記憶體就占用多少,直到記憶體使用慮達到系統峰值時 預留記憶體根據系統預設預留使用為...

ms sql server快取清除與記憶體釋放

sql server系統內 存管理在沒有配置記憶體最大值,很多時候我們會發現執行sql server的系統記憶體往往居高不下。這是由於他對於記憶體使用的策略是有多少閒置的記憶體就占用多少,直到記憶體使用慮達到系統峰值時 預留記憶體根據系統預設 預留使用為準,至少4m 才會清除一些快取釋放少量的記憶體...

SQL Server 快取清除與記憶體釋放

sql server系統記憶體管理在沒有配置記憶體最大值,很多時候我們會發現執行sqlserver的系統記憶體往往居高不下。這是由於他對於記憶體使用的策略是有多少閒置的記憶體就占用多少,直到記憶體使用慮達到系統峰值時 預留記憶體根據系統預設預留使用為準,至少4m 才會清除一些快取釋放少量的記憶體為新...