最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【真正的和平模式】三、結(jié)構(gòu)的生成

2023-08-21 21:39 作者:VUMO北極鵝  | 我要投稿

上一篇講了任務(wù)系統(tǒng)的實(shí)現(xiàn),內(nèi)容畢竟偏,并非所有人都需要它。本篇講結(jié)構(gòu)如何生成。

開頭想說(shuō)點(diǎn)騷話,實(shí)在想不出就算了,直接步入正題。

本文首發(fā)于知乎,筆者是作者本人,第二轉(zhuǎn)載到bilibili平臺(tái)。原文鏈接:?https://zhuanlan.zhihu.com/p/646365902

一、結(jié)構(gòu)的分類

生成結(jié)構(gòu)多種多樣,為了方便區(qū)分,我根據(jù)生成方式大致可以分為三類:普通結(jié)構(gòu)、多級(jí)結(jié)構(gòu)和拼圖結(jié)構(gòu)。

從原版里舉幾個(gè)例子:

  • 埋藏的寶藏、沉船、沙漠神殿、叢林神廟等屬于普通結(jié)構(gòu),特點(diǎn)是它們只有一個(gè)piece,而且通常使用nbt來(lái)保存結(jié)構(gòu)的模板。

  • 林地府邸、要塞、下界要塞、海底神殿等屬于多級(jí)結(jié)構(gòu),特點(diǎn)是它們有多個(gè)piece,生成分多個(gè)層級(jí),而且沒(méi)有nbt模板,僅通過(guò)代碼控制生成,不同piece隨著結(jié)構(gòu)的生成通過(guò)某種狀態(tài)轉(zhuǎn)移來(lái)切換。

  • 掠奪者前哨站、村莊、堡壘遺跡(即豬堡)、遠(yuǎn)古城市屬于拼圖結(jié)構(gòu),特點(diǎn)是有一個(gè)中心、仍然是多層生成、有多個(gè)結(jié)構(gòu)中可能存在的模板、模板中通過(guò)拼圖方塊控制接下來(lái)的生成方向與目標(biāo)池。

需要注意的是,有些結(jié)構(gòu)比較特殊,如雪屋這個(gè)結(jié)構(gòu)似乎要介于普通結(jié)構(gòu)與多級(jí)結(jié)構(gòu)之間——取決于它是否有地下室,不過(guò)我們可以把它歸入第二類中。

在代碼實(shí)現(xiàn)方面,拼圖結(jié)構(gòu)無(wú)需額外代碼控制生成,只需完成數(shù)據(jù)包即可。而其他兩種則需要額外的結(jié)構(gòu)注冊(cè)與生成,尤其是第二種,需要相對(duì)多一些的代碼量。

二、結(jié)構(gòu)的注冊(cè)

1.19.3及之后,結(jié)構(gòu)和結(jié)構(gòu)集本身無(wú)需多余的注冊(cè),通過(guò)數(shù)據(jù)包即可實(shí)現(xiàn)生成。不過(guò)StructureType和StructurePieceType依然需要常規(guī)注冊(cè)。

StructureType用于世界生成時(shí)唯一標(biāo)識(shí)當(dāng)前區(qū)塊包含的結(jié)構(gòu)類型,并鏈接特定的CODEC完成序列化和反序列化。

以《真正的和平模式》中的五個(gè)結(jié)構(gòu)舉例(無(wú)需包含拼圖結(jié)構(gòu)),注冊(cè)方法如下:

而StructurePieceType則用于世界生成中標(biāo)識(shí)結(jié)構(gòu)的每一個(gè)部分——比如多級(jí)結(jié)構(gòu)中的要塞的每個(gè)房間、雪屋的主體、地下室和梯子等等,對(duì)于普通結(jié)構(gòu)而言則只需要注冊(cè)本體的PieceType:

注意,世界生成是允許動(dòng)態(tài)注冊(cè)的,因此沒(méi)有客戶端服務(wù)端的同步檢測(cè)(因而僅修改世界生成的mod可以僅服務(wù)端加載)、甚至有些內(nèi)容并不需要延遲注冊(cè)(使用DeferredRegister)。你可以直接在模組的構(gòu)造時(shí)加載這個(gè)注冊(cè)工具類。

以廢棄的魔法池為例,生成Piece的寫法如下:

addPieces方法則是入口方法,將結(jié)構(gòu)的所以部分加入StructurePieceAccessor參與世界生成。注意ABANDONED_MAGIC_POOL表征了結(jié)構(gòu)nbt的路徑,它被放在數(shù)據(jù)包的data\real_peaceful_mode\structures中。

AbandonedMagicPoolPiece繼承了TemplateStructurePiece結(jié)構(gòu)部分模板類,若無(wú)其它內(nèi)容,只需重寫一個(gè)空的handleDataMarker函數(shù)即可——如果你使用了數(shù)據(jù)模式的結(jié)構(gòu)方塊,在這里當(dāng)然需要作額外處理,這部分接下來(lái)再講;如果有其它需要存儲(chǔ)的數(shù)據(jù),則需要重寫addAdditionalSaveData函數(shù);另外生成過(guò)程中可能需要額外的方塊變化,如隨機(jī)苔蘚化、裂紋、氧化等等,這部分可以用postProcess來(lái)實(shí)現(xiàn),其過(guò)程中調(diào)用this.placeBlock函數(shù)改變模板的方塊來(lái)放置到世界中——本例則實(shí)現(xiàn)了磚塊和木頭的隨機(jī)破壞和替換為蜘蛛網(wǎng)。

