API調(diào)用海關(guān)和Creep狀態(tài)棧-Screeps技術(shù)詳解

API調(diào)用海關(guān)技術(shù)
作用:將所有screep操作預(yù)定義,在每個(gè)tick末尾全部執(zhí)行咖气。

意義:運(yùn)算-調(diào)用分離区赵,可以更直觀的統(tǒng)計(jì)api的調(diào)用情況和運(yùn)算的執(zhí)行情況

這有點(diǎn)像海關(guān)一樣,所有的貨物都集中到一艘船上之后珠漂,這艘船才會(huì)發(fā)出晚缩。這個(gè)技術(shù)的源本是跨Tick執(zhí)行任務(wù)衍生出來(lái)的,為了讓跨Tick執(zhí)行任務(wù)的框架具有低耦合性媳危、高拓展性荞彼,將這個(gè)板塊分離了出來(lái)。

實(shí)現(xiàn)效果

//MODEL就是你定義的海關(guān)待笑,這里暫時(shí)用MODEL命名鸣皂,你可以將它掛到global上以便于上下文的調(diào)用
//MODEL.intent(tick,gameObjectId,intentData);

intent(1098888,'c49nsb54snw616',{
handler:'harvest',
targetId:'46whwjj464sjwns'
});

那么,海關(guān)可在任意一刻收到該intent并記錄暮蹂,然后在游戲時(shí)間為tick時(shí)使用data中的數(shù)據(jù)對(duì)gameObjectId指定的對(duì)象調(diào)用data中定義的方法寞缝。

有同學(xué)常問(wèn),這樣的intent的操作仰泻,怎么判斷返回值呢荆陆?
這里有兩個(gè)方案

回調(diào)式返回,顧名思義集侯,就是在調(diào)用intent的入?yún)⒛┪蔡砑右粋€(gè)回調(diào)方法被啼,到了執(zhí)行該方法的時(shí)候,將返回值傳遞給回調(diào)方法浅悉,再去處理相關(guān)操作趟据。
但這樣做有個(gè)致命缺陷,它讓跨tick執(zhí)行任務(wù)的容錯(cuò)率大大降低术健,并且可能存在不停的內(nèi)嵌調(diào)用汹碱。


在我認(rèn)真分析了跨Tick執(zhí)行任務(wù)框架的真正意義后,我發(fā)現(xiàn)這樣做并不完善荞估。但狀態(tài)模擬技術(shù)在這上面的發(fā)揮就能相得益彰了咳促。

既然是跨Tick執(zhí)行任務(wù)稚新,那么我們的API就不能變得只對(duì)一個(gè)Tick有效,于是我們拋棄了原來(lái)所有的原生API跪腹,將其重寫褂删,把API也直接提升到跨Tick的層次上。例如

原來(lái)的harvest方法變成某1Tick調(diào)用一次冲茸,剩下的Tick就會(huì)自動(dòng)完成尋路和Harvest操作屯阀。

在最新的TickStream我們是這么做的


我們聚焦在Register上(目前最新版本將其更名為Registry),在TickStream我們不再需要調(diào)用API轴术,更多的是去定義难衰,定義一個(gè)房間,在房間里面定義一個(gè)Creep逗栽,在Creep上定義一個(gè)控制器盖袭,在控制器上定義和命名狀態(tài)機(jī)和實(shí)現(xiàn)功能。例如定義一個(gè)為Harvest的狀態(tài)彼宠,并用代碼實(shí)現(xiàn)Creep如何進(jìn)行Harvest鳄虱。具體如何實(shí)現(xiàn)請(qǐng)看下面

Registry.event([{
name:'CreepNotFree',
event:EVENT_CREEP_NOT_FREE,
attach:ATTACH_CREEP,
call:function(creep){
  creep.state.now.cancel();
},{
name:'UnexpectedCancel',
event:EVENT_CREEP_UNEXPECTED_CANCEL,
attach:ATTACH_CREEP,
call:function(creep){
let before = creep.state.get.before();
creep.state.now.set(before);
}
}]);


Registry.handler([{
name:'harvest',
behavior:function(creep,target){
//判斷自己是否正在另一個(gè)進(jìn)程中
if(creep.state.get.now()!='harvest'){
//如果creep之前已經(jīng)有一個(gè)其他進(jìn)程了,則發(fā)送事件到Event處理器
return Event.creep(EVENT_CREEP_NOT_FREE,creep);
}

//尋找路線
creep.state.now.set('moveTo',target);

//由于是跨Tick執(zhí)行凭峡,你可以認(rèn)為上面這一行代碼執(zhí)行完成后Creep一定在target旁邊了

//harvest拙已,這個(gè)harvest不是用戶定義的,而是通過(guò)intent去調(diào)用了真實(shí)的api
creep.intent(Game.time,'harvest',target)
creep.state.now.done();
}
}]);

我們來(lái)分析一下這些代碼是怎么運(yùn)行的想罕,首先我們要了解creep的狀態(tài)棧悠栓。

狀態(tài)棧

狀態(tài)棧,表示了一個(gè)creep當(dāng)前的狀態(tài)調(diào)用鏈按价,這在跨Tick執(zhí)行任務(wù)中至關(guān)重要惭适。

如上文所述,我們給creep定義了一個(gè)harvest方法楼镐,harveat方法里面又通過(guò)
creep.state.now.set('moveTo',target)調(diào)用了moveTo方法(這個(gè)方法并沒(méi)有寫出來(lái)癞志,因?yàn)楸容^復(fù)雜)。
那么實(shí)際上TickStream在執(zhí)行過(guò)程中框产,這個(gè)Creep的狀態(tài)棧是這樣變化的

  • at harvest
  • at harvest at moveTo
  • at harvest at moveTo at move
  • at harveat at intent

