diff --git a/paper-api/src/main/java/org/bukkit/entity/Fireball.java b/paper-api/src/main/java/org/bukkit/entity/Fireball.java index 252e3d35c0..e2974c49db 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Fireball.java +++ b/paper-api/src/main/java/org/bukkit/entity/Fireball.java @@ -46,10 +46,6 @@ public interface Fireball extends Projectile, Explosive { * The acceleration gets applied to the velocity every tick, depending on * the specific type of the fireball a damping / drag factor is applied so * that the velocity does not grow into infinity. - *
- * Note: that the client may not respect non-default acceleration - * power and will therefore mispredict the location of the fireball, causing - * visual stutter. * * @param acceleration the acceleration */ diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch index d28acac7d5..b651b9bc77 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerEntity.java.patch @@ -28,7 +28,30 @@ this.level = level; this.broadcast = broadcast; this.entity = entity; -@@ -103,16 +_,22 @@ +@@ -98,21 +_,45 @@ + this.trackedDataValues = entity.getEntityData().getNonDefaultValues(); + } + ++ // Paper start - fix desync when a player is added to the tracker ++ public void onPlayerAdd() { ++ // TODO - IMPLEMENT STUBBED METHOD FROM MOONRISE ++ } ++ // Paper end - fix desync when a player is added to the tracker ++ // Paper start - Improve AbstractHurtingProjectile syncing ++ // This can be removed when velocity is no longer downsized when sending it over the protocol. ++ // We create a packet that only updates the velocity on the client. ++ private static final Set RELATIVES = net.minecraft.world.entity.Relative.union(Set.of(net.minecraft.world.entity.Relative.X, net.minecraft.world.entity.Relative.Y, net.minecraft.world.entity.Relative.Z), net.minecraft.world.entity.Relative.ROTATION); ++ public Packet getAccurateVelocityPacket() { ++ return new net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket(this.entity.getId(), ++ new net.minecraft.world.entity.PositionMoveRotation(net.minecraft.world.phys.Vec3.ZERO, this.lastSentMovement, 0, 0), ++ RELATIVES, ++ this.wasOnGround ++ ); ++ } ++ // Paper end - Improve AbstractHurtingProjectile syncing ++ + public void sendChanges() { + List passengers = this.entity.getPassengers(); if (!passengers.equals(this.lastPassengers)) { List list = this.mountedOrDismounted(passengers).map(Entity::getUUID).toList(); this.broadcastWithIgnore.accept(new ClientboundSetPassengersPacket(this.entity), list); @@ -70,6 +93,15 @@ Packet packet = null; boolean flag2 = flag1 || this.tickCount % 60 == 0; boolean flag3 = false; +@@ -188,7 +_,7 @@ + .accept( + new ClientboundBundlePacket( + List.of( +- new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement), ++ this.getAccurateVelocityPacket(), // Paper - Improve AbstractHurtingProjectile syncing + new ClientboundProjectilePowerPacket(abstractHurtingProjectile.getId(), abstractHurtingProjectile.accelerationPower) + ) + ) @@ -227,6 +_,25 @@ this.tickCount++; @@ -131,6 +163,20 @@ } if (!this.entity.getPassengers().isEmpty()) { +@@ -326,6 +_,13 @@ + if (this.entity instanceof Leashable leashable && leashable.isLeashed()) { + consumer.accept(new ClientboundSetEntityLinkPacket(this.entity, leashable.getLeashHolder())); + } ++ // Paper start - Improve AbstractHurtingProjectile syncing ++ // We need to send our more accurate velocity and our acceleration power ++ if (this.entity instanceof AbstractHurtingProjectile abstractHurtingProjectile) { ++ consumer.accept(new ClientboundProjectilePowerPacket(abstractHurtingProjectile.getId(), abstractHurtingProjectile.accelerationPower)); ++ consumer.accept(this.getAccurateVelocityPacket()); ++ } ++ // Paper end - Improve AbstractHurtingProjectile syncing + } + + public Vec3 getPositionBase() { @@ -359,6 +_,11 @@ if (this.entity instanceof LivingEntity) { Set attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java index 7e53e12c8e..5d7976f0ad 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java @@ -62,9 +62,10 @@ public class CraftFireball extends AbstractProjectile implements Fireball { public void setAcceleration(@NotNull Vector acceleration) { Preconditions.checkArgument(acceleration != null, "Vector acceleration cannot be null"); // SPIGOT-6993: AbstractHurtingProjectile#assignDirectionalMovement will normalize the given values - // Note: Because of MC-80142 the fireball will stutter on the client when setting the power to something other than 0 or the normalized vector * 0.1 - this.getHandle().assignDirectionalMovement(CraftVector.toVec3(acceleration), acceleration.length()); - this.update(); // SPIGOT-6579 + // Set the acceleration power in order to properly sync the movement to the client + double length = acceleration.length(); + this.getHandle().accelerationPower = length; + this.getHandle().assignDirectionalMovement(CraftVector.toVec3(acceleration), length); } @NotNull