/net/minecraft/world/entity/monster

This commit is contained in:
Owen1212055 2024-12-14 14:39:36 -05:00
parent f1ee7a0262
commit ea5c599077
50 changed files with 1386 additions and 1620 deletions

View file

@ -0,0 +1,79 @@
--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -64,6 +_,11 @@
AbstractSkeleton.this.setAggressive(true);
}
};
+ // Paper start - shouldBurnInDay API
+ private boolean shouldBurnInDay = true;
+ public boolean shouldBurnInDay() { return shouldBurnInDay; }
+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; }
+ // Paper end - shouldBurnInDay API
protected AbstractSkeleton(EntityType<? extends AbstractSkeleton> entityType, Level level) {
super(entityType, level);
@@ -97,7 +_,7 @@
@Override
public void aiStep() {
- boolean isSunBurnTick = this.isSunBurnTick();
+ boolean isSunBurnTick = this.shouldBurnInDay && this.isSunBurnTick(); // Paper - shouldBurnInDay API
if (isSunBurnTick) {
ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
if (!itemBySlot.isEmpty()) {
@@ -145,7 +_,7 @@
this.populateDefaultEquipmentSlots(random, difficulty);
this.populateDefaultEquipmentEnchantments(level, random, difficulty);
this.reassessWeaponGoal();
- this.setCanPickUpLoot(random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier());
+ this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
LocalDate localDate = LocalDate.now();
int i = localDate.get(ChronoField.DAY_OF_MONTH);
@@ -196,9 +_,19 @@
double d2 = target.getZ() - this.getZ();
double squareRoot = Math.sqrt(d * d + d2 * d2);
if (this.level() instanceof ServerLevel serverLevel) {
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - improve entity shhot bow event - add arrow stack to event
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;
+ }
+
+ if (event.getProjectile() == arrow.getBukkitEntity()) {
+ // CraftBukkit end
Projectile.spawnProjectileUsingShoot(
arrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
);
+ } // CraftBukkit
}
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
@@ -222,11 +_,23 @@
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
this.reassessWeaponGoal();
- }
+ // Paper start - shouldBurnInDay API
+ if (compound.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
+ }
+ // Paper end - shouldBurnInDay API
+ }
+ // Paper start - shouldBurnInDay API
+ @Override
+ public void addAdditionalSaveData(final net.minecraft.nbt.CompoundTag nbt) {
+ super.addAdditionalSaveData(nbt);
+ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
+ }
+ // Paper end - shouldBurnInDay API
@Override
- public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
- super.setItemSlot(slot, stack);
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) { // Paper - Fix silent equipment change
+ super.setItemSlot(slot, stack, silent); // Paper - Fix silent equipment change
if (!this.level().isClientSide) {
this.reassessWeaponGoal();
}

View file

@ -1,22 +1,14 @@
--- a/net/minecraft/world/entity/monster/Bogged.java --- a/net/minecraft/world/entity/monster/Bogged.java
+++ b/net/minecraft/world/entity/monster/Bogged.java +++ b/net/minecraft/world/entity/monster/Bogged.java
@@ -27,6 +27,7 @@ @@ -72,7 +_,20 @@
import net.minecraft.world.level.Level; ItemStack itemInHand = player.getItemInHand(hand);
import net.minecraft.world.level.gameevent.GameEvent; if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) {
import net.minecraft.world.level.storage.loot.BuiltInLootTables; if (this.level() instanceof ServerLevel serverLevel) {
+import org.bukkit.craftbukkit.event.CraftEventFactory; - this.shear(serverLevel, SoundSource.PLAYERS, itemInHand);
public class Bogged extends AbstractSkeleton implements Shearable {
@@ -79,7 +80,20 @@
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
- this.shear(worldserver, SoundSource.PLAYERS, itemstack);
+ // CraftBukkit start + // CraftBukkit start
+ // Paper start - custom shear drops + // Paper start - custom shear drops
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(worldserver, itemstack); + java.util.List<ItemStack> drops = this.generateDefaultDrops(serverLevel, itemInHand);
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); + org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemInHand, hand, drops);
+ if (event != null) { + if (event != null) {
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ // this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients // Paper - no longer needed + // this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients // Paper - no longer needed
@ -26,16 +18,16 @@
+ // Paper end - custom shear drops + // Paper end - custom shear drops
+ } + }
+ // CraftBukkit end + // CraftBukkit end
+ this.shear(worldserver, SoundSource.PLAYERS, itemstack, drops); // Paper - custom shear drops + this.shear(serverLevel, SoundSource.PLAYERS, itemInHand, drops); // Paper - custom shear drops
this.gameEvent(GameEvent.SHEAR, player); this.gameEvent(GameEvent.SHEAR, player);
itemstack.hurtAndBreak(1, player, getSlotForHand(hand)); itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
} }
@@ -133,15 +147,36 @@ @@ -125,15 +_,34 @@
@Override @Override
public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears) { public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears) {
+ // Paper start - custom shear drops + // Paper start - custom shear drops
+ this.shear(world, shearedSoundCategory, shears, this.generateDefaultDrops(world, shears)); + this.shear(level, soundSource, shears, this.generateDefaultDrops(level, shears));
+ } + }
+ +
+ @Override + @Override
@ -48,25 +40,24 @@
+ } + }
+ +
+ @Override + @Override
+ public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears, java.util.List<ItemStack> drops) { + public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears, java.util.List<ItemStack> drops) {
+ // Paper end - custom shear drops + // Paper end - custom shear drops
world.playSound((Player) null, (Entity) this, SoundEvents.BOGGED_SHEAR, shearedSoundCategory, 1.0F, 1.0F); level.playSound(null, this, SoundEvents.BOGGED_SHEAR, soundSource, 1.0F, 1.0F);
- this.spawnShearedMushrooms(world, shears); this.spawnShearedMushrooms(level, shears);
+ this.spawnShearedMushrooms(world, shears, drops); // Paper - custom shear drops
this.setSheared(true); this.setSheared(true);
} }
- private void spawnShearedMushrooms(ServerLevel world, ItemStack shears) { - private void spawnShearedMushrooms(ServerLevel level, ItemStack stack) {
- this.dropFromShearingLootTable(world, BuiltInLootTables.BOGGED_SHEAR, shears, (worldserver1, itemstack1) -> { - this.dropFromShearingLootTable(
- level, BuiltInLootTables.BOGGED_SHEAR, stack, (serverLevel, itemStack) -> this.spawnAtLocation(serverLevel, itemStack, this.getBbHeight())
- );
+ // Paper start - custom shear drops + // Paper start - custom shear drops
+ private void spawnShearedMushrooms(ServerLevel world, ItemStack shears, java.util.List<ItemStack> drops) { + private void spawnShearedMushrooms(ServerLevel world, ItemStack shears, java.util.List<ItemStack> drops) {
+ final ServerLevel worldserver1 = world; // Named for lambda consumption + final ServerLevel worldserver1 = world; // Named for lambda consumption
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles + this.forceDrops = true; // Paper - Add missing forceDrop toggles
+ drops.forEach(itemstack1 -> { + drops.forEach(itemstack1 -> this.spawnAtLocation(world, shears, this.getBbHeight()));
+ // Paper end - custom shear drops
this.spawnAtLocation(worldserver1, itemstack1, this.getBbHeight());
});
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles + this.forceDrops = false; // Paper - Add missing forceDrop toggles
+ // Paper end - custom shear drops
} }
@Override @Override

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/monster/CaveSpider.java
+++ b/net/minecraft/world/entity/monster/CaveSpider.java
@@ -38,7 +_,7 @@
}
if (i > 0) {
- ((LivingEntity)source).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this);
+ ((LivingEntity)source).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
}

View file

@ -0,0 +1,114 @@
--- a/net/minecraft/world/entity/monster/Creeper.java
+++ b/net/minecraft/world/entity/monster/Creeper.java
@@ -49,6 +_,7 @@
public int maxSwell = 30;
public int explosionRadius = 3;
private int droppedSkulls;
+ public Entity entityIgniter; // CraftBukkit
public Creeper(EntityType<? extends Creeper> entityType, Level level) {
super(entityType, level);
@@ -121,7 +_,7 @@
}
if (compound.getBoolean("ignited")) {
- this.ignite();
+ this.entityData.set(Creeper.DATA_IS_IGNITED, true); // Paper - set directly to avoid firing event
}
}
@@ -204,8 +_,19 @@
@Override
public void thunderHit(ServerLevel level, LightningBolt lightning) {
super.thunderHit(level, lightning);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
this.entityData.set(DATA_IS_POWERED, true);
}
+ // CraftBukkit start
+ public void setPowered(boolean powered) {
+ this.entityData.set(Creeper.DATA_IS_POWERED, powered);
+ }
+ // CraftBukkit end
+
@Override
protected InteractionResult mobInteract(Player player, InteractionHand hand) {
@@ -215,8 +_,9 @@
this.level()
.playSound(player, this.getX(), this.getY(), this.getZ(), soundEvent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F);
if (!this.level().isClientSide) {
+ this.entityIgniter = player; // CraftBukkit
this.ignite();
- if (!itemInHand.isDamageableItem()) {
+ if (itemInHand.getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper
itemInHand.shrink(1);
} else {
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
@@ -232,18 +_,29 @@
public void explodeCreeper() {
if (this.level() instanceof ServerLevel serverLevel) {
float f = this.isPowered() ? 2.0F : 1.0F;
+ // CraftBukkit start
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false);
+ if (!event.isCancelled()) {
+ // CraftBukkit end
this.dead = true;
- serverLevel.explode(this, this.getX(), this.getY(), this.getZ(), this.explosionRadius * f, Level.ExplosionInteraction.MOB);
+ serverLevel.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(serverLevel, Entity.RemovalReason.KILLED);
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
+ // CraftBukkit start
+ } else {
+ this.swell = 0;
+ this.entityData.set(DATA_IS_IGNITED, Boolean.valueOf(false)); // Paper
+ }
+ // CraftBukkit end
}
}
private void spawnLingeringCloud() {
Collection<MobEffectInstance> activeEffects = this.getActiveEffects();
- if (!activeEffects.isEmpty()) {
+ if (!activeEffects.isEmpty() && !this.level().paperConfig().entities.behavior.disableCreeperLingeringEffect) { // Paper - Option to disable creeper lingering effect
AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
+ areaEffectCloud.setOwner(this); // CraftBukkit
areaEffectCloud.setRadius(2.5F);
areaEffectCloud.setRadiusOnUse(-0.5F);
areaEffectCloud.setWaitTime(10);
@@ -254,16 +_,26 @@
areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance));
}
- this.level().addFreshEntity(areaEffectCloud);
- }
- }
+ this.level().addFreshEntity(areaEffectCloud, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit
+ }
+ }
+ // Paper start - CreeperIgniteEvent
+ public void setIgnited(boolean ignited) {
+ if (isIgnited() != ignited) {
+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited);
+ if (event.callEvent()) {
+ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited());
+ }
+ }
+ }
+ // Paper end - CreeperIgniteEvent
public boolean isIgnited() {
return this.entityData.get(DATA_IS_IGNITED);
}
public void ignite() {
- this.entityData.set(DATA_IS_IGNITED, true);
+ setIgnited(true); // Paper - CreeperIgniteEvent
}
public boolean canDropMobsSkull() {

View file

@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/monster/Drowned.java --- a/net/minecraft/world/entity/monster/Drowned.java
+++ b/net/minecraft/world/entity/monster/Drowned.java +++ b/net/minecraft/world/entity/monster/Drowned.java
@@ -85,7 +85,7 @@ @@ -85,7 +_,7 @@
this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0)); this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0));
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class)); this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (target, world) -> this.okTarget(target))); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entity, level) -> this.okTarget(entity)));
- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
+ if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper - Check drowned for villager aggression config + if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper - Check drowned for villager aggression config
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false));
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/monster/ElderGuardian.java
+++ b/net/minecraft/world/entity/monster/ElderGuardian.java
@@ -65,7 +_,7 @@
super.customServerAiStep(level);
if ((this.tickCount + this.getId()) % 1200 == 0) {
MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2);
- List<ServerPlayer> list = MobEffectUtil.addEffectToPlayersAround(level, this, this.position(), 50.0, mobEffectInstance, 1200);
+ List<ServerPlayer> list = MobEffectUtil.addEffectToPlayersAround(level, this, this.position(), 50.0, mobEffectInstance, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK, (player) -> new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent((org.bukkit.entity.ElderGuardian) this.getBukkitEntity(), player.getBukkitEntity()).callEvent()); // CraftBukkit // Paper - Add ElderGuardianAppearanceEvent
list.forEach(
serverPlayer -> serverPlayer.connection
.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F))

View file

