net.minecraft.world.entity.animal (thank you wheel of pain)

This commit is contained in:
Noah van der Aa
2024-12-14 17:27:01 +01:00
parent dde17defa5
commit 2a9bf40295
45 changed files with 1239 additions and 1580 deletions

View File

@@ -0,0 +1,10 @@
--- a/net/minecraft/world/entity/animal/AbstractSchoolingFish.java
+++ b/net/minecraft/world/entity/animal/AbstractSchoolingFish.java
@@ -51,6 +_,7 @@
}
public void stopFollowing() {
+ if (this.leader == null) return; // Avoid NPE, plugins can now set the leader and certain fish goals might cause this method to be called
this.leader.removeFollower();
this.leader = null;
}

View File

@@ -0,0 +1,118 @@
--- a/net/minecraft/world/entity/animal/Animal.java
+++ b/net/minecraft/world/entity/animal/Animal.java
@@ -39,6 +_,7 @@
public int inLove;
@Nullable
public UUID loveCause;
+ public ItemStack breedItem; // CraftBukkit - Add breedItem variable
protected Animal(EntityType<? extends Animal> entityType, Level level) {
super(entityType, level);
@@ -78,9 +_,13 @@
}
@Override
- protected void actuallyHurt(ServerLevel level, DamageSource damageSource, float amount) {
+ // CraftBukkit start - void -> boolean
+ public boolean actuallyHurt(ServerLevel worldserver, DamageSource damagesource, float f, org.bukkit.event.entity.EntityDamageEvent event) {
+ boolean damageResult = super.actuallyHurt(worldserver, damagesource, f, event);
+ if (!damageResult) return false;
this.resetLove();
- super.actuallyHurt(level, damageSource, amount);
+ return true;
+ // CraftBukkit end
}
@Override
@@ -138,8 +_,9 @@
if (this.isFood(itemInHand)) {
int age = this.getAge();
if (!this.level().isClientSide && age == 0 && this.canFallInLove()) {
+ final ItemStack breedCopy = itemInHand.copy(); // Paper - Fix EntityBreedEvent copying
this.usePlayerItem(player, hand, itemInHand);
- this.setInLove(player);
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
this.playEatingSound();
return InteractionResult.SUCCESS_SERVER;
}
@@ -176,11 +_,26 @@
return this.inLove <= 0;
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Fix EntityBreedEvent copying
public void setInLove(@Nullable Player player) {
- this.inLove = 600;
+ // Paper start - Fix EntityBreedEvent copying
+ this.setInLove(player, null);
+ }
+ public void setInLove(@Nullable Player player, @Nullable ItemStack breedItemCopy) {
+ if (breedItemCopy != null) this.breedItem = breedItemCopy;
+ // Paper end - Fix EntityBreedEvent copying
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityEnterLoveModeEvent entityEnterLoveModeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600);
+ if (entityEnterLoveModeEvent.isCancelled()) {
+ this.breedItem = null; // Paper - Fix EntityBreedEvent copying; clear if cancelled
+ return;
+ }
+ this.inLove = entityEnterLoveModeEvent.getTicksInLove();
+ // CraftBukkit end
if (player != null) {
this.loveCause = player.getUUID();
}
+ // Paper - Fix EntityBreedEvent copying; set breed item in better place
this.level().broadcastEntityEvent(this, (byte)18);
}
@@ -220,23 +_,45 @@
if (breedOffspring != null) {
breedOffspring.setBaby(true);
breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
- this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring);
- level.addFreshEntityWithPassengers(breedOffspring);
+ // CraftBukkit start - call EntityBreedEvent
+ ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(mate.getLoveCause())).orElse(null);
+ int experience = this.getRandom().nextInt(7) + 1;
+ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(breedOffspring, this, mate, breeder, this.breedItem, experience);
+ if (entityBreedEvent.isCancelled()) {
+ return;
+ }
+ experience = entityBreedEvent.getExperience();
+ this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring, experience);
+ level.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);
+ // CraftBukkit end
}
}
public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) {
- Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(animal.getLoveCause())).ifPresent(player -> {
- player.awardStat(Stats.ANIMALS_BRED);
- CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby);
- });
+ // CraftBukkit start
+ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1);
+ }
+ public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby, int experience) {
+ // CraftBukkit end
+ // Paper start
+ ServerPlayer entityplayer = this.getLoveCause();
+ if (entityplayer == null) entityplayer = animal.getLoveCause();
+ if (entityplayer != null) {
+ // Paper end
+ entityplayer.awardStat(Stats.ANIMALS_BRED);
+ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, animal, baby);
+ } // Paper
this.setAge(6000);
animal.setAge(6000);
this.resetLove();
animal.resetLove();
level.broadcastEntityEvent(this, (byte)18);
if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1));
+ // CraftBukkit start - use event experience
+ if (experience > 0) {
+ level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, baby)); // Paper
+ }
+ // CraftBukkit end
}
}

View File