你可以發(fā)現(xiàn)凄杯,moveTo這個(gè)方法在Harvest下面,表示moveTo這個(gè)行為是因?yàn)閔arvest引起的秉宿。

注意:harvest的behavior并不是每個(gè)tick都去執(zhí)行戒突,而是由TickStream框架驅(qū)動(dòng)并緩存執(zhí)行。只有當(dāng)global清空后描睦,或creep狀態(tài)被重新定向后才會(huì)重新執(zhí)行膊存。

我們主要看harvest方法中的內(nèi)容

這是第一部分

//判斷自己是否正在另一個(gè)進(jìn)程中
if(creep.state.get.now()!='harvest'){
//如果creep之前已經(jīng)有一個(gè)其他進(jìn)程了,則發(fā)送事件到Event處理器
return Event.creep(EVENT_CREEP_NOT_FREE,creep);
}

creep.state.get.now返回的是狀態(tài)棧的棧底,因此只有creep的底棧處于harvest狀態(tài)隔崎,這個(gè)behavior都能正常執(zhí)行今艺。

再看代碼中的

//如果creep之前已經(jīng)有一個(gè)其他進(jìn)程了,則發(fā)送事件到Event處理器
return Event.creep(EVENT_CREEP_NOT_FREE,creep);

你可以在上面的Regiatry中找到對(duì)應(yīng)的方法

function(creep){
  creep.state.now.cancel();
}

這表示爵卒,如果creep當(dāng)前的狀態(tài)不是harvest虚缎,那么就取消當(dāng)前的狀態(tài)

在TickStream框架下,一個(gè)creep如果被其他Handler Cancel了钓株,那么會(huì)狀態(tài)會(huì)自動(dòng)變成發(fā)起cancel的Handler對(duì)應(yīng)的狀態(tài)实牡。

所以此時(shí)creep的狀態(tài)變成了harvest

此時(shí)的狀態(tài)棧
at harvest

繼續(xù)往下

creep.state.now.set('moveTo',...);

此時(shí)creep的狀態(tài)棧
at harvest at moveTo

在moveTo方法中,由tickstream轴合,調(diào)用海關(guān)以及狀態(tài)模擬技術(shù)铲掐,將未來(lái)幾個(gè)tick的尋路
已經(jīng)intent完成,并在每個(gè)tick結(jié)束后自動(dòng)調(diào)用值桩,并對(duì)狀態(tài)棧進(jìn)行壓棧

此時(shí)狀態(tài)棧

at harvest at moveTo at move

這個(gè)時(shí)候因?yàn)閕ntent的存在,其他handler直到move的handler的執(zhí)行結(jié)束后豪椿,對(duì) at move進(jìn)行出棧才能繼續(xù)執(zhí)行奔坟。所以這個(gè)時(shí)候其實(shí)所有handler方法都沒(méi)有執(zhí)行。
即使你刪除代碼creep也能繼續(xù)跑搭盾。

直到move完成后咳秉,此時(shí)creep已經(jīng)來(lái)到target旁邊

此時(shí)的狀態(tài)棧

at harvest at moveTo

moveTo隨即也結(jié)束出棧

at harvest

這個(gè)時(shí)候可以執(zhí)行harvest下面的intent調(diào)用api來(lái)真實(shí)的進(jìn)行harvest了

執(zhí)行完intent后使用
creep.state.now.doen()對(duì)harvest出棧

這個(gè)時(shí)候其他的handler才能對(duì)其進(jìn)行操作,當(dāng)然也可以被其他handler在中途取消鸯隅。

由于我們?cè)趀vent當(dāng)中添加了取消事件澜建,即使被取消,也會(huì)被重新壓棧執(zhí)行蝌以。

好了炕舵。
講原理可能會(huì)有點(diǎn)復(fù)雜,我表達(dá)能力可能不強(qiáng)跟畅,請(qǐng)各位敬請(qǐng)諒解咽筋。下次我會(huì)成體系的講述TickStream的工作細(xì)節(jié),當(dāng)然你也可以借鑒完成自己的跨Tick框架

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末徊件,一起剝皮案震驚了整個(gè)濱河市奸攻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌虱痕,老刑警劉巖睹耐,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異部翘,居然都是意外死亡硝训,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捎迫,“玉大人晃酒,你說(shuō)我怎么就攤上這事≌蓿” “怎么了贝次?”我有些...
    開(kāi)封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)彰导。 經(jīng)常有香客問(wèn)我蛔翅,道長(zhǎng),這世上最難降的妖魔是什么位谋? 我笑而不...
    開(kāi)封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任山析,我火速辦了婚禮,結(jié)果婚禮上掏父,老公的妹妹穿的比我還像新娘笋轨。我一直安慰自己,他們只是感情好赊淑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布爵政。 她就那樣靜靜地躺著,像睡著了一般陶缺。 火紅的嫁衣襯著肌膚如雪钾挟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天饱岸,我揣著相機(jī)與錄音掺出,去河邊找鬼。 笑死苫费,一個(gè)胖子當(dāng)著我的面吹牛汤锨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播黍衙,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼泥畅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了琅翻?” 一聲冷哼從身側(cè)響起位仁,我...
    開(kāi)封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎方椎,沒(méi)想到半個(gè)月后聂抢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棠众,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年琳疏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了有决。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡空盼,死狀恐怖书幕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情揽趾,我是刑警寧澤台汇,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站篱瞎,受9級(jí)特大地震影響苟呐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俐筋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一牵素、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧澄者,春花似錦笆呆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至抱怔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嘀倒,已是汗流浹背屈留。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留测蘑,地道東北人灌危。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像碳胳,于是被迫代替她去往敵國(guó)和親勇蝙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容