在下是久違不見的 #FFFAFA,
最近段考+比賽時間實在太忙碌了,好不容易這次段考也完了(X
有鑑於Minecraft版上並沒有太多對於function功能與製作方法之文章,
為了讓大部分玩家理解function之功能、製作方式、以及其優點而在此作著。
>>本篇適用於Minecraft Java 1.12+至1.13+的版本<<
(以1.13格式介紹為主)
目錄:
- function 基礎檔案建置篇:
1、函數(Function)推薦的編譯工具與編譯方法
2-1、函數(Function) - 於1.12+上的建置檔案流程
2-2、函數(Function) - 於1.13+上的建置檔案流程
3、function檔案的指令格式與運作流程
- function 額外的檔案設定篇:
4、被多層資料夾包裝的function檔案位置
5、控制function檔持續執行(tick)/載入執行(load)的方法
- function 進階應用篇:
6、function的特性:超頻執行
7、執行function時的總執行次數計算方式
- 我的小小心得:
結尾
對於Minecraft巴哈版的一些建議
1、函數(Function)推薦的編譯工具與編譯方法:
小的在此推薦一個個人認為非常好用的編譯工具(多數人也用此編譯器來做function):
如果你一開始的介面不是中文,可以嘗試以下步驟來將編譯器的語言設為中文:
1. 從上欄的選項中找到Settings,點開後選擇Preferences。
2. 開啟設定視窗後,在此視窗中間上方區域Localization下點擊English展開選單,並選中文即可。
現在你有了一個合適的function編譯工具了,
接著就是要如何在地圖檔中「建立一個function」。
(以下建立.mcfunction檔案的文章介紹會區分成1.12與1.13版本)
2-1、函數(Function) - 於1.12上的建置檔案流程:
1.12為function首次發行的版本,
基本上語法、流程和運作模式也在1.12都訂定了,
而後繼的1.13、和未來的1.14也有相繼為function做些微更動。
那麼先來開始1.12之function的檔案建置流程吧:
1. 選擇好要置入function檔案的地圖檔之資料夾,並打開地圖檔資料夾中的data資料夾。
(範例以example_world為地圖檔之資料夾的名稱)
2. 於data資料夾中有兩個資料夾:advancements和functions,開啟functions,
並在functions資料夾裡建立另一個資料夾(此資料夾明稱為執行function時的根目錄資料夾名稱)
(advancements也是1.12的新功能之一,本篇僅教學function,恕不在此介紹advancements之功能,function根目錄之名稱以main作為範例)
※ 請勿將根目錄資料夾名稱用:minecraft,將會覆蓋原本於minecraft中所設置的資料包部分內容,
詳細關於functions在minecraft為根目錄名稱之內容請見文章中第5節。
3. 開啟根目錄資料夾,創建一個新文字文件,並將其副檔名(.txt)改成.mcfunction,
並建議設定以默認使用Notepad++來打開.mcfunction檔案,即完成1.12版本的function創建。
(範例的function檔案命名為:example.mcfunction)
2-2、函數(Function) - 於1.13+上的建置檔案流程:
1.13由於datapack的發展,
將functions、advancements、tags、recipes、structures以及tags功能合併,
有關於datapack詳細內容和做法可見以下參閱文章:
在此以基本的datapack建立方法,以及在datapack中建立可執行的function檔案為主,
以及利用datapack中的tags功能,控制function的連閃和載入時讀取的設定方法。
※1.13版本的命名規則(包含function檔案名稱、根目錄名稱,即datapacks下的所有名稱),
都必須只能使用以下文字來命名(不包含空格):
0123456789 abcdefghijklmnopqrstuvwxyz -_
在創建function前,必須先創建一個可以被使用的datapack,才能在datapack中使用function:
1. 選擇好要置入function檔案的地圖檔之資料夾,並打開地圖檔資料夾中的datapacks資料夾,
並於datapacks資料夾下創建一個新的資料夾,此資料夾名稱為使用function時的數據包名稱。
(範例以example_world為地圖檔之資料夾的名稱,並以namespace為數據包名稱)
2. 開啟數據包資料夾(即namespace),並於資料夾裡創建一個名稱為data的資料夾、
以及創建一個文字文件,並將此文字文件檔名(含副檔名)改成:pack.mcmeta
(位於namespace下的data資料夾以及.mcmeta檔案之名稱必須以上述格式命名,否則將會創建失敗)
3. 開啟pack.mcmeta檔案(使用記事本(.txt)開啟檔案),並於文件檔中輸入以下內容:
{ "pack":{ "pack_format": (任意數字,代表著此資料包的自訂版本), "description": "(任意文字,此為查看資料包時顯示的描述內容)" } } |
{ "pack":{ "pack_format": 1, "description": "a description for the datapack" } } |
(description中的文字可以使用中文字以及部分可以顯示的文字符號)
4. 開啟namespace下的data資料夾,並於data資料夾中創建一個新的資料夾。
(此資料夾的名稱為:執行function時的根目錄資料夾名稱,在此使用main做為範例)
※ 請勿將根目錄資料夾名稱用:minecraft,將會覆蓋原本於minecraft中所設置的資料包部分內容,
詳細關於functions在minecraft為根目錄名稱之內容請見文章中第5節。
5. 開啟根目錄資料夾,創建一個資料夾,並將其命名為functions
(此functions資料夾為使用此資料包時分區為function中內的一個區塊,
即是用來放置function檔案的資料夾)
6. 開啟functions,創建一個新文字文件,並將其副檔名(.txt)改成.mcfunction,
並建議設定以默認使用Notepad++來打開.mcfunction檔案,即完成1.13版本的function創建。
(範例的function檔案命名為:example.mcfunction)
3、function檔案的指令格式與運作流程:
當你的function檔案創建完成了,
那麼就讓我們進入編譯function檔案的製作方法吧!
(範例的function檔案命名為:example.mcfunction,延續章節2-2的步驟與檔案位置)
1. 使用Notepad++開啟你的.mcfunction檔案,進入文件的編輯介面。
2. 點擊上方欄中的「編碼(N)」展開選單,並選擇為「編譯成 UTF-8碼」。
(function最推薦編譯成UTF-8,若使用ANSI時中文和特殊符號可能將不會正常顯示)
※若在遊戲中出現文字不正常顯示之情形,可以先檢查該function是否使用UTF-8來顯示文字
3. 現在你可以開始在function中編輯你的指令了?!
不!你要先遵守以下的function編輯規則:
(1) 所有指令前方一律不得使用" / " (ex. 指令:/say hi,必須要輸入成:say hi)
(2) 類似(1):execute指令中run後接的指令之前方不得使用" / "
(ex. 指令:execute as @p run /say hi,必須要輸入成:execute as @p run say hi)
(3) 所有的指令必須要符合格式,否則你無法在Minecraft中執行該function。
(ex. 指令:weather clear,被輸入成:waether clear時,將不能執行此function,
此指令格式包含:標籤格式、正確的指令文字、可以執行的指令、位置資料格式)
(4) 如要在function中使用備註文字的話,可以使用" # "符號,並在文件該行的#之後輸入備註
(備註可以是任何文字,範例請參閱下方的統一格式範例)
(5) 部分指令無法輸入到function,就如同部分指令不能使用於指令方塊一樣
(6) 指令的執行順序是:由上而下執行,每一次換行(Enter鍵),視為與上一行不同的指令
統一以上(3.)之規則,以下可以成功執行的function檔案內容之範例文字格式:
#先執行傳送自己至另一個玩家(tag=aim) tp @s @p[tag=aim] #再執行function的玩家身上生成一隻著火1秒的殭屍 execute at @s run summon zombie ~ ~ ~ {Fire:20s} |
4. 現在你編譯好一個可以執行的function檔案,點擊左上方的儲存圖像來儲存你的function檔案。
5. 回到你的Minecraft,不論你是否已經進入你要使用function的地圖檔裡,進入你的地圖檔中,
若你已經進入地圖檔,使用指令:/reload來重新載入目前的datapack之中function內容。
<備註> 指令/reload:重新讀取地圖檔中的datapacks資料夾下的全部內容
(包含了functions、advancements...等)和generated資料夾(通常只存有strucutres)下的全部內容。
6. 此時即完成functions的讀取了,接著嘗試在Minecraft中使用此指令來嘗試執行該function:
/function (根目錄):(function檔案名稱)
(依照範例,格式則改成:/function main:example)
若輸出時顯示如下的文字的話,請依照本文章的創建function順序來確定過程是否有錯誤:
(若執行成功的話,將會在自己身上生成一隻著火一秒的殭屍,這也代表你成功創建function了)
4、被多層資料夾包裝的function檔案位置:
如果說你把全部的function檔案都放到同一個資料夾下豈不是太雜亂了?
其實function檔可以再被其他的資料夾所放入,以方便玩家對各個檔案進行分類。
以以上的範例位置繼續延伸,若要執行在main->functions->(資料夾)->example.mcfunction的話:
則使用/function時的指令格式則是:/function main:(資料夾)/example
若資料夾有兩層則是:/function main:(資料夾1)/(資料夾2)/example
...以此類推。
範例:example.mcfunction檔案位置於data->main->functions->all->first下的話,
範例之使用function的指令為:/function main:all/first/example
5、控制function檔案持續執行(tick)/載入執行(load)的方法:
Minecraft在1.13版本的時候由於加入了datapacks,
function的連閃控制上也出現了一點變化,
像是將控制function連閃的功能也併入了datapacks去做控制。
依據以上的範例,目前已有一個function檔案為:example.mcfunction,
位置於地圖檔example_world資料夾中,datapacks/namespace/data/main/functions下。
讓我們退回到資料夾datapacks/namespace/data中,
我們要利用根目錄為minecraft的資料夾來使用這兩個功能:tick (重複執行) / load (/reload後執行),
來操控function檔案於地圖檔中的特殊執行方式。
1. 於data資料夾中,創建一個名稱為minecraft的資料夾。
2. 開啟minecraft資料夾,並於minecraft資料夾中創建一個名稱為tags的資料夾。
(tags功能可以用於統整方塊ID、物品ID偵測、以及允許functions檔案能用tick/load之功能)
3. 開啟tags資料夾,並於tags資料夾中創建一個名稱為functions的資料夾。
4. 開啟functions資料夾,並於functions資料夾中創建兩個文字文件檔,
名稱個別為:tick.json、load.json。
5. 以讓example.mcfunctions被重複執行為目的,以筆記本或是Notepad++打開tick.json檔案,
並在文件內輸入:
{ "values": [ "main:example" ] } |
(load.json中輸入的文字內容與tick.json相當,並且所有在values中的所有目標函數都會依據該檔案的儲存名稱(即tick或load)而被設定以重複執行或是載入時執行)
6. 重返Minecraft,並同樣的使用/reload指令,若你身上一直生成著火的殭屍,則代表你成功了。
小心喔,別被殭屍填滿了你的螢幕(X
6、function的特性:超頻執行
相對於Minecraft的指令方塊,
我想function的超頻執行是它最大的賣點了吧,
而在1.12之前的版本,超頻執行也幾乎是不容易做到的事。
(通常最少也得要有1tick來建構指令方塊串的順序)
位置於地圖檔example_world資料夾中,datapacks/namespace/data/main/functions下。
如果在一連串指令中有一條/function指令時,
則將會把此目標function執行過一遍後才會繼續執行下一個連接的指令。
做法如下:
額外創建一個function檔案為:say.function
與example.mcfunction的根目錄同樣為main,即路徑為:main:say
say chat 1 say chat 2 |
另example.mcfunction的文件內容為:
say hello say this's test function main:say say run function say end |
[@] hello [@] this's test [@] chat 1 [@] chat 2 [@] run function [@] end |
你可以把超頻執行用在重複性多次執行某些指令使用,
亦可以在function中使用記分板來做為計算次數,或是控制次數的功能。
範例如下:
將example.mcfunction內容改成如下:
scoreboard objectives add times dummy scoreboard players set @p times 100 function main:summon |
1.創建times記分板且類別為dummy 2.讓最近玩家的times分數設定為100 3.執行function路徑:main:summon的指令 |
並另建一個function(與example.mcfunction為同一個根目錄)為main:summon,檔案內容如下:
execute at @p[scores={times=1..}] run summon pig ~ ~ ~ scoreboard players remove @p[scores={times=1..}] times 1 execute if entity @p[scores={times=1..}] run function main:summon |
1.從最近玩家的times分數大於等於1者的身上生出一隻豬 2.減少1分最近玩家的times分數 3.如果最近玩家分數times大於等於1時,執行執行function路徑:main:summon的指令 |
當你使用指令:/function main:example時,
將會觸發example.mcfunction中的指令,
並在極短的時間內於最近玩家的身上生成100隻豬。
如果對於指令很熟悉的玩家,會發現execute指令亦有如同於執行function般的類似超頻的效果,
但execute指令後方最多也只能接一條指令,不像function中可以用多條指令來順序的處理物件。
7、執行function時的總執行次數計算方式
究竟為何會需要計算function的總執行次數?
通常是為了對地圖檔進行最大效益的資源省化,
以防止指令過度濫用而導致地圖不順暢的問題,
相對的,執行function的顯示次數也會變得重要,
就如同你在計算程式中的時間一般(類似Big-O)。
我們先假設有三個function檔案:main:a、main:b和main:c
假設函數main:a有10條同樣或是不一樣的非function指令,
函數main:b的指令內容如下:
say I am B function main:c |
函數main:C的指令內容如下:
say I am C function main:a |
但很奇怪的是,main:b+main:c+main:a的指令數目應該是 10+2+2=14才對:
1. 從次數結果「由main:b執行了16條指令」可以知道一開始使用/function main:b <-指令並不計為
執行一次執行,而是由main:b裡的第一條指令才開始計次。
2. 如果函數檔案內有執行函數檔案的指令(function)時,計算該/function指令的次數輸出為:
該函數檔案內的所有的指令條數 + 該函數檔內function指令數目
因此也由於這個額外執行的次數做出兩點推斷(此推斷僅個人意見,若與事實不合請務必讓我知道):
1. 這可能是Mojang的陰謀論(?,為了讓玩家知道使用/function很耗效能,才將次數設定為2。
2. 這可能只是由於使用/function是為了搜索資料夾中的目標函數檔案並開啟,
而第一次次數定義為「搜索」、第二次次數定義為「開啟目標函數」
超頻執行在執行重複的指令狹義上來講是「無限次數」,
但廣義上來講會被規則maxCommandChainLength所限制次數(如int值的最大上限一般),
目的是為了防止玩家過度使用指令而導致地圖檔崩潰所設定的規則,
相對的,這個規則也可以由玩家自己決定上限。
綜合上述推導function執行次數的方式可以推得在maxCommandChainLenght下最大執行次數。
先改寫規則:/gamerule maxCommandChainLength 300
執行一個function檔案:main:say_1,內含的指令如下:
say 1 say 1 function main:say_1 |
[(被重複執行的目標指令) / (function內總指令數+1)] * (maxCommandChainLength值)
而上方的指令「say 1」被執行次數即為:[2/(3+1)]* 300 = 150
(這會是用於用上maxCommandChainLength限制次數時的執行重複性指令次數計算公式)
至於「指令執行次數」的功能與用法,
將會在之後的文章,專門對「最佳化指令執行次數」來深入討論。
結尾:
1.12的function指令改版無疑是對Minecraft的指令界帶來巨大的改變
最近將近一年的時間都沒空發新文真的抱歉了.W. ..,
目前距離學測還有1又1/3個月又1年,
先祝這屆高三的學長姐們學測加油囉,小的還得要多花時間讀書呢。
對於Minecraft巴哈版的一些建議:
在今年經過的多次精華文章選舉過後,可以明顯地觀察到一件事:
>>技術性文章(包含史無前例的教學文、新穎技術、技術分享)幾乎不可能在精華文章選舉中留存<<
這無疑是一個非常嚴重的事情,並且技術部的文章日亦漸減,
加上巴哈版會定期刪除那些文章,
這導致技術部的大部分文章只能存活個短時間,
一但只要沒有收入精華區,那麼就只是很容易被吞沒而已,
並且大部分的技術部精華文都已經過度老舊,應當請求作者更新或是依照版本區分。
複雜的科學與技術都是建立在許多人的觀察、學習、統整、歸納、協議所形成的,
對於那些不懂科學與科技的人,他們理所當然不會去重視這些踐踏在許多人的屍體上的結果,
自然而然不會投給那些:無法讓人理解的複雜技術 和 自己不會接觸的複雜事物。
對於精華文章的收錄,希望能針對技術部的精華文章,
另辦類似「技術部精華文章收錄部門」來做為技術部的精華文章檢定與收錄,
就目前的技術部風氣以及目前還仍保有足夠的技術性人員來說,
如果現在能對於技術部之精華文收錄方式有所更改,
還可以挽回大部分技術人員在技術部發表文章的意願以及想要學習的後代技術人才。
以上純屬我的個人意見,若有無意冒犯或是過度解釋的部分還請見諒。
(點擊圖片,前往我的指令文章收錄小屋)