Minecraft 20w49a 新內(nèi)容特性+代碼探析

20w49a出來了,更改了很多東西。那么直奔主題,開始說說這一個版本干啥了。
首先給出一下這個版本的類更改:
20w46a->20w48a類更改表 https://paste.ubuntu.com/p/DN2qYNZbjF (上周快照的)
20w48a->20w49a類更改表 https://paste.ubuntu.com/p/W3FwCbT2jG/
一.滴水石錐的bug修復(fù)
上一個版本中,鐘乳石在50格以上敲掉就不會掉落(MC-206578),這個版本修復(fù)了,原因是findTip修改回了直接一查到底(尋找范圍最大是int最大值2147483647)。

所以這回牛頓可以安心地火化了(
同時,鐘乳石砸死增加了自己的傷害來源FALLING_STALACTITE(代碼太短小了,不放出來了),并且提示是XX被墜落的鐘乳石刺穿了(新的死亡方式!)。
然后是生電玩家比較在意的東西:石筍的傷害計算方式修改了,不再是以前的直接乘4倍了,現(xiàn)在的公式是:
(fallDistance + 2) * 2

最后,它現(xiàn)在可以自然生成,新加入了溶洞地下生物群系。由于地形生成就是一大堆繁瑣公式,就不在這里提及了。
二.Sculk Sensor(暫無中文譯名)
這是一種新的紅石元件,可以探測振動(說明白就是聲音)。它能檢測8格之內(nèi)的有效振動(8格這里指歐幾里得距離而不是曼哈頓距離)
首先說說它的方塊定義,它有三種屬性:
PHASE 階段,是一個枚舉值,包括COOLDOWN(冷卻),ACTIVE(激活),INACTIVE(未激活)
POWER 充能,也就是紅石信號直接輸出值,一個0-15的整數(shù)值
WATERLOGGED 含水,含水方塊通用的屬性

說完方塊定義,說一下它的其他特性:
第一.這是一個方塊實(shí)體(BlockEntity,在MCP中也叫TileEntity)
和普通的漏斗、熔爐一樣,它是一種方塊實(shí)體,對應(yīng)的類是SculkSensorBlockEntity。
第二.方塊更新
這種新方塊的更新規(guī)律是:先以自身方塊向周圍發(fā)出更新,之后在它的下方方塊上發(fā)出再一次更新,類似充能鐵軌。

這種更新在它激活時被破壞/激活/取消激活時出現(xiàn)。

介紹完簡單特性,下面是監(jiān)聽聲音的原理(可能比較長,請耐心閱讀)
首先來說激活階段,也就是上文的PHASE屬性。當(dāng)它被激活時,它會進(jìn)入40tick的ACTIVE(激活)階段,之后是1tick用于COOLDOWN(冷卻),最后回到INACTIVE(未激活)。這里的所有操作都基于計劃刻。只有當(dāng)它是未激活狀態(tài)時才能接受振動信號。
P.S.為啥有1tick不應(yīng)期?猜測是防止輪回吧。

那么方塊這邊的事情說完了,看看發(fā)出聲音的源頭是怎么通知的吧。
之前我在動態(tài)中做過預(yù)測:這個探測聲音絕不是用了POI。沒錯,它確實(shí)沒有用。不但沒有用,還增加了一個新的通知機(jī)制:GameEvent。
首先看看GameEvent是什么吧:

這個新的事件機(jī)制對象包含了事件名稱和事件通知范圍。目前的通知范圍都是16。當(dāng)你查看現(xiàn)在都有什么GameEvent的時候,你會發(fā)現(xiàn)現(xiàn)在只有所有的可接收振動的事件。

這些事件可以通過Level的postGameEventInRadius方法和ServerLevel、Entity的gameEvent方法發(fā)送,這個就是我們尋找的事件觸發(fā)。

那么這里我們還是給一個例子吧。假如說現(xiàn)在打雷了,那么系統(tǒng)就會對閃電束實(shí)體進(jìn)行執(zhí)行tick,那么這里我們就可以看到調(diào)用gameEvent的影子。

可以看到這里發(fā)送了GameEvent。這里就是監(jiān)聽的起點(diǎn)。接下來來說事件的通知。
在剛才的發(fā)送GameEvent的代碼中,我們看到了它調(diào)用了LevelChunk的方法,如下:

這里我們看到了它創(chuàng)建了一個EuclideanGameEventDispatcher。等下,這名字翻譯過來...歐幾里得?繼續(xù)向下看,我們會發(fā)現(xiàn)它調(diào)用的好像還真是以歐幾里得距離查找的方式。。

那這樣看來,發(fā)送器這一方面已經(jīng)了解的差不多了,下面來看看監(jiān)聽器部分。
在尋找之后,發(fā)現(xiàn)GameEvent有一個子包vibrations,在里面有一個VibrationListener實(shí)現(xiàn)了GameEventListener,看來就是它了。
看看它是怎么創(chuàng)建出來的。之前說過Sculk Sensor是一種BlockEntity,在它的代碼里面就寫到了VibrationListener的初始化,并且將自己作為了設(shè)置傳入到內(nèi)部。

這個方塊實(shí)體內(nèi)部定義了是否應(yīng)該接受這個振動事件和對振動事件的處理。

在onSIGNALReceive中,我們可以看到激活的紅石信號強(qiáng)度是怎么計算的:它通過了一個名字叫g(shù)etRedstoneStrengthForDistance的方法計算,它的定義如下:

那么簡化的公式如下:SIGNAL = max{1,15 - floor(distance / 8.0 * 15.0)},其中distance是向下取整的歐幾里得距離值。

可是這個公式是有問題的:我們可以發(fā)現(xiàn)distance就是一個整數(shù),它的合理范圍是0-8,也就是說,在計算之后只會出這幾種紅石信號(下面的前一個數(shù)字是距離,后一個是紅石信號強(qiáng)度):
0-15,1-14,2-12,3-10,4-8,5-6,6-4,7-2,8-1
也就是說,真正利用的紅石信號也就是這幾個,看來這是一個bug。
同時,這個監(jiān)聽器可以存儲振動來源的類型,因?yàn)樗梢员4鍳ameEvent數(shù)據(jù),之后可以進(jìn)行判斷。這種紅石信號需要用比較器去獲取。


