1.16生物踩坑
我之前在1.12寫過生物,甚至還有菜鳥版教程(https://www.bilibili.com/video/BV1Ar4y1K7Qk?p=10)。
令我沒想到的是,1.16里搞生物比1.12還要復(fù)雜些。多出來的要點是:
你必須手動注冊刷怪蛋,寫好了實體后不會自然有“暴徒卵”。
你不能直接使用MC自己的刷怪蛋,需要自己寫一個刷怪蛋物品類以匹配延遲注冊框架。
你必須手動在FMLInit里設(shè)置任務(wù),以確保生成該生物時不會報屬性exception。
你必須明確地給生物注冊一個渲染器,否則生物一出現(xiàn)會直接崩潰。不只是生物,任何實體都是如此。
1.16里,比較通用的方式是使用DeferRegistry。如果你照抄Boson教程的話,就會用這種方式注冊東西。但……也有些mod不這么干。比如暮色森林,你不能直接照抄暮色的生物源碼,因為兩種體系不兼容。
誠然,Boson的教程教了如何寫實體,也教了如何寫生物(https://boson.v2mcdev.com/entity/passiveentityandai.html),但是他沒有教如何寫刷怪蛋,只是用指令召喚了所寫的生物。。在1.12,一般你看到的教程里,注冊生物后就自然而然地有了刷怪蛋,反而是沒有蛋會比較困難些。
首先我抄了暮色的源碼,然后我發(fā)現(xiàn)拋異常了,因為物品的注冊比生物早,試圖在注冊物品時引用生物類型就直接崩了。

那么,是不是暮色的非延遲注冊導(dǎo)致的呢?我改成了延遲注冊,仍然不行。
根據(jù)群友的指點,我知道了問題所在。

首先,你不能直接用普通的刷怪蛋,因為他不包含supplier(必須立刻傳入對象)。物品比實體先注冊,所以實體無法被存進刷怪蛋。于是,你得自己擴展SpawnEggItem類,讓他接受supplier,對原本的值傳空(實際不能傳空,需要隨便傳個東西進去),然后覆蓋獲取實體類型的方法。
https://forums.minecraftforge.net/topic/81614-how-do-i-make-an-entityspawnegg-class-that-accepts-a-registry-supplier/?tab=comments#comment-387356
然后群友給出了上述的鏈接。根據(jù)鏈接,我寫出了如下的代碼:
以下為com.deeplake.backtones.registry.EntityRegistry節(jié)選,在這里注冊了生物 MJDS_SKELETON:
然后又在我的ItemRegisty里注冊了刷怪蛋。
其中UNCOMON_PROP是隨便一個物品屬性,是什么不重要,默認(rèn)的也可。當(dāng)然了,這個刷怪蛋既沒有翻譯,也沒有圖片,都得自己搞。不過搞這都很簡單,這里就不贅述了。
你可能會問,為什么要搞個DOLPHIN進去呢?我這骷髏又不是海豚。很簡單,我只是隨便傳了個不為空的類別進去,讓他通過notNull檢查。你傳什么都行,只要不為空。你也可以封裝進構(gòu)造函數(shù),把這臟代碼藏起來——反正臟的是forge,不必有負(fù)罪感。底層寫的差,帶動上層一起差。
你試圖消滅造輪子行為嗎?
https://github.com/MinecraftForge/MinecraftForge/pull/6299
別人也是這么想的,然而沒成功。順便一提,鏈接里的Candiboo是我還在菜鳥期就給過我指引的大佬。
那么,到此,進了游戲確實有刷怪蛋了,但是刷不出來生物。刷的時候報錯:

萬能的群大佬zomb又給我指了一條路:https://forums.minecraftforge.net/topic/96085-spawn-custom-mob-error-executing-task-on-server/?tab=comments#comment-437958
于是乎,我的主類里多了如下代碼。
是的,你需要手動告訴forge需要給這生物注冊屬性,這么無聊的步驟在1.12是完全沒有的。
然后你用刷怪蛋一刷……游戲崩了,因為沒注冊渲染類。注冊過就好了。
我有一些生物是沒有模型的,因此我寫了個什么都不渲染的VoidRender給它們。這是我注冊實體渲染的地方:
好,這就差不多了。順便提醒一下各位,1.16官方表里,生物的getPosition這個成員不要使用,它是純客戶端的。在服務(wù)器里一跑就崩。

順便提一下關(guān)于復(fù)活生物的事。
我在一個生物死亡或被去除的瞬間(onRemovedFromWorld)的類型和nbt都存了下來,希望之后可以復(fù)活他。幾經(jīng)嘗試,最終復(fù)活的代碼如上。值得指出的有兩點:
deathTime必須手動重置,它是會存到nbt里的。如果你不重置,可能會導(dǎo)致生物死時服務(wù)端線程不調(diào)用onRemovedFromWorld。
你需要手動把血回滿,血也是存在nbt里的。順便,revive沒有卵用,那是給玩家類使用的,一般的生物調(diào)用了沒有意義。我把生物的uuid設(shè)為新的了,這一步可有可無。
順便,這里也演示了如何在1.16召喚實體與生物。干凈版代碼如下:
和1.12里沒什么區(qū)別吧,只不過addToWorld變成了addFreshEntity。
總之,在各位大佬的幫助下,我總算是在1.16寫出了生物了。
這里給出某知名小說里的俳句:
That is not dead which can eternal lie
And with strange aeons even death may die
我做的事情是寫了一個骷髏戰(zhàn)士,它死亡或被去除時,會在其出生點生成一個復(fù)活云霧。云霧周圍16格沒有玩家時,復(fù)活云霧消失,骷髏戰(zhàn)士重新復(fù)活。這模仿的是某個FC游戲里,玩家離開某處再回來時,會發(fā)現(xiàn)怪物都重置了的效果。
……以及我對之的翻譯:
未死之身永世臥
萬古升詭滅閻羅