开启辅助访问     
收藏本站

站内搜索

搜索

Minecraft(我的世界)苦力怕论坛

[插件开发讨论] 如何优雅地换皮肤给榜一大哥看?

 发表于 2024-3-4 12:41:18|显示全部楼层|阅读模式 IP:江西省
欢迎大家来到兔兔子的直播间~
刷一个嘉年华可以换皮肤哦~

想必跟我一样的擦边主播在此时都会有一个问题:
如何优雅地换皮肤给榜一大哥看?
这个问题会有如下几个选项:
1,原地脱去皮肤,穿上新的皮肤,但是容易被超管封直播间
2,“暂时离开”直播间,在别处换好了皮肤之后再回来,但是可能会损失一些现成的流量
3,圈到圆子了就跑路,不换皮肤了。什么,退钱?退你妈!

但是这些选项显然都有一些代价,那么是否有又便捷又优雅的换皮肤方式呢?

当然有!直接原地把现在穿着的皮肤改为新皮肤就好了!

要给玩家更换皮肤,在服务端需要有以下步骤:
1,获取材质
2,给指定玩家更换材质
3,通过nms使更换生效

第一步和第二步都非常简单,通过bukkitApi即可实现,第三步使用nms包即可实现。但是由于众所周知的原因,nms包的调用非常麻烦,而且对跨版本有一定的局限性,即便可以通过nmsPorxy或是Class.forName()处理起来也并不简单,而且容易发生意料之外的问题。


我们可以使用一个魔法道具——SkinsRestorerApi,让别人去帮忙处理屎山。
以下内容均针对于群组服。

  1. override fun onEnable(){
  2.     skinsRestorerApi = SkinsRestorerProvider.get();
  3.     getProxy().getPluginManager().registerListener(this,this);
  4.     getProxy().registerChannel("BungeeCord");
  5. }

  6. @EventHandler
  7. fun onPluginMessageReceived(e: PluginMessageEvent){
  8.    
  9. }
复制代码
如此,相当于直播间的公告栏
那么如何通过公告栏告诉观众:刷一个嘉年华主播就换皮肤呢

  1. fun skinProperty(value: String, signature: String): SkinProperty {
  2.     return SkinProperty.of(value, signature)
  3. }

  4. fun skinChangeHandle(player: ProxiedPlayer, skin: SkinProperty) {
  5.     proxy.scheduler.runAsync(
  6.         this
  7.     ) {
  8.         skinsRestorerApi.getSkinApplier<ProxiedPlayer>(ProxiedPlayer::class.java).applySkin(player, skin)
  9.     }
  10. }

  11. // 移除皮肤最好考虑一下是否直接换成mc的默认皮肤
  12. fun removeSkin(player: ProxiedPlayer) {
  13.     skinsRestorerApi.playerStorage.removeSkinIdOfPlayer(player.uniqueId)
  14.     proxy.scheduler.runAsync(this) {
  15.         // 如果有相应的正版皮肤  则给正版皮肤
  16.         try {
  17.             val optionalSkin = skinsRestorerApi.playerStorage
  18.                 .getSkinForPlayer(player.uniqueId, player.displayName)
  19.             if (optionalSkin.isPresent) {
  20.                 skinChangeHandle(player, optionalSkin.get())
  21.             }
  22.         } catch () {}
  23.     }
  24. }
复制代码
然后在onPluginMessageReceived中接收榜一大哥的礼物,随后调用skinChangeHandle()即可

那么,榜一大哥要如何刷礼物呢?

  1. fun setSkin(skin: ISkinsEntry){
  2.     this.setTextures(skin.texture,skin.signature)
  3. }

  4. fun setTextures(textures: String, signature: String){
  5.     this.rawPlayer?.let {
  6.         Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, Runnable {
  7.             val b = ByteArrayOutputStream()
  8.             val o = DataOutputStream(b)
  9.             try {
  10.                 o.writeUTF("skin")
  11.                 o.writeUTF(it.uniqueId)
  12.                 o.writeUTF(textures)
  13.                 o.writeUTF(signature)
  14.                 o.flush()
  15.                 // BungeeCord君 我要进来咯!
  16.                 it.sendPluginMessage(plugin, "BungeeCord", b.toByteArray())
  17.             } catch () {}
  18.         }, 20L)
  19.     }
  20. }
复制代码
这里给20个tick的Later是为了预防在PlayerJoinEvent中使用,可能会导致意料之外的错误发生。

由于众所周知的原因,咱们擦边主播会有一部分人守不住底线,脱掉自己皮肤的情况

  1. proxy.scheduler.runAsync(
  2.     this
  3. ) {
  4.     skinsRestorerApi.getSkinApplier<ProxiedPlayer>(ProxiedPlayer::class.java)
  5.         .applySkin(player, SkinProperty.of("", ""))//将皮肤的材质和签名都设置为"",即会换成mc的默认皮肤
  6. }
复制代码


这是我前几天折腾一个即时、动态更换玩家皮肤的需求时的解决方案,由于利益相关,暂时不能抛出完整代码。
使用BC处理是因为SkinsRestorerApi目前要求jdk17(SkinsRestorerApi降版本的话太难用了,那我还不如nmsProxy呢),而这个需求要求的mc版本是1.16.5,需要使用jdk16,于是我选择曲线救国在BC使用SkinsRestorerApi处理玩家皮肤,而子服(paper)只负责告诉bc需要将哪位玩家的皮肤更换为什么材质。

虽然我觉得应该不会有其他人遇到这么奇葩的需求了,但是万一呢。其实主要是想水一帖
因此稍微整理了一下发出来,如果你也遇到了这么奇葩的需求,希望这篇帖子能帮到你。





评分

参与人数 2铁粒 +170收起理由
 我是re*** + 150优秀奖励
 沐九*** + 20主包太有实粒辣

查看全部评分

苦力怕论坛,感谢有您~
 发表于 2024-3-4 12:54:54 来自手机|显示全部楼层 IP:陕西省
好耶,打call
2#2024-3-4 12:54:54回复收起回复
苦力怕论坛,感谢有您~
回复支持

使用道具举报

 发表于 2024-3-4 12:55:03 来自手机|显示全部楼层 IP:安徽省
差一点就点走了
3#2024-3-4 12:55:03收起回复
古明地兔2024-3-4 12:56IP:江西省
回复举报
苦力怕论坛,感谢有您~
回复支持

使用道具举报

本版积分规则

本站
关于我们
联系我们
坛史纲要
官方
哔哩哔哩
技术博客
下载
网易版
安卓版
JAVA
反馈
意见建议
教程中心
更多
捐助本站
QQ群
QQ群

QQ群

访问手机版

访问手机版

手机版|小黑屋|系统状态|klpbbs.com

粤公网安备 44200002445329号 | 由 木韩网络 提供支持 | GMT+8, 2024-12-16 18:11

声明:本站与Mojang以及微软公司没有从属关系

Powered by Discuz! X3.4 粤ICP备2023071842号-3