現(xiàn)在我們已經(jīng)差不多了解完它的觸發(fā)了,現(xiàn)在來看看最后的觸發(fā)條件。
首先,振動來源不能是破壞其他的Sculk Sensor,并且這個Sculk Sensor必須處于未激活狀態(tài)。(代碼部分:SculkSensorBlockEntity#shouldListen)

第二,以本Sculk Sensor為起點(diǎn)到振動源的方塊的射線上不能有任何帶有OCCLUDES_VIBRATION_SIGNALS標(biāo)簽的方塊(也就是羊毛),這個射線是以方塊中心點(diǎn)開始計算的。(代碼部分:VibrationListener#isOccluded)


第三,來源是合法的振動來源,并且實(shí)體不是觀察者模式,在一些特定振動事件中潛行會導(dǎo)致取消監(jiān)聽。(代碼部分:VibrationListener#isValidVibration)
在這些條件滿足之后,監(jiān)聽器會計算出振動到達(dá)Sculk Sensor的時間,計算公式就是向下取整的歐幾里得距離值,也就是和距離是一樣的。這個時間通過tick倒數(shù),同時這個也和振動的粒子效果有關(guān)系。
到這里Sculk Sensor的介紹也就差不多了,接下來看看其他的:限高修改。
三.限高修改
從遠(yuǎn)古時期開始,建筑高度限制一直是0-255。這個版本中通過height(總體高度)和min_y(最低建筑高度)兩種屬性值可以修改這個東西。由于這個東西牽扯了太多的東西,不打算細(xì)講(也許等到穩(wěn)定了之后再去細(xì)講)
首先,Level中增加了新的方法getMinBuildHeight,這是獲取最低建筑高度的。并且很有意思的是,在isInSpawnableBounds這個方法中,寫到了Y軸處在正負(fù)20000000內(nèi)返回true。
在HeightMap中,不少東西也改成了getMinBuildHeight和getHeight的混合。
生成這樣的世界,你需要導(dǎo)入設(shè)置,指定height和min_y。在讀取之后會被保留在NoiseSettings(噪聲生成設(shè)置)里面。

那么這個高度現(xiàn)在可以擴(kuò)展到多少呢?在DimensionType里面,我們找到了答案。

這段代碼中,我們得知:
height和min_y是必須可以被16整除的數(shù)值(保持單位區(qū)塊是完整的)
最大高度(height+min_y)要小于MAX_Y,這個值是2047(2^11-1)。
最低建筑高度(min_y)好像沒限制??
由于我的電腦連256格都費(fèi)勁,所以可能需要大家驗(yàn)證一下。
這個內(nèi)容等下個版本快照繼續(xù)寫,這里太難解析了。
P.S.為什么最大高度是2047?這里是解釋:MC用一個long保存世界的范圍數(shù)據(jù),由于X軸Z軸最大是30000000,由于不具有符號,所以只需要26位就可以保存,所以只剩下12位保存Y軸的大小,因?yàn)橛蟹枺灾荒馨阉O(shè)為-2048~2047。

代碼:Mojang官方混淆表+反混淆+反編譯
反混淆器:MCDynamicExchanger beta 6(正在開發(fā))
beta 5 版本在GitHub上可用,
網(wǎng)址https://github.com/Nickid2018/MCDynamicExchanger
反編譯器:Eclipse插件, FernFlower/CFK
文章中若有錯誤請大家指出,我將修改專欄。