LV. 35
GP 596

【情報】4年過去了,終於可以使用生存模式獲得指令方塊

樓主 NJ彬 njes9701
GP185 BP-
1.12都過去4年了依然有很多不同的新機制被開發出來驚艷著我們,從以前我們都認為某些創造物品例如:
指令方塊.結構方塊.屏障.地獄傳送門.終界傳送門.基岩.生怪磚.石化橡木辦磚.敲擊點燃TNT.甚至在地獄獲得水與其他無法再1.12獲得的方塊。(這邊我只放少數幾種無法透過生存獲得的方塊出來)

這一切都要回到2020年8月28號,國外玩家Coolman發現了一種Falling Block的技術。
簡單來說我們都知道遊戲中常見會掉落的方塊是沙子對吧,他以某種神奇的方式將掉落中的沙子給替換成了"我們要的方塊"透過這種手段我們可以輕而易舉地得到生存沒辦法獲得的方塊。

為了各位方便理解其中簡化了非常多東西,如果要詳細深入可以到文章下面觀看影片。


How it work?
首先必須瞭解掉落沙子的運作原理
這個是掉落方塊的大致運作原理,那我們要從哪邊下手才可以使"掉落沙子"轉變成"其他方塊"呢?
我們只要將方塊轉換為可掉落的實體方塊這個階段,透過某種神奇的方式,將那一格方塊的資訊改變成我們要的方塊就行了,但這要怎麼辦到?

我們要先理解 MultiThreading 多線程:
這邊有個簡單的例子,我要做一道數學題並且將兩個數值拆給兩個人。
可以看見最後的答案必須要兩個人互相合作才能產出答案50。
如果Gura B在計算過程中出錯算成了35那最後的答案會變成70。
如果你夠聰明就可以看見這裡面的漏洞,將掉落沙子的步驟給拆成2線程並且對其中一個線程動手腳來改變方塊數值,但是要怎麼把掉落沙子這個動作給拆成2個線程?

"烽火台"與"染色玻璃"
當你放置有顏色的玻璃在烽火台上會改變它的顏色利用這個機制來實現。
每次破壞或放置染色玻璃or染色玻璃片都會檢查放置的位置往下找是否存在烽火台,這個動作就會額外的創造一個新的線程,這邊就稱玻璃線程,最後這個線程執行完的結果會再回到主線程使烽火台改色。
那要怎麼讓玻璃線程改變掉落沙子的資訊?這邊就要使用到2個技術。
Chuck Swap:
在玩家加載的區塊中生成一個未加載的區塊,並且使用遊戲機制讓他再次載入生成地形。
Instant Tile Tick:
使遊戲的所有事件都變成沒有延遲,中繼器沒延遲.觀察者沒延遲.液體放出來會瞬間散開.火燒木頭會瞬間燒掉等等......

這兩個解釋起來文章的空間不夠我寫,這邊暫時不詳細探討我只說明功能。
其實是懶的寫

首先要怎麼改變掉落沙子的資訊?Async observer line(異步觀察者)可以來改變掉落沙子的資訊。
如何獲得"異步觀察者"呢?回到上面的"玻璃線程"透過放置或破壞染色玻璃產生出一個新線程,並且在這個線程中使用了Chunk Swap技術來產生一個獨立運行在"玻璃線程"的觀察者方塊,而這個觀察者方塊就是我們要的Async observer line(異步觀察者)。
當我們使用異步觀察者輸出對著掉落沙子,這時候就會發生一件很有趣的事情。
可以看見這時候掉落沙子的資訊會被拆分成兩份,這時候如果對著玻璃線程動手腳那就可以成功的改變最後掉落方塊的結果,但是要改變內部資訊的動作要使異步觀察者方塊更新非常的快速且大量這時候就要用到Instant Tile Tick 讓觀察者變成無延遲瞬間動作,但是該做出的方塊更新都沒有少。

當你把觀察者方塊串起來並且在第一個對他做輸入,方塊更新的次數會變成2^N次方數量成長
例如如果將5個觀察者方塊串聯起來會得到2^5=32次方塊更新
20個串聯觀察者更新一次就會來到可怕的2^20=1048576方塊更新

如果你做死把20個串聯觀察者運行在遊戲的主線程上面會直接造成遊戲死當崩潰,但是別忘了我們的觀察者是運行在玻璃線程上面並不會造成崩潰,所以才叫做異步觀察者。