@@ -0,0 +1,153 @@
--- a/net/minecraft/world/entity/animal/Bee.java
+++ b/net/minecraft/world/entity/animal/Bee.java
@@ -144,7 +_,22 @@
public Bee(EntityType<? extends Bee> entityType, Level level) {
super(entityType, level);
- this.moveControl = new FlyingMoveControl(this, 20, true);
+ // Paper start - Fix MC-167279
+ class BeeFlyingMoveControl extends FlyingMoveControl {
+ public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) {
+ super(entity, maxPitchChange, noGravity);
+ }
+
+ @Override
+ public void tick() {
+ if (this.mob.getY() <= Bee.this.level().getMinY()) {
+ this.mob.setNoGravity(false);
+ }
+ super.tick();
+ }
+ }
+ this.moveControl = new BeeFlyingMoveControl(this, 20, true);
+ // Paper end - Fix MC-167279
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(PathType.DANGER_FIRE, -1.0F);
this.setPathfindingMalus(PathType.WATER, -1.0F);
@@ -191,12 +_,19 @@
@Override
public void addAdditionalSaveData(CompoundTag compound) {
+ // CraftBukkit start - selectively save data
+ this.addAdditionalSaveData(compound, true);
+ }
+
+ @Override
+ public void addAdditionalSaveData(CompoundTag compound, boolean includeAll) {
+ // CraftBukkit end
super.addAdditionalSaveData(compound);
- if (this.hasHive()) {
+ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive
compound.put("hive_pos", NbtUtils.writeBlockPos(this.getHivePos()));
}
- if (this.hasSavedFlowerPos()) {
+ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save hive
compound.put("flower_pos", NbtUtils.writeBlockPos(this.getSavedFlowerPos()));
}
@@ -237,7 +_,7 @@
}
if (i > 0) {
- livingEntity.addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this);
+ livingEntity.addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
}
@@ -489,11 +_,12 @@
@Nullable
BeehiveBlockEntity getBeehiveBlockEntity() {
- if (this.hivePos == null) {
- return null;
- } else {
- return this.isTooFarAway(this.hivePos) ? null : this.level().getBlockEntity(this.hivePos, BlockEntityType.BEEHIVE).orElse(null);
+ // Paper start - move over logic to accommodate isTooFarAway with chunk load check
+ if (this.hivePos != null && !this.isTooFarAway(this.hivePos) && this.level().getChunkIfLoadedImmediately(this.hivePos.getX() >> 4, this.hivePos.getZ() >> 4) != null) {
+ return (BeehiveBlockEntity) this.level().getBlockEntity(this.hivePos, BlockEntityType.BEEHIVE).orElse(null);
}
+ return null;
+ // Paper end
}
boolean isHiveValid() {
@@ -520,11 +_,13 @@
this.setFlag(4, hasStung);
}
+ public net.kyori.adventure.util.TriState rollingOverride = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Rolling override
public boolean isRolling() {
return this.getFlag(2);
}
public void setRolling(boolean isRolling) {
+ isRolling = rollingOverride.toBooleanOrElse(isRolling); // Paper - Rolling override
this.setFlag(2, isRolling);
}
@@ -581,7 +_,7 @@
if (beeInteractionEffect != null) {
this.usePlayerItem(player, hand, itemInHand);
if (!this.level().isClientSide) {
- this.addEffect(beeInteractionEffect);
+ this.addEffect(beeInteractionEffect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // Paper - Add missing effect cause
}
return InteractionResult.SUCCESS;
@@ -650,8 +_,9 @@
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {
+ if (!super.hurtServer(level, damageSource, amount)) return false; // CraftBukkit - Only stop pollinating if entity was damaged
this.beePollinateGoal.stopPollinating();
- return super.hurtServer(level, damageSource, amount);
+ return true; // CraftBukkit - Only stop pollinating if entity was damaged
}
}
@@ -772,7 +_,7 @@
@VisibleForDebug
public class BeeGoToHiveGoal extends Bee.BaseBeeGoal {
public static final int MAX_TRAVELLING_TICKS = 2400;
- int travellingTicks = Bee.this.level().random.nextInt(10);
+ int travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues
private static final int MAX_BLACKLISTED_TARGETS = 3;
final List<BlockPos> blacklistedTargets = Lists.newArrayList();
@Nullable
@@ -888,7 +_,7 @@
public class BeeGoToKnownFlowerGoal extends Bee.BaseBeeGoal {
private static final int MAX_TRAVELLING_TICKS = 2400;
- int travellingTicks = Bee.this.level().random.nextInt(10);
+ int travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues
BeeGoToKnownFlowerGoal() {
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
@@ -986,7 +_,7 @@
}
}
- if (blockState1 != null) {
+ if (blockState1 != null && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockPos, blockState1)) { // CraftBukkit
Bee.this.level().levelEvent(2011, blockPos, 15);
Bee.this.level().setBlockAndUpdate(blockPos, blockState1);
Bee.this.incrementNumCropsGrownSincePollination();
@@ -1010,7 +_,7 @@
@Override
protected void alertOther(Mob mob, LivingEntity target) {
if (mob instanceof Bee && this.mob.hasLineOfSight(target)) {
- mob.setTarget(target);
+ mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason
}
}
}
@@ -1168,7 +_,7 @@
Bee.this.dropFlower();
this.pollinating = false;
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
- } else {
+ } else if (Bee.this.savedFlowerPos != null) { // Paper - add null check since API can manipulate this
Vec3 vec3 = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0, 0.6F, 0.0);
if (vec3.distanceTo(Bee.this.position()) > 1.0) {
this.hoverPos = vec3;

View File

@@ -0,0 +1,32 @@
--- a/net/minecraft/world/entity/animal/Bucketable.java
+++ b/net/minecraft/world/entity/animal/Bucketable.java
@@ -88,9 +_,19 @@
static <T extends LivingEntity & Bucketable> Optional<InteractionResult> bucketMobPickup(Player player, InteractionHand hand, T entity) {
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.getItem() == Items.WATER_BUCKET && entity.isAlive()) {
- entity.playSound(entity.getPickupSound(), 1.0F, 1.0F);
+ // CraftBukkit start
+ // entity.playSound(entity.getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down
ItemStack bucketItemStack = entity.getBucketItemStack();
entity.saveToBucketTag(bucketItemStack);
+ org.bukkit.event.player.PlayerBucketEntityEvent playerBucketFishEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerFishBucketEvent(entity, player, itemInHand, bucketItemStack, hand);
+ bucketItemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket());
+ if (playerBucketFishEvent.isCancelled()) {
+ player.containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
+ entity.resendPossiblyDesyncedEntityData((ServerPlayer) player); // Paper
+ return Optional.of(InteractionResult.FAIL);
+ }
+ entity.playSound(entity.getPickupSound(), 1.0F, 1.0F);
+ // CraftBukkit end
ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, bucketItemStack, false);
player.setItemInHand(hand, itemStack);
Level level = entity.level();
@@ -98,7 +_,7 @@
CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer)player, bucketItemStack);
}
- entity.discard();
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
return Optional.of(InteractionResult.SUCCESS);
} else {
return Optional.empty();

View File

@@ -0,0 +1,75 @@
--- a/net/minecraft/world/entity/animal/Cat.java
+++ b/net/minecraft/world/entity/animal/Cat.java
@@ -342,7 +_,7 @@
TagKey<CatVariant> tagKey = flag ? CatVariantTags.FULL_MOON_SPAWNS : CatVariantTags.DEFAULT_SPAWNS;
BuiltInRegistries.CAT_VARIANT.getRandomElementOf(tagKey, level.getRandom()).ifPresent(this::setVariant);
ServerLevel level1 = level.getLevel();
- if (level1.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) {
+ if (level1.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK, level).isValid()) { // Paper - Fix swamp hut cat generation deadlock
this.setVariant(BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.ALL_BLACK));
this.setPersistenceRequired();
}
@@ -359,6 +_,11 @@
if (item instanceof DyeItem dyeItem) {
DyeColor dyeColor = dyeItem.getDyeColor();
if (dyeColor != this.getCollarColor()) {
+ // Paper start - Add EntityDyeEvent and CollarColorable interface
+ final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) enumcolor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
+ if (!event.callEvent()) return InteractionResult.FAIL;
+ dyeColor = DyeColor.byId(event.getColor().getWoolData());
+ // Paper end - Add EntityDyeEvent and CollarColorable interface
if (!this.level().isClientSide()) {
this.setCollarColor(dyeColor);
itemInHand.consume(1, player);
@@ -371,7 +_,7 @@
if (!this.level().isClientSide()) {
this.usePlayerItem(player, hand, itemInHand);
FoodProperties foodProperties = itemInHand.get(DataComponents.FOOD);
- this.heal(foodProperties != null ? foodProperties.nutrition() : 1.0F);
+ this.heal(foodProperties != null ? foodProperties.nutrition() : 1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper - Add missing regain reason
this.playEatingSound();
}
@@ -433,7 +_,7 @@
}
private void tryToTame(Player player) {
- if (this.random.nextInt(3) == 0) {
+ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
this.tame(player);
this.setOrderedToSit(true);
this.level().broadcastEntityEvent(this, (byte)7);
@@ -567,15 +_,20 @@
.dropFromGiftLootTable(
getServerLevel(this.cat),
BuiltInLootTables.CAT_MORNING_GIFT,
- (serverLevel, itemStack) -> serverLevel.addFreshEntity(
- new ItemEntity(
+ (serverLevel, itemStack) -> {
+ // CraftBukkit start
+ ItemEntity item = new ItemEntity(
serverLevel,
(double)mutableBlockPos.getX() - Mth.sin(this.cat.yBodyRot * (float) (Math.PI / 180.0)),
mutableBlockPos.getY(),
(double)mutableBlockPos.getZ() + Mth.cos(this.cat.yBodyRot * (float) (Math.PI / 180.0)),
itemStack
- )
- )
+ );
+ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) item.getBukkitEntity());
+ if (!event.callEvent()) return;
+ serverLevel.addFreshEntity(item);
+ // CraftBukkit end
+ }
);
}
@@ -602,7 +_,7 @@
static class CatTemptGoal extends TemptGoal {
@Nullable
- private Player selectedPlayer;
+ private LivingEntity selectedPlayer; // CraftBukkit
private final Cat cat;
public CatTemptGoal(Cat cat, double speedModifier, Predicate<ItemStack> items, boolean canScare) {

View File

@@ -0,0 +1,15 @@
--- a/net/minecraft/world/entity/animal/Chicken.java
+++ b/net/minecraft/world/entity/animal/Chicken.java
@@ -91,10 +_,12 @@
this.flap = this.flap + this.flapping * 2.0F;
if (this.level() instanceof ServerLevel serverLevel && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) {
+ this.forceDrops = true; // CraftBukkit
if (this.dropFromGiftLootTable(serverLevel, BuiltInLootTables.CHICKEN_LAY, this::spawnAtLocation)) {
this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
this.gameEvent(GameEvent.ENTITY_PLACE);
}
+ this.forceDrops = false; // CraftBukkit
this.eggTime = this.random.nextInt(6000) + 6000;
}

View File

@@ -0,0 +1,19 @@
--- a/net/minecraft/world/entity/animal/Cow.java
+++ b/net/minecraft/world/entity/animal/Cow.java
@@ -88,8 +_,15 @@
public InteractionResult mobInteract(Player player, InteractionHand hand) {
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.BUCKET) && !this.isBaby()) {
+ // CraftBukkit start - Got milk?
+ org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand);
+ if (event.isCancelled()) {
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F);
- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, Items.MILK_BUCKET.getDefaultInstance());
+ ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
player.setItemInHand(hand, itemStack);
return InteractionResult.SUCCESS;
} else {

View File

@@ -0,0 +1,77 @@
--- a/net/minecraft/world/entity/animal/Dolphin.java
+++ b/net/minecraft/world/entity/animal/Dolphin.java
@@ -63,6 +_,12 @@
import net.minecraft.world.phys.Vec3;
public class Dolphin extends AgeableWaterCreature {
+ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
+ @Override
+ public int getDefaultMaxAirSupply() {
+ return TOTAL_AIR_SUPPLY;
+ }
+ // CraftBukkit end
private static final EntityDataAccessor<BlockPos> TREASURE_POS = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BLOCK_POS);
private static final EntityDataAccessor<Boolean> GOT_FISH = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BOOLEAN);
private static final EntityDataAccessor<Integer> MOISTNESS_LEVEL = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.INT);
@@ -196,7 +_,7 @@
@Override
public int getMaxAirSupply() {
- return 4800;
+ return this.maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
}
@Override
@@ -229,11 +_,15 @@
if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) {
ItemStack item = entity.getItem();
if (this.canHoldItem(item)) {
+ // CraftBukkit start - call EntityPickupItemEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, false).isCancelled()) return;
+ item = entity.getItem(); // CraftBukkit- update ItemStack from event
+ // CraftBukkit end
this.onItemPickup(entity);
this.setItemSlot(EquipmentSlot.MAINHAND, item);
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
this.take(entity, item.getCount());
- entity.discard();
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
}
}
}
@@ -341,7 +_,7 @@
@Nullable
@Override
- protected SoundEvent getDeathSound() {
+ public SoundEvent getDeathSound() { // Paper - decompile error
return SoundEvents.DOLPHIN_DEATH;
}
@@ -497,7 +_,7 @@
@Override
public void start() {
- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin);
+ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit
}
@Override
@@ -516,7 +_,7 @@
}
if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) {
- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin);
+ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit
}
}
}
@@ -586,7 +_,7 @@
0.3F * Mth.cos(Dolphin.this.getYRot() * (float) (Math.PI / 180.0)) * Mth.cos(Dolphin.this.getXRot() * (float) (Math.PI / 180.0))
+ Mth.sin(f1) * f2
);
- Dolphin.this.level().addFreshEntity(itemEntity);
+ Dolphin.this.spawnAtLocation(getServerLevel(Dolphin.this), itemEntity); // Paper - Call EntityDropItemEvent
}
}
}

View File

@@ -0,0 +1,143 @@
--- a/net/minecraft/world/entity/animal/Fox.java
+++ b/net/minecraft/world/entity/animal/Fox.java
@@ -413,7 +_,7 @@
this.setSleeping(compound.getBoolean("Sleeping"));
this.setVariant(Fox.Variant.byName(compound.getString("Type")));
- this.setSitting(compound.getBoolean("Sitting"));
+ this.setSitting(compound.getBoolean("Sitting"), false); // Paper - Add EntityToggleSitEvent
this.setIsCrouching(compound.getBoolean("Crouching"));
if (this.level() instanceof ServerLevel) {
this.setTargetGoals();
@@ -425,6 +_,12 @@
}
public void setSitting(boolean sitting) {
+ // Paper start - Add EntityToggleSitEvent
+ this.setSitting(sitting, true);
+ }
+ public void setSitting(boolean sitting, boolean fireEvent) {
+ if (fireEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return;
+ // Paper end - Add EntityToggleSitEvent
this.setFlag(1, sitting);
}
@@ -484,19 +_,20 @@
itemEntity.setPickUpDelay(40);
itemEntity.setThrower(this);
this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F);
- this.level().addFreshEntity(itemEntity);
+ this.spawnAtLocation((net.minecraft.server.level.ServerLevel) this.level(), itemEntity); // Paper - Call EntityDropItemEvent
}
}
private void dropItemStack(ItemStack stack) {
ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), stack);
- this.level().addFreshEntity(itemEntity);
+ this.spawnAtLocation((net.minecraft.server.level.ServerLevel) this.level(), itemEntity); // Paper - Call EntityDropItemEvent
}
@Override
protected void pickUpItem(ServerLevel level, ItemEntity entity) {
ItemStack item = entity.getItem();
- if (this.canHoldItem(item)) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, item.getCount() - 1, !this.canHoldItem(item)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent
+ item = entity.getItem(); // CraftBukkit - update item after event
int count = item.getCount();
if (count > 1) {
this.dropItemStack(item.split(count - 1));
@@ -507,7 +_,7 @@
this.setItemSlot(EquipmentSlot.MAINHAND, item.split(1));
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
this.take(entity, item.getCount());
- entity.discard();
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
this.ticksSinceEaten = 0;
}
}
@@ -671,15 +_,33 @@
return this.getTrustedUUIDs().contains(uuid);
}
- @Override
- protected void dropAllDeathLoot(ServerLevel level, DamageSource damageSource) {
+ // Paper start - handle the bitten item separately like vanilla
+ @Override
+ protected boolean shouldSkipLoot(EquipmentSlot slot) {
+ return slot == EquipmentSlot.MAINHAND;
+ }
+ // Paper end
+
+ @Override
+ // Paper start - Cancellable death event
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(ServerLevel level, DamageSource damageSource) {
ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND);
- if (!itemBySlot.isEmpty()) {
+ boolean releaseMouth = false;
+ if (!itemBySlot.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Fix MC-153010
this.spawnAtLocation(level, itemBySlot);
+ releaseMouth = true;
+ }
+
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(level, damageSource);
+ // Below is code to drop
+ if (deathEvent == null || deathEvent.isCancelled()) return deathEvent;
+
+ if (releaseMouth) {
+ // Paper end
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
}
- super.dropAllDeathLoot(level, damageSource);
+ return deathEvent; // Paper - Cancellable death event
}
public static boolean isPathClear(Fox fox, LivingEntity livingEntity) {
@@ -853,6 +_,14 @@
if (loveCause1 != null && loveCause != loveCause1) {
fox.addTrustedUUID(loveCause1.getUUID());
}
+ // CraftBukkit start - call EntityBreedEvent
+ fox.setAge(-24000);
+ fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
+ int experience = this.animal.getRandom().nextInt(7) + 1;
+ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(fox, this.animal, this.partner, loveCause, this.animal.breedItem, experience);
+ if (entityBreedEvent.isCancelled()) return;
+ experience = entityBreedEvent.getExperience();
+ // CraftBukkit end
if (serverPlayer != null) {
serverPlayer.awardStat(Stats.ANIMALS_BRED);
@@ -863,15 +_,17 @@
this.partner.setAge(6000);
this.animal.resetLove();
this.partner.resetLove();
- fox.setAge(-24000);
- fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
- serverLevel.addFreshEntityWithPassengers(fox);
+ level.addFreshEntityWithPassengers(fox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
this.level.broadcastEntityEvent(this.animal, (byte)18);
if (serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- this.level
- .addFreshEntity(
- new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1)
- );
+ // CraftBukkit start - use event experience
+ if (experience > 0) {
+ this.level
+ .addFreshEntity(
+ new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, loveCause, fox) // Paper
+ );
+ }
+ // CraftBukkit end
}
}
}
@@ -934,6 +_,7 @@
private void pickSweetBerries(BlockState state) {
int ageValue = state.getValue(SweetBerryBushBlock.AGE);
state.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(1));
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1))) return; // CraftBukkit - call EntityChangeBlockEvent
int i = 1 + Fox.this.level().random.nextInt(2) + (ageValue == 3 ? 1 : 0);
ItemStack itemBySlot = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND);
if (itemBySlot.isEmpty()) {

View File

@@ -0,0 +1,20 @@
--- a/net/minecraft/world/entity/animal/IronGolem.java
+++ b/net/minecraft/world/entity/animal/IronGolem.java
@@ -104,7 +_,7 @@
@Override
protected void doPush(Entity entity) {
if (entity instanceof Enemy && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) {
- this.setTarget((LivingEntity)entity);
+ this.setTarget((LivingEntity)entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason
}
super.doPush(entity);
@@ -303,7 +_,7 @@
BlockPos blockPos = this.blockPosition();
BlockPos blockPos1 = blockPos.below();
BlockState blockState = level.getBlockState(blockPos1);
- if (!blockState.entityCanStandOn(level, blockPos1, this)) {
+ if (!blockState.entityCanStandOn(level, blockPos1, this) && !this.level().paperConfig().entities.spawning.ironGolemsCanSpawnInAir) { // Paper - Add option to allow iron golems to spawn in air
return false;
} else {
for (int i = 1; i < 3; i++) {

View File

@@ -0,0 +1,59 @@
--- a/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
@@ -110,7 +_,17 @@
return InteractionResult.SUCCESS;
} else 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()) 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));
}
@@ -163,15 +_,32 @@
@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.SHEAR_MOOSHROOM, shears, (ignored, stack) -> {
+ for (int i = 0; i < stack.getCount(); ++i) drops.add(stack.copyWithCount(1));
+ });
+ return drops;
+ }
+
+ @Override
+ public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears, java.util.List<ItemStack> drops) {
+ // Paper end
level.playSound(null, this, SoundEvents.MOOSHROOM_SHEAR, soundSource, 1.0F, 1.0F);
this.convertTo(EntityType.COW, ConversionParams.single(this, false, false), mob -> {
level.sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0);
- this.dropFromShearingLootTable(level, BuiltInLootTables.SHEAR_MOOSHROOM, shears, (serverLevel, itemStack) -> {
- for (int i = 0; i < itemStack.getCount(); i++) {
- serverLevel.addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), itemStack.copyWithCount(1)));
- }
+ // Paper start - custom shear drops; moved drop generation to separate method
+ drops.forEach(drop -> {
+ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), drop);
+ this.spawnAtLocation(level, entityitem);
});
- });
+ // Paper end - custom shear drops
+ }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SHEARED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); // CraftBukkit
}
@Override