最終效果

那么入口函數(shù)如何調(diào)用呢?此處需要一個(gè)繼承Structure并定義CODEC的類來(lái)解決:

其中findGenerationPoint用來(lái)找到區(qū)塊中哪個(gè)位置可用于結(jié)構(gòu)生成,如果存在便執(zhí)行生成函數(shù)——generatePieces是生成結(jié)構(gòu)的函數(shù),addPieces入口便是在這里被調(diào)用。type則是生成結(jié)構(gòu)的類型,對(duì)應(yīng)著前文的StructureType。

以前還需重寫step函數(shù),否則會(huì)拋出異常——1.19.3后不再需要多此一舉,因?yàn)榭梢灾苯釉跀?shù)據(jù)包的json里寫了。

三、普通結(jié)構(gòu)數(shù)據(jù)包的編寫

前文只是實(shí)現(xiàn)了結(jié)構(gòu)的注冊(cè)和生成邏輯的編寫,還沒(méi)能真正將結(jié)構(gòu)生成在世界中。由于1.19.3代碼結(jié)構(gòu)的大改,僅需實(shí)現(xiàn)數(shù)據(jù)包即可實(shí)現(xiàn)結(jié)構(gòu)的生成。

以廢棄的魔法池為例,我們?cè)赿ata\real_peaceful_mode\worldgen\structure目錄下創(chuàng)建abandoned_magic_pool.json:

其中type對(duì)應(yīng)著StructureType,需要與注冊(cè)保持一致;spawn_overrides重寫了結(jié)構(gòu)內(nèi)部的生物生成,如古城不會(huì)生成任何生物、掠奪者前哨站會(huì)源源不斷生成掠奪者等;step表示生成的步驟,最常見的則是"underground_structures"和"surface_structures";terrain_adaptation是生成后的地形調(diào)整,建議地表建筑使用"beard_thin"保證不會(huì)懸空,而地下建筑則多為"bury",古城使用了"beard_box",懸空建筑(如水晶頭骨浮島)則留空;最重要的,biomes表示結(jié)構(gòu)生成的群系,最好使用TagKey表示,于是我們?cè)赿ata\real_peaceful_mode\tags\worldgen\biome\has_structure目錄下創(chuàng)建abandoned_magic_pool.json:

實(shí)現(xiàn)了結(jié)構(gòu),接下來(lái)實(shí)現(xiàn)結(jié)構(gòu)集——即多個(gè)變種的相同類型結(jié)構(gòu)的集合,如村莊結(jié)構(gòu)集包括平原、熱帶草原、沙漠、雪原和針葉林五個(gè)變種,廢棄的傳送門結(jié)構(gòu)集則包括下界、高山、深海、沙漠和普通等變種。

我們?cè)赿ata\real_peaceful_mode\worldgen\structure_set目錄下創(chuàng)建abandoned_magic_pools.json:

salt建議隨機(jī)生成,不要跟任何結(jié)構(gòu)重復(fù);separation是同一結(jié)構(gòu)集內(nèi)兩個(gè)結(jié)構(gòu)間的最小距離(單位:區(qū)塊),而spacing則是兩個(gè)結(jié)構(gòu)間的平均距離(單位:區(qū)塊),顯然這個(gè)值要大于separation;type則是結(jié)構(gòu)的分布,random_spread是隨機(jī)分布,而concentric_rings則是類似要塞的分布方式——若是random_spread,還有可選的字段spread_type,可選值包括linear和triangular,即距離分布的類型,triangular使得結(jié)構(gòu)更加平均分散,而linear距離的方差則更大。structures包括了這個(gè)結(jié)構(gòu)集的所有結(jié)構(gòu),并以權(quán)重組織著它們的生成。

按照這個(gè)步驟走下來(lái)的話,你的結(jié)構(gòu)大概率就生成在世界中了。不過(guò)還有一些特殊情況,比如拼圖結(jié)構(gòu)的定義,以及processor list的編寫。

四、拼圖結(jié)構(gòu)的模板池和processor list

首先給原版知識(shí)儲(chǔ)備較少的朋友們介紹一下什么是拼圖結(jié)構(gòu)。在處理結(jié)構(gòu)群(如村莊)或較大面積結(jié)構(gòu)的生成(如古城)時(shí),或者希望在結(jié)構(gòu)生成過(guò)程中不同“部分”的連接引入隨機(jī)性時(shí)(如堡壘遺跡),可以考慮使用拼圖結(jié)構(gòu)。拼圖結(jié)構(gòu)的每個(gè)模板結(jié)構(gòu)都應(yīng)該包含拼圖方塊,并指定name(拼圖名稱)、final_state(拼圖方塊最終轉(zhuǎn)變成什么方塊)、joint(拼接類型)、pool(目標(biāo)池)、target(需要對(duì)接的拼圖名稱)——兩個(gè)拼圖方塊之間分別以相同的name與target互相連接,而生成過(guò)程中拼圖方塊則從pool目標(biāo)模板池中選擇新的結(jié)構(gòu)并拼接好后生成。