好的寫到這邊我已經盡力以簡單的方式介紹給大家,但這還沒完繼續!
做出上面那麼多特殊的技術要怎麼去把一個方塊的資訊給套用成另一個方塊呢?
我們先來看看指令方塊的物品ID
指令方塊 ID:137
13 bit二進位ID: 0 1000 1001 0000
我先來解釋下每個物品儲存在區塊中變成二進位的方式
首先0 1000 1001 0000 後面4bit是儲存方塊的方向,0 1000 1001 0000 前面9bit是儲存方塊ID
鐵砧
鐵砧 ID:145
13 bit二進位ID: 0 1001 0001 0000
水 ID:9
13 bit二進位ID: 0 0000 1001 0000

這時候問你鐵砧+水會=什麼?
沒錯指令方塊!
鐵砧   13 bit二進位ID: 0 1001 0001 0000
水13 bit二進位ID: 0 0000 1001 0000
將上面兩個紅色二進位部分合併起來就變成了指令方塊的二進位ID了!
指令方塊 13 bit二進位ID: 0 1000 1001 0000
但是要怎麼把兩個不相干的ID合起來呢?
在SubChunk子區塊中也就是你按下F3+G顯示出來區塊中藍色線之間的區塊就是子區塊
他的儲存格式會依造區塊中有多少blockstates來決定儲存方式。
0-16 Linear
17-256 hashmap
257+ Registry
我們接下來要使用的是Registry 在這之前必須先在區塊中填滿257種不同的blockstates很簡單只要放置
很多不同指向性的方塊在同一個子區塊中填滿前257格。
Registry中使用的是long array  在JAVA 中 long 的長度為64bit
這時候你會發現1個long最多儲存4個方塊資訊,1個方塊資訊長度為13bit
所以最後多的12bit怎麼辦呢? 當然是生成第二個long接著儲存用拉!
如果將鐵砧與水放在兩個long的連接位置,如果鐵砧被方塊更新第一個會先叫出前面鐵砧的long資訊,但會發現鐵砧剛好卡在兩個long之間,所以會再次呼叫第二段的long,最關鍵的地方如果我們把呼叫long的線程拆分成兩個並且同時間呼叫會發生什麼事情?
沒錯鐵砧跟水的二進位會被混再一起而形成一個新的方塊,也就是指令方塊。
使用異步觀察者方塊對著目標方塊不斷大量更新,也就是上面說的不斷的呼叫該區塊的long讀取資訊,
這時候來讀取資訊的線程只會有主線程,與玻璃線程也就是異步觀察者方塊所造成的更新。

好了這時候你就真的以生存的方式獲得指令方塊了!但是他會直接以方塊得形式出現在鐵砧的位置上
而不是物品,那要怎麼把指令方塊轉換為物品型態呢?
回到上面的Falling Block 這個是為了要讓你可以把無法採集的方塊轉換為物品才出現的技術,現在我們生出來一個指令方塊後,要如何轉換為掉落物?
回到上面的blockstates儲存列表
0-16 Linear
17-256 Hashmap
257+ Registry
我們可以瞭解下Registry與Hashmap之間的差異性
Registry 這個儲存方式可以讓你無中生有的方式獲得新的方塊,透過重組兩個方塊的二進位ID
Hashmap 只能讀取已存在的方塊,並且資料的數值是以順序來做儲存,該區域的方塊會依造不同數量的blockstates來決定如何儲存方塊數值。
17-32 5 bit Hashmap
33-64 6 bit Hashmap
65-128 7 bit Hashmap
129-256 8 bit Hashmap
這邊我們會用到7bit Hashmap 也就是要提前把子區塊填充滿至65個blockstates來達到此條件
假設我們在這個子區塊中放了沙子與指令方塊在某個特殊的位置
沙子ID:0000011   DEC_ID: 3
空氣ID:0000000 DEC_ID:0
指令方塊ID:0000010DEC_ID:2
一樣使用上面的技巧將空氣與沙子二進位混和再一起就會變成~ 沒錯二氧化二矽
沙子:0000011    
空氣:0000000
指令方塊:0000010
(演示用不代表實際運作情形)
當活塞拉回或是推出,沙子都會有一瞬間變為掉落方塊,在那個瞬間對方塊數據做更改
並且將掉落方塊用史萊姆方塊推出,掉落在柵欄上來轉變成物品。

好了到這邊大致上的原理就是這樣,已經夠簡化過程了如果你想要詳細了解可以從文章下面的幾部影片
去觀看,阿對了看Myren的影片會讓你收益滿滿喔:D

Falling block 被開發 by coolman

什麼神奇的魔力即使在Minecon 上 Myren的麥克風就算很好,卻可以把麥克風音質給變成100塊錢的音質








185
-
未登入的勇者,要加入 2 樓的討論嗎?
板務人員: