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