View File

@@ -0,0 +1,20 @@
--- a/net/minecraft/world/entity/animal/Ocelot.java
+++ b/net/minecraft/world/entity/animal/Ocelot.java
@@ -125,7 +_,7 @@
@Override
public boolean removeWhenFarAway(double distanceToClosestPlayer) {
- return !this.isTrusting() && this.tickCount > 2400;
+ return !this.isTrusting() && this.tickCount > 2400 && !this.hasCustomName() && !this.isLeashed(); // Paper - honor name and leash
}
public static AttributeSupplier.Builder createAttributes() {
@@ -159,7 +_,7 @@
if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemInHand) && player.distanceToSqr(this) < 9.0) {
this.usePlayerItem(player, hand, itemInHand);
if (!this.level().isClientSide) {
- if (this.random.nextInt(3) == 0) {
+ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check
this.setTrusting(true);
this.spawnTrustingParticles(true);
this.level().broadcastEntityEvent(this, (byte)41);

View File

@@ -0,0 +1,81 @@
--- a/net/minecraft/world/entity/animal/Panda.java
+++ b/net/minecraft/world/entity/animal/Panda.java
@@ -127,6 +_,7 @@
}
public void sit(boolean sitting) {
+ if (!new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; // Paper - Add EntityToggleSitEvent
this.setFlag(8, sitting);
}
@@ -516,24 +_,28 @@
for (Panda panda : level.getEntitiesOfClass(Panda.class, this.getBoundingBox().inflate(10.0))) {
if (!panda.isBaby() && panda.onGround() && !panda.isInWater() && panda.canPerformAction()) {
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
panda.jumpFromGround();
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
}
}
if (this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
this.dropFromGiftLootTable(serverLevel, BuiltInLootTables.PANDA_SNEEZE, this::spawnAtLocation);
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
}
}
@Override
protected void pickUpItem(ServerLevel level, ItemEntity entity) {
- if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && canPickUpAndEat(entity)) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, !(this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.canPickUpAndEat(entity))).isCancelled()) { // CraftBukkit
this.onItemPickup(entity);
ItemStack item = entity.getItem();
this.setItemSlot(EquipmentSlot.MAINHAND, item);
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
this.take(entity, item.getCount());
- entity.discard();
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
}
}
@@ -624,8 +_,9 @@
this.usePlayerItem(player, hand, itemInHand);
this.ageUp((int)(-this.getAge() / 20 * 0.1F), true);
} else if (!this.level().isClientSide && this.getAge() == 0 && this.canFallInLove()) {
+ final ItemStack breedCopy = itemInHand.copy(); // Paper - Fix EntityBreedEvent copying
this.usePlayerItem(player, hand, itemInHand);
- this.setInLove(player);
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
} else {
if (!(this.level() instanceof ServerLevel serverLevel) || this.isSitting() || this.isInWater()) {
return InteractionResult.PASS;
@@ -635,7 +_,9 @@
this.eat(true);
ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND);
if (!itemBySlot.isEmpty() && !player.hasInfiniteMaterials()) {
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
this.spawnAtLocation(serverLevel, itemBySlot);
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
}
this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(itemInHand.getItem(), 1));
@@ -861,7 +_,7 @@
@Override
protected void alertOther(Mob mob, LivingEntity target) {
if (mob instanceof Panda && mob.isAggressive()) {
- mob.setTarget(target);
+ mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit
}
}
}
@@ -1090,7 +_,9 @@
public void stop() {
ItemStack itemBySlot = Panda.this.getItemBySlot(EquipmentSlot.MAINHAND);
if (!itemBySlot.isEmpty()) {
+ Panda.this.forceDrops = true; // Paper - Add missing forceDrop toggles
Panda.this.spawnAtLocation(getServerLevel(Panda.this.level()), itemBySlot);
+ Panda.this.forceDrops = false; // Paper - Add missing forceDrop toggles
Panda.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
int i = Panda.this.isLazy() ? Panda.this.random.nextInt(50) + 10 : Panda.this.random.nextInt(150) + 10;
this.cooldown = Panda.this.tickCount + i * 20;

View File

@@ -0,0 +1,44 @@
--- a/net/minecraft/world/entity/animal/Parrot.java
+++ b/net/minecraft/world/entity/animal/Parrot.java
@@ -257,7 +_,7 @@
}
if (!this.level().isClientSide) {
- if (this.random.nextInt(10) == 0) {
+ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
this.tame(player);
this.level().broadcastEntityEvent(this, (byte)7);
} else {
@@ -278,7 +_,7 @@
}
} else {
this.usePlayerItem(player, hand, itemInHand);
- this.addEffect(new MobEffectInstance(MobEffects.POISON, 900));
+ this.addEffect(new MobEffectInstance(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit
if (player.isCreative() || !this.isInvulnerable()) {
this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE);
}
@@ -373,8 +_,8 @@
}
@Override
- public boolean isPushable() {
- return true;
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
}
@Override
@@ -387,10 +_,11 @@
@Override
public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
if (this.isInvulnerableTo(level, damageSource)) {
+ if (!super.hurtServer(level, damageSource, amount)) return false; // CraftBukkit
return false;
} else {
this.setOrderedToSit(false);
- return super.hurtServer(level, damageSource, amount);
+ return true; // CraftBukkit
}
}

View File

@@ -0,0 +1,18 @@
--- a/net/minecraft/world/entity/animal/Pig.java
+++ b/net/minecraft/world/entity/animal/Pig.java
@@ -214,7 +_,14 @@
}
mob.setPersistenceRequired();
- });
+ // CraftBukkit start
+ }, null, null);
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPigZapEvent(this, lightning, zombifiedPiglin).isCancelled()) {
+ return;
+ }
+ level.addFreshEntity(zombifiedPiglin, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING);
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.TRANSFORMATION); // CraftBukkit - add Bukkit remove cause
+ // CraftBukkit end
if (zombifiedPiglin == null) {
super.thunderHit(level, lightning);
}