@ -0,0 +1,144 @@
--- a/net/minecraft/world/entity/monster/EnderMan.java
+++ b/net/minecraft/world/entity/monster/EnderMan.java
@@ -116,10 +_,26 @@
}
@Override
- public void setTarget(@Nullable LivingEntity livingEntity) {
- super.setTarget(livingEntity);
+ public void setTarget(@Nullable LivingEntity target) {
+ // CraftBukkit start - fire event
+ this.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true);
+ }
+
+ // Paper start - EndermanEscapeEvent
+ private boolean tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason reason) {
+ return new com.destroystokyo.paper.event.entity.EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent();
+ }
+ // Paper end - EndermanEscapeEvent
+
+ @Override
+ public boolean setTarget(LivingEntity target, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) {
+ if (!super.setTarget(target, reason, fireEvent)) {
+ return false;
+ }
+ target = this.getTarget();
+ // CraftBukkit end
AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED);
- if (livingEntity == null) {
+ if (target == null) {
this.targetChangeTime = 0;
this.entityData.set(DATA_CREEPY, false);
this.entityData.set(DATA_STARED_AT, false);
@@ -131,6 +_,7 @@
attribute.addTransientModifier(SPEED_MODIFIER_ATTACKING);
}
}
+ return true; // CraftBukkit
}
@Override
@@ -212,6 +_,14 @@
}
boolean isBeingStaredBy(Player player) {
+ // Paper start - EndermanAttackPlayerEvent
+ final boolean shouldAttack = isBeingStaredBy0(player);
+ final com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity());
+ event.setCancelled(!shouldAttack);
+ return event.callEvent();
+ }
+ private boolean isBeingStaredBy0(Player player) {
+ // Paper end - EndermanAttackPlayerEvent
return LivingEntity.PLAYER_NOT_WEARING_DISGUISE_ITEM.test(player) && this.isLookingAtMe(player, 0.025, true, false, new double[]{this.getEyeY()});
}
@@ -251,7 +_,7 @@
float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue();
if (lightLevelDependentMagicValue > 0.5F
&& level.canSeeSky(this.blockPosition())
- && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F) {
+ && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent
this.setTarget(null);
this.teleport();
}
@@ -372,11 +_,13 @@
} else {
boolean flag1 = flag && this.hurtWithCleanWater(level, damageSource, (ThrownPotion)damageSource.getDirectEntity(), amount);
+ if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent
for (int i = 0; i < 64; i++) {
if (this.teleport()) {
return true;
}
}
+ } // Paper - EndermanEscapeEvent
return flag1;
}
@@ -400,6 +_,15 @@
public void setBeingStaredAt() {
this.entityData.set(DATA_STARED_AT, true);
}
+ // Paper start
+ public void setCreepy(boolean creepy) {
+ this.entityData.set(EnderMan.DATA_CREEPY, creepy);
+ }
+
+ public void setHasBeenStaredAt(boolean hasBeenStaredAt) {
+ this.entityData.set(EnderMan.DATA_STARED_AT, hasBeenStaredAt);
+ }
+ // Paper end
@Override
public boolean requiresCustomPersistence() {
@@ -460,16 +_,19 @@
int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0);
int floor2 = Mth.floor(this.enderman.getZ() - 1.0 + random.nextDouble() * 2.0);
BlockPos blockPos = new BlockPos(floor, floor1, floor2);
- BlockState blockState = level.getBlockState(blockPos);
+ BlockState blockState = level.getBlockStateIfLoaded(blockPos); // Paper - Prevent endermen from loading chunks
+ if (blockState == null) return; // Paper - Prevent endermen from loading chunks
BlockPos blockPos1 = blockPos.below();
BlockState blockState1 = level.getBlockState(blockPos1);
BlockState carriedBlock = this.enderman.getCarriedBlock();
if (carriedBlock != null) {
carriedBlock = Block.updateFromNeighbourShapes(carriedBlock, this.enderman.level(), blockPos);
if (this.canPlaceBlock(level, blockPos, carriedBlock, blockState, blockState1, blockPos1)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockPos, carriedBlock)) { // CraftBukkit - Place event
level.setBlock(blockPos, carriedBlock, 3);
level.gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this.enderman, carriedBlock));
this.enderman.setCarriedBlock(null);
+ } // CraftBukkit
}
}
}
@@ -567,7 +_,7 @@
} else {
if (this.target != null && !this.enderman.isPassenger()) {
if (this.enderman.isBeingStaredBy((Player)this.target)) {
- if (this.target.distanceToSqr(this.enderman) < 16.0) {
+ if (this.target.distanceToSqr(this.enderman) < 16.0 && this.enderman.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper - EndermanEscapeEvent
this.enderman.teleport();
}
@@ -606,15 +_,18 @@
int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0);
int floor2 = Mth.floor(this.enderman.getZ() - 2.0 + random.nextDouble() * 4.0);
BlockPos blockPos = new BlockPos(floor, floor1, floor2);
- BlockState blockState = level.getBlockState(blockPos);
+ BlockState blockState = level.getBlockStateIfLoaded(blockPos); // Paper - Prevent endermen from loading chunks
+ if (blockState == null) return; // Paper - Prevent endermen from loading chunks
Vec3 vec3 = new Vec3(this.enderman.getBlockX() + 0.5, floor1 + 0.5, this.enderman.getBlockZ() + 0.5);
Vec3 vec31 = new Vec3(floor + 0.5, floor1 + 0.5, floor2 + 0.5);
BlockHitResult blockHitResult = level.clip(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
boolean flag = blockHitResult.getBlockPos().equals(blockPos);
if (blockState.is(BlockTags.ENDERMAN_HOLDABLE) && flag) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockPos, blockState.getFluidState().createLegacyBlock())) { // CraftBukkit - Place event // Paper - fix wrong block state
level.removeBlock(blockPos, false);
level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(this.enderman, blockState));
this.enderman.setCarriedBlock(blockState.getBlock().defaultBlockState());
+ } // CraftBukkit
}
}
}

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/monster/Endermite.java
+++ b/net/minecraft/world/entity/monster/Endermite.java
@@ -121,7 +_,7 @@
}
if (this.life >= 2400) {
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
}

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/monster/Evoker.java
+++ b/net/minecraft/world/entity/monster/Evoker.java
@@ -264,7 +_,7 @@
serverLevel.getScoreboard().addPlayerToTeam(vex.getScoreboardName(), team);
}
- serverLevel.addFreshEntityWithPassengers(vex);
+ serverLevel.addFreshEntityWithPassengers(vex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason
serverLevel.gameEvent(GameEvent.ENTITY_PLACE, blockPos, GameEvent.Context.of(Evoker.this));
}
}

View file

@ -0,0 +1,23 @@
--- a/net/minecraft/world/entity/monster/Ghast.java
+++ b/net/minecraft/world/entity/monster/Ghast.java
@@ -63,6 +_,12 @@
return this.explosionPower;
}
+ // Paper start
+ public void setExplosionPower(int explosionPower) {
+ this.explosionPower = explosionPower;
+ }
+ // Paper end
+
@Override
protected boolean shouldDespawnInPeaceful() {
return true;
@@ -277,6 +_,7 @@
}
LargeFireball largeFireball = new LargeFireball(level, this.ghast, vec3.normalize(), this.ghast.getExplosionPower());
+ largeFireball.bukkitYield = largeFireball.explosionPower = this.ghast.getExplosionPower(); // CraftBukkit - set bukkitYield when setting explosionpower
largeFireball.setPos(this.ghast.getX() + viewVector.x * 4.0, this.ghast.getY(0.5) + 0.5, largeFireball.getZ() + viewVector.z * 4.0);
level.addFreshEntity(largeFireball);
this.chargeTime = -40;

View file

@ -1,19 +1,19 @@
--- a/net/minecraft/world/entity/monster/Guardian.java --- a/net/minecraft/world/entity/monster/Guardian.java
+++ b/net/minecraft/world/entity/monster/Guardian.java +++ b/net/minecraft/world/entity/monster/Guardian.java
@@ -60,6 +60,7 @@ @@ -59,6 +_,7 @@
private boolean clientSideTouchedGround; private boolean clientSideTouchedGround;
@Nullable @Nullable
public RandomStrollGoal randomStrollGoal; public RandomStrollGoal randomStrollGoal;
+ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field + public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field
public Guardian(EntityType<? extends Guardian> type, Level world) { public Guardian(EntityType<? extends Guardian> entityType, Level level) {
super(type, world); super(entityType, level);
@@ -75,7 +76,7 @@ @@ -73,7 +_,7 @@
MoveTowardsRestrictionGoal pathfindergoalmovetowardsrestriction = new MoveTowardsRestrictionGoal(this, 1.0D); protected void registerGoals() {
MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0);
this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); this.randomStrollGoal = new RandomStrollGoal(this, 1.0, 80);
- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); - this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this));
+ this.goalSelector.addGoal(4, this.guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field + this.goalSelector.addGoal(4, this.guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field
this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); this.goalSelector.addGoal(5, moveTowardsRestrictionGoal);
this.goalSelector.addGoal(7, this.randomStrollGoal); this.goalSelector.addGoal(7, this.randomStrollGoal);
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/monster/Husk.java
+++ b/net/minecraft/world/entity/monster/Husk.java
@@ -57,7 +_,7 @@
boolean flag = super.doHurtTarget(level, source);
if (flag && this.getMainHandItem().isEmpty() && source instanceof LivingEntity) {
float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty();
- ((LivingEntity)source).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int)effectiveDifficulty), this);
+ ((LivingEntity)source).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int)effectiveDifficulty), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
return flag;

View file

@ -1,33 +1,26 @@
--- a/net/minecraft/world/entity/monster/Illusioner.java --- a/net/minecraft/world/entity/monster/Illusioner.java
+++ b/net/minecraft/world/entity/monster/Illusioner.java +++ b/net/minecraft/world/entity/monster/Illusioner.java
@@ -184,7 +184,17 @@ @@ -180,9 +_,19 @@
Level world = this.level(); double d2 = target.getZ() - this.getZ();
double squareRoot = Math.sqrt(d * d + d2 * d2);
if (world instanceof ServerLevel worldserver) { if (this.level() instanceof ServerLevel serverLevel) {
+ // Paper start - EntityShootBowEvent + // Paper start - EntityShootBowEvent
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, target.getUsedItemHand(), 0.8F, true); + org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), 0.8F, true);
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ event.getProjectile().remove(); + event.getProjectile().remove();
+ return; + return;
+ } + }
+ +
+ if (event.getProjectile() == entityarrow.getBukkitEntity()) { + if (event.getProjectile() == mobArrow.getBukkitEntity()) {
Projectile.spawnProjectileUsingShoot(entityarrow, worldserver, itemstack1, d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - worldserver.getDifficulty().getId() * 4)); Projectile.spawnProjectileUsingShoot(
mobArrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
);
+ } + }
+ // Paper end - EntityShootBowEvent + // Paper end - EntityShootBowEvent
} }
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
@@ -218,7 +228,7 @@ @@ -229,7 +_,7 @@
@Override
protected void performSpellCasting() {
- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200));
+ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit
}
@Nullable
@@ -269,7 +279,7 @@
@Override @Override
protected void performSpellCasting() { protected void performSpellCasting() {
@ -36,3 +29,12 @@
} }
@Override @Override
@@ -261,7 +_,7 @@
@Override
protected void performSpellCasting() {
- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200));
+ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit
}
@Nullable

View file

@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/monster/Monster.java --- a/net/minecraft/world/entity/monster/Monster.java
+++ b/net/minecraft/world/entity/monster/Monster.java +++ b/net/minecraft/world/entity/monster/Monster.java
@@ -92,7 +92,7 @@ @@ -92,7 +_,7 @@
return false; return false;
} else { } else {
DimensionType dimensionType = world.dimensionType(); DimensionType dimensionType = level.dimensionType();
- int i = dimensionType.monsterSpawnBlockLightLimit(); - int i = dimensionType.monsterSpawnBlockLightLimit();
+ int i = world.getLevel().paperConfig().entities.spawning.monsterSpawnMaxLightLevel.or(dimensionType.monsterSpawnBlockLightLimit()); // Paper - Configurable max block light for monster spawning + int i = world.getLevel().paperConfig().entities.spawning.monsterSpawnMaxLightLevel.or(dimensionType.monsterSpawnBlockLightLimit()); // Paper - Configurable max block light for monster spawning
if (i < 15 && world.getBrightness(LightLayer.BLOCK, pos) > i) { if (i < 15 && level.getBrightness(LightLayer.BLOCK, pos) > i) {
return false; return false;
} else { } else {

View file

@ -0,0 +1,69 @@
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -141,7 +_,7 @@
@Override
public void aiStep() {
- if (this.isAlive() && this.isSunBurnTick()) {
+ if (this.isAlive() && this.shouldBurnInDay && this.isSunBurnTick()) { // Paper - shouldBurnInDay API
this.igniteForSeconds(8.0F);
}
@@ -165,6 +_,14 @@
}
this.setPhantomSize(compound.getInt("Size"));
+ // Paper start
+ if (compound.hasUUID("Paper.SpawningEntity")) {
+ this.spawningEntity = compound.getUUID("Paper.SpawningEntity");
+ }
+ if (compound.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
+ }
+ // Paper end
}
@Override
@@ -174,6 +_,12 @@
compound.putInt("AY", this.anchorPoint.getY());
compound.putInt("AZ", this.anchorPoint.getZ());
compound.putInt("Size", this.getPhantomSize());
+ // Paper start
+ if (this.spawningEntity != null) {
+ compound.putUUID("Paper.SpawningEntity", this.spawningEntity);
+ }
+ compound.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay);
+ // Paper end
}
@Override
@@ -222,6 +_,19 @@
return targetingConditions.test(level, this, entity);
}
+ // Paper start
+ @Nullable
+ java.util.UUID spawningEntity;
+
+ @Nullable
+ public java.util.UUID getSpawningEntity() {
+ return this.spawningEntity;
+ }
+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; }
+ private boolean shouldBurnInDay = true;
+ public boolean shouldBurnInDay() { return shouldBurnInDay; }
+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; }
+ // Paper end
static enum AttackPhase {
CIRCLE,
SWOOP;
@@ -247,7 +_,8 @@
for (Player player : nearbyPlayers) {
if (Phantom.this.canAttack(serverLevel, player, TargetingConditions.DEFAULT)) {
- Phantom.this.setTarget(player);
+ if (!level().paperConfig().entities.behavior.phantomsOnlyAttackInsomniacs || EntitySelector.IS_INSOMNIAC.test(player)) // Paper - Add phantom creative and insomniac controls
+ Phantom.this.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason
return true;
}
}

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/monster/Pillager.java
+++ b/net/minecraft/world/entity/monster/Pillager.java
@@ -214,7 +_,7 @@
this.onItemPickup(entity);
ItemStack itemStack = this.inventory.addItem(item);
if (itemStack.isEmpty()) {
- entity.discard();
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
} else {
item.setCount(itemStack.getCount());
}

View file

@ -0,0 +1,31 @@
--- a/net/minecraft/world/entity/monster/Ravager.java
+++ b/net/minecraft/world/entity/monster/Ravager.java
@@ -151,12 +_,19 @@
BlockState blockState = serverLevel.getBlockState(blockPos);
Block block = blockState.getBlock();
if (block instanceof LeavesBlock) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockPos, blockState.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+ continue;
+ }
+ // CraftBukkit end
flag = serverLevel.destroyBlock(blockPos, true, this) || flag;
}
}
if (!flag && this.onGround()) {
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
this.jumpFromGround();
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
}
}
@@ -257,7 +_,7 @@
double d = entity.getX() - this.getX();
double d1 = entity.getZ() - this.getZ();
double max = Math.max(d * d + d1 * d1, 0.001);
- entity.push(d / max * 4.0, 0.2, d1 / max * 4.0);
+ entity.push(d / max * 4.0, 0.2, d1 / max * 4.0, this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
}
@Override

View file

