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.

This commit is contained in:
gnembon committed 2020-12-24 06:48:14 -04:00
1 parent f0a52fc751
commit d6eb53b6ce
4 files changed
+41 -9

No files matched your search

@@ -5,4 +5,7 @@ import carpet.helpers.EntityPlayerActionPack;
public interface ServerPlayerEntityInterface public interface ServerPlayerEntityInterface
{ {
EntityPlayerActionPack getActionPack(); EntityPlayerActionPack getActionPack();
void invalidateEntityObjectReference();
boolean isInvalidEntityObject();
} }
@@ -1,5 +1,6 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.ServerPlayerEntityInterface;
import net.minecraft.server.PlayerManager; import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -17,4 +18,11 @@ public class PlayerManager_scarpetEventsMixin
{ {
PLAYER_RESPAWNS.onPlayerEvent(player); 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<ServerPlayerEntity> cir)
{
((ServerPlayerEntityInterface)player).invalidateEntityObjectReference();
}
} }
@@ -1,6 +1,7 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.EntityInterface; import carpet.fakes.EntityInterface;
import carpet.fakes.ServerPlayerEntityInterface;
import carpet.script.EntityEventsGroup; import carpet.script.EntityEventsGroup;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import net.minecraft.entity.Entity; 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; import static carpet.script.CarpetEventServer.Event.STATISTICS;
@Mixin(ServerPlayerEntity.class) @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) 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()); PLAYER_CHANGES_DIMENSION.onDimensionChange(player, previousLocation, to, previousDimension, destination.getRegistryKey());
} }
};
@Override
public void invalidateEntityObjectReference()
{
isInvalidReference = true;
} }
@Override
public boolean isInvalidEntityObject()
{
return isInvalidReference;
}
} }
@@ -7,6 +7,7 @@ import carpet.fakes.LivingEntityInterface;
import carpet.fakes.MemoryInterface; import carpet.fakes.MemoryInterface;
import carpet.fakes.MobEntityInterface; import carpet.fakes.MobEntityInterface;
import carpet.fakes.HungerManagerInterface; import carpet.fakes.HungerManagerInterface;
import carpet.fakes.ServerPlayerEntityInterface;
import carpet.fakes.ServerPlayerInteractionManagerInterface; import carpet.fakes.ServerPlayerInteractionManagerInterface;
import carpet.helpers.Tracer; import carpet.helpers.Tracer;
import carpet.network.ServerNetworkHandler; 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. // TODO: decide whether copy(entity) should duplicate entity in the world.
public class EntityValue extends Value public class EntityValue extends Value
{ {
private final Entity entity; private Entity entity;
public EntityValue(Entity e) public EntityValue(Entity e)
{ {
@@ -119,6 +120,11 @@ public class EntityValue extends Value
public Entity getEntity() 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; return entity;
} }
@@ -170,7 +176,7 @@ public class EntityValue extends Value
@Override @Override
public String getString() public String getString()
{ {
return entity.getName().getString(); return getEntity().getName().getString();
} }
@Override @Override
@@ -184,7 +190,7 @@ public class EntityValue extends Value
{ {
if (v instanceof EntityValue) if (v instanceof EntityValue)
{ {
return entity.getEntityId()==((EntityValue) v).entity.getEntityId(); return getEntity().getEntityId()==((EntityValue) v).getEntity().getEntityId();
} }
return super.equals((Value)v); return super.equals((Value)v);
} }
@@ -220,7 +226,7 @@ public class EntityValue extends Value
@Override @Override
public int hashCode() public int hashCode()
{ {
return entity.hashCode(); return getEntity().hashCode();
} }
public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server) public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server)
@@ -374,7 +380,7 @@ public class EntityValue extends Value
throw new InternalExpressionException("Unknown entity feature: "+what); throw new InternalExpressionException("Unknown entity feature: "+what);
try try
{ {
return featureAccessors.get(what).apply(entity, arg); return featureAccessors.get(what).apply(getEntity(), arg);
} }
catch (NullPointerException npe) catch (NullPointerException npe)
{ {
@@ -835,7 +841,7 @@ public class EntityValue extends Value
throw new InternalExpressionException("Unknown entity action: " + what); throw new InternalExpressionException("Unknown entity action: " + what);
try try
{ {
featureModifiers.get(what).accept(entity, toWhat); featureModifiers.get(what).accept(getEntity(), toWhat);
} }
catch (NullPointerException npe) catch (NullPointerException npe)
{ {
@@ -1468,7 +1474,7 @@ public class EntityValue extends Value
EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName); EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName);
if (event == null) if (event == null)
throw new InternalExpressionException("Unknown entity event: " + eventName); 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 @Override
@@ -1477,7 +1483,7 @@ public class EntityValue extends Value
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
tag.put("Data", getEntity().toTag( 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; return tag;
} }
} }