View File

@@ -0,0 +1,57 @@
--- a/net/minecraft/world/entity/animal/Pufferfish.java
+++ b/net/minecraft/world/entity/animal/Pufferfish.java
@@ -95,24 +_,36 @@
public void tick() {
if (!this.level().isClientSide && this.isAlive() && this.isEffectiveAi()) {
if (this.inflateCounter > 0) {
+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent
if (this.getPuffState() == 0) {
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_UP);
this.setPuffState(1);
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
} else if (this.inflateCounter > 40 && this.getPuffState() == 1) {
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_UP);
this.setPuffState(2);
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
}
+ if (increase) // Paper - Add PufferFishStateChangeEvent
this.inflateCounter++;
} else if (this.getPuffState() != 0) {
+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent
if (this.deflateTimer > 60 && this.getPuffState() == 2) {
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_OUT);
this.setPuffState(1);
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
} else if (this.deflateTimer > 100 && this.getPuffState() == 1) {
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_OUT);
this.setPuffState(0);
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
}
+ if (increase) // Paper - Add PufferFishStateChangeEvent
this.deflateTimer++;
}
}
@@ -136,7 +_,7 @@
private void touch(ServerLevel level, Mob mob) {
int puffState = this.getPuffState();
if (mob.hurtServer(level, this.damageSources().mobAttack(this), 1 + puffState)) {
- mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this);
+ mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F);
}
}
@@ -151,7 +_,7 @@
serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F));
}
- entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this);
+ entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
}
}

