一些你該知道的事
===
除了理解Forge和MCP這些大佬寫出來的工具以外,還有一些瑣瑣碎碎的東西
但有一些其實是很重要的事情,我說真的( • ̀ω•́ )
在本章節你會了解
---
- Minecraft官方對於模組開發的態度
- MCP的一些使用規範
- Forge官方論壇已經不支援1.13以下的發問
- 如何寫出效能好的模組
Minecraft官方對於模組開發的態度
---
從[這一篇](https://hackmd.io/@immortalmice/BJQZGVkuI)我們提到了製作模組中,前人為我們鋪的道路
裡面用到了反編譯和反混淆技術,如果你先前知道這兩個技術,那你應該會聯想到這件事
**反編譯和反混淆在法律上有很大的爭議空間,特別是智慧財產權**
我看過網路教學表示Minecraft官方並未公開允許對他們的產品Minecraft進行反混淆與反編譯,因此撰寫模組處於一個灰色地帶
我一直這樣認為,直到我親自去看了Minecraft的[使用條例](https://account.mojang.com/terms?ref=ft),摘要便已經提及
> 貴用戶得開發工具、外掛程式及服務,惟禁止開發出貌似本公司官方產品或正式核准產品之成品,且不得使用本公司的標誌等。禁止未經本公司核准,將本公司提供的任何項目移作商業用途。
因此就我的理解上來說,Minecraft官方有明列允許此件事情
更詳細的內容建議打開下面完整的使用條例閱讀,特別是**Commercial usage guidelines**下的**延伸功能及「MOD」段落**,而這邊就不再提及
所以也許我當初看的教學已經過時了吧......
而快照[19W36A](https://www.minecraft.net/en-us/article/minecraft-snapshot-19w36a)發布的時候,Minecraft官方做了一件事
**他們宣布從該版本開始包括未來,都會發布類別/方法/欄位的混淆映射表(Obfuscation Maps)**
若要獲得這個混淆映射表,你可以到.minecraft\versions下找到你要的版本資料夾,打開裡面的json檔,找到arguments.downloads的區塊,裡面包含了客戶端及伺服器端的混淆映射表連結,像[這個](https://launcher.mojang.com/v1/objects/bd9efb5f556f0e44f04adde7aeeba219421585c2/client.txt)是1.15.2的客戶端混淆映射表
他們宣布這件事情,自然在模組圈的討論炸了開來,這代表了我們不必再去猜測這些類別/方法/欄位的功用
但很遺憾的,這消息對於Forge官方以及大部分的人來說是什麼都沒有改變(´・\_・\`)
你可以看[這篇在Minecraft公布消息兩天後的後帖子討論](https://www.minecraftforge.net/forum/topic/75642-what-does-this-means-for-forge/),裡面他們的說法原文是
> We will be making an announcement about it when we can. The current state is that it means almost nothing for us. As the license doesn't allow for us to actually USE this information.
We are waiting to hear back from Mojang's legal team {This is all stuff they could of answered before the public announcement by asking us, but whatever}
Keep an eye on Github/Twitter and we'll keep you updated.
因為根據官方在發布消息同時給出的法律免責聲明,Forge團隊是不能直接使用這混淆映射表在他們開發的程式上的,因為Forge要做的事並不被法律免責聲明所包含,事實上,按照官方的這個法律免責聲明,沒有任何模組作者可以使用這份混淆映射表
這是法律免責聲明中最重要的一句話,殺死了一切模組作者使用它的可能性
> You may copy and use this information for your internal, reference purposes.
根據對原版Minecraft的尊重,Forge他們的確也沒使用官方的映射表,所以你在建立起的開發環境中依舊會看到Searge Name的出現
但我相信,Minecraft官方是真心想要幫助我們模組作者的,只是他們把事情搞砸了
如果你對於Forge團隊們寄給Minecraft法律團隊的信後來收到了什麼樣的回覆,以及Forge和MCP未來的立場的話,可以看[這篇聲明](https://cpw.github.io/MinecraftMappingData),裡面Forge用 "legal poison" 來形容用這法律免責聲明發布的混淆映射表
不過,如果你要說以這種形式公開混淆映射表其實對MCP團隊帶來了更糟糕的處境,我不會反對
因為他們要在避免和公開混淆映射表撞名的情況下,做出他們的MCP Mapping
簡單來說,如果公開的映射表名字是dropApple,而MCP Mapping也使用dropApple這名字的話,他們在法律上會踩上很危險的區域
要如何去找出一個不是公開混淆映射表的名字,並且這名字要很好的表達該函式的用途,這是MCP將會面臨的棘手問題
MCP的一些使用規範
---
MCP的授權協議,在[這篇Wiki](https://minecraft.gamepedia.com/Programs_and_editors/Mod_Coder_Pack)寫得已經很詳盡了,你可以切中文觀看
以下我拉出裡面的一段內容
>你可以
- 使用 MCP 反編譯 Minecraft 客戶端和伺服器 jar 文件。
- 使用反編譯源碼創建 Minecraft Mod。
- 重新編譯修改版 Minecraft。
- 重混淆你的 Minecraft Mod 類。
你不可以
- 使用 MCP 做任何違反 Mojang 的 Minecraft 使用條款。
- 發布或修改盜版的 Minecraft。
- 發布修改過的或未修改過的 MCP。
- 在沒有明確的寫權限下使用 MCP 的任何腳本、工具或數據文件。
- 把 MCP 拿來賺錢(不包括使用 MCP 構建的 Mod)。
- 使用 MCP 創建用於惡意破壞或利用伺服器錯誤的客戶端。
- 以任何形式發布反編譯後的 Minecraft 源碼。
基本上看過一遍就可以了,你會很清楚你該怎麼使用MCP而不犯法 (ゝ∀・)
Forge官方論壇已經不支援1.13以下的發問
---
這是Forge官方論壇中的一個版面,叫做[Modder Support](https://www.minecraftforge.net/forum/forum/70-modder-support/)
絕大部分,當你遇到問題,網路上也找不到答案,也無法自行解決的時候,你可以在這論壇發問
但如同標題所說,Forge官方論壇已經不支援1.13以下的發問
你依舊可以開發1.12.2的模組,甚至是1.7.10
但是你沒辦法在這論壇中發問後得到幫助
你說如果硬是要發個文問的話會怎麼樣?
恩哼哼,問M鼠就對啦!~~因為當時不知道這件事情的他做過~~
管理員會跳出來說
> 1.12 is no longer supported on this forum.
Please update to a modern version of Minecraft to receive support.
**然後就把你的帖子回覆功能給鎖了**
當然,M鼠就是曾經被鎖的那位இдஇ
如果你想看正式的聲明,請看[這篇帖子](https://www.minecraftforge.net/forum/topic/79304-112114-and-lts-system/)
希望看到這裡的各位,不會變成和被鎖帖子的M鼠一樣(☍﹏⁰。)
如何寫出效能好的模組
---
各位都知道,寫程式,功能的正確性是合格的門檻
寫出來的東西沒能符合要求,那就是不合格沒得說
(Bug不一樣,每個人多多少少一定都會寫出Bug,有責任地去解決它就可以了)
過了合格的門檻之後呢?那就是效能的問題了
一個模組的效能主要有兩方面,運算效能和記憶體效能
前者會影響遊戲是否會卡頓、要等很久才能收到伺服器同步、甚至玩家根本動不了
後者,當記憶體瀕臨最高的限界時,Java會執行垃圾回收機制(GC),在回收的過程中,幾乎所有的執行續(thread)都會**暫停**,一直到GC完成工作
也就是如果在玩Minecraft的當下,記憶體一直在高點的狀況,會導致遊戲出現相隔時間相等的卡頓,因為記憶體被GC釋放後,很快的新的記憶體又被程序吃光,觸發下一次GC程序
大家都知道,Minecraft有個很特別的東西,那就是Tick,以一秒二十個為單位
每一個Tick,程式會算出所有下一個Tick應該被更新的資料
運算完成後如果用到的時間小於二十分之一秒的話,程式會等待剩餘的時間,並在時間到的時候把剛才運算出的新資料應用上去
那如果運算一個Tick花的時間多於二十分之一秒會怎樣?
程式依舊會算完,並直接應用,但這時一秒就不再是二十個Tick了,這就會造成卡頓
在開發模組的過程中,有很多東西會跟Tick相關,也有Forge寫好的東西可以使用,比如說net.minecraftforge.event.TickEvent下的子事件:ServerTickEvent、ClientTickEvent、PlayerTickEvent...等等
甚至對於方塊實體(TileEntity),你有一個ITickable的介面(interface)可以直接使用
這些東西都可以讓你在每個Tick都執行一次你指定的工作
但請先冷靜想想,你真的需要用到這些東西嗎?
因為這代表了你寫的東西在一秒內執行了二十次,如果你寫的工作很繁重,就很容易造成負荷過高,導致遊戲卡頓
就算沒有,消耗這麼多的運算資源,也不是件好事
所以,在使用這些東西時,請先想想有沒有更好的方案
比如說,你需要監看一個欄位的數值,並在改變的時候做出相應的動作
- 比較壞的方法是,用Tick來去監看這個欄位是否改變
- 好的方法是,請改變欄位的那個人在改變完後主動過來通知並執行你的程式
兩者被執行的次數顯而易見(´_ゝ\`)
當然,不是所有東西都能這麼完美的有替代方案可用
你依舊可以用這些Tick事件,只是他應當是最後一個考慮的選擇
*備註:如果因為要高效能,結果讓整份程式碼散亂、艱澀難懂的話,請自行斟酌處理* (๑•́ ₃ •̀๑)
另外,如果不可避免的要用到Tick事件,請盡量讓你的方法是最簡潔並且容易在早期判斷需不需要執行這件事
- 比如說這是個比較不好的示範
```java=
public static void onWorldTick(WorldTickEvent event){
Data dataPreparedToApply = new Data(...);
//Do something to configure your data
...
if(event.world.isBlockPresent(new BlockPos(...))){
//Do the thing you want
}
}
```
- 這是個比較好的示範
```java=
public static void onWorldTick(WorldTickEvent event){
if(event.world.isBlockPresent(new BlockPos(...))){
Data dataPreparedToApply = new Data(...);
//Do something to configure your data
...
//Do the thing you want
}
}
```
如此一來,每次執行你的方法的時候,如果是不需要做事的情況,很快的就離開了這方法
而不是被宣告了許多東西後確認,這時才發現其實你不需要做任何事
或者是說,如果有一個東西其實只需要被執行運算一次,得到的數值就再也不會改變了
那麼,你可以用**快取**這個數值的方式,讓這個東西在第二次存取時不用再跑一次運算
最後,請你拿出你的最大努力,寫出你能寫得最好的程式碼d(\`・∀・)b
讓玩家能順暢的玩你的模組
玩家在玩遊戲時,通常不會注意到你的模組很順暢
但不順暢的時候,玩家會很容易就注意到
那麼,就一起來寫出很棒的模組,讓玩家露出笑容吧!✧*。٩(ˊᗜˋ*)و✧*。
---
*本頁面撰寫於2020/04/12,目前最後更新日期為2020/05/22*
*若上述時間與你閱讀的時間相距過遠,請自行斟酌是否採用本頁面的資訊*