第一百一十章 UUID
在Minecraft JAVA 1.7.10版本更新中,Mojang認(rèn)為玩家可以更改用戶名。但如果玩家可以更改用戶名,那么一個(gè)用戶名就不能完全代表一個(gè)玩家。解決這個(gè)問題的唯一辦法,就是給玩家添加一個(gè)從按下注冊(cè)那一鍵開始就不能改變的唯一識(shí)別碼。
使用什么樣的識(shí)別碼呢?Mojang直接就采用了不管是在Minecraft中還是在網(wǎng)絡(luò)上都十分常用的『Universally Unique Identifier』來作為玩家的不可改變識(shí)別碼,這就是作者在之前經(jīng)常提到的UUID,它的中文名叫做『通用唯一識(shí)別碼』。
一個(gè)UUID本質(zhì)上是一個(gè)長(zhǎng)達(dá)128位的隨機(jī)生成的二進(jìn)制數(shù)字,但我們不可能直接使用它的二進(jìn)制形式,而是使用它的『十六進(jìn)制』或『十進(jìn)制』形式。
在十六進(jìn)制中,最常見的形式就是:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
這是UUID的『十六進(jìn)制表示形式』。準(zhǔn)確的來講,是『有連字符的十六進(jìn)制(Hyphenated hexadecimal)』形式。這種形式的UUID本質(zhì)上是將UUID轉(zhuǎn)化到十六進(jìn)制后,再用連字符『-』將其分割成8+4+4+4+12的5段。
當(dāng)然,把連字符去掉就是純潔的『十六進(jìn)制形式(String without hyphens)』了:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
只不過去掉連字符的話,你有很大概率會(huì)抄錯(cuò),所以還是建議在抄UUID之前給它加上個(gè)連字符。
什么?你不知道十六進(jìn)制?
那你總知道十進(jìn)制吧?在十進(jìn)制中,數(shù)字是逢十進(jìn)一。比如:
5+5=10
所以對(duì)于十六進(jìn)制來講,數(shù)字就是逢十六進(jìn)一。比如:
(5+5)+7=a+7=11
其中,字母『a』在十六進(jìn)制中代表『十』這個(gè)數(shù)字。以此類推,b代表『十一』、c代表『十二』.......f代表『十五』。
這就是十六進(jìn)制,你懂了嗎?
回到正題。我們?cè)诘谝话倭懔聲r(shí)就已經(jīng)遇到過『有連字符的十六進(jìn)制』這種形式的UUID了。你還記得嗎?讓我們回憶一下:
『/attribute @s minecraft:generic.max_health modifier value get 1-1-1-1-1 2.0』
其中,參數(shù)『1-1-1-1-1』就是一個(gè)『有連字符的十六進(jìn)制』形式的UUID。等等,為什么這個(gè)UUID不是8+4+4+4+12的?
如果你有注意到游戲返回的消息,就會(huì)發(fā)現(xiàn),這種UUID在游戲眼中會(huì)被視為:
『00000001-0001-0001-0001-000000000001』
也就是說,UUID中數(shù)字前面的0可以被省略。比如:
『00000101-0001-0003-0015-000000032300』
上面這串UUID就可以省略成:
『101-1-3-15-32300』
這是一個(gè)非常人性化的設(shè)計(jì),也非常符合數(shù)學(xué)。
需要注意,如果是『10000001-1001-1001-1001-100000000001』這樣的,可不要想著縮寫成:
11-11-11-11-11
不然游戲會(huì)以為這個(gè)UUID是『00000011-0011-0011-0011-000000000011』的縮寫。
這種縮寫不僅僅在『有連字符的十六進(jìn)制』形式中可用,在其他形式中照樣可用。
現(xiàn)在你知道了十六進(jìn)制形式的UUID。那之前的UUIDMost(UUID高位)和UUIDLeast(UUID低位)到底是啥呢?
在解答之前,作者建議你先去找一個(gè)進(jìn)制轉(zhuǎn)換器,以方便現(xiàn)學(xué)現(xiàn)做。
以剛才的『00000001-0001-0001-0001-000000000001』舉例,現(xiàn)在它是十六進(jìn)制。
把前面三段(00000001-0001-0001)和后面兩段(0001-000000000001)分開,并分別劃成10進(jìn)制,變成:4295032833和281474976710657這兩個(gè)數(shù)。
這兩個(gè)數(shù)就是這個(gè)UUID的高位以及低位了。其實(shí)高位以及低位就是將十六進(jìn)制的UUID切成兩半然后劃成10進(jìn)制得出的數(shù),說明白點(diǎn),就是:
xxxxxxxx-xxxx-xxxx 這一段轉(zhuǎn)換成10進(jìn)制就是UUID Most
xxxx-xxxxxxxxxxxx 這一段轉(zhuǎn)換成10進(jìn)制就是UUID Least
?。ㄔ贜BT中,這兩個(gè)標(biāo)簽的數(shù)據(jù)類型都為L(zhǎng)ong長(zhǎng)整型)
但要注意,如果沒有特別指明,你是不知道一個(gè)16進(jìn)制的數(shù)字到底是正還是負(fù)。
原因的話,百度/谷歌一下,你就知道(畢竟這是Minecraft指令教學(xué),不是計(jì)算機(jī)課)。
這種高位和低位的UUID形式,被稱為『高低位(Most/Least)』。這種形式在Minecraft Java1.16版本更新前幾乎遍地都是,但在Java1.16更新中卻幾乎絕跡了。
為何?因?yàn)樵?.16版本更新后,NBT中大部分UUID再也不是『高低位』形式,而是使用了一個(gè)全新的表現(xiàn)方式:整型數(shù)組(int-array)
其樣式我們?cè)谥耙呀?jīng)碰過好幾次了。比如下面這一串:
[I;-678432868,1549618207,-1367000395,-2137777200]
好像這種形式的UUID和其他形式?jīng)]有太大關(guān)系。
但其實(shí)這種UUID和其他形式的UUID也可以互相轉(zhuǎn)換,不然正版玩家的UUID就得重新設(shè)置。
如果你不想了解的話,可以跳過這一段,去看看UUID到底該如何獲取。
但如果你想了解的話,不妨也來看一看。
仔細(xì)觀察這一串?dāng)?shù)組,你會(huì)發(fā)現(xiàn)這4串?dāng)?shù)字有正負(fù)號(hào),并且沒有出現(xiàn)字母,加上這是個(gè)『整型數(shù)組』。這些證據(jù)都證明,這四串?dāng)?shù),是十進(jìn)制。
既然是十進(jìn)制,那就好辦了。根據(jù)UUID Most以及UUID Least的經(jīng)驗(yàn),這四串?dāng)?shù),極有可能是十六進(jìn)制的UUID平均分成4段再分別劃成十進(jìn)制的數(shù)。
為了驗(yàn)證我們的猜想,先隨機(jī)一個(gè)UUID:
十六進(jìn)制——09fa22c0-807d-4a29-b0fa-a6513fab4822
數(shù)組形——[I;167387840,-2139272663,-1325750703,1068189730]
將『09fa22c0-807d-4a29-b0fa-a6513fab4822』的連字符去掉,再平均分成4段,并取最前面的那一段,也就是:
09fa22c0
劃成十進(jìn)制就是:167387840!
這種數(shù)組形式的UUID本質(zhì)上就是將16進(jìn)制形態(tài)的UUID平均分成四段再分別劃成十進(jìn)制最后組合成一個(gè)數(shù)組!
等等,遇到了一個(gè)小問題,這個(gè)負(fù)數(shù)問題,該怎么辦?
百毒一下,你就知道。
說了這么多UUID,那么UUID該怎么獲取?
如果你是一位Java版的腐竹,開著一個(gè)服務(wù)器,那你就可以到服務(wù)器的根目錄找到一個(gè)名叫usercache.json或usernamecache.json的文件,里面有全部服務(wù)器玩家的UUID。
對(duì)于Java的正版玩家來說,有許多網(wǎng)站可以通過輸入玩家的名字或UUID來查詢一個(gè)正版玩家的皮膚、UUID等信息,甚至可以知道這個(gè)玩家去過哪些服務(wù)器,這些服務(wù)器現(xiàn)在有多少人在線,他的游戲時(shí)長(zhǎng)是多少!雖然不知道這些數(shù)據(jù)是怎么獲取的(極有可能是爬蟲),但這也方便我們查詢自己的UUID(以及別人的)。
比如最常見的mcuuid.net和namemc.com。
但別忘了,實(shí)體也有UUID。那實(shí)體的UUID如何獲???
有很多種方法,你可以去網(wǎng)上搜。這里只講一個(gè)最方便的:
在Java1.13及以上版本中,使用聊天欄填寫指令時(shí),只要你的準(zhǔn)心對(duì)著一個(gè)實(shí)體,在填寫目標(biāo)選擇器類型的參數(shù)時(shí)你就可以通過Tab鍵一鍵獲取到這個(gè)實(shí)體的UUID(有連字符的十六進(jìn)制形式)。
對(duì)了,正版玩家的UUID還可以通過Mojang給出的api來獲取,具體用法為:
api.mojang.com/users/profiles/minecraft/一個(gè)正版玩家的用戶名
這里拿一個(gè)用戶名叫做『Minecraft』的正版玩家舉例,輸入api.mojang.com/users/profiles/minecraft/Minecraft,網(wǎng)頁(yè)就會(huì)返回如下JSON:
{“name“:“Minecraft“,“id“:“b2732392fae140c3b836a066c6debd8f“}
其中的id就是這名玩家的十六進(jìn)制UUID。
附錄:UUID歷史
Java
1.16——NBT中的UUID幾乎都改成了整形數(shù)組的形式,拋棄了原有的高低位形式。