
封面图拍摄自 HYPIXEL 主城

最近 Mojang 在基岩版的商店里上架了一套“汉服”皮肤汉服小姐姐真可爱prprpr,看上去还不错,价格也很亲民,就顺手买了下来。

商店页面
买完之后我发现一个问题,我想在我的 Java 版里也使用这套皮肤,然而 Mojang 并不提供这两个游戏的联动,于是……
有困难当然要自己想办法解决。

最先想到的当然是把皮肤文件提取出来,可惜我想到的,Mojang 也想到了。
我使用的 iOS 版本已经禁止用户通过电脑直接访问应用数据了,只能通过备份来访问,提取出来之后……

这是嘛玩意
这个 zipe 看样子是加密过的皮肤文件,但是经过多方搜索,没有查到任何关于这个相关的信息,能查到的大多也是和我一样遇到 zipe 不知道怎么处理的人。
这样不行的话……

玩家之间通过服务器联机的时候,是可以相互看到对方的皮肤的,那么皮肤的数据会通过服务器进行传输。我想到了通过在服务器上动手脚来做这件事。
基岩版虽然支持的平台更多,但是服务器程序却不像 Java 版那样直接提供给玩家。有些国内外大佬自己写了兼容的服务器,其中有一个据说比较好的 NukkitX,那我今天就拿它来试手。
NukkitX 的 GitHub 项目地址:https://github.com/NukkitX/Nukkit
简单搜索了一下,皮肤相关的代码写在 src/main/java/cn/nukkit/entity/data/Skin.java 中,只要对它稍微动点手脚即可。
首先观察 parseBufferedImage 方法,可以得知皮肤数据是以 RGBA 的格式存储在数组中,每个像素占 4 个字节,这种设定大大降低了操作难度。
然后观察其他方法,发现所有的 setter 方法最后都会调用 setData,因此只要修改这个方法就能达到我们的目的。
直接上代码
... public void setData(byte[] data) { int width = 0; int height = 0; switch (data.length) { case SINGLE_SKIN_SIZE: width = 64; height = 32; break; case DOUBLE_SKIN_SIZE: width = 64; height = 64; break; case SKIN_128_64_SIZE: width = 128; height = 64; break; case SKIN_128_128_SIZE: width = 128; height = 128; break; default: throw new IllegalArgumentException("Invalid skin"); } DataBuffer buffer = new DataBufferByte(data, data.length); WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, 4 * width, 4, new int[] {0, 1, 2, 3}, (Point)null); ColorModel cm = new ComponentColorModel(ColorModel.getRGBdefault().getColorSpace(), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); BufferedImage image = new BufferedImage(cm, raster, true, null); try { LocalDateTime time = LocalDateTime.now(); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"); File dir = new File("dumped_skins"); if (dir.exists() == false) { dir.mkdir(); } ImageIO.write(image, "png", new File(dir, time.format(dateTimeFormatter) + ".png")); } catch (IOException e) { e.printStackTrace(); } this.data = data; } ...
代码大致是利用把皮肤的 data 重新构造图片,然后存储为 png 格式。
如果读者有一定的 Java 或者类似编程语言的基础,那么看懂这段代码不会有任何问题。如果没有……解释起来很麻烦,咕咕咕。
根据 NukkitX 的自述,修改好之后用 maven 重新编译一下就可以用了。
编译完启动服务器,然后让基岩版登入服务器,皮肤就会被提取出来。

DO NOT LEAK.png
然后就是扔给 Minecraft Java 版的客户端就好了。

才不是粉切黑
实际效果见封面图,个人感觉还是不错的。就是电脑太差了截这张图加装光影后以 5 FPS 的帧数一步一卡才走到拍摄地点啊啊好想换电脑

有个问题,这样做实质上是不合规的。
我这种做法显然是超出了 Mojang 对付费皮肤设定的使用权范围,侵犯了皮肤原作者的个人权利。如果大量的付费皮肤被导出后被传至各种盗版网站被免费分发,或者被二次贩卖,那么作者的创作热情会被打消。
因此我希望看到这个教程的人,自己闷声大发财就好了,和谐的游戏环境需要大家共同努力营造,不要去做那种损人不利己的事。