View File

@@ -0,0 +1,23 @@
--- a/net/minecraft/world/entity/animal/Rabbit.java
+++ b/net/minecraft/world/entity/animal/Rabbit.java
@@ -88,7 +_,7 @@
super(entityType, level);
this.jumpControl = new Rabbit.RabbitJumpControl(this);
this.moveControl = new Rabbit.RabbitMoveControl(this);
- this.setSpeedModifier(0.0);
+ //this.setSpeedModifier(0.0); // CraftBukkit
}
@Override
@@ -561,9 +_,11 @@
if (this.canRaid && block instanceof CarrotBlock) {
int ageValue = blockState.getValue(CarrotBlock.AGE);
if (ageValue == 0) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockPos, blockState.getFluidState().createLegacyBlock())) return; // CraftBukkit // Paper - fix wrong block state
level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 2);
level.destroyBlock(blockPos, true, this.rabbit);
} else {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockPos, blockState.setValue(CarrotBlock.AGE, ageValue - 1))) return; // CraftBukkit // Paper - fix wrong block state
level.setBlock(blockPos, blockState.setValue(CarrotBlock.AGE, Integer.valueOf(ageValue - 1)), 2);
level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(this.rabbit));
level.levelEvent(2001, blockPos, Block.getId(blockState));

