酒醉的鸵鸟
本帖最后由 酒醉的鸵鸟 于 2022-1-19 22:04 编辑

游戏版本1.16.5,mod加载器为fabric

今天在写mod,想为马加一个跳跃提升的效果,但是无论我给马赋上多少等级的跳跃提升(不管用指令还是药水),马的跳跃高度都没有改变。好奇之下,我翻开了反编译后的源码:

  1.        if (this.jumpStrength > 0.0f && !this.isInAir() && this.onGround) {
  2.             double d = this.getJumpStrength() * (double)this.jumpStrength * (double)this.getJumpVelocityMultiplier();
  3.             double e = this.hasStatusEffect(StatusEffects.JUMP_BOOST) ? d + (double)((float)(this.getStatusEffect(StatusEffects.JUMP_BOOST).getAmplifier() + 1) * 0.1f) : d;
  4.             Vec3d vec3d = this.getVelocity();
  5.             this.setVelocity(vec3d.x, e, vec3d.z);
  6.             this.setInAir(true);
  7.             this.velocityDirty = true;
  8.             if (g > 0.0f) {
  9.                 float h = MathHelper.sin(this.yaw * ((float)Math.PI / 180));
  10.                 float i = MathHelper.cos(this.yaw * ((float)Math.PI / 180));
  11.                 this.setVelocity(this.getVelocity().add(-0.4f * h * this.jumpStrength, 0.0, 0.4f * i * this.jumpStrength));
  12.             }
  13.             this.jumpStrength = 0.0f;
  14.         }
复制代码
这段中有一个d和e,可以初步判断d应该是没有考虑跳跃提升效果的跳跃高度,e应该是考虑跳跃提升后的。
我用Mixin注入了这个方法,在d和e赋值之后给玩家发送消息,从游戏中获取每次跳跃时的d和e,并判断是否存在药水效果。
为马增加药水效果前(before是e的值,after是d的值):


为马增加药水效果后:


然而,当我退出存档重进后(此时药水效果还在持续时间内)


可以发现,重进存档后游戏才认为马获得了跳跃提升效果,并为e赋上了正确的值
耐心等待过后发现,如果药水时间耗尽,此时我不退出存档,跳跃提升效果会一直存在!

------------------------------------------------------------------------------------------------------------------
虽然这个bug没有影响多大的游戏体验,但是发现之后还是比较震惊的,毕竟跳跃提升这个效果已经存在很多个版本了。
我觉得这对我们(准)开发者来说是一个小经验,可能没有玩家发现这个(毕竟很少人会给马用跳跃提升药水),就算发现了可能也没有多大重视,而开发者可能也不会花太多心思来测试这个小功能,所以。。。。开发mod时应该注意多测试各个功能是否真正实现了



青蛙的名单
这个或许应该可以作为一个bug提交给MOJANG了吧

Ryen_Now
快点提交BUG,给同行们添绊子

酒醉的鸵鸟
青蛙的名单 发表于 2022-1-19 22:34
这个或许应该可以作为一个bug提交给MOJANG了吧

