第九十八章 觸發(fā)器-簡(jiǎn)單的注冊(cè)/登錄系統(tǒng) 上
(本章已于2022年7月31日重寫(xiě))
現(xiàn)在,我們已經(jīng)了解了N多條指令,并學(xué)會(huì)了搭建紅石邏輯組,但我們似乎并沒(méi)有拿所學(xué)的知識(shí)來(lái)做點(diǎn)什么有趣的東西。在此前的章節(jié)中,最多最多,我們也就用了幾個(gè)命令方塊來(lái)實(shí)現(xiàn)諸如生成鉆石之類(lèi)的小功能,談不上有多厲害。
所以在接下來(lái)的內(nèi)容中,我們將會(huì)用指令在Minecraft Java1.19版本中嘗試做出一個(gè)有趣的具有實(shí)際功能的東西,那到底這個(gè)東西是什么呢?
在『第五十一章 whitelist-白名單』這一個(gè)章節(jié),我提到了在Minecraft Java的離線(xiàn)服務(wù)器中,單純使用白名單并不保險(xiǎn)。而在給出的三個(gè)解決方法中,第二條寫(xiě)到:
『不要使用原版的服務(wù)端,采用第三方可以裝插件的服務(wù)端或在原版服務(wù)端的基礎(chǔ)上裝Forge再加上SpongeForge(海綿端),并給服務(wù)器裝上適宜的登錄插件,讓玩家進(jìn)入服務(wù)器還需輸入一次密碼進(jìn)行二次驗(yàn)證』
現(xiàn)在有很多Minecraft Java服務(wù)器就是這么干。這些服務(wù)器往往會(huì)開(kāi)兩個(gè)甚至更多的MC服務(wù)器——一個(gè)主服,另一個(gè)是專(zhuān)門(mén)用來(lái)登錄的登錄服。當(dāng)玩家想要進(jìn)入他們的服務(wù)器時(shí),往往并不會(huì)直接進(jìn)入到主服,而是先進(jìn)入到登錄服進(jìn)行登錄,登錄成功后玩家才能進(jìn)入到主服(例子有EaseCation服務(wù)器,你在服務(wù)器退出登錄后就會(huì)來(lái)到它的登錄服)。對(duì)于某些沒(méi)錢(qián)的服務(wù)器來(lái)說(shuō),雖然開(kāi)不了登錄服,但也會(huì)裝一些登錄插件,讓玩家在登錄之后才能進(jìn)行全部的操作。
但是不管怎樣,以上的效果都是要在安裝第三方服務(wù)端,并安裝服務(wù)器插件(甚至可能還要配置數(shù)據(jù)庫(kù))之后才能做到。那在原版中,我們能否通過(guò)指令來(lái)實(shí)現(xiàn)以上效果呢?
如果僅僅說(shuō)是做出一個(gè)『注冊(cè)/登錄』的效果來(lái)說(shuō),在Minecraft Java版中當(dāng)然是可以的,而且也很容易做出來(lái)。讓我們來(lái)試一試。
要做出『注冊(cè)/登錄』系統(tǒng),首先我們要清楚:
什么是注冊(cè)和登錄?
Oxford Languages詞典對(duì)『注冊(cè)』一詞的定義如下:
『特指電子計(jì)算機(jī)某網(wǎng)絡(luò)的用戶(hù)向該網(wǎng)絡(luò)輸入用戶(hù)名、密碼等,以取得對(duì)該網(wǎng)絡(luò)的使用許可』
結(jié)合我們平常注冊(cè)賬號(hào)的常識(shí),不難得出,注冊(cè)和登錄的流程是這樣的:
用戶(hù)向服務(wù)器發(fā)送注冊(cè)/登錄請(qǐng)求→服務(wù)器讓用戶(hù)填寫(xiě)用戶(hù)名和密碼等信息→用戶(hù)填寫(xiě)完后,將信息發(fā)送至服務(wù)器→服務(wù)器檢查信息→服務(wù)器根據(jù)檢查的結(jié)果,判斷是否允許用戶(hù)進(jìn)行下一步操作
現(xiàn)在,我們要在Minecraft中做出『注冊(cè)/登錄』的效果,本質(zhì)上其實(shí)就是要實(shí)現(xiàn)上面的流程。而為了實(shí)現(xiàn)上面的流程,我們就要研究一下如何把上面的流程轉(zhuǎn)化到Minecraft中。
我們可以做一個(gè)房間,設(shè)置出生點(diǎn)就在這個(gè)房間里面,然后放置一個(gè)按鈕在墻上,并告訴玩家需要點(diǎn)擊這個(gè)按鈕來(lái)注冊(cè)/登錄。玩家點(diǎn)擊這個(gè)按鈕后,就會(huì)激活相應(yīng)的邏輯組運(yùn)行指令,此時(shí)就可以輸入用戶(hù)名和密碼進(jìn)行注冊(cè)或登錄,命令方塊也會(huì)獲取到玩家填寫(xiě)的內(nèi)容,并進(jìn)行一番操作,最后告訴玩家是否成功,如果成功則將他傳送到外面。
前半段很簡(jiǎn)單,我們可以很容易做出來(lái)一個(gè)里面放著一個(gè)按鈕的房間(插圖98-1)。難點(diǎn)其實(shí)在后半段,有兩個(gè)難點(diǎn)要解決:
①怎么讓玩家輸入用戶(hù)名和密碼,并將這些信息存儲(chǔ)到哪里?
?、谠趺礄z測(cè)玩家輸入的內(nèi)容是否符合要求?
先來(lái)看第一個(gè)問(wèn)題。
讓玩家輸入用戶(hù)名和密碼,首先就是要有一個(gè)能夠讓玩家輸入文字的地方。在Minecraft中,哪里可以輸入文字呢?
多得去了!聊天框、書(shū)與筆、鐵砧、命令方塊......重點(diǎn)在于,我們是否可以正確獲取到玩家輸入的文字,并將其儲(chǔ)存起來(lái)?
先來(lái)看看書(shū)與筆。我們可以檢測(cè)書(shū)與筆的NBT,然后將獲取到的信息儲(chǔ)存在.......
書(shū)與筆的內(nèi)容肯定不只是數(shù)字,所以我們不能將信息儲(chǔ)存在計(jì)分板中,只能將信息儲(chǔ)存到某個(gè)NBT標(biāo)簽中。然而,一方面我們還沒(méi)有正式學(xué)習(xí)NBT,另一方面我們也不知道儲(chǔ)存在哪里,儲(chǔ)存完后又該如何獲取如何修改,因此采用書(shū)與筆作為輸入框的方法對(duì)于現(xiàn)在的我們來(lái)說(shuō),不可取。
既然書(shū)與筆不可取,那么鐵砧、命令方塊等一大堆東西就都不行了。額,所以現(xiàn)在,我們應(yīng)該怎么獲取、從哪獲取到玩家的輸入內(nèi)容并將其儲(chǔ)存起來(lái)呢?
或許我們應(yīng)該換個(gè)角度思考:我們可以將玩家輸入的內(nèi)容存儲(chǔ)到哪里?
對(duì)于現(xiàn)在的我們來(lái)說(shuō),計(jì)分板是個(gè)不錯(cuò)的選擇。等等,那么我們是否可以開(kāi)放一個(gè)計(jì)分項(xiàng)讓玩家自由修改,然后我們?cè)購(gòu)闹蝎@取計(jì)分項(xiàng)的值呢?
好主意!但問(wèn)題來(lái)了,要修改計(jì)分項(xiàng)的話(huà),玩家就得有2級(jí)權(quán)限(Java版),但就算是個(gè)傻子也不會(huì)給剛進(jìn)服的玩家2級(jí)權(quán)限吧?況且,/op和/deop可不能在命令方塊中運(yùn)行。
那是否有沒(méi)有一種方法,能夠讓沒(méi)有權(quán)限的玩家也能夠修改特定計(jì)分項(xiàng)的值呢?
還真有!那就是:
觸發(fā)器(Trigger)
在『第四十一章 objectives——管理一個(gè)計(jì)分項(xiàng)』中,我們?cè)?jīng)了解到trigger準(zhǔn)則計(jì)分項(xiàng)所具有的特性:
『觸發(fā)器,類(lèi)似于dummy,但所有玩家均可修改自己的trigger型計(jì)分項(xiàng)』
也就是說(shuō),我們可以創(chuàng)建一個(gè)trigger準(zhǔn)則的計(jì)分項(xiàng),然后指示玩家去修改自己在這個(gè)計(jì)分項(xiàng)上的分?jǐn)?shù),進(jìn)而達(dá)到『玩家輸入,我們也能檢測(cè)到并儲(chǔ)存』的效果。
那我們到底該怎樣正確使用觸發(fā)器呢?
讓我們先創(chuàng)建一個(gè)trigger準(zhǔn)則的計(jì)分項(xiàng):
/scoreboard objectives add password trigger
這將會(huì)創(chuàng)建一個(gè)叫做『password』的trigger準(zhǔn)則計(jì)分項(xiàng),我們將會(huì)使用它來(lái)儲(chǔ)存玩家的密碼。
然后呢,怎么讓玩家能夠修改?
你應(yīng)該知道,讓玩家使用/scoreboard players set 去修改自己的trigger類(lèi)計(jì)分項(xiàng)的分?jǐn)?shù)是不現(xiàn)實(shí)的,因?yàn)閟coreboard必須要2級(jí)權(quán)限才能使用。因此,Mojang專(zhuān)門(mén)為觸發(fā)器加入了一條指令:
/trigger
作用:修改執(zhí)行者自己的trigger計(jì)分項(xiàng)上的分?jǐn)?shù)
存在版本:Java1.8-今
需要權(quán)限等級(jí):Java-0
需要作弊:否
格式:
/trigger <允許的trigger計(jì)分項(xiàng)>
\\使執(zhí)行者自己在指定計(jì)分項(xiàng)上的分?jǐn)?shù)+1\\
/trigger <允許的trigger計(jì)分項(xiàng)>(add|set)<值>
\\設(shè)置執(zhí)行者自己在指定計(jì)分項(xiàng)上的分?jǐn)?shù)\\
舉個(gè)例子:
/trigger password set 1
如果password是個(gè)已被啟用的trigger計(jì)分項(xiàng),那么運(yùn)行上述指令將會(huì)修改執(zhí)行者自己在password計(jì)分項(xiàng)上的分?jǐn)?shù)為1。
等等,『已被啟用』是個(gè)啥意思?trigger計(jì)分項(xiàng)要被修改還得先啟用?
沒(méi)錯(cuò),Mojang雖然給了我們觸發(fā)器,但是這個(gè)觸發(fā)器并不是隨時(shí)隨地都能讓沒(méi)權(quán)限的玩家自由修改的。要讓玩家能夠使用觸發(fā)器,首先你需要使用scoreboard players enable命令來(lái)為指定玩家啟用觸發(fā)器:
/scoreboard players enable <目標(biāo)>
比如:
/scoreboard players enable @s password
就可以讓我們自己能夠修改一次password。注意?。〔皇菬o(wú)限修改,而是只能修改一次!
就算你為指定玩家啟用了觸發(fā)器,但只要那批玩家使用trigger指令修改了一次,那么觸發(fā)器就會(huì)自動(dòng)關(guān)閉,直到我們?cè)俅螢樗麄冮_(kāi)啟觸發(fā)器。也就是說(shuō),如果你這樣運(yùn)行指令,將會(huì)得到如下結(jié)果:
/scoreboard players enable @s password
已為XXX啟用了觸發(fā)器[password]
/trigger password set 1
已觸發(fā)[passoword](數(shù)值已設(shè)為1)
/trigger password set 1
你尚無(wú)法觸發(fā)這個(gè)記分項(xiàng)
總而言之:要讓玩家修改觸發(fā)器,得先打開(kāi)觸發(fā)器,然后玩家就能夠修改一次,修改完后觸發(fā)器自動(dòng)關(guān)閉,直到下一次被打開(kāi)。
懂了吧?現(xiàn)在我們回來(lái)看看上面的第一個(gè)問(wèn)題,你是否已經(jīng)想到了解決辦法?
沒(méi)錯(cuò),就是:
先創(chuàng)建一個(gè)儲(chǔ)存密碼用的password的觸發(fā)器計(jì)分項(xiàng)(這步我們上面已經(jīng)完成了)。當(dāng)玩家按下按鈕時(shí),為其打開(kāi)該觸發(fā)器,并指示玩家通過(guò)/trigger指令修改該觸發(fā)器的值,同時(shí)不斷檢測(cè)玩家是否已經(jīng)輸入。當(dāng)檢測(cè)到玩家輸入時(shí),對(duì)玩家輸入的內(nèi)容進(jìn)行檢查,如果符合條件則通過(guò)檢測(cè),否則重新打開(kāi)觸發(fā)器,讓玩家重新輸入。
這已經(jīng)非常符合最終的注冊(cè)和登錄流程了。但是我們?nèi)匀灰鉀Q兩個(gè)問(wèn)題:
?、偃绾螜z測(cè)玩家是否輸入了密碼?
?、诘降酌艽a要符合怎樣的條件才可以通過(guò)檢測(cè)?
?。òψ髡撸脩?hù)名呢?用戶(hù)名怎么辦?)
?。ㄆ鋵?shí)不需要用戶(hù)名,玩家名稱(chēng)完全可以當(dāng)成用戶(hù)名來(lái)使用)
對(duì)于第一個(gè)問(wèn)題,我們有兩個(gè)解決辦法:
?、俨粩鄼z測(cè)觸發(fā)器的值是否改變,也就是通過(guò)execute的條件子命令判斷
這個(gè)方法最簡(jiǎn)單,但是有些問(wèn)題:萬(wàn)一玩家輸入的是默認(rèn)值該怎么辦?
②不斷嘗試為指定玩家打開(kāi)觸發(fā)器,并將成功次數(shù)存儲(chǔ)到另一個(gè)計(jì)分項(xiàng)上
這個(gè)方法也很簡(jiǎn)單,只要計(jì)分項(xiàng)的值不等于0,就代表著打開(kāi)觸發(fā)器成功,也就代表玩家已經(jīng)輸入過(guò)了。這同時(shí)也能解決『萬(wàn)一玩家輸入的是默認(rèn)值』的問(wèn)題。
因此,我們不妨采用第二個(gè)解決辦法,創(chuàng)建一個(gè)專(zhuān)門(mén)的計(jì)分項(xiàng)來(lái)記錄觸發(fā)器是否打開(kāi)成功:
/scoreboard objectives add is_typed dummy
然后在等待玩家輸入密碼的過(guò)程中,不斷重復(fù)執(zhí)行:
/execute as 玩家 store success score @s is_typed run scoreboard players enable @s password
隨后檢測(cè)就可以了。
第二個(gè)問(wèn)題就更簡(jiǎn)單了,因?yàn)檫@個(gè)問(wèn)題沒(méi)有標(biāo)準(zhǔn)答案,我們也不會(huì)在這章討論這個(gè)問(wèn)題。
現(xiàn)在,我們成功解決了輸入的問(wèn)題,整個(gè)『注冊(cè)/登錄』系統(tǒng)的最大難關(guān)已被拔除。在下一章,我們將會(huì)嘗試搭建一個(gè)簡(jiǎn)陋的Beta版本,來(lái)檢測(cè)一下我們的想法是否可行。