View File

@@ -0,0 +1,75 @@
--- a/net/minecraft/world/entity/animal/Sheep.java
+++ b/net/minecraft/world/entity/animal/Sheep.java
@@ -40,7 +_,6 @@
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
@@ -158,7 +_,19 @@
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.SHEARS)) {
if (this.level() instanceof ServerLevel serverLevel && this.readyForShearing()) {
- 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()) {
+ 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));
return InteractionResult.SUCCESS_SERVER;
@@ -172,14 +_,28 @@
@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.SHEAR_SHEEP, shears, (ignored, stack) -> {
+ for (int i = 0; i < stack.getCount(); ++i) drops.add(stack.copyWithCount(1));
+ });
+ 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.SHEEP_SHEAR, soundSource, 1.0F, 1.0F);
- this.dropFromShearingLootTable(
- level,
- BuiltInLootTables.SHEAR_SHEEP,
- shears,
- (serverLevel, itemStack) -> {
- for (int i = 0; i < itemStack.getCount(); i++) {
- ItemEntity itemEntity = this.spawnAtLocation(serverLevel, itemStack.copyWithCount(1), 1.0F);
+ drops.forEach(itemstack1 -> { // Paper - custom drops - loop in generated default drops
+ if (true) { // Paper - custom drops - loop in generated default drops
+ this.forceDrops = true; // CraftBukkit
+ ItemEntity itemEntity = this.spawnAtLocation(level, itemstack1, 1.0F); // Paper - custom drops - copy already done above
+ this.forceDrops = false; // CraftBukkit
if (itemEntity != null) {
itemEntity.setDeltaMovement(
itemEntity.getDeltaMovement()
@@ -287,6 +_,7 @@
@Override
public void ate() {
+ if (!new org.bukkit.event.entity.SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity()).callEvent()) return; // CraftBukkit
super.ate();
this.setSheared(false);
if (this.isBaby()) {

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/animal/ShoulderRidingEntity.java
+++ b/net/minecraft/world/entity/animal/ShoulderRidingEntity.java
@@ -19,7 +_,7 @@
compoundTag.putString("id", this.getEncodeId());
this.saveWithoutId(compoundTag);
if (player.setEntityOnShoulder(compoundTag)) {
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
return true;
} else {
return false;

View File

@@ -0,0 +1,74 @@
--- a/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
@@ -92,7 +_,7 @@
super.aiStep();
if (this.level() instanceof ServerLevel serverLevel) {
if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) {
- this.hurtServer(serverLevel, this.damageSources().onFire(), 1.0F);
+ this.hurtServer(serverLevel, this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING
}
if (!serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
@@ -107,7 +_,7 @@
int floor2 = Mth.floor(this.getZ() + (i / 2 % 2 * 2 - 1) * 0.25F);
BlockPos blockPos = new BlockPos(floor, floor1, floor2);
if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) {
- this.level().setBlockAndUpdate(blockPos, blockState);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockPos, blockState, this)) continue; // CraftBukkit
this.level().gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this, blockState));
}
}
@@ -135,7 +_,19 @@
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()) {
+ 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));
}
@@ -148,11 +_,29 @@
@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.SHEAR_SNOW_GOLEM, 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.SNOW_GOLEM_SHEAR, soundSource, 1.0F, 1.0F);
this.setPumpkin(false);
- this.dropFromShearingLootTable(
- level, BuiltInLootTables.SHEAR_SNOW_GOLEM, shears, (serverLevel, itemStack) -> this.spawnAtLocation(serverLevel, itemStack, this.getEyeHeight())
- );
+ drops.forEach(itemstack1 -> { // Paper - custom shear drops
+ this.forceDrops = true; // CraftBukkit
+ this.spawnAtLocation(level, itemstack1, this.getEyeHeight());
+ this.forceDrops = false; // CraftBukkit
+ });
}
@Override

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/animal/Squid.java
+++ b/net/minecraft/world/entity/animal/Squid.java
@@ -46,7 +_,7 @@
public Squid(EntityType<? extends Squid> entityType, Level level) {
super(entityType, level);
- this.random.setSeed(this.getId());
+ //this.random.setSeed(this.getId()); // Paper - Share random for entities to make them more random
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
}

View File

@@ -0,0 +1,75 @@
--- a/net/minecraft/world/entity/animal/Turtle.java
+++ b/net/minecraft/world/entity/animal/Turtle.java
@@ -303,7 +_,9 @@
protected void ageBoundaryReached() {
super.ageBoundaryReached();
if (!this.isBaby() && this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
+ this.forceDrops = true; // CraftBukkit
this.spawnAtLocation(serverLevel, Items.TURTLE_SCUTE, 1);
+ this.forceDrops = false; // CraftBukkit
}
}
@@ -328,7 +_,7 @@
@Override
public void thunderHit(ServerLevel level, LightningBolt lightning) {
- this.hurtServer(level, this.damageSources().lightningBolt(), Float.MAX_VALUE);
+ this.hurtServer(level, this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
}
@Override
@@ -355,6 +_,10 @@
if (loveCause == null && this.partner.getLoveCause() != null) {
loveCause = this.partner.getLoveCause();
}
+ // Paper start - Add EntityFertilizeEggEvent event
+ io.papermc.paper.event.entity.EntityFertilizeEggEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this.animal, this.partner);
+ if (event.isCancelled()) return;
+ // Paper end - Add EntityFertilizeEggEvent event
if (loveCause != null) {
loveCause.awardStat(Stats.ANIMALS_BRED);
@@ -368,7 +_,7 @@
this.partner.resetLove();
RandomSource random = this.animal.getRandom();
if (getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1));
+ if (event.getExperience() > 0) this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), , event.getExperience(), org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, loveCause)); // Paper - Add EntityFertilizeEggEvent event
}
}
}
@@ -392,7 +_,7 @@
this.turtle.hasEgg()
|| this.turtle.getRandom().nextInt(reducedTickDelay(700)) == 0
&& !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0)
- );
+ ) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper - Turtle API
}
@Override
@@ -500,16 +_,22 @@
BlockPos blockPos = this.turtle.blockPosition();
if (!this.turtle.isInWater() && this.isReachedTarget()) {
if (this.turtle.layEggCounter < 1) {
- this.turtle.setLayingEgg(true);
+ this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos)).callEvent()); // Paper - Turtle API
} else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) {
+ // Paper start - Turtle API
+ int eggCount = this.turtle.random.nextInt(4) + 1;
+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos.above()), eggCount);
+ if (layEggEvent.callEvent() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()))) {
+ // Paper end
Level level = this.turtle.level();
level.playSound(null, blockPos, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + level.random.nextFloat() * 0.2F);
BlockPos blockPos1 = this.blockPos.above();
BlockState blockState = Blocks.TURTLE_EGG
.defaultBlockState()
- .setValue(TurtleEggBlock.EGGS, Integer.valueOf(this.turtle.random.nextInt(4) + 1));
+ .setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()); // Paper
level.setBlock(blockPos1, blockState, 3);
level.gameEvent(GameEvent.BLOCK_PLACE, blockPos1, GameEvent.Context.of(this.turtle, blockState));
+ } // Paper
this.turtle.setHasEgg(false);
this.turtle.setLayingEgg(false);
this.turtle.setInLoveTime(600);