@ -0,0 +1,46 @@
--- a/net/minecraft/world/entity/monster/Shulker.java
+++ b/net/minecraft/world/entity/monster/Shulker.java
@@ -274,7 +_,13 @@
@Override
public void stopRiding() {
- super.stopRiding();
+ // Paper start - Force entity dismount during teleportation
+ this.stopRiding(false);
+ }
+ @Override
+ public void stopRiding(boolean suppressCancellation) {
+ super.stopRiding(suppressCancellation);
+ // Paper end - Force entity dismount during teleportation
if (this.level().isClientSide) {
this.clientOldAttachPosition = this.blockPosition();
}
@@ -387,6 +_,14 @@
&& this.level().getWorldBorder().isWithinBounds(blockPos1)
&& this.level().noCollision(this, new AABB(blockPos1).deflate(1.0E-6))) {
Direction direction = this.findAttachableSurface(blockPos1);
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityTeleportEvent teleportEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(this, blockPos1.getX(), blockPos1.getY(), blockPos1.getZ());
+ if (teleportEvent.isCancelled() || teleportEvent.getTo() == null) { // Paper
+ return false;
+ } else {
+ blockPos1 = org.bukkit.craftbukkit.util.CraftLocation.toBlockPosition(teleportEvent.getTo());
+ }
+ // CraftBukkit end
if (direction != null) {
this.unRide();
this.setAttachFace(direction);
@@ -453,7 +_,12 @@
if (shulker != null) {
shulker.setVariant(this.getVariant());
shulker.moveTo(vec3);
- this.level().addFreshEntity(shulker);
+ // Paper start - Shulker duplicate event
+ if (!new io.papermc.paper.event.entity.ShulkerDuplicateEvent((org.bukkit.entity.Shulker) shulker.getBukkitEntity(), (org.bukkit.entity.Shulker) this.getBukkitEntity()).callEvent()) {
+ return;
+ }
+ // Paper end - Shulker duplicate event
+ this.level().addFreshEntity(shulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life
}
}
}

View file

@ -0,0 +1,40 @@
--- a/net/minecraft/world/entity/monster/Silverfish.java
+++ b/net/minecraft/world/entity/monster/Silverfish.java
@@ -119,7 +_,7 @@
return true;
} else {
Player nearestPlayer = level.getNearestPlayer(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 5.0, true);
- return nearestPlayer == null;
+ return !(nearestPlayer != null && !nearestPlayer.affectsSpawning) && nearestPlayer == null; // Paper - Affects Spawning API
}
}
@@ -170,9 +_,14 @@
BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection);
BlockState blockState = levelAccessor.getBlockState(blockPos);
if (InfestedBlock.isCompatibleHostBlock(blockState)) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos, InfestedBlock.infestedStateByHost(blockState))) {
+ return;
+ }
+ // CraftBukkit end
levelAccessor.setBlock(blockPos, InfestedBlock.infestedStateByHost(blockState), 3);
this.mob.spawnAnim();
- this.mob.discard();
+ this.mob.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause
}
}
}
@@ -212,6 +_,12 @@
BlockState blockState = level.getBlockState(blockPos1);
Block block = blockState.getBlock();
if (block instanceof InfestedBlock) {
+ // CraftBukkit start
+ BlockState afterState = getServerLevel(level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? blockState.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(level.getBlockState(blockPos1)); // Paper - fix wrong block state
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockPos1, afterState)) { // Paper - fix wrong block state
+ continue;
+ }
+ // CraftBukkit end
if (getServerLevel(level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
level.destroyBlock(blockPos1, true, this.silverfish);
} else {

View file

@ -1,24 +1,23 @@
--- a/net/minecraft/world/entity/monster/Skeleton.java --- a/net/minecraft/world/entity/monster/Skeleton.java
+++ b/net/minecraft/world/entity/monster/Skeleton.java +++ b/net/minecraft/world/entity/monster/Skeleton.java
@@ -94,12 +94,19 @@ @@ -89,11 +_,18 @@
} }
protected void doFreezeConversion() { protected void doFreezeConversion() {
- this.convertTo(EntityType.STRAY, ConversionParams.single(this, true, true), (entityskeletonstray) -> { - this.convertTo(EntityType.STRAY, ConversionParams.single(this, true, true), mob -> {
+ final Stray stray = this.convertTo(EntityType.STRAY, ConversionParams.single(this, true, true), (entityskeletonstray) -> { // Paper - Fix issues with mob conversion; reset conversion time to prevent event spam + final Stray stray = this.convertTo(EntityType.STRAY, ConversionParams.single(this, true, true), (entityskeletonstray) -> { // Paper - Fix issues with mob conversion; reset conversion time to prevent event spam
if (!this.isSilent()) { if (!this.isSilent()) {
this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); this.level().levelEvent(null, 1048, this.blockPosition(), 0);
} }
- }); - });
+ }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN);// CraftBukkit - add spawn and transform reasons + // CraftBukkit start - add spawn and transform reasons
+ + }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN);
+ // Paper start - Fix issues with mob conversion; reset conversion time to prevent event spam + // Paper start - Fix issues with mob conversion; reset conversion time to prevent event spam
+ if (stray == null) { + if (stray == null) {
+ this.conversionTime = 300; + this.conversionTime = 300;
+ } + }
+ // Paper end - Fix issues with mob conversion + // Paper end - Fix issues with mob conversion
+ + // CraftBukkit end - add spawn and transform reasons
} }
@Override @Override

View file

@ -0,0 +1,219 @@
--- a/net/minecraft/world/entity/monster/Slime.java
+++ b/net/minecraft/world/entity/monster/Slime.java
@@ -110,6 +_,7 @@
super.addAdditionalSaveData(compound);
compound.putInt("Size", this.getSize() - 1);
compound.putBoolean("wasOnGround", this.wasOnGround);
+ compound.putBoolean("Paper.canWander", this.canWander); // Paper
}
@Override
@@ -117,6 +_,11 @@
this.setSize(compound.getInt("Size") + 1, false);
super.readAdditionalSaveData(compound);
this.wasOnGround = compound.getBoolean("wasOnGround");
+ // Paper start
+ if (compound.contains("Paper.canWander")) {
+ this.canWander = compound.getBoolean("Paper.canWander");
+ }
+ // Paper end
}
public boolean isTiny() {
@@ -197,6 +_,13 @@
@Override
public void remove(Entity.RemovalReason reason) {
+ // CraftBukkit start - add Bukkit remove cause
+ this.remove(reason, null);
+ }
+
+ @Override
+ public void remove(Entity.RemovalReason entity_removalreason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) {
+ // CraftBukkit end
int size = this.getSize();
if (!this.level().isClientSide && size > 1 && this.isDeadOrDying()) {
float width = this.getDimensions(this.getPose()).width();
@@ -204,18 +_,45 @@
int i = size / 2;
int i1 = 2 + this.random.nextInt(3);
PlayerTeam team = this.getTeam();
+ // CraftBukkit start
+ org.bukkit.event.entity.SlimeSplitEvent event = new org.bukkit.event.entity.SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), i1);
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled() && event.getCount() > 0) {
+ i1 = event.getCount();
+ } else {
+ super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause
+ return;
+ }
+ java.util.List<net.minecraft.world.entity.LivingEntity> slimes = new java.util.ArrayList<>(i1);
+ // CraftBukkit end
for (int i2 = 0; i2 < i1; i2++) {
float f1 = (i2 % 2 - 0.5F) * f;
float f2 = (i2 / 2 - 0.5F) * f;
- this.convertTo(this.getType(), new ConversionParams(ConversionType.SPLIT_ON_DEATH, false, false, team), EntitySpawnReason.TRIGGERED, mob -> {
+ Slime converted = this.convertTo(this.getType(), new ConversionParams(ConversionType.SPLIT_ON_DEATH, false, false, team), EntitySpawnReason.TRIGGERED, (mob) -> { // CraftBukkit
+ mob.aware = this.aware; // Paper - Fix nerfed slime when splitting
mob.setSize(i, true);
mob.moveTo(this.getX() + f1, this.getY() + 0.5, this.getZ() + f2, this.random.nextFloat() * 360.0F, 0.0F);
- });
- }
+ // CraftBukkit start
+ }, null, null);
+ if (converted != null) {
+ slimes.add(converted);
+ }
+ // CraftBukkit end
+ }
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) {
+ super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause
+ return;
+ }
+ for (LivingEntity living : slimes) {
+ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason
+ }
+ // CraftBukkit end
}
- super.remove(reason);
+ super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause
}
@Override
@@ -281,9 +_,13 @@
return checkMobSpawnRules(entityType, level, spawnReason, pos, random);
}
+ // Paper start - Replace rules for Height in Swamp Biome
+ final double maxHeightSwamp = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.maximum;
+ final double minHeightSwamp = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.minimum;
+ // Paper end
if (level.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS)
- && pos.getY() > 50
- && pos.getY() < 70
+ && pos.getY() > minHeightSwamp // Paper - Replace rules for Height in Swamp Biome
+ && pos.getY() < maxHeightSwamp // Paper - Replace rules for Height in Swamp Biome
&& random.nextFloat() < 0.5F
&& random.nextFloat() < level.getMoonBrightness()
&& level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
@@ -295,8 +_,11 @@
}
ChunkPos chunkPos = new ChunkPos(pos);
- boolean flag = WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel)level).getSeed(), 987234911L).nextInt(10) == 0;
- if (random.nextInt(10) == 0 && flag && pos.getY() < 40) {
+ boolean flag = level.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel) level).getSeed(), level.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
+ // Paper start - Replace rules for Height in Slime Chunks
+ final double maxHeightSlimeChunk = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
+ if (random.nextInt(10) == 0 && flag && pos.getY() < maxHeightSlimeChunk) {
+ // Paper end - Replace rules for Height in Slime Chunks
return checkMobSpawnRules(entityType, level, spawnReason, pos, random);
}
}
@@ -367,7 +_,16 @@
@Override
public boolean canUse() {
LivingEntity target = this.slime.getTarget();
- return target != null && this.slime.canAttack(target) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
+
+ // Paper start - Slime pathfinder events
+ if (target == null || !target.isAlive()) {
+ return false;
+ }
+ if (!this.slime.canAttack(target)) {
+ return false;
+ }
+ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity()).callEvent();
+ // Paper end - Slime pathfinder events
}
@Override
@@ -379,7 +_,16 @@
@Override
public boolean canContinueToUse() {
LivingEntity target = this.slime.getTarget();
- return target != null && this.slime.canAttack(target) && --this.growTiredTimer > 0;
+
+ // Paper start - Slime pathfinder events
+ if (target == null || !target.isAlive()) {
+ return false;
+ }
+ if (!this.slime.canAttack(target)) {
+ return false;
+ }
+ return --this.growTiredTimer > 0 && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity()).callEvent();
+ // Paper end - Slime pathfinder events
}
@Override
@@ -398,6 +_,12 @@
slimeMoveControl.setDirection(this.slime.getYRot(), this.slime.isDealsDamage());
}
}
+ // Paper start - Slime pathfinder events; clear timer and target when goal resets
+ public void stop() {
+ this.growTiredTimer = 0;
+ this.slime.setTarget(null);
+ }
+ // Paper end - Slime pathfinder events
}
static class SlimeFloatGoal extends Goal {
@@ -411,7 +_,7 @@
@Override
public boolean canUse() {
- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
+ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - Slime pathfinder events
}
@Override
@@ -441,7 +_,7 @@
@Override
public boolean canUse() {
- return !this.slime.isPassenger();
+ return !this.slime.isPassenger() && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - Slime pathfinder events
}
@Override
@@ -519,7 +_,7 @@
@Override
public boolean canUse() {
- return this.slime.getTarget() == null
+ return this.slime.getTarget() == null && this.slime.canWander // Paper - Slime pathfinder events
&& (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION))
&& this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
}
@@ -529,6 +_,11 @@
if (--this.nextRandomizeTime <= 0) {
this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
this.chosenDegrees = this.slime.getRandom().nextInt(360);
+ // Paper start - Slime pathfinder events
+ com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent event = new com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), this.chosenDegrees);
+ if (!this.slime.canWander || !event.callEvent()) return;
+ this.chosenDegrees = event.getNewYaw();
+ // Paper end - Slime pathfinder events
}
if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) {
@@ -536,4 +_,14 @@
}
}
}
+ // Paper start - Slime pathfinder events
+ private boolean canWander = true;
+ public boolean canWander() {
+ return canWander;
+ }
+
+ public void setWander(boolean canWander) {
+ this.canWander = canWander;
+ }
+ // Paper end - Slime pathfinder events
}

View file

