寫了Minecraft資料包,但是Python
最近收到了一個朋友的委託,寫6個Minecraft的資料包,然後我有委託費,估價後總計730
其實我很早以前蠻喜歡寫指令的,我去過一些Minecraft關於指令的營隊
後來慢慢淡出之後,多了很多新的用法,我也就慢慢沒有學了
我最近又把它學起來,還學了一些關於合成跟戰利品的寫法
其實我體驗蠻深的,關於指令與程式
我學程式大概是在我開始淡出Minecraft之後不久,真的可以了解很多以前不曉得的東西,還有創新的做法
我以前會去翻一些阿神玩過的資料包源碼,會看到一些我看不懂的操作,後來學程式之後才看得懂
今天來講一下各個資料包製作過程學習到的新知跟用法
(文長,涉及Minecraft技術層面,慎入)
冶煉挖礦
挖掉需要燒製的礦物後,可以直接掉落錠,而且會出現火焰特效和火熄滅的聲音
這個我就想到了計分板可以記錄行為的特性
這個用法我也是這次在嘗試的過程才能靈活應用的
原理就是對每個需求方塊建立一個專屬計分板來記錄挖掘次數
然後偵測到變化就執行動作,並且把分數歸零
關於掉落的部分可以直接去改配方表,算蠻簡單的部分
快速合成
新增一些比較難取得物資的合成方式,如金蘋果減少金錠,還有終界水晶、經驗瓶等
合成轉隨機
其中困擾我比較多的是隨機附魔書,他要求可以合成隨機附魔書
但配方表的物品必須是固定的,就算要附魔也只能是固定的效果跟層級
後來我想到合成一個帶有特殊標籤的無效果附魔書命名為「隨機附魔書」,然後用偵測玩家身上物品去替換就好了
我使用的標籤是{random:1b}
關於偵測玩家身上物品我也學了一小段時間,主要是要學習NBT路徑偵測
可以偵測玩家身上的NBT是否含有{Inventory:[{components:{"minecraft:custom_data":{random:1b}}}]}
意思是Inventory
的陣列裡面是否包含一個字典,裡面的components
的"minecraft:custom_data"
含有資料{random:1b}
這種寫法可以自動尋找一個陣列裡面符合條件的字典或元件,我覺得蠻方便的,只不過要學一下
隨機附魔
再來是隨機附魔的部分,我本來打算把全部的附魔書都寫進去loot_table做隨機掉落
但我發現了神奇的東西:
物品設定function裡面竟然有一個函數叫做enchant_randomly
,直接附一個隨機效果跟等級
真是感謝開發人員腦洞大了一點拯救我,要是我真的想不到玩家會需要這個功能
所以最後我偵測玩家身上的特殊標籤物品,然後用戰利品掉落替換
更好的箱子
在所有結構的箱子裡面新增一些物品,每個物品有自己的機率和最小最大數量
這個我就蠻煩惱的了,因為他是要「新增」而不是更改,意味著我必須擁有原本的合成表,再加上新的物品
這個我真的思考蠻久的,後來我想到用/datapack list
指令的時候,有出現過vanilla資料包,也就是原本的內容
我就開始挖掘這個資料包可以從哪裡找到,因為裡面有我需要的所有東西
後來找到方法:把遊戲本身的.jar檔案解壓縮,裡面有一個資料夾就包含了遊戲的所有內容
就成功找到所有戰利品了
還有新的問題是,箱子戰利品有超級多個,我不可能一個一個插入貼上吧
這時候我學習Python的意義就展現出來了
我先寫好新增的內容,然後用os抓資料夾的檔案,開啟每個檔案用json模組載入成字典
然後在獎池裡面append我的內容,再寫回去
這真的是我第一次拿Python去做資料包,以前的我都以為那些大神都純手打,最多用VSCode的外掛幫忙
其實學一點簡單的程式可以高效率的完成這件事
受傷獲得物品
受傷就獲得一個物品,而且可以指定某一個玩家的開關
這兩個都蠻難處理的,特別是我想要把使用的人輸入的指令限定在簡單的/function
就很困難
開關
首先要處理開關的部分,就遇到了需要使用者輸入/scoreboard
之類的指令才能指定玩家
也就是傳統的偵測分數
但我沒有玩的這期間,Minecraft有了Macro變數,可以在function指令後面以json格式輸入
函數的一條指令裡面前面加上$
,而引用變數的地方用$(var)
就可以做到了
/function data:speak {"content":"Hello, world!"}
1 | $say $(content) |
我只要用這種方法就可以減少使用時必須要多種指令的困擾,可以限定在/function
就好了
然後做個計分板分數偵測就可以了
隨機物品
再來是隨機物品的部分,可以用loot_table把所有物品灌進去就好了
但主要是我需要全部物品的ID
我想到我在用的VSCode資料包輔助外掛可以推薦全部的物品自動補全,代表源碼的哪裡一定有可以直接複製的全部物品清單
這樣我用Python一樣寫進去就好了
我去翻了外掛的github儲存庫結果翻不到,我想到前陣子蠻紅的deepwiki,可以掃描repo並生成一份文檔
我就去用了deepwiki,是沒有翻到那個清單,不過被我挖到作者提供了API
裡面包含所有Minecraft註冊的物品、配方、結構、維度等ID
於是我就抓了物品的ID,用Python寫進去
偵測受傷
最後是偵測受傷的部分,這部分我做比較快
計分板有個條件是可以即時同步玩家血量,這點可以應用
因為玩家受傷不只會從20往下扣,也可能從17、10之類的,所以不能單純偵測是不是20
所以我用了一個血量計分板跟自訂計分版
開啟的時候會把血量計分板同步一次到自訂計分板
- 當偵測到血量<自訂:觸發隨機物品並同步一次
- 當偵測到血量>自訂:僅同步一次(代表血量正在恢復而非受傷)
隨機合成
把配方表的結果打亂,也就是每一種配方合成出來的東西都不是原本的東西,而且要可以再次打亂
所以我不能只做一次打亂就交卷,我要做可以自行重複打亂的機制
這個東西理論上就只能改配方表,所以我就從這邊下手
根據前面已經有的經驗,我去挖了原版的配方,也從API抓了物品清單
然後我用Python遍歷一次每個配方,從物品清單中隨機挑選一個填入result,並從清單中刪除,最後寫回去
然後我煞費苦心的研究了os.path
,因為我要把我的檔案包裝成直接執行而不需考慮終端開啟的路徑
所以我要指定好檔案的絕對路徑,這部分我問GPT蠻多的
我在資料包裡面多留了幾個檔案,一個是包含所有原始配方的資料夾,一個是物品清單的json檔
方便我直接取用原本的資料來打亂
最後請對方在電腦上裝Python,這樣他可以自己執行隨機打亂的腳本
也還好用到的套件都是Python預設就有的,不然還要裝一堆套件,又有環境問題
行走的TNT
所有玩家腳下非空氣方塊不斷替換成TNT方塊,跳躍會生成即將爆炸的TNT,要可以開關此玩法
替換方塊
其實設置方塊蠻簡單的,一直用execute
讓玩家setblock就好,前提是腳底下的方塊不是air
我一開始忘記/setblock
幾乎沒有什麼條件可以設定
後來又改用/fill
,結果發現只能指定要替換什麼,不能指定不替換什麼
最後改用/execute
,讓玩家自己偵測腳底下方塊是不是空氣
跳躍(離開地板)
這部分困難的就是跳躍偵測了,網路上其實找不太到教學,最多就是蹲下,而且很複雜
我一開始去找自訂述詞(predicate),有找到is_on_ground
的偵測
可以偵測玩家是否站在方塊實體上
這樣只要把它設成false
為符合,不斷偵測符不符合就好,一旦出現符合就觸發生成TNT
後來發現玩家跳躍後落下過程中會不斷生成,於是我使用tag邏輯來做到一次觸發:
讓玩家在自己身上加上一個名為jump
的tag
過程:
- 1 偵測沒有jump且離開地面的玩家
- 符合的玩家就觸發事件並幫自己加上jump(把自己從偵測1中排除)
- 2 偵測有jump且在地面的玩家
- 移除jump(把自己加回去偵測1)
跳躍
後來又遇到新的問題
玩家會被炸飛,炸飛也算離開地面
同樣的問題還有從高處走下來,就算1格也會觸發
最後還是想到計分板的奇奇怪怪統計規則,挖了一下資料發現可以統計跳躍次數
這時候就簡單了,只要跳躍次數的分數是1就觸發並重設分數
這樣就可以精準的判斷跳躍,而不是粗略的判斷離開地面而已
總結
這次委託算是我長久以來第一次開始複習指令和配方、戰利品
因為寫程式寫久了會有一些新的思維出現,以前單純玩Minecraft的時候其實想不到的
而且我也把Python實際應用在大量資料變更,我覺得或許學程式的意義就在這裡
解決生活中的問題其實比想像中容易,而且蠻有成就感的
如果你有看到這裡,偷偷告訴你
封面本來是美麗的村莊,我在這裡和平的測試指令
直到我開始做TNT