View File

@@ -0,0 +1,13 @@
--- a/net/minecraft/world/entity/animal/WaterAnimal.java
+++ b/net/minecraft/world/entity/animal/WaterAnimal.java
@@ -70,6 +_,10 @@
) {
int seaLevel = level.getSeaLevel();
int i = seaLevel - 13;
+ // Paper start - Make water animal spawn height configurable
+ seaLevel = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(seaLevel);
+ i = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(i);
+ // Paper end - Make water animal spawn height configurable
return pos.getY() >= i
&& pos.getY() <= seaLevel
&& level.getFluidState(pos.below()).is(FluidTags.WATER)

View File

@@ -0,0 +1,95 @@
--- a/net/minecraft/world/entity/animal/Wolf.java
+++ b/net/minecraft/world/entity/animal/Wolf.java
@@ -344,8 +_,9 @@
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {
+ if (!super.hurtServer(level, damageSource, amount)) return false; // CraftBukkit
this.setOrderedToSit(false);
- return super.hurtServer(level, damageSource, amount);
+ return true; // CraftBUkkit
}
}
@@ -355,10 +_,11 @@
}
@Override
- protected void actuallyHurt(ServerLevel level, DamageSource damageSource, float amount) {
+ public boolean actuallyHurt(ServerLevel level, DamageSource damageSource, float amount, org.bukkit.event.entity.EntityDamageEvent event) { // CraftBukkit - void -> boolean
if (!this.canArmorAbsorb(damageSource)) {
- super.actuallyHurt(level, damageSource, amount);
+ super.actuallyHurt(level, damageSource, amount, event); // CraftBukkit
} else {
+ if (event.isCancelled()) return false; // CraftBukkit - SPIGOT-7815: if the damage was cancelled, no need to run the wolf armor behaviour
ItemStack bodyArmorItem = this.getBodyArmorItem();
int damageValue = bodyArmorItem.getDamageValue();
int maxDamage = bodyArmorItem.getMaxDamage();
@@ -378,6 +_,7 @@
);
}
}
+ return true; // CraftBukkit // Paper - return false ONLY if event was cancelled
}
private boolean canArmorAbsorb(DamageSource damageSource) {
@@ -388,7 +_,7 @@
protected void applyTamingSideEffects() {
if (this.isTame()) {
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(40.0);
- this.setHealth(40.0F);
+ this.setHealth(this.getMaxHealth()); // CraftBukkit - 40.0 -> getMaxHealth()
} else {
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0);
}
@@ -408,7 +_,7 @@
this.usePlayerItem(player, hand, itemInHand);
FoodProperties foodProperties = itemInHand.get(DataComponents.FOOD);
float f = foodProperties != null ? foodProperties.nutrition() : 1.0F;
- this.heal(2.0F * f);
+ this.heal(2.0F * f, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit
return InteractionResult.SUCCESS;
}
@@ -441,7 +_,7 @@
this.setOrderedToSit(!this.isOrderedToSit());
this.jumping = false;
this.navigation.stop();
- this.setTarget(null);
+ this.setTarget(null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason
return InteractionResult.SUCCESS.withoutItem();
}
@@ -453,7 +_,9 @@
ItemStack bodyArmorItem = this.getBodyArmorItem();
this.setBodyArmorItem(ItemStack.EMPTY);
if (this.level() instanceof ServerLevel serverLevel) {
+ this.forceDrops = true; // CraftBukkit
this.spawnAtLocation(serverLevel, bodyArmorItem);
+ this.forceDrops = false; // CraftBukkit
}
return InteractionResult.SUCCESS;
@@ -461,6 +_,13 @@
DyeColor dyeColor = dyeItem.getDyeColor();
if (dyeColor != this.getCollarColor()) {
+ // Paper start - Add EntityDyeEvent and CollarColorable interface
+ final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) dyeColor.getId()), player.getBukkitEntity());
+ if (!event.callEvent()) {
+ return InteractionResult.FAIL;
+ }
+ dyeColor = DyeColor.byId(event.getColor().getWoolData());
+ // Paper end - Add EntityDyeEvent and CollarColorable interface
this.setCollarColor(dyeColor);
itemInHand.consume(1, player);
return InteractionResult.SUCCESS;
@@ -475,7 +_,7 @@
}
private void tryToTame(Player player) {
- if (this.random.nextInt(3) == 0) {
+ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check.
this.tame(player);
this.navigation.stop();
this.setTarget(null);