@ -1,21 +1,11 @@
--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java --- a/net/minecraft/world/entity/monster/SpellcasterIllager.java
+++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java +++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java
@@ -17,6 +17,9 @@ @@ -208,6 +_,11 @@
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.level.Level;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
public abstract class SpellcasterIllager extends AbstractIllager {
@@ -159,6 +162,11 @@
public void tick() { public void tick() {
--this.attackWarmupDelay; this.attackWarmupDelay--;
if (this.attackWarmupDelay == 0) { if (this.attackWarmupDelay == 0) {
+ // CraftBukkit start + // CraftBukkit start
+ if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) { + if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) {
+ return; + return;
+ } + }
+ // CraftBukkit end + // CraftBukkit end

View file

@ -1,29 +1,29 @@
--- a/net/minecraft/world/entity/monster/Spider.java --- a/net/minecraft/world/entity/monster/Spider.java
+++ b/net/minecraft/world/entity/monster/Spider.java +++ b/net/minecraft/world/entity/monster/Spider.java
@@ -82,7 +82,7 @@ @@ -79,7 +_,7 @@
public void tick() { public void tick() {
super.tick(); super.tick();
if (!this.level().isClientSide) { if (!this.level().isClientSide) {
- this.setClimbing(this.horizontalCollision); - this.setClimbing(this.horizontalCollision);
+ this.setClimbing(this.horizontalCollision && (this.level().paperConfig().entities.behavior.allowSpiderWorldBorderClimbing || !(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(this.level().getWorldBorder(), this.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) && this.level().getWorldBorder().isInsideCloseToBorder(this, this.getBoundingBox())))); // Paper - Add config option for spider worldborder climbing (Inflate by +EPSILON as collision will just barely place us outside border) + this.setClimbing(this.horizontalCollision && (this.level().paperConfig().entities.behavior.allowSpiderWorldBorderClimbing || !(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(this.level().getWorldBorder(), this.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) && this.level().getWorldBorder().isInsideCloseToBorder(this, this.getBoundingBox())))); // Paper - Add config option for spider worldborder climbing (Inflate by +EPSILON as collision will just barely place us outside border)
} }
} }
@@ -126,7 +126,7 @@
@@ -121,7 +_,7 @@
@Override @Override
public boolean canBeAffected(MobEffectInstance effect) { public boolean canBeAffected(MobEffectInstance potioneffect) {
- return effect.is(MobEffects.POISON) ? false : super.canBeAffected(effect); - return !potioneffect.is(MobEffects.POISON) && super.canBeAffected(potioneffect);
+ return effect.is(MobEffects.POISON) && this.level().paperConfig().entities.mobEffects.spidersImmuneToPoisonEffect ? false : super.canBeAffected(effect); // Paper - Add config for mobs immune to default effects + return potioneffect.is(MobEffects.POISON) && this.level().paperConfig().entities.mobEffects.spidersImmuneToPoisonEffect ? false : super.canBeAffected(potioneffect); // Paper - Add config for mobs immune to default effects
} }
public boolean isClimbing() { public boolean isClimbing() {
@@ -172,7 +172,7 @@ @@ -165,7 +_,7 @@
Holder<MobEffect> holder = entityspider_groupdataspider.effect; if (spawnGroupData instanceof Spider.SpiderEffectsGroupData spiderEffectsGroupData) {
Holder<MobEffect> holder = spiderEffectsGroupData.effect;
if (holder != null) { if (holder != null) {
- this.addEffect(new MobEffectInstance(holder, -1)); - this.addEffect(new MobEffectInstance(holder, -1));
+ this.addEffect(new MobEffectInstance(holder, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, world instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit + this.addEffect(new MobEffectInstance(holder, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, level instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit
} }
} }

View file

@ -1,12 +1,12 @@
--- a/net/minecraft/world/entity/monster/Strider.java --- a/net/minecraft/world/entity/monster/Strider.java
+++ b/net/minecraft/world/entity/monster/Strider.java +++ b/net/minecraft/world/entity/monster/Strider.java
@@ -350,7 +350,14 @@ @@ -309,7 +_,14 @@
|| blockStateOnLegacy.is(BlockTags.STRIDER_WARM_BLOCKS)
boolean flag2 = flag1; || this.getFluidHeight(FluidTags.LAVA) > 0.0;
boolean flag1 = this.getVehicle() instanceof Strider strider && strider.isSuffocating();
- this.setSuffocating(!flag || flag2); - this.setSuffocating(!flag || flag1);
+ // CraftBukkit start + // CraftBukkit start
+ boolean suffocating = !flag || flag2; + boolean suffocating = !flag || flag1;
+ if (suffocating ^ this.isSuffocating()) { + if (suffocating ^ this.isSuffocating()) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { + if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) {
+ this.setSuffocating(suffocating); + this.setSuffocating(suffocating);

View file

@ -1,18 +1,6 @@
--- a/net/minecraft/world/entity/monster/Vex.java --- a/net/minecraft/world/entity/monster/Vex.java
+++ b/net/minecraft/world/entity/monster/Vex.java +++ b/net/minecraft/world/entity/monster/Vex.java
@@ -354,7 +354,10 @@ @@ -296,7 +_,7 @@
for (int i = 0; i < 3; ++i) {
BlockPos blockposition1 = blockposition.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7);
- if (Vex.this.level().isEmptyBlock(blockposition1)) {
+ // Paper start - Don't load chunks
+ final net.minecraft.world.level.block.state.BlockState blockState = Vex.this.level().getBlockStateIfLoaded(blockposition1);
+ if (blockState != null && blockState.isAir()) {
+ // Paper end - Don't load chunks
Vex.this.moveControl.setWantedPosition((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 0.25D);
if (Vex.this.getTarget() == null) {
Vex.this.getLookControl().setLookAt((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 180.0F, 20.0F);
@@ -381,7 +384,7 @@
@Override @Override
public void start() { public void start() {
@ -21,3 +9,15 @@
super.start(); super.start();
} }
} }
@@ -355,7 +_,10 @@
for (int i = 0; i < 3; i++) {
BlockPos blockPos = boundOrigin.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7);
- if (Vex.this.level().isEmptyBlock(blockPos)) {
+ // Paper start - Don't load chunks
+ final net.minecraft.world.level.block.state.BlockState blockState = Vex.this.level().getBlockStateIfLoaded(blockPos);
+ if (blockState != null && blockState.isAir()) {
+ // Paper end - Don't load chunks
Vex.this.moveControl.setWantedPosition(blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5, 0.25);
if (Vex.this.getTarget() == null) {
Vex.this.getLookControl().setLookAt(blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5, 180.0F, 20.0F);

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Vindicator.java --- a/net/minecraft/world/entity/monster/Vindicator.java
+++ b/net/minecraft/world/entity/monster/Vindicator.java +++ b/net/minecraft/world/entity/monster/Vindicator.java
@@ -184,7 +184,7 @@ @@ -184,7 +_,7 @@
static class VindicatorBreakDoorGoal extends BreakDoorGoal { static class VindicatorBreakDoorGoal extends BreakDoorGoal {
public VindicatorBreakDoorGoal(Mob mob) { public VindicatorBreakDoorGoal(Mob mob) {

View file

@ -1,23 +1,22 @@
--- a/net/minecraft/world/entity/monster/Witch.java --- a/net/minecraft/world/entity/monster/Witch.java
+++ b/net/minecraft/world/entity/monster/Witch.java +++ b/net/minecraft/world/entity/monster/Witch.java
@@ -124,9 +124,15 @@ @@ -122,8 +_,14 @@
ItemStack mainHandItem = this.getMainHandItem();
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
PotionContents potioncontents = (PotionContents) itemstack.get(DataComponents.POTION_CONTENTS); PotionContents potionContents = mainHandItem.get(DataComponents.POTION_CONTENTS);
+ // Paper start - WitchConsumePotionEvent + // Paper start - WitchConsumePotionEvent
+ if (itemstack.is(Items.POTION)) { + if (mainHandItem.is(Items.POTION)) {
+ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); + com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack));
+ potioncontents = event.callEvent() ? org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getPotion()).get(DataComponents.POTION_CONTENTS) : null; + potionContents = event.callEvent() ? org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getPotion()).get(DataComponents.POTION_CONTENTS) : null;
+ } + }
+ // Paper end - WitchConsumePotionEvent + // Paper end - WitchConsumePotionEvent
if (mainHandItem.is(Items.POTION) && potionContents != null) {
if (itemstack.is(Items.POTION) && potioncontents != null) { - potionContents.forEachEffect(this::addEffect);
- potioncontents.forEachEffect(this::addEffect); + potionContents.forEachEffect((effect) -> this.addEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK)); // CraftBukkit
+ potioncontents.forEachEffect((effect) -> this.addEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK)); // CraftBukkit
} }
this.gameEvent(GameEvent.DRINK); this.gameEvent(GameEvent.DRINK);
@@ -146,17 +152,7 @@ @@ -147,26 +_,7 @@
} }
if (holder != null) { if (holder != null) {
@ -25,23 +24,30 @@
- this.usingTime = this.getMainHandItem().getUseDuration(this); - this.usingTime = this.getMainHandItem().getUseDuration(this);
- this.setUsingItem(true); - this.setUsingItem(true);
- if (!this.isSilent()) { - if (!this.isSilent()) {
- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); - this.level()
- .playSound(
- null,
- this.getX(),
- this.getY(),
- this.getZ(),
- SoundEvents.WITCH_DRINK,
- this.getSoundSource(),
- 1.0F,
- 0.8F + this.random.nextFloat() * 0.4F
- );
- } - }
- -
- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); - AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED);
- - attribute.removeModifier(SPEED_MODIFIER_DRINKING_ID);
- attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING_ID); - attribute.addTransientModifier(SPEED_MODIFIER_DRINKING);
- attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING);
+ this.setDrinkingPotion(PotionContents.createItemStack(Items.POTION, holder)); // Paper - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out + this.setDrinkingPotion(PotionContents.createItemStack(Items.POTION, holder)); // Paper - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out
} }
} }
@@ -166,7 +162,24 @@ @@ -178,6 +_,23 @@
}
super.aiStep(); super.aiStep();
+ } }
+
+ // Paper start - moved to its own method + // Paper start - moved to its own method
+ public void setDrinkingPotion(ItemStack potion) { + public void setDrinkingPotion(ItemStack potion) {
+ potion = org.bukkit.craftbukkit.event.CraftEventFactory.handleWitchReadyPotionEvent(this, potion); + potion = org.bukkit.craftbukkit.event.CraftEventFactory.handleWitchReadyPotionEvent(this, potion);
@ -56,22 +62,23 @@
+ +
+ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING_ID); + attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING_ID);
+ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING);
} + }
+ // Paper end + // Paper end
+
@Override @Override
public SoundEvent getCelebrateSound() { public SoundEvent getCelebrateSound() {
@@ -231,6 +244,13 @@ return SoundEvents.WITCH_CELEBRATE;
ServerLevel worldserver = (ServerLevel) world; @@ -244,6 +_,13 @@
ItemStack itemstack = PotionContents.createItemStack(Items.SPLASH_POTION, holder);
if (this.level() instanceof ServerLevel serverLevel) {
ItemStack itemStack = PotionContents.createItemStack(Items.SPLASH_POTION, holder);
+ // Paper start - WitchThrowPotionEvent + // Paper start - WitchThrowPotionEvent
+ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); + com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack));
+ if (!event.callEvent()) { + if (!event.callEvent()) {
+ return; + return;
+ } + }
+ itemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); + itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion());
+ // Paper end - WitchThrowPotionEvent + // Paper end - WitchThrowPotionEven
Projectile.spawnProjectileUsingShoot(ThrownPotion::new, worldserver, itemstack, this, d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); Projectile.spawnProjectileUsingShoot(ThrownPotion::new, serverLevel, itemStack, this, d, d1 + squareRoot * 0.2, d2, 0.75F, 8.0F);
} }

View file

@ -0,0 +1,19 @@
--- a/net/minecraft/world/entity/monster/WitherSkeleton.java
+++ b/net/minecraft/world/entity/monster/WitherSkeleton.java
@@ -105,7 +_,7 @@
return false;
} else {
if (source instanceof LivingEntity) {
- ((LivingEntity)source).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this);
+ ((LivingEntity)source).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
return true;
@@ -121,6 +_,6 @@
@Override
public boolean canBeAffected(MobEffectInstance potioneffect) {
- return !potioneffect.is(MobEffects.WITHER) && super.canBeAffected(potioneffect);
+ return potioneffect.is(MobEffects.WITHER) && this.level().paperConfig().entities.mobEffects.immuneToWitherEffect.witherSkeleton ? false : super.canBeAffected(potioneffect); // Paper - Add config for mobs immune to default effects
}
}

View file

@ -0,0 +1,239 @@
--- a/net/minecraft/world/entity/monster/Zombie.java
+++ b/net/minecraft/world/entity/monster/Zombie.java
@@ -68,9 +_,7 @@
public class Zombie extends Monster {
private static final ResourceLocation SPEED_MODIFIER_BABY_ID = ResourceLocation.withDefaultNamespace("baby");
- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(
- SPEED_MODIFIER_BABY_ID, 0.5, AttributeModifier.Operation.ADD_MULTIPLIED_BASE
- );
+ private final AttributeModifier babyModifier = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_ID, this.level().paperConfig().entities.behavior.babyZombieMovementModifier, AttributeModifier.Operation.ADD_MULTIPLIED_BASE); // Paper - Make baby speed configurable
private static final ResourceLocation REINFORCEMENT_CALLER_CHARGE_ID = ResourceLocation.withDefaultNamespace("reinforcement_caller_charge");
private static final AttributeModifier ZOMBIE_REINFORCEMENT_CALLEE_CHARGE = new AttributeModifier(
ResourceLocation.withDefaultNamespace("reinforcement_callee_charge"), -0.05F, AttributeModifier.Operation.ADD_VALUE
@@ -87,13 +_,16 @@
private static final EntityDimensions BABY_DIMENSIONS = EntityType.ZOMBIE.getDimensions().scale(0.5F).withEyeHeight(0.93F);
private static final float BREAK_DOOR_CHANCE = 0.1F;
public static final Predicate<Difficulty> DOOR_BREAKING_PREDICATE = difficulty -> difficulty == Difficulty.HARD;
- private final BreakDoorGoal breakDoorGoal = new BreakDoorGoal(this, DOOR_BREAKING_PREDICATE);
+ private final BreakDoorGoal breakDoorGoal; // Paper - move down
private boolean canBreakDoors;
private int inWaterTime;
public int conversionTime;
+ // private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Paper - remove anti tick skipping measures / wall time
+ private boolean shouldBurnInDay = true; // Paper - Add more Zombie API
public Zombie(EntityType<? extends Zombie> entityType, Level level) {
super(entityType, level);
+ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(level.paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(entityType, level.paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityType.ZOMBIE)))); // Paper - Configurable door breaking difficulty
}
public Zombie(Level level) {
@@ -102,7 +_,7 @@
@Override
protected void registerGoals() {
- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0, 3));
+ if (this.level().paperConfig().entities.behavior.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0, 3)); // Paper - Add zombie targets turtle egg config
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
this.addBehaviourGoals();
@@ -114,7 +_,7 @@
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0));
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
+ if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Spigot
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
}
@@ -168,11 +_,16 @@
@Override
protected int getBaseExperienceReward(ServerLevel level) {
+ final int previousReward = this.xpReward; // Paper - store previous value to reset after calculating XP reward
if (this.isBaby()) {
this.xpReward = (int)(this.xpReward * 2.5);
}
- return super.getBaseExperienceReward(level);
+ // Paper start - store previous value to reset after calculating XP reward
+ int reward = super.getBaseExperienceReward(level);
+ this.xpReward = previousReward;
+ return reward;
+ // Paper end - store previous value to reset after calculating XP reward
}
@Override
@@ -180,9 +_,9 @@
this.getEntityData().set(DATA_BABY_ID, childZombie);
if (this.level() != null && !this.level().isClientSide) {
AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED);
- attribute.removeModifier(SPEED_MODIFIER_BABY_ID);
+ attribute.removeModifier(this.babyModifier.id()); // Paper - Make baby speed configurable
if (childZombie) {
- attribute.addTransientModifier(SPEED_MODIFIER_BABY);
+ attribute.addTransientModifier(this.babyModifier); // Paper - Make baby speed configurable
}
}
}
@@ -221,6 +_,7 @@
}
super.tick();
+ // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
}
@Override
@@ -251,7 +_,14 @@
super.aiStep();
}
+ // Paper start - Add more Zombie API
+ public void stopDrowning() {
+ this.conversionTime = -1;
+ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false);
+ }
+ // Paper end - Add more Zombie API
public void startUnderWaterConversion(int conversionTime) {
+ // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall tim
this.conversionTime = conversionTime;
this.getEntityData().set(DATA_DROWNED_CONVERSION_ID, true);
}
@@ -264,31 +_,49 @@
}
protected void convertToZombieType(EntityType<? extends Zombie> entityType) {
- this.convertTo(
+ Zombie converted = this.convertTo( // CraftBukkit
entityType,
ConversionParams.single(this, true, true),
- zombie -> zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier())
- );
+ // CraftBukkit start
+ zombie -> {zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier());},
+ org.bukkit.event.entity.EntityTransformEvent.TransformReason.DROWNED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DROWNED);
+ if (converted == null) {
+ ((org.bukkit.entity.Zombie) this.getBukkitEntity()).setConversionTime(-1); // CraftBukkit - SPIGOT-5208: End conversion to stop event spam
+ }
+ // CraftBukkit end
}
@VisibleForTesting
public boolean convertVillagerToZombieVillager(ServerLevel level, Villager villager) {
+ // CraftBukkit start
+ return Zombie.convertVillagerToZombieVillager(level, villager, this.blockPosition(), this.isSilent(), org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.INFECTION) != null;
+ }
+
+ public static ZombieVillager convertVillagerToZombieVillager(ServerLevel level, Villager villager, net.minecraft.core.BlockPos blockPosition, boolean silent, org.bukkit.event.entity.EntityTransformEvent.TransformReason transformReason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+ // CraftBukkit end
ZombieVillager zombieVillager = villager.convertTo(EntityType.ZOMBIE_VILLAGER, ConversionParams.single(villager, true, true), mob -> {
mob.finalizeSpawn(level, level.getCurrentDifficultyAt(mob.blockPosition()), EntitySpawnReason.CONVERSION, new Zombie.ZombieGroupData(false, true));
mob.setVillagerData(villager.getVillagerData());
mob.setGossips(villager.getGossips().store(NbtOps.INSTANCE));
mob.setTradeOffers(villager.getOffers().copy());
mob.setVillagerXp(villager.getVillagerXp());
- if (!this.isSilent()) {
- level.levelEvent(null, 1026, this.blockPosition(), 0);
+ // CraftBukkit start
+ if (!silent) {
+ level.levelEvent(null, 1026, blockPosition, 0);
}
+ // CraftBukkit end
});
- return zombieVillager != null;
+ return zombieVillager;
}
public boolean isSunSensitive() {
- return true;
- }
+ return this.shouldBurnInDay; // Paper - Add more Zombie API
+ }
+ // Paper start - Add more Zombie API
+ public void setShouldBurnInDay(boolean shouldBurnInDay) {
+ this.shouldBurnInDay = shouldBurnInDay;
+ }
+ // Paper end - Add more Zombie API
@Override
public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
@@ -321,13 +_,13 @@
if (SpawnPlacements.isSpawnPositionOk(type, level, blockPos)
&& SpawnPlacements.checkSpawnRules(type, level, EntitySpawnReason.REINFORCEMENT, blockPos, level.random)) {
zombie.setPos(i1, i2, i3);
- if (!level.hasNearbyAlivePlayer(i1, i2, i3, 7.0)
+ if (!level.hasNearbyAlivePlayerThatAffectsSpawning(i1, i2, i3, 7.0) // Paper - affects spawning api
&& level.isUnobstructed(zombie)
&& level.noCollision(zombie)
&& (zombie.canSpawnInLiquids() || !level.containsAnyLiquid(zombie.getBoundingBox()))) {
- zombie.setTarget(target);
+ zombie.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit
zombie.finalizeSpawn(level, level.getCurrentDifficultyAt(zombie.blockPosition()), EntitySpawnReason.REINFORCEMENT, null);
- level.addFreshEntityWithPassengers(zombie);
+ level.addFreshEntityWithPassengers(zombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit
AttributeInstance attribute = this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE);
AttributeModifier modifier = attribute.getModifier(REINFORCEMENT_CALLER_CHARGE_ID);
double d = modifier != null ? modifier.amount() : 0.0;
@@ -352,7 +_,14 @@
if (flag) {
float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty();
if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < effectiveDifficulty * 0.3F) {
- source.igniteForSeconds(2 * (int)effectiveDifficulty);
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityCombustByEntityEvent event = new org.bukkit.event.entity.EntityCombustByEntityEvent(this.getBukkitEntity(), source.getBukkitEntity(), (float) (2 * (int)effectiveDifficulty));
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ source.igniteForSeconds(event.getDuration(), false);
+ }
+ // CraftBukkit end
}
}
@@ -412,6 +_,7 @@
compound.putBoolean("CanBreakDoors", this.canBreakDoors());
compound.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1);
compound.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1);
+ compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper - Add more Zombie API
}
@Override
@@ -423,12 +_,18 @@
if (compound.contains("DrownedConversionTime", 99) && compound.getInt("DrownedConversionTime") > -1) {
this.startUnderWaterConversion(compound.getInt("DrownedConversionTime"));
}
+ // Paper start - Add more Zombie API
+ if (compound.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
+ }
+ // Paper end - Add more Zombie API
}
@Override
public boolean killedEntity(ServerLevel level, LivingEntity entity) {
boolean flag = super.killedEntity(level, entity);
- if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager villager) {
+ final double fallbackChance = level.getDifficulty() == Difficulty.HARD ? 100d : level.getDifficulty() == Difficulty.NORMAL ? 50d : 0d; // Paper - Configurable chance of villager zombie infection
+ if (this.random.nextDouble() * 100 < level.paperConfig().entities.behavior.zombieVillagerInfectionChance.or(fallbackChance) && entity instanceof Villager villager) { // Paper - Configurable chance of villager zombie infection
if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
return flag;
}
@@ -465,7 +_,7 @@
spawnGroupData = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
float specialMultiplier = difficulty.getSpecialMultiplier();
if (spawnReason != EntitySpawnReason.CONVERSION) {
- this.setCanPickUpLoot(random.nextFloat() < 0.55F * specialMultiplier);
+ this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.zombies || random.nextFloat() < 0.55F * specialMultiplier); // Paper - Add world settings for mobs picking up loot
}
if (spawnGroupData == null) {
@@ -492,7 +_,7 @@
chicken1.finalizeSpawn(level, difficulty, EntitySpawnReason.JOCKEY, null);
chicken1.setChickenJockey(true);
this.startRiding(chicken1);
- level.addFreshEntity(chicken1);
+ level.addFreshEntity(chicken1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit
}
}
}

