mirror of
https://github.com/PaperMC/Paper.git
synced 2025-07-31 20:22:05 -07:00
/net/minecraft/world/entity/monster
This commit is contained in:
@@ -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();
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
--- a/net/minecraft/world/entity/monster/Bogged.java
|
||||
+++ b/net/minecraft/world/entity/monster/Bogged.java
|
||||
@@ -72,7 +_,20 @@
|
||||
ItemStack itemInHand = player.getItemInHand(hand);
|
||||
if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
- this.shear(serverLevel, SoundSource.PLAYERS, itemInHand);
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(serverLevel, itemInHand);
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemInHand, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ // this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients // Paper - no longer needed
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
+ // Paper end - custom shear drops
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ this.shear(serverLevel, SoundSource.PLAYERS, itemInHand, drops); // Paper - custom shear drops
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
}
|
||||
@@ -125,15 +_,34 @@
|
||||
|
||||
@Override
|
||||
public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(level, soundSource, shears, this.generateDefaultDrops(level, shears));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops(final ServerLevel serverLevel, final ItemStack shears) {
|
||||
+ final java.util.List<ItemStack> drops = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
|
||||
+ this.dropFromShearingLootTable(serverLevel, BuiltInLootTables.BOGGED_SHEAR, shears, (ignored, stack) -> {
|
||||
+ drops.add(stack);
|
||||
+ });
|
||||
+ return drops;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears, java.util.List<ItemStack> drops) {
|
||||
+ // Paper end - custom shear drops
|
||||
level.playSound(null, this, SoundEvents.BOGGED_SHEAR, soundSource, 1.0F, 1.0F);
|
||||
this.spawnShearedMushrooms(level, shears);
|
||||
this.setSheared(true);
|
||||
}
|
||||
|
||||
- private void spawnShearedMushrooms(ServerLevel level, ItemStack stack) {
|
||||
- this.dropFromShearingLootTable(
|
||||
- level, BuiltInLootTables.BOGGED_SHEAR, stack, (serverLevel, itemStack) -> this.spawnAtLocation(serverLevel, itemStack, this.getBbHeight())
|
||||
- );
|
||||
+ // Paper start - custom shear drops
|
||||
+ private void spawnShearedMushrooms(ServerLevel world, ItemStack shears, java.util.List<ItemStack> drops) {
|
||||
+ final ServerLevel worldserver1 = world; // Named for lambda consumption
|
||||
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
|
||||
+ drops.forEach(itemstack1 -> this.spawnAtLocation(world, shears, this.getBbHeight()));
|
||||
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
|
||||
+ // Paper end - custom shear drops
|
||||
}
|
||||
|
||||
@Override
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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() {
|
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/monster/Drowned.java
|
||||
+++ b/net/minecraft/world/entity/monster/Drowned.java
|
||||
@@ -85,7 +_,7 @@
|
||||
this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0));
|
||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class));
|
||||
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));
|
||||
+ 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, Axolotl.class, true, false));
|
||||
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
|
@@ -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))
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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;
|
@@ -0,0 +1,19 @@
|
||||
--- a/net/minecraft/world/entity/monster/Guardian.java
|
||||
+++ b/net/minecraft/world/entity/monster/Guardian.java
|
||||
@@ -59,6 +_,7 @@
|
||||
private boolean clientSideTouchedGround;
|
||||
@Nullable
|
||||
public RandomStrollGoal randomStrollGoal;
|
||||
+ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field
|
||||
|
||||
public Guardian(EntityType<? extends Guardian> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -73,7 +_,7 @@
|
||||
protected void registerGoals() {
|
||||
MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0);
|
||||
this.randomStrollGoal = new RandomStrollGoal(this, 1.0, 80);
|
||||
- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this));
|
||||
+ this.goalSelector.addGoal(4, this.guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field
|
||||
this.goalSelector.addGoal(5, moveTowardsRestrictionGoal);
|
||||
this.goalSelector.addGoal(7, this.randomStrollGoal);
|
||||
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
@@ -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;
|
@@ -0,0 +1,40 @@
|
||||
--- a/net/minecraft/world/entity/monster/Illusioner.java
|
||||
+++ b/net/minecraft/world/entity/monster/Illusioner.java
|
||||
@@ -180,9 +_,19 @@
|
||||
double d2 = target.getZ() - this.getZ();
|
||||
double squareRoot = Math.sqrt(d * d + d2 * d2);
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
+ // Paper start - EntityShootBowEvent
|
||||
+ 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()) {
|
||||
+ event.getProjectile().remove();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (event.getProjectile() == mobArrow.getBukkitEntity()) {
|
||||
Projectile.spawnProjectileUsingShoot(
|
||||
mobArrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
|
||||
);
|
||||
+ }
|
||||
+ // Paper end - EntityShootBowEvent
|
||||
}
|
||||
|
||||
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
|
||||
@@ -229,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
protected void performSpellCasting() {
|
||||
- Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this);
|
||||
+ Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
|
||||
}
|
||||
|
||||
@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
|
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/monster/Monster.java
|
||||
+++ b/net/minecraft/world/entity/monster/Monster.java
|
||||
@@ -92,7 +_,7 @@
|
||||
return false;
|
||||
} else {
|
||||
DimensionType dimensionType = level.dimensionType();
|
||||
- int i = dimensionType.monsterSpawnBlockLightLimit();
|
||||
+ int i = world.getLevel().paperConfig().entities.spawning.monsterSpawnMaxLightLevel.or(dimensionType.monsterSpawnBlockLightLimit()); // Paper - Configurable max block light for monster spawning
|
||||
if (i < 15 && level.getBrightness(LightLayer.BLOCK, pos) > i) {
|
||||
return false;
|
||||
} else {
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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());
|
||||
}
|
@@ -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
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
@@ -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 {
|
@@ -0,0 +1,23 @@
|
||||
--- a/net/minecraft/world/entity/monster/Skeleton.java
|
||||
+++ b/net/minecraft/world/entity/monster/Skeleton.java
|
||||
@@ -89,11 +_,18 @@
|
||||
}
|
||||
|
||||
protected void doFreezeConversion() {
|
||||
- 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
|
||||
if (!this.isSilent()) {
|
||||
this.level().levelEvent(null, 1048, this.blockPosition(), 0);
|
||||
}
|
||||
- });
|
||||
+ // 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
|
||||
+ if (stray == null) {
|
||||
+ this.conversionTime = 300;
|
||||
+ }
|
||||
+ // Paper end - Fix issues with mob conversion
|
||||
+ // CraftBukkit end - add spawn and transform reasons
|
||||
}
|
||||
|
||||
@Override
|
@@ -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
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java
|
||||
+++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java
|
||||
@@ -208,6 +_,11 @@
|
||||
public void tick() {
|
||||
this.attackWarmupDelay--;
|
||||
if (this.attackWarmupDelay == 0) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.performSpellCasting();
|
||||
SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F);
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
--- a/net/minecraft/world/entity/monster/Spider.java
|
||||
+++ b/net/minecraft/world/entity/monster/Spider.java
|
||||
@@ -79,7 +_,7 @@
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (!this.level().isClientSide) {
|
||||
- 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean canBeAffected(MobEffectInstance potioneffect) {
|
||||
- return !potioneffect.is(MobEffects.POISON) && super.canBeAffected(potioneffect);
|
||||
+ 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() {
|
||||
@@ -165,7 +_,7 @@
|
||||
if (spawnGroupData instanceof Spider.SpiderEffectsGroupData spiderEffectsGroupData) {
|
||||
Holder<MobEffect> holder = spiderEffectsGroupData.effect;
|
||||
if (holder != null) {
|
||||
- this.addEffect(new MobEffectInstance(holder, -1));
|
||||
+ this.addEffect(new MobEffectInstance(holder, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, level instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,18 @@
|
||||
--- a/net/minecraft/world/entity/monster/Strider.java
|
||||
+++ b/net/minecraft/world/entity/monster/Strider.java
|
||||
@@ -309,7 +_,14 @@
|
||||
|| blockStateOnLegacy.is(BlockTags.STRIDER_WARM_BLOCKS)
|
||||
|| this.getFluidHeight(FluidTags.LAVA) > 0.0;
|
||||
boolean flag1 = this.getVehicle() instanceof Strider strider && strider.isSuffocating();
|
||||
- this.setSuffocating(!flag || flag1);
|
||||
+ // CraftBukkit start
|
||||
+ boolean suffocating = !flag || flag1;
|
||||
+ if (suffocating ^ this.isSuffocating()) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) {
|
||||
+ this.setSuffocating(suffocating);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
super.tick();
|
@@ -0,0 +1,23 @@
|
||||
--- a/net/minecraft/world/entity/monster/Vex.java
|
||||
+++ b/net/minecraft/world/entity/monster/Vex.java
|
||||
@@ -296,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
- Vex.this.setTarget(Vex.this.owner.getTarget());
|
||||
+ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit
|
||||
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);
|
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/monster/Vindicator.java
|
||||
+++ b/net/minecraft/world/entity/monster/Vindicator.java
|
||||
@@ -184,7 +_,7 @@
|
||||
|
||||
static class VindicatorBreakDoorGoal extends BreakDoorGoal {
|
||||
public VindicatorBreakDoorGoal(Mob mob) {
|
||||
- super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE);
|
||||
+ super(mob, 6, com.google.common.base.Predicates.in(mob.level().paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(mob.getType(), mob.level().paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityType.VINDICATOR)))); // Paper - Configurable door breaking difficulty
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
|
||||
}
|
||||
|
@@ -0,0 +1,84 @@
|
||||
--- a/net/minecraft/world/entity/monster/Witch.java
|
||||
+++ b/net/minecraft/world/entity/monster/Witch.java
|
||||
@@ -122,8 +_,14 @@
|
||||
ItemStack mainHandItem = this.getMainHandItem();
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
||||
PotionContents potionContents = mainHandItem.get(DataComponents.POTION_CONTENTS);
|
||||
+ // Paper start - WitchConsumePotionEvent
|
||||
+ 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));
|
||||
+ potionContents = event.callEvent() ? org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getPotion()).get(DataComponents.POTION_CONTENTS) : null;
|
||||
+ }
|
||||
+ // Paper end - WitchConsumePotionEvent
|
||||
if (mainHandItem.is(Items.POTION) && potionContents != null) {
|
||||
- potionContents.forEachEffect(this::addEffect);
|
||||
+ potionContents.forEachEffect((effect) -> this.addEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK)); // CraftBukkit
|
||||
}
|
||||
|
||||
this.gameEvent(GameEvent.DRINK);
|
||||
@@ -147,26 +_,7 @@
|
||||
}
|
||||
|
||||
if (holder != null) {
|
||||
- this.setItemSlot(EquipmentSlot.MAINHAND, PotionContents.createItemStack(Items.POTION, holder));
|
||||
- this.usingTime = this.getMainHandItem().getUseDuration(this);
|
||||
- this.setUsingItem(true);
|
||||
- if (!this.isSilent()) {
|
||||
- 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 attribute = this.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
- attribute.removeModifier(SPEED_MODIFIER_DRINKING_ID);
|
||||
- attribute.addTransientModifier(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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +_,23 @@
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
+ // Paper start - moved to its own method
|
||||
+ public void setDrinkingPotion(ItemStack potion) {
|
||||
+ potion = org.bukkit.craftbukkit.event.CraftEventFactory.handleWitchReadyPotionEvent(this, potion);
|
||||
+ this.setItemSlot(EquipmentSlot.MAINHAND, potion);
|
||||
+ this.usingTime = this.getMainHandItem().getUseDuration(this);
|
||||
+ this.setUsingItem(true);
|
||||
+ 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);
|
||||
+ }
|
||||
+
|
||||
+ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
+
|
||||
+ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING_ID);
|
||||
+ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public SoundEvent getCelebrateSound() {
|
||||
return SoundEvents.WITCH_CELEBRATE;
|
||||
@@ -244,6 +_,13 @@
|
||||
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
ItemStack itemStack = PotionContents.createItemStack(Items.SPLASH_POTION, holder);
|
||||
+ // 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));
|
||||
+ if (!event.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion());
|
||||
+ // Paper end - WitchThrowPotionEven
|
||||
Projectile.spawnProjectileUsingShoot(ThrownPotion::new, serverLevel, itemStack, this, d, d1 + squareRoot * 0.2, d2, 0.75F, 8.0F);
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
@@ -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(
|
Reference in New Issue
Block a user