LV. 1
GP 23

【情報】Reactant 工具教學﹣材質混合

樓主 靴子貓 setak0
GP13 BP-
圖量很大,而且有不少GIF圖,有流量限制的建議先關一下圖片

基礎教學  •  界面工具  •  材質混合  •  ????



前言


在這章開始前要再三聲明,Reactant大多數的工具是為了插件開發者而設計的,所以不太用問我:「這個能不能透過config的手段製作?」。此外Reactant是Spigot插件的開發工具集合,並不是模組工具喔。這裹新增的物品是依靠材質包達成,所以對玩家來說只需要接受伺服器的材質包即可。

先談談為甚麼要我要寫這個材質混合工具(攪拌機?),在1.14前要是我們要在沒有模組的情況下,想使用材質包的手段增加自定義的物品材質,方法只有在model文件中為物件增加predicate,
利用物品在不同耐久時能顯示不同的model這一機制實現,這種方法一是設定麻煩,二是還會把耐久這個屬性吃掉。

而從1.14開始,minecraft為物品增加了一樣叫CustomModelData的額外資訊,也就是我們可以透過在prediciate中判定物品的CustomModelData(下簡稱data)來類示不同的物品model,對故事地圖作者來說實在一大福音,終於有一種能夠正常地使用的自定物品材質方式。可是要是通用向的插件怎麼辦?要是插件A附帶了自定的材質要玩家安裝,而插件B也有自定的材質,那開服的人要怎樣同時用這2個插件?不就只能自己用手逐一合併model文件了嗎?

而旦這也會出現另一個問題,假如插件A把data=100的鑽石劍當成自已的屠龍刀,不幸地插件B又把
data=100的鑽石劍當成自已的水果刀,這樣的衝突情況只好要插件作者在發現跟別的插件衝突後修改屠龍刀/水果刀的data,可是這樣根本用不了啊,你根本不知道到底哪一個區段的data沒有人用,這樣對開發插件來說根本沒有任何可用性呀。那麼能夠把這個噁心的問題解決的工具就是Resource Stirrer,材質攪拌機了。