View file

@ -0,0 +1,107 @@
--- a/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -33,6 +_,7 @@
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.entity.ai.village.ReputationEventType;
+import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerData;
import net.minecraft.world.entity.npc.VillagerDataHolder;
import net.minecraft.world.entity.npc.VillagerProfession;
@@ -68,6 +_,7 @@
@Nullable
private MerchantOffers tradeOffers;
private int villagerXp;
+ private int lastTick = net.minecraft.server.MinecraftServer.currentTick; // CraftBukkit - add field
public ZombieVillager(EntityType<? extends ZombieVillager> entityType, Level level) {
super(entityType, level);
@@ -140,6 +_,11 @@
public void tick() {
if (!this.level().isClientSide && this.isAlive() && this.isConverting()) {
int conversionProgress = this.getConversionProgress();
+ // CraftBukkit start - Use wall time instead of ticks for villager conversion
+ // TODO: WE WANT TO REMOVE THIS? I THOUGHT WE REMOVED IT.
+ int elapsedTicks = net.minecraft.server.MinecraftServer.currentTick - this.lastTick;
+ conversionProgress *= elapsedTicks;
+ // CraftBukkit end
this.villagerConversionTime -= conversionProgress;
if (this.villagerConversionTime <= 0) {
this.finishConversion((ServerLevel)this.level());
@@ -147,6 +_,7 @@
}
super.tick();
+ this.lastTick = net.minecraft.server.MinecraftServer.currentTick; // CraftBukkit
}
@Override
@@ -183,12 +_,20 @@
}
public void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) {
+ // Paper start - missing entity behaviour api - converting without entity event
+ this.startConverting(conversionStarter, villagerConversionTime, true);
+ }
+
+ public void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime, boolean broadcastEntityEvent) {
+ // Paper end - missing entity behaviour api - converting without entity event
this.conversionStarter = conversionStarter;
this.villagerConversionTime = villagerConversionTime;
this.getEntityData().set(DATA_CONVERTING_ID, true);
- this.removeEffect(MobEffects.WEAKNESS);
- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)));
- this.level().broadcastEntityEvent(this, (byte)16);
+ // CraftBukkit start
+ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION);
+ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION);
+ // CraftBukkit end
+ if (broadcastEntityEvent) this.level().broadcastEntityEvent(this, (byte)16); // Paper - missing entity behaviour api - converting without entity event
}
@Override
@@ -213,7 +_,7 @@
}
private void finishConversion(ServerLevel serverLevel) {
- this.convertTo(
+ Villager converted = this.convertTo( // CraftBukkit
EntityType.VILLAGER,
ConversionParams.single(this, false, false),
villager -> {
@@ -223,6 +_,7 @@
SlotAccess slot = villager.getSlot(equipmentSlot.getIndex() + 300);
slot.set(this.getItemBySlot(equipmentSlot));
}
+ this.forceDrops = false; // CraftBukkit
villager.setVillagerData(this.getVillagerData());
if (this.gossips != null) {
@@ -237,19 +_,24 @@
villager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(villager.blockPosition()), EntitySpawnReason.CONVERSION, null);
villager.refreshBrain(serverLevel);
if (this.conversionStarter != null) {
- Player playerByUuid = serverLevel.getPlayerByUUID(this.conversionStarter);
+ Player playerByUuid = serverLevel.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check global player list where appropriate
if (playerByUuid instanceof ServerPlayer) {
CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer)playerByUuid, this, villager);
serverLevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, playerByUuid, villager);
}
}
- villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0));
+ villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit
if (!this.isSilent()) {
serverLevel.levelEvent(null, 1027, this.blockPosition(), 0);
}
- }
+ }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.CURED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CURED // CraftBukkit
);
+ // CraftBukkit start
+ if (converted == null) {
+ ((org.bukkit.entity.ZombieVillager) this.getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam
+ }
+ // CraftBukkit end
}
@VisibleForTesting

View file

@ -0,0 +1,62 @@
--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java
+++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java
@@ -56,6 +_,7 @@
private static final int ALERT_RANGE_Y = 10;
private static final UniformInt ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6);
private int ticksUntilNextAlert;
+ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper - fix PigZombieAngerEvent cancellation
public ZombifiedPiglin(EntityType<? extends ZombifiedPiglin> entityType, Level level) {
super(entityType, level);
@@ -71,7 +_,7 @@
protected void addBehaviourGoals() {
this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0, false));
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0));
- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
+ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = (new HurtByTargetGoal(this)).setAlertOthers()); // Paper - fix PigZombieAngerEvent cancellation
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true));
}
@@ -148,7 +_,7 @@
.filter(zombifiedPiglin -> zombifiedPiglin != this)
.filter(zombifiedPiglin -> zombifiedPiglin.getTarget() == null)
.filter(zombifiedPiglin -> !zombifiedPiglin.isAlliedTo(this.getTarget()))
- .forEach(zombifiedPiglin -> zombifiedPiglin.setTarget(this.getTarget()));
+ .forEach(zombifiedPiglin -> zombifiedPiglin.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true)); // CraftBukkit
}
private void playAngerSound() {
@@ -156,7 +_,7 @@
}
@Override
- public void setTarget(@Nullable LivingEntity livingEntity) {
+ public boolean setTarget(@Nullable LivingEntity livingEntity, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature
if (this.getTarget() == null && livingEntity != null) {
this.playFirstAngerSoundIn = FIRST_ANGER_SOUND_DELAY.sample(this.random);
this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random);
@@ -166,12 +_,22 @@
this.setLastHurtByPlayer((Player)livingEntity);
}
- super.setTarget(livingEntity);
+ return super.setTarget(livingEntity, reason, fireEvent); // CraftBukkit
}
@Override
public void startPersistentAngerTimer() {
- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random));
+ // CraftBukkit start
+ net.minecraft.world.entity.Entity entity = ((ServerLevel) this.level()).getEntity(this.getPersistentAngerTarget());
+ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random));
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ this.setPersistentAngerTarget(null);
+ pathfinderGoalHurtByTarget.stop(); // Paper - fix PigZombieAngerEvent cancellation
+ return;
+ }
+ this.setRemainingPersistentAngerTime(event.getNewAnger());
+ // CraftBukkit end
}
public static boolean checkZombifiedPiglinSpawnRules(

View file

@ -1,74 +0,0 @@
--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -97,9 +97,15 @@
abstract SoundEvent getStepSound();
+ // Paper start - shouldBurnInDay API
+ private boolean shouldBurnInDay = true;
+ public boolean shouldBurnInDay() { return shouldBurnInDay; }
+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; }
+ // Paper end - shouldBurnInDay API
+
@Override
public void aiStep() {
- boolean flag = this.isSunBurnTick();
+ boolean flag = shouldBurnInDay && this.isSunBurnTick(); // Paper - shouldBurnInDay API
if (flag) {
ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
@@ -152,7 +158,7 @@
this.populateDefaultEquipmentSlots(randomsource, difficulty);
this.populateDefaultEquipmentEnchantments(world, randomsource, difficulty);
this.reassessWeaponGoal();
- this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier());
+ this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
LocalDate localdate = LocalDate.now();
int i = localdate.get(ChronoField.DAY_OF_MONTH);
@@ -209,7 +215,17 @@
Level world = this.level();
if (world instanceof ServerLevel worldserver) {
- Projectile.spawnProjectileUsingShoot(entityarrow, worldserver, itemstack1, d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - worldserver.getDifficulty().getId() * 4));
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - improve entity shhot bow event - add arrow stack to event
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;
+ }
+
+ if (event.getProjectile() == entityarrow.getBukkitEntity()) {
+ Projectile.spawnProjectileUsingShoot(entityarrow, worldserver, itemstack1, d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - worldserver.getDifficulty().getId() * 4));
+ }
+ // CraftBukkit end
}
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
@@ -233,11 +249,24 @@
public void readAdditionalSaveData(CompoundTag nbt) {
super.readAdditionalSaveData(nbt);
this.reassessWeaponGoal();
+ // Paper start - shouldBurnInDay API
+ if (nbt.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay");
+ }
+ // Paper end - shouldBurnInDay API
}
+ // Paper start - shouldBurnInDay API
@Override
- public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
- super.setItemSlot(slot, stack);
+ public void addAdditionalSaveData(CompoundTag nbt) {
+ super.addAdditionalSaveData(nbt);
+ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
+ }
+ // Paper end - shouldBurnInDay API
+
+ @Override
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) { // Paper - Fix silent equipment change
+ super.setItemSlot(slot, stack, silent); // Paper - Fix silent equipment change
if (!this.level().isClientSide) {
this.reassessWeaponGoal();
}

View file

@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/monster/CaveSpider.java
+++ b/net/minecraft/world/entity/monster/CaveSpider.java
@@ -40,7 +40,7 @@
}
if (b0 > 0) {
- ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this);
+ ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
}

View file

