From d6eb53b6ce9ca12cef88ff555c1d3ce55c5099fc Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 24 Dec 2020 06:48:14 -0400 Subject: [PATCH] player entity value may become invalid due to respawns. This not only fixes #633, but also other cases where player reference is used over time while player respawns and its instance is recycled. --- .../fakes/ServerPlayerEntityInterface.java | 3 +++ .../PlayerManager_scarpetEventsMixin.java | 8 +++++++ .../ServerPlayerEntity_scarpetEventMixin.java | 17 +++++++++++++- .../java/carpet/script/value/EntityValue.java | 22 ++++++++++++------- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/main/java/carpet/fakes/ServerPlayerEntityInterface.java b/src/main/java/carpet/fakes/ServerPlayerEntityInterface.java index 1d7aa428..9fd69a30 100644 --- a/src/main/java/carpet/fakes/ServerPlayerEntityInterface.java +++ b/src/main/java/carpet/fakes/ServerPlayerEntityInterface.java @@ -5,4 +5,7 @@ import carpet.helpers.EntityPlayerActionPack; public interface ServerPlayerEntityInterface { EntityPlayerActionPack getActionPack(); + void invalidateEntityObjectReference(); + boolean isInvalidEntityObject(); + } diff --git a/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java b/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java index 6911f8f1..0d2d1c96 100644 --- a/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java @@ -1,5 +1,6 @@ package carpet.mixins; +import carpet.fakes.ServerPlayerEntityInterface; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; import org.spongepowered.asm.mixin.Mixin; @@ -17,4 +18,11 @@ public class PlayerManager_scarpetEventsMixin { PLAYER_RESPAWNS.onPlayerEvent(player); } + + @Inject(method = "respawnPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;onSpawn()V")) + private void invalidatePreviousInstance(ServerPlayerEntity player, boolean alive, CallbackInfoReturnable cir) + { + ((ServerPlayerEntityInterface)player).invalidateEntityObjectReference(); + } + } diff --git a/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java b/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java index f53ad308..511d56dc 100644 --- a/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java @@ -1,6 +1,7 @@ package carpet.mixins; import carpet.fakes.EntityInterface; +import carpet.fakes.ServerPlayerEntityInterface; import carpet.script.EntityEventsGroup; import com.mojang.authlib.GameProfile; import net.minecraft.entity.Entity; @@ -28,8 +29,11 @@ import static carpet.script.CarpetEventServer.Event.PLAYER_FINISHED_USING_ITEM; import static carpet.script.CarpetEventServer.Event.STATISTICS; @Mixin(ServerPlayerEntity.class) -public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity +public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity implements ServerPlayerEntityInterface { + // to denote if the player reference is valid + + private boolean isInvalidReference = false; public ServerPlayerEntity_scarpetEventMixin(World world, BlockPos blockPos, float f, GameProfile gameProfile) { @@ -109,6 +113,17 @@ public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity } PLAYER_CHANGES_DIMENSION.onDimensionChange(player, previousLocation, to, previousDimension, destination.getRegistryKey()); } + }; + + @Override + public void invalidateEntityObjectReference() + { + isInvalidReference = true; } + @Override + public boolean isInvalidEntityObject() + { + return isInvalidReference; + } } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 283d3548..9504166a 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -7,6 +7,7 @@ import carpet.fakes.LivingEntityInterface; import carpet.fakes.MemoryInterface; import carpet.fakes.MobEntityInterface; import carpet.fakes.HungerManagerInterface; +import carpet.fakes.ServerPlayerEntityInterface; import carpet.fakes.ServerPlayerInteractionManagerInterface; import carpet.helpers.Tracer; import carpet.network.ServerNetworkHandler; @@ -90,7 +91,7 @@ import static carpet.utils.MobAI.genericJump; // TODO: decide whether copy(entity) should duplicate entity in the world. public class EntityValue extends Value { - private final Entity entity; + private Entity entity; public EntityValue(Entity e) { @@ -119,6 +120,11 @@ public class EntityValue extends Value public Entity getEntity() { + if (entity instanceof ServerPlayerEntity && ((ServerPlayerEntityInterface)entity).isInvalidEntityObject()) + { + ServerPlayerEntity newPlayer = entity.getServer().getPlayerManager().getPlayer(entity.getUuid()); + if (newPlayer != null) entity = newPlayer; + } return entity; } @@ -170,7 +176,7 @@ public class EntityValue extends Value @Override public String getString() { - return entity.getName().getString(); + return getEntity().getName().getString(); } @Override @@ -184,7 +190,7 @@ public class EntityValue extends Value { if (v instanceof EntityValue) { - return entity.getEntityId()==((EntityValue) v).entity.getEntityId(); + return getEntity().getEntityId()==((EntityValue) v).getEntity().getEntityId(); } return super.equals((Value)v); } @@ -220,7 +226,7 @@ public class EntityValue extends Value @Override public int hashCode() { - return entity.hashCode(); + return getEntity().hashCode(); } public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server) @@ -374,7 +380,7 @@ public class EntityValue extends Value throw new InternalExpressionException("Unknown entity feature: "+what); try { - return featureAccessors.get(what).apply(entity, arg); + return featureAccessors.get(what).apply(getEntity(), arg); } catch (NullPointerException npe) { @@ -835,7 +841,7 @@ public class EntityValue extends Value throw new InternalExpressionException("Unknown entity action: " + what); try { - featureModifiers.get(what).accept(entity, toWhat); + featureModifiers.get(what).accept(getEntity(), toWhat); } catch (NullPointerException npe) { @@ -1468,7 +1474,7 @@ public class EntityValue extends Value EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName); if (event == null) throw new InternalExpressionException("Unknown entity event: " + eventName); - ((EntityInterface)entity).getEventContainer().addEvent(event, cc.host, fun, args); + ((EntityInterface)getEntity()).getEventContainer().addEvent(event, cc.host, fun, args); } @Override @@ -1477,7 +1483,7 @@ public class EntityValue extends Value if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); CompoundTag tag = new CompoundTag(); tag.put("Data", getEntity().toTag( new CompoundTag())); - tag.put("Name", StringTag.of(Registry.ENTITY_TYPE.getId(entity.getType()).toString())); + tag.put("Name", StringTag.of(Registry.ENTITY_TYPE.getId(getEntity().getType()).toString())); return tag; } }