--- a/net/minecraft/world/entity/monster/EntityZombieVillager.java +++ b/net/minecraft/world/entity/monster/EntityZombieVillager.java @@ -51,6 +51,14 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.IBlockData; +// CraftBukkit start +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.entity.npc.EntityVillager; +import org.bukkit.entity.ZombieVillager; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityTransformEvent; +// CraftBukkit end + public class EntityZombieVillager extends EntityZombie implements VillagerDataHolder { public static final DataWatcherObject DATA_CONVERTING_ID = DataWatcher.defineId(EntityZombieVillager.class, DataWatcherRegistry.BOOLEAN); @@ -69,6 +77,7 @@ @Nullable private MerchantRecipeList tradeOffers; private int villagerXp = 0; + private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field public EntityZombieVillager(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -99,12 +108,12 @@ public void readAdditionalSaveData(NBTTagCompound nbttagcompound) { super.readAdditionalSaveData(nbttagcompound); this.entityData.set(EntityZombieVillager.DATA_VILLAGER_DATA, (VillagerData) nbttagcompound.read("VillagerData", VillagerData.CODEC).orElseGet(EntityVillager::createDefaultVillagerData)); - this.tradeOffers = (MerchantRecipeList) nbttagcompound.read("Offers", MerchantRecipeList.CODEC, this.registryAccess().createSerializationContext(DynamicOpsNBT.INSTANCE)).orElse((Object) null); - this.gossips = (Reputation) nbttagcompound.read("Gossips", Reputation.CODEC).orElse((Object) null); + this.tradeOffers = (MerchantRecipeList) nbttagcompound.read("Offers", MerchantRecipeList.CODEC, this.registryAccess().createSerializationContext(DynamicOpsNBT.INSTANCE)).orElse(null); // CraftBukkit - decompile error + this.gossips = (Reputation) nbttagcompound.read("Gossips", Reputation.CODEC).orElse(null); // CraftBukkit - decompile error int i = nbttagcompound.getIntOr("ConversionTime", -1); if (i != -1) { - UUID uuid = (UUID) nbttagcompound.read("ConversionPlayer", UUIDUtil.CODEC).orElse((Object) null); + UUID uuid = (UUID) nbttagcompound.read("ConversionPlayer", UUIDUtil.CODEC).orElse(null); // CraftBukkit - decompile error this.startConverting(uuid, i); } else { @@ -119,6 +128,10 @@ public void tick() { if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { int i = this.getConversionProgress(); + // CraftBukkit start - Use wall time instead of ticks for villager conversion + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + i *= elapsedTicks; + // CraftBukkit end this.villagerConversionTime -= i; if (this.villagerConversionTime <= 0) { @@ -127,6 +140,7 @@ } super.tick(); + this.lastTick = MinecraftServer.currentTick; // CraftBukkit } @Override @@ -167,8 +181,10 @@ this.conversionStarter = uuid; this.villagerConversionTime = i; this.getEntityData().set(EntityZombieVillager.DATA_CONVERTING_ID, true); - this.removeEffect(MobEffects.WEAKNESS); - this.addEffect(new MobEffect(MobEffects.STRENGTH, i, Math.min(this.level().getDifficulty().getId() - 1, 0))); + // CraftBukkit start + this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); + this.addEffect(new MobEffect(MobEffects.STRENGTH, i, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); + // CraftBukkit end this.level().broadcastEntityEvent(this, (byte) 16); } @@ -185,7 +201,8 @@ } private void finishConversion(WorldServer worldserver) { - this.convertTo(EntityTypes.VILLAGER, ConversionParams.single(this, false, false), (entityvillager) -> { + EntityVillager converted = this.convertTo(EntityTypes.VILLAGER, ConversionParams.single(this, false, false), (entityvillager) -> { // CraftBukkit + this.forceDrops = false; // CraftBukkit for (EnumItemSlot enumitemslot : this.dropPreservedEquipment(worldserver, (itemstack) -> { return !EnchantmentManager.has(itemstack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE); })) { @@ -215,12 +232,16 @@ } } - entityvillager.addEffect(new MobEffect(MobEffects.NAUSEA, 200, 0)); + entityvillager.addEffect(new MobEffect(MobEffects.NAUSEA, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit if (!this.isSilent()) { worldserver.levelEvent((Entity) null, 1027, this.blockPosition(), 0); } - - }); + // CraftBukkit start + }, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); + if (converted == null) { + ((ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam + } + // CraftBukkit end } @VisibleForTesting