@ -1,132 +0,0 @@
--- a/net/minecraft/world/entity/monster/Creeper.java
+++ b/net/minecraft/world/entity/monster/Creeper.java
@@ -42,6 +42,13 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEvent;
+// CraftBukkit start;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.entity.ExplosionPrimeEvent;
+// CraftBukkit end
+
public class Creeper extends Monster {
private static final EntityDataAccessor<Integer> DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT);
@@ -52,6 +59,7 @@
public int maxSwell = 30;
public int explosionRadius = 3;
private int droppedSkulls;
+ public Entity entityIgniter; // CraftBukkit
public Creeper(EntityType<? extends Creeper> type, Level world) {
super(type, world);
@@ -125,7 +133,7 @@
}
if (nbt.getBoolean("ignited")) {
- this.ignite();
+ this.entityData.set(Creeper.DATA_IS_IGNITED, true); // Paper - set directly to avoid firing event
}
}
@@ -214,9 +222,20 @@
@Override
public void thunderHit(ServerLevel world, LightningBolt lightning) {
super.thunderHit(world, lightning);
+ // CraftBukkit start
+ if (CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
this.entityData.set(Creeper.DATA_IS_POWERED, true);
}
+ // CraftBukkit start
+ public void setPowered(boolean powered) {
+ this.entityData.set(Creeper.DATA_IS_POWERED, powered);
+ }
+ // CraftBukkit end
+
@Override
protected InteractionResult mobInteract(Player player, InteractionHand hand) {
ItemStack itemstack = player.getItemInHand(hand);
@@ -226,8 +245,9 @@
this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F);
if (!this.level().isClientSide) {
+ this.entityIgniter = player; // CraftBukkit
this.ignite();
- if (!itemstack.isDamageableItem()) {
+ if (itemstack.getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper
itemstack.shrink(1);
} else {
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
@@ -246,11 +266,21 @@
if (world instanceof ServerLevel worldserver) {
float f = this.isPowered() ? 2.0F : 1.0F;
+ // CraftBukkit start
+ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false);
+ if (!event.isCancelled()) {
+ // CraftBukkit end
this.dead = true;
- worldserver.explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, Level.ExplosionInteraction.MOB);
+ worldserver.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(worldserver, Entity.RemovalReason.KILLED);
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
+ // CraftBukkit start
+ } else {
+ this.swell = 0;
+ this.entityData.set(DATA_IS_IGNITED, Boolean.valueOf(false)); // Paper
+ }
+ // CraftBukkit end
}
}
@@ -258,9 +288,10 @@
private void spawnLingeringCloud() {
Collection<MobEffectInstance> collection = this.getActiveEffects();
- if (!collection.isEmpty()) {
+ if (!collection.isEmpty() && !this.level().paperConfig().entities.behavior.disableCreeperLingeringEffect) { // Paper - Option to disable creeper lingering effect
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
+ entityareaeffectcloud.setOwner(this); // CraftBukkit
entityareaeffectcloud.setRadius(2.5F);
entityareaeffectcloud.setRadiusOnUse(-0.5F);
entityareaeffectcloud.setWaitTime(10);
@@ -274,7 +305,7 @@
entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect));
}
- this.level().addFreshEntity(entityareaeffectcloud);
+ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit
}
}
@@ -284,9 +315,20 @@
}
public void ignite() {
- this.entityData.set(Creeper.DATA_IS_IGNITED, true);
+ // Paper start - CreeperIgniteEvent
+ setIgnited(true);
}
+ public void setIgnited(boolean ignited) {
+ if (isIgnited() != ignited) {
+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited);
+ if (event.callEvent()) {
+ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited());
+ }
+ }
+ // Paper end - CreeperIgniteEvent
+ }
+
public boolean canDropMobsSkull() {
return this.isPowered() && this.droppedSkulls < 1;
}

View file

@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/monster/ElderGuardian.java
+++ b/net/minecraft/world/entity/monster/ElderGuardian.java
@@ -67,7 +67,7 @@
super.customServerAiStep(world);
if ((this.tickCount + this.getId()) % 1200 == 0) {
MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2);
- List<ServerPlayer> list = MobEffectUtil.addEffectToPlayersAround(world, this, this.position(), 50.0D, mobeffect, 1200);
+ List<ServerPlayer> list = MobEffectUtil.addEffectToPlayersAround(world, this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK, (player) -> new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent((org.bukkit.entity.ElderGuardian) this.getBukkitEntity(), player.getBukkitEntity()).callEvent()); // CraftBukkit // Paper - Add ElderGuardianAppearanceEvent
list.forEach((entityplayer) -> {
entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F));

View file

@ -1,157 +0,0 @@
--- a/net/minecraft/world/entity/monster/EnderMan.java
+++ b/net/minecraft/world/entity/monster/EnderMan.java
@@ -68,6 +68,10 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
+// CraftBukkit start;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityTargetEvent;
+// CraftBukkit end
public class EnderMan extends Monster implements NeutralMob {
@@ -112,10 +116,26 @@
@Override
public void setTarget(@Nullable LivingEntity target) {
- super.setTarget(target);
+ // CraftBukkit start - fire event
+ this.setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true);
+ }
+
+ // Paper start - EndermanEscapeEvent
+ private boolean tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason reason) {
+ return new com.destroystokyo.paper.event.entity.EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent();
+ }
+ // Paper end - EndermanEscapeEvent
+
+ @Override
+ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) {
+ if (!super.setTarget(entityliving, reason, fireEvent)) {
+ return false;
+ }
+ entityliving = this.getTarget();
+ // CraftBukkit end
AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
- if (target == null) {
+ if (entityliving == null) {
this.targetChangeTime = 0;
this.entityData.set(EnderMan.DATA_CREEPY, false);
this.entityData.set(EnderMan.DATA_STARED_AT, false);
@@ -127,6 +147,7 @@
attributemodifiable.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING);
}
}
+ return true;
}
@@ -212,6 +233,14 @@
}
boolean isBeingStaredBy(Player player) {
+ // Paper start - EndermanAttackPlayerEvent
+ final boolean shouldAttack = isBeingStaredBy0(player);
+ final com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity());
+ event.setCancelled(!shouldAttack);
+ return event.callEvent();
+ }
+ private boolean isBeingStaredBy0(Player player) {
+ // Paper end - EndermanAttackPlayerEvent
return !LivingEntity.PLAYER_NOT_WEARING_DISGUISE_ITEM.test(player) ? false : this.isLookingAtMe(player, 0.025D, true, false, new double[]{this.getEyeY()});
}
@@ -241,7 +270,7 @@
if (world.isDay() && this.tickCount >= this.targetChangeTime + 600) {
float f = this.getLightLevelDependentMagicValue();
- if (f > 0.5F && world.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) {
+ if (f > 0.5F && world.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent
this.setTarget((LivingEntity) null);
this.teleport();
}
@@ -367,11 +396,13 @@
} else {
flag1 = flag && this.hurtWithCleanWater(world, source, (ThrownPotion) source.getDirectEntity(), amount);
+ if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent
for (int i = 0; i < 64; ++i) {
if (this.teleport()) {
return true;
}
}
+ } // Paper - EndermanEscapeEvent
return flag1;
}
@@ -397,6 +428,16 @@
this.entityData.set(EnderMan.DATA_STARED_AT, true);
}
+ // Paper start
+ public void setCreepy(boolean creepy) {
+ this.entityData.set(EnderMan.DATA_CREEPY, creepy);
+ }
+
+ public void setHasBeenStaredAt(boolean hasBeenStaredAt) {
+ this.entityData.set(EnderMan.DATA_STARED_AT, hasBeenStaredAt);
+ }
+ // Paper end
+
@Override
public boolean requiresCustomPersistence() {
return super.requiresCustomPersistence() || this.getCarriedBlock() != null;
@@ -457,7 +498,8 @@
int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D);
int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D);
BlockPos blockposition = new BlockPos(i, j, k);
- BlockState iblockdata = world.getBlockState(blockposition);
+ BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper - Prevent endermen from loading chunks
+ if (iblockdata == null) return; // Paper - Prevent endermen from loading chunks
BlockPos blockposition1 = blockposition.below();
BlockState iblockdata1 = world.getBlockState(blockposition1);
BlockState iblockdata2 = this.enderman.getCarriedBlock();
@@ -465,9 +507,11 @@
if (iblockdata2 != null) {
iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition);
if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) {
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event
world.setBlock(blockposition, iblockdata2, 3);
world.gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2));
this.enderman.setCarriedBlock((BlockState) null);
+ } // CraftBukkit
}
}
@@ -499,16 +543,19 @@
int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D);
int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D);
BlockPos blockposition = new BlockPos(i, j, k);
- BlockState iblockdata = world.getBlockState(blockposition);
+ BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper - Prevent endermen from loading chunks
+ if (iblockdata == null) return; // Paper - Prevent endermen from loading chunks
Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D);
Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D);
BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition);
if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) {
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // CraftBukkit - Place event // Paper - fix wrong block state
world.removeBlock(blockposition, false);
world.gameEvent((Holder) GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata));
this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState());
+ } // CraftBukkit
}
}
@@ -592,7 +639,7 @@
} else {
if (this.target != null && !this.enderman.isPassenger()) {
if (this.enderman.isBeingStaredBy((Player) this.target)) {
- if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) {
+ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.enderman.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper - EndermanEscapeEvent
this.enderman.teleport();
}

View file

@ -1,21 +0,0 @@
--- a/net/minecraft/world/entity/monster/Endermite.java
+++ b/net/minecraft/world/entity/monster/Endermite.java
@@ -24,6 +24,9 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
+// CraftBukkit start
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
public class Endermite extends Monster {
@@ -113,7 +116,7 @@
}
if (this.life >= 2400) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}

View file

@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/monster/Evoker.java
+++ b/net/minecraft/world/entity/monster/Evoker.java
@@ -212,7 +212,7 @@
worldserver.getScoreboard().addPlayerToTeam(entityvex.getScoreboardName(), scoreboardteam);
}
- worldserver.addFreshEntityWithPassengers(entityvex);
+ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason
worldserver.gameEvent((Holder) GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of((Entity) Evoker.this));
}
}

View file

@ -1,25 +0,0 @@
--- a/net/minecraft/world/entity/monster/Ghast.java
+++ b/net/minecraft/world/entity/monster/Ghast.java
@@ -64,7 +64,13 @@
public int getExplosionPower() {
return this.explosionPower;
+ }
+
+ // Paper start
+ public void setExplosionPower(int explosionPower) {
+ this.explosionPower = explosionPower;
}
+ // Paper end
@Override
protected boolean shouldDespawnInPeaceful() {
@@ -333,6 +339,8 @@
LargeFireball entitylargefireball = new LargeFireball(world, this.ghast, vec3d1.normalize(), this.ghast.getExplosionPower());
+ // CraftBukkit - set bukkitYield when setting explosionpower
+ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower();
entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D);
world.addFreshEntity(entitylargefireball);
this.chargeTime = -40;

View file

@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/monster/Husk.java
+++ b/net/minecraft/world/entity/monster/Husk.java
@@ -59,7 +59,7 @@
if (flag && this.getMainHandItem().isEmpty() && target instanceof LivingEntity) {
float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty();
- ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this);
+ ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
return flag;

View file

@ -1,78 +0,0 @@
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -139,7 +139,7 @@
@Override
public void aiStep() {
- if (this.isAlive() && this.isSunBurnTick()) {
+ if (this.isAlive() && this.shouldBurnInDay && this.isSunBurnTick()) { // Paper - shouldBurnInDay API
this.igniteForSeconds(8.0F);
}
@@ -161,6 +161,14 @@
}
this.setPhantomSize(nbt.getInt("Size"));
+ // Paper start
+ if (nbt.hasUUID("Paper.SpawningEntity")) {
+ this.spawningEntity = nbt.getUUID("Paper.SpawningEntity");
+ }
+ if (nbt.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay");
+ }
+ // Paper end
}
@Override
@@ -170,6 +178,12 @@
nbt.putInt("AY", this.anchorPoint.getY());
nbt.putInt("AZ", this.anchorPoint.getZ());
nbt.putInt("Size", this.getPhantomSize());
+ // Paper start
+ if (this.spawningEntity != null) {
+ nbt.putUUID("Paper.SpawningEntity", this.spawningEntity);
+ }
+ nbt.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay);
+ // Paper end
}
@Override
@@ -219,6 +233,20 @@
return predicate.test(world, this, target);
}
+ // Paper start
+ @Nullable
+ java.util.UUID spawningEntity;
+
+ @Nullable
+ public java.util.UUID getSpawningEntity() {
+ return this.spawningEntity;
+ }
+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; }
+ private boolean shouldBurnInDay = true;
+ public boolean shouldBurnInDay() { return shouldBurnInDay; }
+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; }
+ // Paper end
+
private static enum AttackPhase {
CIRCLE, SWOOP;
@@ -522,14 +550,15 @@
List<Player> list = worldserver.getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D));
if (!list.isEmpty()) {
- list.sort(Comparator.comparing(Entity::getY).reversed());
+ list.sort(Comparator.comparing((Entity e) -> { return e.getY(); }).reversed()); // CraftBukkit - decompile error
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Player entityhuman = (Player) iterator.next();
if (Phantom.this.canAttack(worldserver, entityhuman, TargetingConditions.DEFAULT)) {
- Phantom.this.setTarget(entityhuman);
+ if (!level().paperConfig().entities.behavior.phantomsOnlyAttackInsomniacs || EntitySelector.IS_INSOMNIAC.test(entityhuman)) // Paper - Add phantom creative and insomniac controls
+ Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason
return true;
}
}

View file

@ -1,21 +0,0 @@
--- a/net/minecraft/world/entity/monster/Pillager.java
+++ b/net/minecraft/world/entity/monster/Pillager.java
@@ -52,6 +52,9 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.ServerLevelAccessor;
+// CraftBukkit start
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
public class Pillager extends AbstractIllager implements CrossbowAttackMob, InventoryCarrier {
@@ -206,7 +209,7 @@
ItemStack itemstack1 = this.inventory.addItem(itemstack);
if (itemstack1.isEmpty()) {
- itemEntity.discard();
+ itemEntity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
} else {
itemstack.setCount(itemstack1.getCount());
}

View file

@ -1,41 +0,0 @@
--- a/net/minecraft/world/entity/monster/Ravager.java
+++ b/net/minecraft/world/entity/monster/Ravager.java
@@ -42,6 +42,9 @@
import net.minecraft.world.level.pathfinder.PathType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
public class Ravager extends Raider {
@@ -158,12 +161,19 @@
Block block = iblockdata.getBlock();
if (block instanceof LeavesBlock) {
+ // CraftBukkit start
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+ continue;
+ }
+ // CraftBukkit end
flag = worldserver.destroyBlock(blockposition, true, this) || flag;
}
}
if (!flag && this.onGround()) {
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
this.jumpFromGround();
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
}
}
}
@@ -281,7 +291,7 @@
double d1 = entity.getZ() - this.getZ();
double d2 = Math.max(d0 * d0 + d1 * d1, 0.001D);
- entity.push(d0 / d2 * 4.0D, 0.2D, d1 / d2 * 4.0D);
+ entity.push(d0 / d2 * 4.0D, 0.2D, d1 / d2 * 4.0D, this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
}
@Override

View file

