From 1380be670540494fb8048f4fec6b995d7243732f Mon Sep 17 00:00:00 2001 From: iceBear67 Date: Tue, 17 Sep 2024 20:29:39 +0800 Subject: [PATCH] fix: implement ProjectileEntity#getOwner correctly (looks like MCPE-55823) --- .../server/fixes/ProjectileEntityMixin.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/io/ib67/sfcraft/mixin/server/fixes/ProjectileEntityMixin.java diff --git a/src/main/java/io/ib67/sfcraft/mixin/server/fixes/ProjectileEntityMixin.java b/src/main/java/io/ib67/sfcraft/mixin/server/fixes/ProjectileEntityMixin.java new file mode 100644 index 0000000..40c7677 --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/mixin/server/fixes/ProjectileEntityMixin.java @@ -0,0 +1,62 @@ +package io.ib67.sfcraft.mixin.server.fixes; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.server.world.ServerWorld; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.UUID; + +@Mixin(ProjectileEntity.class) +public class ProjectileEntityMixin { + @Shadow + private @Nullable Entity owner; + + @Shadow + private @Nullable UUID ownerUuid; + + @Unique + private boolean isPlayer; + + @Inject(at = @At("HEAD"), method = "setOwner") + private void setOwner(@Nullable Entity owner, CallbackInfo ci) { + isPlayer = owner instanceof PlayerEntity; + } + + /** + * @reason Implement the logic correctly. + */ + @Overwrite + public @Nullable Entity getOwner() { + if (this.owner != null && !this.owner.isRemoved()) { + return this.owner; + } else if (this.ownerUuid != null) { + var server = $().getWorld().getServer(); + if (server == null) { + return null; + } + if (isPlayer) { + return server.getPlayerManager().getPlayer(this.ownerUuid); + } else { + for (ServerWorld world : server.getWorlds()) { + var entity = world.getEntity(this.ownerUuid); + if (entity != null) return entity; + } + } + } + return null; + } + + @Unique + private ProjectileEntity $() { + return (ProjectileEntity) (Object) this; + } +}