推 smmoon : 只能推了 114.32.144.77 01/23 08:13
推 ghostmote : 好久沒看到技術文118.163.154.205 01/23 17:07
總算有時間可以補充點東西。
欲使用排程的物件 times_check.c
│ │
│對 times_check.c 設定時間及工作 │
├───────────────→┤呼叫 set_times_check 函數
│ │
│ 然後等約定的時間到的時候 │
│ │
│times_check.c 第一次呼叫該物件 │
├←───────────────┤
根據該呼叫 │ │
└─→ │times_check.c->set_times_no_save│
│令 times_check.c 多次呼叫上面的 │
│函數去設定幾秒後要做哪些工作 │
├───────────────→┤然後 times_check.c 移除該排程
│ │只留 set_times_no_save 的設定
│ │
│ 然後等約定的時間陸續到了時 │
│ │
都是去呼叫 │times_check.c 在約定的時間呼叫 │
times_check ├←───────────────┤
函數 │times_check.c 在約定的時間呼叫 │
├←───────────────┤
│times_check.c 在約定的時間呼叫 │
├←───────────────┤
│ . │
│ . │
│ . │
│ │
│ 直到全部的呼叫都已結束 │
然後不同的工作排程允許做疊合,彼此之間不會互相影響。
上面可以 work 的條件就是 times_check.c 會週期時間去判斷當下的
時間(time())是不是有什麼工作要做,有三種實現做法
1.利用擁有心跳的物件會每一秒呼叫一次自己的 heart_beat 函數
2.或是利用 preload 先載入該物件,然後在其 create 函數內使用
call_out 的語法,再於其 call_out 的目標函數內亦使用 call_out
(也就是 loop call out)
3.或是利用其它 call_out 物件,例如典型的 weather_d.c 天氣物
件,假設該天氣物件每 60 秒(每分鐘)都會固定 call_out 什麼函
數,那就可以利用該函數來做為排程控制。(精準度設為"分"即可)
然後再以排程拍賣為例,一般的 mud,多是使用 call_out 做為拍賣
流控的手段,而且會判斷拍賣期間是不是有玩家持續出價,有的話就
會一直延後拍賣結束的時間。
這種做法並不利於使用約定好的排程來控制。
所以 sanc 有另外寫一支拍賣用的程式 blarket,它的流程全部都可
由拍賣舉辦者來控制,亦即要五分鐘後結標、十分鐘後結標、甚至是
30 分鐘後才結標都可以,只要下 blarket -end 即可結標。
(blarket 語源為 black market = 黑市,即取黑市拍賣會的意思)
它的最大好處就是使用者方便控制流程,又不會使用到 call_out 這
個 loading 較高的東西,在 sanc 以這個指令舉辦特殊的拍賣會是
wiz 專用的,玩家則可以 blarket -bet 來競標,沒記錯的話我也有
把這支程式放在 tmi2_mudlib_v3_改 裡頭。(因為作者是我)
※ 編輯: laechan (122.117.106.224), 01/23/2018 18:08:50
推 typers : 推L大對mud的熱情 36.234.4.226 01/23 19:44
→ typers : 但heart_beat為單位的排程,真心不推 36.234.4.226 01/23 19:49
→ laechan : 現在電腦效能都很好滴122.117.106.224 01/23 20:10
推 kyoe : 後期開發的mud大多已經利用h_b來取 60.250.92.145 01/25 10:17
推 kyoe : 代callout,我們叫他timed/scheduled 60.250.92.145 01/25 10:21
推 kyoe : 不過都是新的才用,舊的懶改,哈哈 60.250.92.145 01/25 10:25
推 kyoe : 還是要推推,現在在搞的人越來越少了 60.250.92.145 01/25 10:28
我個人目前有想過在 sanc 實裝「地上的物品經過一段時間後會
風化」的設定,以前是想用被動觸發式,物品被 move 到地上時
就 set("move_times",time());,但是這樣就需要 init 函數的
輔助,因此只能侷限在特定種類的物品。
至於 call_out 或 heart_beat 則差不多是同時期想到的其它做
法,用 heart_beat 主要是把該物品比方屍體 corpse 當成生物
,該物品本身就有心跳,那自然可以順利判斷,而且把它當生物
本身也有很多好處(雖然不合理)。
再之後,則產生以 times_check.c 來跑的做法:
1.玩家陣亡時,呼叫出屍體,並做 set_times_no_save 的設定
並輔以 set("remove_times",time()+幾秒後);
2.times_check 依照設定,分段去
call_other(這具屍體,"times_check",帶不同的參數);
3.最終 times_check 會去移除屍體。在上述執行過程中,如果
times_check 被 update 或 reborn,屍體也會被 look_d.c
依照 query("remove_times") 的判斷來移除。
(玩家進入房間時會呼叫 look_d.c 的 look_room 函數觀看
房間,利用這一點)
以上是閒聊,剛好有想到。
其實最終都會回到一個關鍵問題:如果同一時間出現大量屍體呢?
(所以 sanc 沒有屍體...雖然不合理)
國外有篇文章
http://lpmuds.net/smf/index.php?topic=1171.0
比方以底下這句
The "Performance" file in the root directory of FluffOS's
source (couldn't find online copy) says not to give objects
heartbeats unless really necessary, and to do as little in
the heart_beat function as possible.
那其實以下我覺得都對
1.盡量不使用 heart_beat (比方使用 call_out)
2.盡量減少使用 heart_beat (比方只讓少數物件有 heart_beat)
那我個人的看法是 call_out 跟 heart_beat 都可以用,但也都
應該少用,unless really necessary。比方只是單純希望幾秒後
去呼叫什麼,秒數不長,呼叫完就沒了,那我就會用 call_out,
但如果這類呼叫一直出現(比方喝藥水、施法的過程中都會出現)
,我就會考慮 call_out 以外的做法,比方在 sanc 我採取的做
法就是瞬喝藥水、瞬施法術(雖然不合理):
> cast pray
[瞬間]
你緩緩唸道: 深眠於心靈深處的潛在力量,藉神之力甦醒吧!
你開始唸起古老的咒文: ~ 9 ~ ~ ~ 祈禱術 ~
你感覺自己體內的魔力變得活性化,頭腦也靈活了不少!
[然後馬上要再 cast 時]
> cast pray
你要等一下才可以再施法喔。
heart_beat 也是一樣,通常某些我覺得不得已需使用的場合,
該物件都不會是恆久存在的(times_check.c例外),也就是說就
算我讓某物件 set_heart_beat(1),我也會讓它盡量快點消失,
或者是將它消失的機制寫得完善一點。(例如sanc的副本系統)
我一般在使用 heart_beat 時會參考兩個標的
1.user 的 heart_beat
2.monster 的 heart_beat
sanc 玩家的 heart_beat 函數其實密密麻麻寫了蠻多段東西,
我大概就是以這個來評估我寫的其它 heart_beat 物件,跑起
來會不會出問題,目前看起來大概沒啥問題。
最後,目前 sanc 避免心跳過程中產生錯誤的做法只有一個:
catch(call_other(目標物件,"函數",...));
總而言之就是懶人做法 :)
※ 編輯: laechan (122.117.106.224), 01/25/2018 11:44:39
推 msrvoice : 技術文, 好久沒看到了, 居還還看懂 180.217.170.77 01/25 22:44
推 taily : l大,程式參數都滿長的:D 210.64.180.213 01/26 17:37
推 kruz : 推一下 24.6.220.133 01/30 03:29
推 darkmoon1725: 推推 59.115.58.244 02/02 21:48