@ -1,59 +0,0 @@
--- a/net/minecraft/world/entity/monster/Shulker.java
+++ b/net/minecraft/world/entity/monster/Shulker.java
@@ -59,6 +59,12 @@
import net.minecraft.world.phys.Vec3;
import org.joml.Vector3f;
+// CraftBukkit start
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.entity.EntityTeleportEvent;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
+
public class Shulker extends AbstractGolem implements VariantHolder<Optional<DyeColor>>, Enemy {
private static final ResourceLocation COVERED_ARMOR_MODIFIER_ID = ResourceLocation.withDefaultNamespace("covered");
@@ -283,7 +289,13 @@
@Override
public void stopRiding() {
- super.stopRiding();
+ // Paper start - Force entity dismount during teleportation
+ this.stopRiding(false);
+ }
+ @Override
+ public void stopRiding(boolean suppressCancellation) {
+ super.stopRiding(suppressCancellation);
+ // Paper end - Force entity dismount during teleportation
if (this.level().isClientSide) {
this.clientOldAttachPosition = this.blockPosition();
}
@@ -402,6 +414,14 @@
Direction enumdirection = this.findAttachableSurface(blockposition1);
if (enumdirection != null) {
+ // CraftBukkit start
+ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ());
+ if (teleportEvent.isCancelled() || teleportEvent.getTo() == null) { // Paper
+ return false;
+ } else {
+ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo());
+ }
+ // CraftBukkit end
this.unRide();
this.setAttachFace(enumdirection);
this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F);
@@ -472,7 +492,12 @@
if (entityshulker != null) {
entityshulker.setVariant(this.getVariant());
entityshulker.moveTo(vec3d);
- this.level().addFreshEntity(entityshulker);
+ // Paper start - Shulker duplicate event
+ if (!new io.papermc.paper.event.entity.ShulkerDuplicateEvent((org.bukkit.entity.Shulker) entityshulker.getBukkitEntity(), (org.bukkit.entity.Shulker) this.getBukkitEntity()).callEvent()) {
+ return;
+ }
+ // Paper end - Shulker duplicate event
+ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life
}
}

View file

@ -1,51 +0,0 @@
--- a/net/minecraft/world/entity/monster/Silverfish.java
+++ b/net/minecraft/world/entity/monster/Silverfish.java
@@ -30,6 +30,10 @@
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.InfestedBlock;
import net.minecraft.world.level.block.state.BlockState;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
public class Silverfish extends Monster {
@@ -119,7 +123,7 @@
} else {
Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true);
- return entityhuman == null;
+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API
}
}
@@ -160,6 +164,12 @@
Block block = iblockdata.getBlock();
if (block instanceof InfestedBlock) {
+ // CraftBukkit start
+ BlockState afterState = getServerLevel(world).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? iblockdata.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)); // Paper - fix wrong block state
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, afterState)) { // Paper - fix wrong block state
+ continue;
+ }
+ // CraftBukkit end
if (getServerLevel(world).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
world.destroyBlock(blockposition1, true, this.silverfish);
} else {
@@ -229,9 +239,14 @@
BlockState iblockdata = world.getBlockState(blockposition);
if (InfestedBlock.isCompatibleHostBlock(iblockdata)) {
+ // CraftBukkit start
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3);
this.mob.spawnAnim();
- this.mob.discard();
+ this.mob.discard(EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause
}
}

View file

@ -1,239 +0,0 @@
--- a/net/minecraft/world/entity/monster/Slime.java
+++ b/net/minecraft/world/entity/monster/Slime.java
@@ -46,6 +46,14 @@
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.PlayerTeam;
+// CraftBukkit start
+import java.util.ArrayList;
+import java.util.List;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.entity.EntityTransformEvent;
+import org.bukkit.event.entity.SlimeSplitEvent;
+// CraftBukkit end
public class Slime extends Mob implements Enemy {
@@ -111,6 +119,7 @@
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
super.addAdditionalSaveData(nbt);
+ nbt.putBoolean("Paper.canWander", this.canWander); // Paper
nbt.putInt("Size", this.getSize() - 1);
nbt.putBoolean("wasOnGround", this.wasOnGround);
}
@@ -119,6 +128,11 @@
public void readAdditionalSaveData(CompoundTag nbt) {
this.setSize(nbt.getInt("Size") + 1, false);
super.readAdditionalSaveData(nbt);
+ // Paper start
+ if (nbt.contains("Paper.canWander")) {
+ this.canWander = nbt.getBoolean("Paper.canWander");
+ }
+ // Paper end
this.wasOnGround = nbt.getBoolean("wasOnGround");
}
@@ -197,11 +211,18 @@
@Override
public EntityType<? extends Slime> getType() {
- return super.getType();
+ return (EntityType<? extends Slime>) super.getType(); // CraftBukkit - decompile error
}
@Override
public void remove(Entity.RemovalReason reason) {
+ // CraftBukkit start - add Bukkit remove cause
+ this.remove(reason, null);
+ }
+
+ @Override
+ public void remove(Entity.RemovalReason entity_removalreason, EntityRemoveEvent.Cause cause) {
+ // CraftBukkit end
int i = this.getSize();
if (!this.level().isClientSide && i > 1 && this.isDeadOrDying()) {
@@ -210,19 +231,47 @@
int j = i / 2;
int k = 2 + this.random.nextInt(3);
PlayerTeam scoreboardteam = this.getTeam();
+
+ // CraftBukkit start
+ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k);
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled() && event.getCount() > 0) {
+ k = event.getCount();
+ } else {
+ super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause
+ return;
+ }
+ List<LivingEntity> slimes = new ArrayList<>(j);
+ // CraftBukkit end
for (int l = 0; l < k; ++l) {
float f2 = ((float) (l % 2) - 0.5F) * f1;
float f3 = ((float) (l / 2) - 0.5F) * f1;
- this.convertTo(this.getType(), new ConversionParams(ConversionType.SPLIT_ON_DEATH, false, false, scoreboardteam), EntitySpawnReason.TRIGGERED, (entityslime) -> {
+ Slime converted = this.convertTo(this.getType(), new ConversionParams(ConversionType.SPLIT_ON_DEATH, false, false, scoreboardteam), EntitySpawnReason.TRIGGERED, (entityslime) -> { // CraftBukkit
+ entityslime.aware = this.aware; // Paper - Fix nerfed slime when splitting
entityslime.setSize(j, true);
entityslime.moveTo(this.getX() + (double) f2, this.getY() + 0.5D, this.getZ() + (double) f3, this.random.nextFloat() * 360.0F, 0.0F);
- });
+ // CraftBukkit start
+ }, null, null);
+ if (converted != null) {
+ slimes.add(converted);
+ }
+ // CraftBukkit end
}
+ // CraftBukkit start
+ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) {
+ super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause
+ return;
+ }
+ for (LivingEntity living : slimes) {
+ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason
+ }
+ // CraftBukkit end
}
- super.remove(reason);
+ super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause
}
@Override
@@ -291,7 +340,11 @@
return checkMobSpawnRules(type, world, spawnReason, pos, random);
}
- if (world.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
+ // Paper start - Replace rules for Height in Swamp Biome
+ final double maxHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.maximum;
+ final double minHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.minimum;
+ if (world.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > minHeightSwamp && pos.getY() < maxHeightSwamp && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
+ // Paper end - Replace rules for Height in Swamp Biome
return checkMobSpawnRules(type, world, spawnReason, pos, random);
}
@@ -300,9 +353,12 @@
}
ChunkPos chunkcoordintpair = new ChunkPos(pos);
- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), 987234911L).nextInt(10) == 0;
+ boolean flag = world.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
- if (random.nextInt(10) == 0 && flag && pos.getY() < 40) {
+ // Paper start - Replace rules for Height in Slime Chunks
+ final double maxHeightSlimeChunk = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
+ if (random.nextInt(10) == 0 && flag && pos.getY() < maxHeightSlimeChunk) {
+ // Paper end - Replace rules for Height in Slime Chunks
return checkMobSpawnRules(type, world, spawnReason, pos, random);
}
}
@@ -432,7 +488,7 @@
@Override
public boolean canUse() {
- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
+ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - Slime pathfinder events
}
@Override
@@ -469,7 +525,15 @@
public boolean canUse() {
LivingEntity entityliving = this.slime.getTarget();
- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl);
+ // Paper start - Slime pathfinder events
+ if (entityliving == null || !entityliving.isAlive()) {
+ return false;
+ }
+ if (!this.slime.canAttack(entityliving)) {
+ return false;
+ }
+ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent();
+ // Paper end - Slime pathfinder events
}
@Override
@@ -482,7 +546,15 @@
public boolean canContinueToUse() {
LivingEntity entityliving = this.slime.getTarget();
- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0);
+ // Paper start - Slime pathfinder events
+ if (entityliving == null || !entityliving.isAlive()) {
+ return false;
+ }
+ if (!this.slime.canAttack(entityliving)) {
+ return false;
+ }
+ return --this.growTiredTimer > 0 && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent();
+ // Paper end - Slime pathfinder events
}
@Override
@@ -505,6 +577,13 @@
}
}
+
+ // Paper start - Slime pathfinder events; clear timer and target when goal resets
+ public void stop() {
+ this.growTiredTimer = 0;
+ this.slime.setTarget(null);
+ }
+ // Paper end - Slime pathfinder events
}
private static class SlimeRandomDirectionGoal extends Goal {
@@ -520,7 +599,7 @@
@Override
public boolean canUse() {
- return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
+ return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - Slime pathfinder events
}
@Override
@@ -528,6 +607,11 @@
if (--this.nextRandomizeTime <= 0) {
this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
+ // Paper start - Slime pathfinder events
+ com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent event = new com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), this.chosenDegrees);
+ if (!this.slime.canWander || !event.callEvent()) return;
+ this.chosenDegrees = event.getNewYaw();
+ // Paper end - Slime pathfinder events
}
MoveControl controllermove = this.slime.getMoveControl();
@@ -550,7 +634,7 @@
@Override
public boolean canUse() {
- return !this.slime.isPassenger();
+ return !this.slime.isPassenger() && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - Slime pathfinder events
}
@Override
@@ -563,4 +647,15 @@
}
}
+
+ // Paper start - Slime pathfinder events
+ private boolean canWander = true;
+ public boolean canWander() {
+ return canWander;
+ }
+
+ public void setWander(boolean canWander) {
+ this.canWander = canWander;
+ }
+ // Paper end - Slime pathfinder events
}

View file

@ -1,19 +0,0 @@
--- a/net/minecraft/world/entity/monster/WitherSkeleton.java
+++ b/net/minecraft/world/entity/monster/WitherSkeleton.java
@@ -110,7 +110,7 @@
return false;
} else {
if (target instanceof LivingEntity) {
- ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this);
+ ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
return true;
@@ -127,6 +127,6 @@
@Override
public boolean canBeAffected(MobEffectInstance effect) {
- return effect.is(MobEffects.WITHER) ? false : super.canBeAffected(effect);
+ return effect.is(MobEffects.WITHER) && this.level().paperConfig().entities.mobEffects.immuneToWitherEffect.witherSkeleton ? false : super.canBeAffected(effect); // Paper - Add config for mobs immune to default effects
}
}

View file