如果單純只是用來混合材質包的話,其實作用看上去並沒有很大,個人認為RPG類型的伺服器應該才會對這類工具有比較大的需求。但萬丈高樓都是先由地基開始,下一篇教學文會再為大家奉上真正的主菜,拜託好好看下去吧,下一篇有驚喜絕對沒有在騙你(可是主菜還沒開始煮,還在卡住

順帶一提,這篇對技術的要求會比較少,應該算是所有Reactant系列的教學文中最輕鬆的一篇了。(雖然這工具背後花了我很多時間寫/_>\



目錄


1.1 事前配置
1.1.1 基底材質包
1.1.2 minecraft原生物品模型
1.1.3 設定檔
1.1.4 指令介紹
1.2 開發
1.2.1 起手式
1.2.2 ItemResourcesTable 資源表
1.2.3 Scale, Translation 和 Rotation
1.2.4 材質動畫
1.2.5 多層材質
1.2.6 使用已有的模型
1.3 取得物品



1.1 事前配置


ResourceStirrer自身並沒有包括在Reactant內,需要另行下載,最新版在這裹抓,一樣要抓最新有"-all.jar"後綴的文件。此外請確保伺服器內的Reactant也是最新的0.1.6-SNAPSHOT

首先在開始使用ResourceStirrer前先說明ResourceStirrer的文件結構。
在第一次運行後應該會自動生成以下的文件
plugins/Reactant/ResourceStirrer/
base/ 用來放基底材質包
models/item/ 用來放minecraft原生的物品模型
output/
packing/ 打包前用來放文件的暫時性文件夾,不用管
resources.zip 攪拌好的材質包
resources.zip.sha1 材質包的sha1
stirrer-meta-lock.json 重要,這個不能亂動
刪了的話所有已經分配好的自定物品就會作廢了XD
建議備份時不要忘記這個文件
config.json 主要設定檔

*對,我不喜歡yaml的縮進,所以Reactant的設定檔都是json。

基本上所有的文檔都可以在不同server中共用唯獨一個文件每個server都要分開使用,便是stirrer-meta-lock.json
插件開發者也應該注意你不應該要求別人使用你的lock file,因為lock file其實是根據伺服器所安裝的插件而產生的。
依照增加插件的次序不同,內容也會不同,所以每個人的lock file完全不同也是十分正常的事,乖乖交由Resource stirrer管理這個文件就好。

1.1.1 基底材質包

假如你有一個材質包想放進去用,ResourceStirrer可以基於已有的材質包作stirring。
如果有的話請unzip那個材質包然後把assets,pack.mcmeta,pack.png等的都放進base內
使用別人製作的材質包當作基底前,記得要注意別人有沒有授權你修改後再發佈。

1.1.2 minecraft原生物品模型

假如大家跳過這步,直接打"/ress update"的話,會發現有類似以下的warning
Default model is not existing: ".../plugins/Reactant/ResourceStirrer/models/item/nether_star.json", using empty json object.
Default model is not existing: ".../plugins/Reactant/ResourceStirrer/models/item/wooden_axe.json", using empty json object.

ResourceStirrer自帶了2個自定材質用來當testing,一個是使用了地獄之星,另一個使用了木斧。那為甚麼會出這個warning呢?
這裹要先談一下原生的item model(物品模型)內到底放了甚麼
    1. 對於方塊類物品,它們的物品模型會用"parent"指向自已的方塊模型
    2. 對於普通物品,它們的物品模型會用"parent"指向"item/generated",也就是平面物品,然後再把"texture/layerX"指向材質圖片
因為增加物品predicate需要寫入物品模型,可是ResourceStirrer不知道那個物品的模型本來長甚麼樣子啊?
所以就要由你來提供當前minecraft版本的item model,不然的話ResourceStirrer會假設你不需要原生的模型了,然後會幫你基於一個空白的物品模型進行修改,這種情況下你的自定物品會成功顯示可是原本的物品就會變成空白了XD

那麼為ResourceStirrer提供物品模型的方法如下:
    1. 用壓縮軟件打開/<minecraft_path>/versions/1.15.1/1.15.1.jar (按照自已所需的版本)
    2. 然後把assets/minecraft/models/item整個解壓至ResourceStirrer/models/item
然後ResourceStirrer就會基於你提供的model進行修改了,如果你在使用的基底材質包有在提供某些物品的模型的話會優先使用那個模型。

1.1.3 設定檔

預設產生出來的設定檔應該如下所示:
{
  "customDataRange": {
    "min": 100
  },
  "updateOnStart": false,
  "uglify": true,
  "development": {
    "developmentHTTPServer": {
      "enabled": false,
      "port": 8499,
      "threads": 8
    },
    "autoPushing": {
      "pushAfterUpdate": false,
      "pushWhenPlayerJoin": false,
      "resourcePackUrl": "h ttp://localhost:8499/resources.zip"
    }
  }
}

這個預設設定是為了正式開服而配置的。假如使用這個設定檔,開服的人需要在插件有所更動時使用"/ress update"指令更新output內的材質包,而且除了使用指令時才進行更新外,ResourceStirrer不會做任何事情。這樣的設定也比較合符常理,因為正式上線的伺服不會經常更動插件啊。

customDataRange.min 要從哪一個custom model data開始分配
updateOnStart 要不要在enable的時侯更新一次材質包
假如不是正在開發的話應該不用每次也update一次
uglify 產生出來的材質名字要不要使用混淆
如果你不想別人知道那些材質的用途的話可以設為true,
材質的名字會變成隨機產生的uuid
開發的話建議關掉不然怎debug
development 十分方便的開發用材質http server
開啟的話Server能夠作為web server提供最新的材質包
.developmentHttpServer
.enable 如果你的伺服不是開發用而是正式上線的話這個絕對要關掉
因為會吃大量流量,而且被ddos這個位置就慘了QQ

正式服的話建議放到雲端上例如aws s3或者google cloud storage那類東西
不要貪方便用自已電腦host,你以為你家的網絡有多快 = =
.port 不解釋
.threads httpServer要在線程池開多少線程
.autoPushing
.pushAfterUpdate 材質更新後自動向client推送材質包
.pushWhenPlayerJoin 玩家進入時推送材質包
.resourcePackUrl 在本機用developmentHttpServeer的話按照預設就可以了

先提醒一下 pushWhenPlayerJoin 這個有點奇怪的bug,client重啟後第一次進入時會push不到材質,Disconnect後再進一次就可以了,反正只是用來開發我也不太想找原因,正式使用的話應該會使用server.properties來放材質吧 = =

所以開發用的設定應該要像下面一樣,這樣設定的話修改插件後用/reload就可以在插件重載時自動推送新的材質到client了。
{
  "customDataRange": {
    "min": 100
  },
  "updateOnStart": true,
  "uglify": false,
  "development": {
    "developmentHTTPServer": {
      "enabled": true,
      "port": 8499,
      "threads": 8
    },
    "autoPushing": {
      "pushAfterUpdate": true,
      "pushWhenPlayerJoin": true,
      "resourcePackUrl": "h ttp://localhost:8499/resources.zip"
    }
  }
}

到這裹基本的配置就應該完成了

1.1.4 指令介紹

Resource Stirrer附帶了3個指令
全寫 懶人 說明
/ressourcestirrer item /ress i   用UI顯示自定物品圖庫,按一下物品可以複製至自已的物品欄。
可以用以下方式篩選:
  1. /ress i <萬用字元>
    例如 /ress i dev.* 可以顯示所有用"dev."開始的identifier
  2. /ress i -p <正規表達式>
    需要用的就會明白怎樣用這個,不多介紹了
/ressourcestirrer update /ress update 更新材質包
/ressourcestirrer fixtool /ress fix    列出已經分配了但沒有在使用的custom model data
          

現在使用/ress i 打開圖庫,按綠色羊毛到下一頁,要是依次見到空白的材質,紅色的斧頭和一顆水滴狀有動畫的地獄之星就代表材質包能夠產生出來喔。



1.2 開發

1.2.1 起手式

先打開build.gradle.kts,找到"dependencies"那一個區塊,在裹面加上
compileOnly("dev.reactant:resource-stirrer:0.1.6-SNAPSHOT")
另外也請再三確認reactant的版本也是0.1.6-SNAPSHOT

然後refresh一下gradle project。

1.2.2 ItemResourcesTable 資源表

要加入自定物品材質,首先要建立一個ItemResourceTable,注意需要使用object而不是class。
這個ItemResourceTable放在哪裹都可以,只要位於@ReactantPlugin內注明的package即可,不然ResourceStirrer會找不到。在ItemResourceTable的construtor內輸入identifierPrefix,也就是物品識別名稱的前綴,建議使用自已的package名以免和別人的名字相撞。

當建立好資源表後,就可以開始增加我們的物品了,這裹我先畫出一支法杖。要是傷害大家的眼晴的話真的萬分抱歉 /_>\
注意一件事,minecraft材質方面的處理很雞肋,一個像素只能夠是透明或者不透明,圖片的alpha通道貌似無法顯示出來,所以大家不用試半透明效果了。
*沒有透明就沒法在旋轉像素風的圖片時做smoothing了,結果法杖就變得凹凸不平

把圖片export成為png後,放進project的src/main/resources(放plugin.yml的位置)內的任意地方,想怎樣用folder分類就任君選擇吧。


然後回到剛剛建立的資源表,使用以下的方法建立ItemResource,然後放進變量內。
val VARIABLE_NAME = byClassLoader(圖片路徑, 識別名稱, 物品類型)
*注意圖片路徑不要包含副檔名


注意事項
  • 放進變量這個動作很重要,而且變量必需為public,除非你不想這個變量被當成資源來加載。
  • 當建立好一個資源後請不要胡亂更改表的prefix或者資源的identifier(識別名稱),因為一但更動了就會視為一個新的資源而被分配為一個新的itemModelData。
  • 一個識別名稱被定義為某一個Material後就無法再改改成不同的Material了(除非更改或者刪掉那個lock file來重新生成),所以建立前要先想好。
  • 一個資源的最終identifier是會用到識別名稱和資源表的前綴組合而成的,所以也請不要從一個表移至另一個表,這樣也會令identifier改變。
  • 至於更改表的class名字,變量的名字,材質的位置,更換不同的圖片,這些都是完全沒有問題的。

這個時候build一下插件然後/reload再進去用/ress i看一下新的材質。

然後我們再來看看ResourceStirrer在背後生成了一個怎樣的材質包。以下是因為我們增加了一支法杖而自動產生出來的新文件。從這裹我們可以見到ResourceStirrer的做法是先拿Stick的原生模型,增加overrides節點,然後把所有custom_model_data為101的木棒都指向一個新的模型,最後把新的模型指向我們的材質。(感覺這工具很多餘的你確定不用ResourceStirrer產生這堆json而用人手做真的會比較好嗎?...

啊好棒,就這點code加一張圖片就能加一種新物品外觀。可是。。方向跟位置都不對,而且太迷你了啊。接下來的章節就會介紹怎樣對物品加上scale, translation和rotation。

題外話

個人覺得要完全重啟來測試實在太廢時,所以基本上試插件的時候都會用/reload,但是build好後要用手把jar copy去plugins下這個動作並不符合我的懶人原則。這裹給大家一個較便捷的方式,使用reactant cli生成的project內的build script其實可以幫大家在build完後自動把成品複製至server的plugins內。只要把Environment Variable加一個PLUGIN_DEPLOY_PATH就可以好好享受「1.修改 2.建置 3.reload 4.看效果」的爽快XD,就看大家有沒有這個需要吧。


技術向 - 所以到底這個ItemResourceTable是甚麼?

當ResourceStirrer的ItemResourceManagingService載入時就會用Reflection的方式把所有加了@ResourcesTable的object翻出來遍歷一次來註冊。ItemResourcesTable自身是implement了Iterable<ItemResource>,而iterator()的實現就是把所有declaredMemberProperties和nestedClass(只限object)拿出來,然後:
  1. 如果這個property是一個ItemResource:註冊它
  2. 如果這個property是Iterable,Array或者Map,那就把它拿來重覆以上動作 (Map的話會只拿values)
假如你感覺這個Table不太好使,想自已實現的話可以extend ItemResourceTable再改喔。

1.2.3 Scale, Translation 和 Rotation

能夠自動生成item model是很棒,可是要是我想對物品進行大小,位置和縮放的調整要怎麼辦。
對於這個問題,我們其實是可以直接對itemModel的不同屬性都用DSL的方式修改。

可是個人覺得用這個方法修改好像不太直觀,始終看上去有一樣比較raw的感覺?所以再在下面介紹另一種方式給大家,自已看看哪一種比較好用就用哪一種吧。

首先是用rotation的modifier把物品在第三人稱右手的模型稍爲旋轉。

然後再用scale把物品放大1倍。
這裹提示大家一下,ItemModel.DisplayTypes.thirdperson_righthand 這樣的名字實在太長,這裹直接用import把它import進來了,所以就直接變了thirdperson_righthand。

最後用translation把物品的位置向前和向上移動一下,這樣就有點法杖的樣子了。

當然,為了以後其他的法杖都能重用效果,可以使用private val的方法把modifiers都包裝一下。(注意,一定不能public不然會被當成item resource來嘗試讀取,然後就...)。最後的code看起來像這樣。

1.2.4 材質動畫

要是想讓材質有點動畫怎麼辦?假如我們要打算幫這把法杖加入10幀的動畫,就要得先造出10張圖。要是對材質包製作很熟悉的話可以直接跳過這裹。

個人是用Krita來畫的,畫圖的功能十分齊全,而且還能做點小動畫,而且還是開源,難道不用嗎?

這裹不是要你完成後export gif,而是要把每一幀的圖都像下圖左邊的樣子匯出出來,然後把全部都疊起來,做出下圖右面的樣子。
個人是不太知道有甚麼修圖軟件可以一次過把大量圖片合併成右邊的樣子,要是說在linux的情況下我會用imagemagick來批量處理,windows上裝了的話應該也行,有興趣的話可以試一下這個imagemagick的指令:
convert -append wand_*.png wand_animated.png
當然了,比較原始地用人手一件一件放上去也不是不行XD

做好了這張圖後就可以放進resources裹了,可是單單是這樣的話應該沒法動或者會變成紫黑色的"材質丟失"圖示。因為我們還沒有為它加上mcmeta(一個用來描述要怎樣動的文件)。這個文件要怎樣寫應該很容易google到,所以就不作介紹了。寫好了以後只要使用相同的名字加上.mcmeta後綴,ResourceStirrer就會自動抓這個文件一起攪拌了。
上圖我是把它作為新資源加入的,所以gem_wand還在這裹。

要是我只是想做簡單的動畫,不想多加一個mcmeta行不行?當然可以,在沒有mcmeta文件的情況下可以使用下面的animation frametime modifier,然後就會在Stirring的時侯自動產生mcmeta了。
效果圖如下。
啊。。。做壞了,傳說中的物攻法師

1.2.5 多層材質

有部分的物件會有多層的材質,例如煙火之星會有一層不可上色和一層可上色的材質,這種情況下我們要使用另一種byClassLoader的呼叫方法。

不過在開始修改code前,先把法杖的核心弄成可以上色吧。這裹我直接把法杖核心的圖層拿出來加上HSL濾鏡,把飽和度拉到0來去除顏色,然後把明度拉高一點,不然上色的效果會比較深色,很難看。
再分別把只有法杖核心的圖片(注意位置要對好)和只有法杖本體的圖片分開export出來
這裹我們會用煙火之星作為基底物品來示範,煙火之星的layer0是不會上色的,而layer1會根據效果上色,所以我們把核心放在layer1,法杖放在layer0。然後像下面那樣呼叫byClassLoader。
為了展示一下效果,我再加了一個event listener,在玩家按shift時隨機更換物品顏色。
有人可能會問trySetColor是甚麼鬼,這個其實只是Reactant提供的小工具,會依照你的物品類型嘗試幫你設定itemMeta來更換顏色,例如皮革裝和藥水這類型的物品。

最後看一下效果。


1.2.6 使用已有的模型

可是。。。我的物品是用blockbench做的3d模型啊,那要怎樣辦?ResourceStirrer其實也可以載入現存的物品模型。那假設我們用blockbench做了法杖的3d模型,然後用Export Blockmodel的方法拿到了模型的json檔。
模型的樣子大約是長這樣。
然後連同使用了的textures都丟進去。
再使用以下的方法呼叫:
byClassLoader(模型路徑,textures,識別名稱,物品類別)
使用時要注意textures map的key要與model內的textures相同才可以正確指向材質喔。然後效果就是這樣,至於那個核心有點茶色的像素貌似只是因為我用了錯的方式做這個模型。可是實際上我根本不會3d modeling啊,所以我做的時侯是用平面的法杖圖片做每次1px的邊緣腐蝕,再把腐蝕0次,1次和2次的結果拼在一起來做出這樣的3d效果。



1.3 取得物品

直接用資源表的variable呼叫.similarItemStack就能拿到了,是不是很無腦?
這個ResourceStirrer的主要用途只是幫你自動生成材質包,需要配搭其他物品庫才能正常使用,之後要怎樣修改,或者要傳給哪一個物品library當作外觀就由各位自由發揮了,使用時只要不把itemModelData或者type改掉就可以正確顯示出來。
但是要留意一下,在ResourceStirringService載入前是無法拿到任何資源的物品的,因為那時根本還沒有資源被分配到任何custom model data啊。如果你的component需要在onEnable時取得自定的物品,那你必須為你的component注入ResourceStirringService,這樣Reactant就會幫你把你的component排在ResourceStirringService之後再載入了。



1.4 常見問題


Q: 可以轉載嗎?
A: 可以,但請附上原文鏈接gitlab鏈接,轉載後希望可以通知一下我。而轉載須要依照以下條款。


這篇資訊量比較少感謝大家花時間觀看有問題或者意見歡迎以留言的方式提出
要是想討論問題的話也能到discord找我,連接附在Reactant CLI生成project後的信息內
13
-
未登入的勇者,要加入 2 樓的討論嗎?
板務人員:

1307 筆精華,09/21 更新
一個月內新增 3
歡迎加入共同維護。


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】