Expected:
Baby Zombified Piglin Chicken Jockeys spawned from Nether portals to have a teleportation cooldown similar to the other Zombified Piglin variants spawned. The Baby
Observed Results:
Baby Zombified Piglin Chicken Jockeys spawned from Nether portals have no teleportation cooldown, thus instantly teleporting to the opposing dimension.
Steps To Reproduce:
Build a maximum-size portal Nether Portal in the Overworld or Nether at least two blocks above ground to prevent zombified piglins from leaving and entering the portal
Place trap doors on both sides of the bottom obsidian to allow zombified piglins to exit the portal and not return
Connect the portal to the other dimension by entering it
Stay in one dimension within the portal's ability to summon zombified piglin and tick sprint until you see the observed results.
Attachments
Comments 2
Can confirm via code analysis, and testing the issue in 1.21.
Here inside NetherPortalBlock.java which handles the code for spawning zombie piglins inside of portals, their nether portal cooldown is reset as expected when they spawn.
protected void randomTick(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource randomSource) {
if (serverLevel.dimensionType().natural() && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && randomSource.nextInt(2000) < serverLevel.getDifficulty().getId()) {
while(serverLevel.getBlockState(blockPos).is(this)) {
blockPos = blockPos.below();
}
if (serverLevel.getBlockState(blockPos).isValidSpawn(serverLevel, blockPos, EntityType.ZOMBIFIED_PIGLIN)) {
Entity zombifiedPiglin = EntityType.ZOMBIFIED_PIGLIN.spawn(serverLevel, blockPos.above(), MobSpawnType.STRUCTURE);
if (zombifiedPiglin != null) {
// Portal cooldown reset
zombifiedPiglin.setPortalCooldown();
}
}
}
}
When looking inside of Zombie.java method finalizeSpawn(), you can see that when the chicken for the zombie jockey is spawned, its nether portal cooldown is never reset, so it instantly travels through the portal.
. . .
if (spawnGroupData1 instanceof Zombie.ZombieGroupData) {
Zombie.ZombieGroupData zombieGroupData = (Zombie.ZombieGroupData)spawnGroupData1;
if (zombieGroupData.isBaby) {
this.setBaby(true);
if (zombieGroupData.canSpawnJockey) {
if ((double)var5.nextFloat() < 0.05D) {
List entitiesOfClass = serverLevelAccessor.getEntitiesOfClass(Chicken.class, this.getBoundingBox().inflate(5.0D, 3.0D, 5.0D), EntitySelector.ENTITY_NOT_BEING_RIDDEN);
if (!entitiesOfClass.isEmpty()) {
Chicken chicken = (Chicken)entitiesOfClass.get(0);
chicken.setChickenJockey(true);
this.startRiding(chicken);
}
} else if ((double)var5.nextFloat() < 0.05D) {
Chicken chicken = (Chicken)EntityType.CHICKEN.create(this.level());
if (chicken != null) {
chicken.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F);
chicken.finalizeSpawn(serverLevelAccessor, difficultyInstance, MobSpawnType.JOCKEY, (SpawnGroupData)null);
chicken.setChickenJockey(true);
this.startRiding(chicken);
serverLevelAccessor.addFreshEntity(chicken);
}
}
}
}
this.setCanBreakDoors(this.supportsBreakDoorGoal() && var5.nextFloat() < var6 * 0.1F);
this.populateDefaultEquipmentSlots(var5, difficultyInstance);
this.populateDefaultEquipmentEnchantments(serverLevelAccessor, var5, difficultyInstance);
}
. . .
Whether or not the code in question is optimal isn't clear to me, but the fix I made was to add a "resetPortalCooldown()" method call on the chicken entity after finalizeSpawn()
is called. The chicken is not immediately teleported, but instead spawns just like all other pigmen do fixing the issue. Here is a demonstration:
Please provide clear steps to reproduce the described behavior alongside your expected and observed results. Attaching any necessary worlds or structures would also be very helpful.