@ -1,304 +0,0 @@
--- a/net/minecraft/world/entity/monster/Zombie.java
+++ b/net/minecraft/world/entity/monster/Zombie.java
@@ -6,19 +6,6 @@
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;
-import net.minecraft.core.BlockPos;
-import net.minecraft.nbt.CompoundTag;
-import net.minecraft.nbt.NbtOps;
-import net.minecraft.nbt.Tag;
-import net.minecraft.network.syncher.EntityDataAccessor;
-import net.minecraft.network.syncher.EntityDataSerializers;
-import net.minecraft.network.syncher.SynchedEntityData;
-import net.minecraft.resources.ResourceLocation;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.sounds.SoundEvent;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.Difficulty;
@@ -66,11 +53,31 @@
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.core.BlockPos;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtOps;
+import net.minecraft.nbt.Tag;
+import net.minecraft.network.syncher.EntityDataAccessor;
+import net.minecraft.network.syncher.EntityDataSerializers;
+import net.minecraft.network.syncher.SynchedEntityData;
+import net.minecraft.resources.ResourceLocation;
+// CraftBukkit start
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.sounds.SoundEvent;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.tags.FluidTags;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityCombustByEntityEvent;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.event.entity.EntityTransformEvent;
+// CraftBukkit end
public class Zombie extends Monster {
private static final ResourceLocation SPEED_MODIFIER_BABY_ID = ResourceLocation.withDefaultNamespace("baby");
- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_ID, 0.5D, AttributeModifier.Operation.ADD_MULTIPLIED_BASE);
+ private final AttributeModifier babyModifier = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_ID, this.level().paperConfig().entities.behavior.babyZombieMovementModifier, AttributeModifier.Operation.ADD_MULTIPLIED_BASE); // Paper - Make baby speed configurable
private static final ResourceLocation REINFORCEMENT_CALLER_CHARGE_ID = ResourceLocation.withDefaultNamespace("reinforcement_caller_charge");
private static final AttributeModifier ZOMBIE_REINFORCEMENT_CALLEE_CHARGE = new AttributeModifier(ResourceLocation.withDefaultNamespace("reinforcement_callee_charge"), -0.05000000074505806D, AttributeModifier.Operation.ADD_VALUE);
private static final ResourceLocation LEADER_ZOMBIE_BONUS_ID = ResourceLocation.withDefaultNamespace("leader_zombie_bonus");
@@ -91,10 +98,12 @@
private boolean canBreakDoors;
private int inWaterTime;
public int conversionTime;
+ // private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Paper - remove anti tick skipping measures / wall time
+ private boolean shouldBurnInDay = true; // Paper - Add more Zombie API
public Zombie(EntityType<? extends Zombie> type, Level world) {
super(type, world);
- this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE);
+ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(world.paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(type, world.paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityType.ZOMBIE)))); // Paper - Configurable door breaking difficulty
}
public Zombie(Level world) {
@@ -103,7 +112,7 @@
@Override
protected void registerGoals() {
- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3));
+ if (this.level().paperConfig().entities.behavior.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper - Add zombie targets turtle egg config
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
this.addBehaviourGoals();
@@ -115,7 +124,7 @@
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers(ZombifiedPiglin.class));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
+ if ( this.level().spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Spigot
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
}
@@ -165,11 +174,16 @@
@Override
protected int getBaseExperienceReward(ServerLevel world) {
+ final int previousReward = this.xpReward; // Paper - store previous value to reset after calculating XP reward
if (this.isBaby()) {
this.xpReward = (int) ((double) this.xpReward * 2.5D);
}
- return super.getBaseExperienceReward(world);
+ // Paper start - store previous value to reset after calculating XP reward
+ int reward = super.getBaseExperienceReward(world);
+ this.xpReward = previousReward;
+ return reward;
+ // Paper end - store previous value to reset after calculating XP reward
}
@Override
@@ -178,9 +192,9 @@
if (this.level() != null && !this.level().isClientSide) {
AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY_ID);
+ attributemodifiable.removeModifier(this.babyModifier.id()); // Paper - Make baby speed configurable
if (baby) {
- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY);
+ attributemodifiable.addTransientModifier(this.babyModifier); // Paper - Make baby speed configurable
}
}
@@ -203,7 +217,7 @@
public void tick() {
if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) {
if (this.isUnderWaterConverting()) {
- --this.conversionTime;
+ --this.conversionTime; // Paper - remove anti tick skipping measures / wall time
if (this.conversionTime < 0) {
this.doUnderWaterConversion();
}
@@ -220,6 +234,7 @@
}
super.tick();
+ // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
}
@Override
@@ -253,7 +268,14 @@
super.aiStep();
}
+ // Paper start - Add more Zombie API
+ public void stopDrowning() {
+ this.conversionTime = -1;
+ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false);
+ }
+ // Paper end - Add more Zombie API
public void startUnderWaterConversion(int ticksUntilWaterConversion) {
+ // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
this.conversionTime = ticksUntilWaterConversion;
this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true);
}
@@ -267,32 +289,51 @@
}
protected void convertToZombieType(EntityType<? extends Zombie> entityType) {
- this.convertTo(entityType, ConversionParams.single(this, true, true), (entityzombie) -> {
+ Zombie converted = this.convertTo(entityType, ConversionParams.single(this, true, true), (entityzombie) -> { // CraftBukkit
entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier());
- });
+ // CraftBukkit start
+ }, EntityTransformEvent.TransformReason.DROWNED, CreatureSpawnEvent.SpawnReason.DROWNED);
+ if (converted == null) {
+ ((org.bukkit.entity.Zombie) this.getBukkitEntity()).setConversionTime(-1); // CraftBukkit - SPIGOT-5208: End conversion to stop event spam
+ }
+ // CraftBukkit end
}
@VisibleForTesting
public boolean convertVillagerToZombieVillager(ServerLevel world, Villager villager) {
- ZombieVillager entityzombievillager = (ZombieVillager) villager.convertTo(EntityType.ZOMBIE_VILLAGER, ConversionParams.single(villager, true, true), (entityzombievillager1) -> {
- entityzombievillager1.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombievillager1.blockPosition()), EntitySpawnReason.CONVERSION, new Zombie.ZombieGroupData(false, true));
- entityzombievillager1.setVillagerData(villager.getVillagerData());
- entityzombievillager1.setGossips((Tag) villager.getGossips().store(NbtOps.INSTANCE));
- entityzombievillager1.setTradeOffers(villager.getOffers().copy());
- entityzombievillager1.setVillagerXp(villager.getVillagerXp());
- if (!this.isSilent()) {
- world.levelEvent((Player) null, 1026, this.blockPosition(), 0);
+ // CraftBukkit start
+ return Zombie.convertVillagerToZombieVillager(world, villager, this.blockPosition(), this.isSilent(), EntityTransformEvent.TransformReason.INFECTION, CreatureSpawnEvent.SpawnReason.INFECTION) != null;
+ }
+
+ public static ZombieVillager convertVillagerToZombieVillager(ServerLevel worldserver, Villager entityvillager, net.minecraft.core.BlockPos blockPosition, boolean silent, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) {
+ // CraftBukkit end
+ ZombieVillager entityzombievillager = (ZombieVillager) entityvillager.convertTo(EntityType.ZOMBIE_VILLAGER, ConversionParams.single(entityvillager, true, true), (entityzombievillager1) -> {
+ entityzombievillager1.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager1.blockPosition()), EntitySpawnReason.CONVERSION, new Zombie.ZombieGroupData(false, true));
+ entityzombievillager1.setVillagerData(entityvillager.getVillagerData());
+ entityzombievillager1.setGossips((Tag) entityvillager.getGossips().store(NbtOps.INSTANCE));
+ entityzombievillager1.setTradeOffers(entityvillager.getOffers().copy());
+ entityzombievillager1.setVillagerXp(entityvillager.getVillagerXp());
+ // CraftBukkit start
+ if (!silent) {
+ worldserver.levelEvent((Player) null, 1026, blockPosition, 0);
}
- });
+ }, transformReason, spawnReason);
- return entityzombievillager != null;
+ return entityzombievillager;
+ // CraftBukkit end
}
public boolean isSunSensitive() {
- return true;
+ return this.shouldBurnInDay; // Paper - Add more Zombie API
}
+ // Paper start - Add more Zombie API
+ public void setShouldBurnInDay(boolean shouldBurnInDay) {
+ this.shouldBurnInDay = shouldBurnInDay;
+ }
+ // Paper end - Add more Zombie API
+
@Override
public boolean hurtServer(ServerLevel world, DamageSource source, float amount) {
if (!super.hurtServer(world, source, amount)) {
@@ -323,10 +364,10 @@
if (SpawnPlacements.isSpawnPositionOk(entitytypes, world, blockposition) && SpawnPlacements.checkSpawnRules(entitytypes, world, EntitySpawnReason.REINFORCEMENT, blockposition, world.random)) {
entityzombie.setPos((double) i1, (double) j1, (double) k1);
- if (!world.hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && world.isUnobstructed(entityzombie) && world.noCollision((Entity) entityzombie) && (entityzombie.canSpawnInLiquids() || !world.containsAnyLiquid(entityzombie.getBoundingBox()))) {
- entityzombie.setTarget(entityliving);
+ if (!world.hasNearbyAlivePlayerThatAffectsSpawning((double) i1, (double) j1, (double) k1, 7.0D) && world.isUnobstructed(entityzombie) && world.noCollision((Entity) entityzombie) && (entityzombie.canSpawnInLiquids() || !world.containsAnyLiquid(entityzombie.getBoundingBox()))) { // Paper - affects spawning api
+ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit
entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), EntitySpawnReason.REINFORCEMENT, (SpawnGroupData) null);
- world.addFreshEntityWithPassengers(entityzombie);
+ world.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit
AttributeInstance attributemodifiable = this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE);
AttributeModifier attributemodifier = attributemodifiable.getModifier(Zombie.REINFORCEMENT_CALLER_CHARGE_ID);
double d0 = attributemodifier != null ? attributemodifier.amount() : 0.0D;
@@ -352,7 +393,14 @@
float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty();
if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) {
- target.igniteForSeconds((float) (2 * (int) f));
+ // CraftBukkit start
+ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), (float) (2 * (int) f)); // PAIL: fixme
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ target.igniteForSeconds(event.getDuration(), false);
+ }
+ // CraftBukkit end
}
}
@@ -385,7 +433,7 @@
@Override
public EntityType<? extends Zombie> getType() {
- return super.getType();
+ return (EntityType<? extends Zombie>) super.getType(); // CraftBukkit - decompile error
}
protected boolean canSpawnInLiquids() {
@@ -414,6 +462,7 @@
nbt.putBoolean("CanBreakDoors", this.canBreakDoors());
nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1);
nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1);
+ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper - Add more Zombie API
}
@Override
@@ -425,6 +474,11 @@
if (nbt.contains("DrownedConversionTime", 99) && nbt.getInt("DrownedConversionTime") > -1) {
this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime"));
}
+ // Paper start - Add more Zombie API
+ if (nbt.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay");
+ }
+ // Paper end - Add more Zombie API
}
@@ -432,10 +486,8 @@
public boolean killedEntity(ServerLevel world, LivingEntity other) {
boolean flag = super.killedEntity(world, other);
- if ((world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager entityvillager) {
- if (world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
- return flag;
- }
+ final double fallbackChance = world.getDifficulty() == Difficulty.HARD ? 100d : world.getDifficulty() == Difficulty.NORMAL ? 50d : 0d; // Paper - Configurable chance of villager zombie infection
+ if (this.random.nextDouble() * 100 < world.paperConfig().entities.behavior.zombieVillagerInfectionChance.or(fallbackChance) && other instanceof Villager entityvillager) { // Paper - Configurable chance of villager zombie infection
if (this.convertVillagerToZombieVillager(world, entityvillager)) {
flag = false;
@@ -468,7 +520,7 @@
float f = difficulty.getSpecialMultiplier();
if (spawnReason != EntitySpawnReason.CONVERSION) {
- this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * f);
+ this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.zombies || randomsource.nextFloat() < 0.55F * f); // Paper - Add world settings for mobs picking up loot
}
if (object == null) {
@@ -496,7 +548,7 @@
entitychicken1.finalizeSpawn(world, difficulty, EntitySpawnReason.JOCKEY, (SpawnGroupData) null);
entitychicken1.setChickenJockey(true);
this.startRiding(entitychicken1);
- world.addFreshEntity(entitychicken1);
+ world.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit
}
}
}

View file

@ -1,149 +0,0 @@
--- a/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -18,10 +18,6 @@
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.sounds.SoundEvent;
-import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
@@ -35,6 +31,7 @@
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.entity.ai.village.ReputationEventType;
+import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerData;
import net.minecraft.world.entity.npc.VillagerDataHolder;
import net.minecraft.world.entity.npc.VillagerProfession;
@@ -52,6 +49,16 @@
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
+// CraftBukkit start
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.sounds.SoundEvent;
+import net.minecraft.sounds.SoundEvents;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityTransformEvent;
+// CraftBukkit end
+
public class ZombieVillager extends Zombie implements VillagerDataHolder {
private static final Logger LOGGER = LogUtils.getLogger();
@@ -69,6 +76,7 @@
@Nullable
private MerchantOffers tradeOffers;
private int villagerXp;
+ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field
public ZombieVillager(EntityType<? extends ZombieVillager> type, Level world) {
super(type, world);
@@ -87,7 +95,7 @@
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
super.addAdditionalSaveData(nbt);
- DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData());
+ DataResult<Tag> dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error
Logger logger = ZombieVillager.LOGGER;
Objects.requireNonNull(logger);
@@ -122,7 +130,7 @@
}
if (nbt.contains("Offers")) {
- DataResult dataresult1 = MerchantOffers.CODEC.parse(this.registryAccess().createSerializationContext(NbtOps.INSTANCE), nbt.get("Offers"));
+ DataResult<MerchantOffers> dataresult1 = MerchantOffers.CODEC.parse(this.registryAccess().createSerializationContext(NbtOps.INSTANCE), nbt.get("Offers")); // CraftBukkit - decompile error
Logger logger1 = ZombieVillager.LOGGER;
Objects.requireNonNull(logger1);
@@ -149,6 +157,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) {
@@ -157,6 +169,7 @@
}
super.tick();
+ this.lastTick = MinecraftServer.currentTick; // CraftBukkit
}
@Override
@@ -194,12 +207,20 @@
}
public void startConverting(@Nullable UUID uuid, int delay) {
+ // Paper start - missing entity behaviour api - converting without entity event
+ this.startConverting(uuid, delay, true);
+ }
+
+ public void startConverting(@Nullable UUID uuid, int delay, boolean broadcastEntityEvent) {
+ // Paper end - missing entity behaviour api - converting without entity event
this.conversionStarter = uuid;
this.villagerConversionTime = delay;
this.getEntityData().set(ZombieVillager.DATA_CONVERTING_ID, true);
- this.removeEffect(MobEffects.WEAKNESS);
- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, delay, Math.min(this.level().getDifficulty().getId() - 1, 0)));
- this.level().broadcastEntityEvent(this, (byte) 16);
+ // CraftBukkit start
+ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION);
+ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, delay, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION);
+ // CraftBukkit end
+ if (broadcastEntityEvent) this.level().broadcastEntityEvent(this, (byte) 16); // Paper - missing entity behaviour api - converting without entity event
}
@Override
@@ -215,10 +236,11 @@
}
private void finishConversion(ServerLevel world) {
- this.convertTo(EntityType.VILLAGER, ConversionParams.single(this, false, false), (entityvillager) -> {
+ Villager converted = this.convertTo(EntityType.VILLAGER, ConversionParams.single(this, false, false), (entityvillager) -> { // CraftBukkit
Iterator iterator = this.dropPreservedEquipment(world, (itemstack) -> {
return !EnchantmentHelper.has(itemstack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE);
}).iterator();
+ this.forceDrops = false; // CraftBukkit
while (iterator.hasNext()) {
EquipmentSlot enumitemslot = (EquipmentSlot) iterator.next();
@@ -240,7 +262,7 @@
entityvillager.finalizeSpawn(world, world.getCurrentDifficultyAt(entityvillager.blockPosition()), EntitySpawnReason.CONVERSION, (SpawnGroupData) null);
entityvillager.refreshBrain(world);
if (this.conversionStarter != null) {
- Player entityhuman = world.getPlayerByUUID(this.conversionStarter);
+ Player entityhuman = world.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check global player list where appropriate
if (entityhuman instanceof ServerPlayer) {
CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager);
@@ -248,12 +270,16 @@
}
}
- entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0));
+ entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit
if (!this.isSilent()) {
world.levelEvent((Player) null, 1027, this.blockPosition(), 0);
}
-
- });
+ // CraftBukkit start
+ }, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED);
+ if (converted == null) {
+ ((org.bukkit.entity.ZombieVillager) this.getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam
+ }
+ // CraftBukkit end
}
@VisibleForTesting

View file

@ -1,67 +0,0 @@
--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java
+++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java
@@ -56,6 +56,7 @@
private static final int ALERT_RANGE_Y = 10;
private static final UniformInt ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6);
private int ticksUntilNextAlert;
+ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper - fix PigZombieAngerEvent cancellation
public ZombifiedPiglin(EntityType<? extends ZombifiedPiglin> type, Level world) {
super(type, world);
@@ -71,7 +72,7 @@
protected void addBehaviourGoals() {
this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false));
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers());
+ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); // Paper - fix PigZombieAngerEvent cancellation
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true));
}
@@ -149,7 +150,7 @@
}).filter((entitypigzombie) -> {
return !entitypigzombie.isAlliedTo((Entity) this.getTarget());
}).forEach((entitypigzombie) -> {
- entitypigzombie.setTarget(this.getTarget());
+ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit
});
}
@@ -158,22 +159,32 @@
}
@Override
- public void setTarget(@Nullable LivingEntity target) {
- if (this.getTarget() == null && target != null) {
+ public boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature
+ if (this.getTarget() == null && entityliving != null) {
this.playFirstAngerSoundIn = ZombifiedPiglin.FIRST_ANGER_SOUND_DELAY.sample(this.random);
this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random);
}
- if (target instanceof Player) {
- this.setLastHurtByPlayer((Player) target);
+ if (entityliving instanceof Player) {
+ this.setLastHurtByPlayer((Player) entityliving);
}
- super.setTarget(target);
+ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit
}
@Override
public void startPersistentAngerTimer() {
- this.setRemainingPersistentAngerTime(ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random));
+ // CraftBukkit start
+ Entity entity = ((ServerLevel) this.level()).getEntity(this.getPersistentAngerTarget());
+ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random));
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ this.setPersistentAngerTarget(null);
+ pathfinderGoalHurtByTarget.stop(); // Paper - fix PigZombieAngerEvent cancellation
+ return;
+ }
+ this.setRemainingPersistentAngerTime(event.getNewAnger());
+ // CraftBukkit end
}
public static boolean checkZombifiedPiglinSpawnRules(EntityType<ZombifiedPiglin> type, LevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random) {