這部分同樣只需要添加數(shù)據(jù)包。以苦力怕小鎮(zhèn)為例,需要在data\real_peaceful_mode\worldgen\template_pool\creeper_town目錄下編寫模板池,以房屋池為例(houses.json):

elements包含了所有池內(nèi)的模板結(jié)構(gòu),每個(gè)結(jié)構(gòu)由element和weight組成,分別表示結(jié)構(gòu)細(xì)節(jié)和權(quán)重。

element_type常有以下三種取值:

  • minecraft:empty_pool_element:即空結(jié)構(gòu),表示在一定權(quán)重下,該位置不生成新的模板。

  • minecraft:legacy_single_pool_element:?jiǎn)谓Y(jié)構(gòu),通過(guò)location定位在structures文件夾中的模板結(jié)構(gòu)。

  • minecraft:feature_pool_element:即地物結(jié)構(gòu),直接生成一個(gè)地物,通過(guò)feature定位一個(gè)地物的注冊(cè)名。

另外兩個(gè)很好理解,主要介紹一下單結(jié)構(gòu)的一些屬性——

  • location:結(jié)構(gòu)模板的id

  • processors:processor list的id

  • projection:投影類型,包括rigid(視為整體放置,多用于房屋、農(nóng)田、水井等不因地形改變而改變的結(jié)構(gòu)部分)和terrain_matching(匹配地形,多用于道路)。

那么processor list又是什么?其實(shí)就是一個(gè)結(jié)構(gòu)的部分生成結(jié)束后再進(jìn)行的處理,與前文的postProcess函數(shù)功能類似。如苦力怕小鎮(zhèn)的道路使用了如下處理,使得水和極少部分的沙礫被替換為了凝灰?guī)r磚(street_creeper_town.json):

其詳細(xì)寫法,建議參考官方wiki:https://minecraft.fandom.com/zh/wiki/%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%96%E7%95%8C%E7%94%9F%E6%88%90/processor。

五、怎么生成和編輯結(jié)構(gòu)nbt文件?

前文的所有介紹,默認(rèn)你知道了所有關(guān)于生成nbt文件的知識(shí),這里額外多提一嘴,防止有人不知道這個(gè)問(wèn)題的答案,影響閱讀體驗(yàn)。

首先隨便建點(diǎn)什么,想生成啥就建啥:

粉色苦力怕的“結(jié)構(gòu)”

然后拿出結(jié)構(gòu)方塊,調(diào)整到save模式,然后調(diào)整邊框和大小使得整個(gè)結(jié)構(gòu)完全被白線包裹:

結(jié)構(gòu)方塊UI

然后輸入結(jié)構(gòu)名——這是個(gè)id,以命名空間:名稱的方式命名。如果需要儲(chǔ)存實(shí)體,請(qǐng)將右側(cè)的Include Entities調(diào)為ON。

最后點(diǎn)擊右側(cè)SAVE保存,便可在世界文件夾/generated/<命名空間>/structures目錄下找到它。將這個(gè)nbt復(fù)制到你的模組數(shù)據(jù)包目錄的對(duì)應(yīng)位置中,必要時(shí)可打開NBTExplorer,甚至IDEA安裝Minecraft Development插件也可直接編輯:

IDEA中直接編輯nbt內(nèi)容

這些nbt由三部分構(gòu)成——方塊、實(shí)體、調(diào)色板。方塊即結(jié)構(gòu)每個(gè)位置的方塊,包括方塊實(shí)體等;而實(shí)體則在開啟Include Entities時(shí)被保存;調(diào)色板包括所有可能的方塊狀態(tài),方塊中state數(shù)值即為調(diào)色板的下標(biāo)。

接下來(lái)我可能會(huì)講講地物和群系的生成,這部分也以數(shù)據(jù)包為主,涉及代碼較少,敬請(qǐng)期待!

筆者從事開發(fā)不久,文章如有疏漏,敬請(qǐng)斧正!


【真正的和平模式】三、結(jié)構(gòu)的生成的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
朝阳区| 柘城县| 曲水县| 中西区| 隆化县| 江陵县| 青铜峡市| 鄂州市| 谢通门县| 杨浦区| 河津市| 高淳县| 濮阳市| 兰考县| 文水县| 镇巴县| 三亚市| 蒲江县| 呈贡县| 清水河县| 永登县| 福贡县| 东乌| 运城市| 江北区| 沁水县| 鄢陵县| 盐边县| 潞西市| 海原县| 中宁县| 吴桥县| 永济市| 永吉县| 益阳市| 古田县| 孟津县| 新巴尔虎左旗| 永吉县| 新泰市| 陕西省|