標籤:

如何評價我的世界中國版?

如何評價我的世界中國版客戶端上有一個防沉迷Mod,當遊戲時間超過閾值後,就會執行一個指令(對,你沒聽錯,就是指令),這個指令不需要任何許可權即可執行,服務端上安裝的防沉迷插件收到指令後,就會按照客戶端的要求(對,沒聽錯,按照客戶端的要求)設置玩家打破方塊時有多少幾率不掉落物品。

然而。

插件的「打破方塊不掉落物品」實現居然是直接把方塊的類型設為空氣,而且監聽器的優先順序還是 NORMAL,並且還不 ignoreCancelled,也就是說無視了所有其他插件的方塊破壞監聽器。

······

於是結果就是,當玩家進入防沉迷的時候,有幾率可以無視許可權破壞任何方塊。

······

······

······

於是,測試開始的當天,各個伺服器的主城均受到不同程度的破壞。而且還不止是主城,還包括小遊戲、領地等,總之就是能拆的都被拆了。

等有玩家發現了那個指令,直接將幾率設為100%那就更有意思了之前這個回答有提到網易違反 Forge 開源協議的事,後來那部分我想想後又刪了。但發現一堆回答和其他論壇的帖子(比如Github上的issue)留了這個回答的鏈接,看起來我好像是第一個發現這個問題的…讓這些鏈接變成無意義的感覺不大好,所以我想還是應該再把那部分加回來。

(並非之前的版本。更詳細。嫌太長或看不懂可只看加粗)

網易啟動器下載的客戶端內置了幾個Mod,根據名字猜測,它們有用來做登錄驗證的,防沉迷的,等等。它們的類沒法直接被反編譯,因為網易對它們進行了AES加密。網易自己修改了 Forge 和 Launchwrapper,以在Mod的類被載入JVM時對其進行即時解密,並且阻止用戶私自安裝的「未授權」的Mod。

*更新:網易於7/18凌晨時發布公告,表示同意開源。在此之後,Forge 的作者(非常良心的)花了一點時間寫了一份長長的分析報告,比我原來寫的詳細多了(畢竟作者本人嘛),於是我決定在此回答中將不必要的部分刪去,就保留兩點:

看了 Forge原版 中這個類的注釋後,我發現網易並不是故意抹去版本號的,而是因為這個版本號會在被 Jenkins 自動構建平台構建時自動 +1s,而網易構建時沒有使用 Jenkins ,所以默認為 0。注釋見ForgeVersion.java#L37-L

如何評價我的世界中國版40") !important;">)

網易修改了 ASMModParser 類,在載入 class 文件時使用 ReflectionAPI 執行類文件解密。吐槽一下這讀取輸入流中所有的數據為 byte[] 的實現簡直了……即使你不會用各種別人已經幫你寫好的類庫,也沒必要這樣實現啊!這代碼真的不是開玩笑?……private static byte[] readClass(final InputStream is, boolean close)

throws IOException {

if (is == null) {

throw new IOException("Class not found");

}

try {

byte[] b = new byte[is.available()];

int len = 0;

while (true) {

int n = is.read(b, len, b.length - len);

if (n == -1) {

if (len < b.length) {

byte[] c = new byte[len];

System.arraycopy(b, 0, c, 0, len);

b = c;

}

return b;

}

len += n;

if (len == b.length) {

int last = is.read();

if (last < 0) {

return b;

}

byte[] c = new byte[b.length + 1000];

System.arraycopy(b, 0, c, 0, len);

c[len++] = (byte) last;

b = c;

}

}

} finally {

if (close) {

is.close();

}

}

}

即使不用任何庫,非要自己實現的情況下,一般人至少也會寫成這樣吧:(舉例子,應該還有更簡單的,輕噴)private static byte[] readClass(InputStream in, boolean close) throws IOException {

try{

ByteArrayOutputStream out = new ByteArrayOutputStream();

byte[] buf = new byte[4096];

int len;

while((len = in.read(buf)) != -1)

out.write(buf, 0, len);

return out.toByteArray();

}finally{

if(close) in.close();

}

}

一個簡單的功能能寫這麼複雜真的活久見……天生自帶混淆……作者可以去參加國際C語言混亂代碼大賽") !important;">了。

如何評價我的世界中國版


推薦閱讀:

我的世界中文版羊毛怎麼製作?
《機械迷城》開發商的新作是個笑話
模擬人生4有什麼奇葩玩法?
火柴人遊戲系列合集?
虛榮有什麼武器裝備?

TAG:遊戲 | Minecraft |