敢问该如何提交bug,或者如何联系到mojang呢
(不知道mojang会把这个定为bug还是特性

青蛙的名单
酒醉的鸵鸟 发表于 2022-1-19 22:54
敢问该如何提交bug,或者如何联系到mojang呢
(不知道mojang会把这个定为bug还是特性) ...

https://bugs.mojang.com/

名副其实
非常成功的一次,一次发现BUG的经历
你发现这个BUG的价值已经远大于你一开始的想法了。
也就是说,这个问题直到1.16前都一直存在

夏至锐
利害,我连mod都不会写就只能观望大佬了qwq毕竟发现bug也是一件很酷的事情qwq(还能把开发者连夜抓起来加班awa)

酒醉的鸵鸟

这个网站的账号怎么弄,好像不是mojang的账号,叫啥.....jira?

constLI
我感觉会被认为是特性,估计也不会修复

Ph-苯
本帖最后由 Ph-苯 于 2022-1-21 15:30 编辑

我混入了net.minecraft.entity.LivingEntity#getJumpBoostVelocityModifier:
  1. @Inject(method = "getJumpBoostVelocityModifier", at = @At("RETURN"))
  2. private void onGetJumpBoostVelocityModifier(CallbackInfoReturnable<Double> cir) {
  3.         Main.print("entity=%s\nhasStatusEffect=%s\ngetStatusEffect=%s\ngetJumpBoostVelocityModifier=%s".formatted(
  4.           this,
  5.           hasStatusEffect(StatusEffects.JUMP_BOOST),
  6.           getStatusEffect(StatusEffects.JUMP_BOOST),
  7.           cir.getReturnValueD()));
  8. }
复制代码
发现,其它生物在跳跃时,该消息是从服务端打印的:
  1. entity=HuskEntity['尸壳'/4, l='ServerLevel[试验场]', x=4.96, y=-10.00, z=44.30]
  2. hasStatusEffect=false
  3. getStatusEffect=null
  4. getJumpBoostVelocityModifier=0.0
复制代码
玩家在跳跃时,该消息在客户端和服务端都会打印:
  1. entity=ClientPlayerEntity['Phoupraw'/6, l='ClientLevel', x=11.98, y=-8.00, z=46.77]
  2. hasStatusEffect=false
  3. getStatusEffect=null
  4. getJumpBoostVelocityModifier=0.0
复制代码
  1. entity=ServerPlayerEntity['Phoupraw'/6, l='ServerLevel[试验场]', x=11.98, y=-8.00, z=46.77]
  2. hasStatusEffect=false
  3. getStatusEffect=null
  4. getJumpBoostVelocityModifier=0.0
复制代码
但马在跳跃时,该消息只在客户端打印:
  1. entity=HorseEntity['马'/13, l='ClientLevel', x=15.59, y=-8.00, z=58.73]
  2. hasStatusEffect=false
  3. getStatusEffect=null
  4. getJumpBoostVelocityModifier=0.0
复制代码

在给马施加跳跃提升效果后,打印出的消息是:
  1. entity=HorseEntity['马'/13, l='ClientLevel', x=15.59, y=-8.00, z=58.73]
  2. hasStatusEffect=false
  3. getStatusEffect=null
  4. getJumpBoostVelocityModifier=0.0
复制代码
重进存档后,打印出的消息是:
  1. entity=HorseEntity['马'/18, l='ClientLevel', x=20.19, y=-8.00, z=61.37]
  2. hasStatusEffect=true
  3. getStatusEffect=effect.minecraft.jump_boost, Duration: 2554
  4. getJumpBoostVelocityModifier=0.10000000149011612
复制代码

我猜测,施加的状态效果没有立即从服务端传递给客户端,而是等到重进存档,才用NBT的方式传递给客户端。
而恰巧不知为何,马的getJumpBoostVelocityModifier只在客户端调用,所以就造成了这种不同步的现象。
再次探究发现,马在跳跃时需要jumpStrength > 0才会进入楼主所说的那个if分支,而jumpStrength默认是0,其setter是setJumpStrength,但setJumpStrength只在ClientPlayerEntity的tickMovement里被调用,所以只有在客户端才会进入楼主所说的那个if分支,只有在客户端才会调用getJumpBoostVelocityModifier,而施加药水效果是服务端处理的,并没有立刻传递给客户端,所以重进存档之前,在客户端,马是没有跳跃提升效果的。
至于马在客户端的运动是怎么传递给服务端的……

CNKaiGeGe
那叫BUG吗?那叫特性!!!

酒醉的鸵鸟
Ph-苯 发表于 2022-1-21 15:08
我混入了net.minecraft.entity.LivingEntity#getJumpBoostVelocityModifier:发现,其它生物在跳跃时,该消 ...

大佬太强了!!是不是可以得出结论:这个bug可以通过发送C2S包来同步jumpStrength数据来解决?
不过我还有个问题,类似位置坐标这样的数据不是应该在服务端处理后同步到客户端吗,为什么会用客户端的数据来同步呢?

Ph-苯
本帖最后由 Ph-苯 于 2022-1-22 00:25 编辑
酒醉的鸵鸟 发表于 2022-1-21 20:16
大佬太强了!!是不是可以得出结论:这个bug可以通过发送C2S包来同步jumpStrength数据来解决?
不过我还 ...
是不是可以得出结论:这个bug可以通过发送C2S包来同步jumpStrength数据来解决?

应该可以,只是可能要新建类。
不过我还有个问题,类似位置坐标这样的数据不是应该在服务端处理后同步到客户端吗,为什么会用客户端的数据来同步呢?

我也很纳闷。mojang的代码真是屎山……

(还有我不是大佬😂,只是个挖坑不填的蒟蒻😂)

xmdhs
已经有相关的 bug 反馈了,目前还没有修复
https://bugs.mojang.com/browse/MC-121788

WeiQu_钻石块
不愧是BUGJUMP
代码如屎

mingtfarc
我也遇到过这个问题,后来我猜测:可能是Mojang忘记写马的s2c的同步数据包导致的

szq2516
自己写的 mod 怎么加载到游戏中啊~

Green绿小草E5
MC有bug?

807222124
mojang设计师awa

Yi_Kerman
酒醉的鸵鸟 发表于 2022-1-20 09:41
这个网站的账号怎么弄,好像不是mojang的账号,叫啥.....jira?

Jira是Atlassian的项目与事务跟踪工具, 被Mojang用来追踪bug

MYFF
很好很强大

1602425035
mcbbs有你更精彩

第一页 上一页 下一页 最后一页