Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: MiniDigger | Martin <admin@minidigger.dev>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com>
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
Nassim Jahnke
2025-04-12 17:26:44 +02:00
parent 0767902699
commit f00727c57e
2092 changed files with 50551 additions and 48729 deletions

View File

@@ -1,22 +1,31 @@
--- a/net/minecraft/world/entity/AgeableMob.java
+++ b/net/minecraft/world/entity/AgeableMob.java
@@ -20,6 +_,7 @@
protected int age;
protected int forcedAge;
@@ -22,6 +_,7 @@
protected int age = 0;
protected int forcedAge = 0;
protected int forcedAgeTimer;
+ public boolean ageLocked; // CraftBukkit
protected AgeableMob(EntityType<? extends AgeableMob> entityType, Level level) {
super(entityType, level);
@@ -66,6 +_,7 @@
@@ -68,13 +_,15 @@
}
public void ageUp(int amount, boolean forced) {
+ if (this.ageLocked) return; // Paper - Honor ageLock
int age = this.getAge();
+ int previousAge = age; // Paper - Decompile fix: lvt reassignment lost
age += amount * 20;
if (age > 0) {
@@ -104,6 +_,7 @@
age = 0;
}
- int i1 = age - age;
+ int i1 = age - previousAge; // Paper - Decompile fix
this.setAge(age);
if (forced) {
this.forcedAge += i1;
@@ -106,6 +_,7 @@
super.addAdditionalSaveData(compound);
compound.putInt("Age", this.getAge());
compound.putInt("ForcedAge", this.forcedAge);
@@ -24,15 +33,15 @@
}
@Override
@@ -111,6 +_,7 @@
@@ -113,6 +_,7 @@
super.readAdditionalSaveData(compound);
this.setAge(compound.getInt("Age"));
this.forcedAge = compound.getInt("ForcedAge");
+ this.ageLocked = compound.getBoolean("AgeLocked"); // CraftBukkit
this.setAge(compound.getIntOr("Age", 0));
this.forcedAge = compound.getIntOr("ForcedAge", 0);
+ this.ageLocked = compound.getBooleanOr("AgeLocked", false); // CraftBukkit
}
@Override
@@ -125,7 +_,7 @@
@@ -127,7 +_,7 @@
@Override
public void aiStep() {
super.aiStep();

View File

@@ -1,24 +1,24 @@
--- a/net/minecraft/world/entity/AreaEffectCloud.java
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
@@ -47,7 +_,7 @@
public float radiusOnUse;
public float radiusPerTick;
@@ -59,7 +_,7 @@
public float radiusOnUse = 0.0F;
public float radiusPerTick = 0.0F;
@Nullable
- private LivingEntity owner;
+ private net.minecraft.world.entity.LivingEntity owner;
@Nullable
public UUID ownerUUID;
@@ -177,7 +_,7 @@
@@ -193,7 +_,7 @@
private void serverTick(ServerLevel level) {
if (this.tickCount >= this.waitTime + this.duration) {
if (this.duration != -1 && this.tickCount >= this.waitTime + this.duration) {
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
boolean isWaiting = this.isWaiting();
boolean flag = this.tickCount < this.waitTime;
@@ -190,7 +_,7 @@
@@ -206,7 +_,7 @@
if (this.radiusPerTick != 0.0F) {
radius += this.radiusPerTick;
if (radius < 0.5F) {
@@ -27,15 +27,15 @@
return;
}
@@ -220,6 +_,7 @@
list.addAll(this.potionContents.customEffects());
@@ -222,6 +_,7 @@
this.potionContents.forEachEffect(list::add, this.potionDurationScale);
List<LivingEntity> entitiesOfClass = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox());
if (!entitiesOfClass.isEmpty()) {
+ List<org.bukkit.entity.LivingEntity> entities = new java.util.ArrayList<>(); // CraftBukkit
for (LivingEntity livingEntity : entitiesOfClass) {
if (!this.victims.containsKey(livingEntity)
&& livingEntity.isAffectedByPotions()
@@ -228,6 +_,17 @@
@@ -230,6 +_,17 @@
double d1 = livingEntity.getZ() - this.getZ();
double d2 = d * d + d1 * d1;
if (d2 <= radius * radius) {
@@ -52,13 +52,13 @@
+ // CraftBukkit end
this.victims.put(livingEntity, this.tickCount + this.reapplicationDelay);
for (MobEffectInstance mobEffectInstance1 : list) {
@@ -236,14 +_,14 @@
for (MobEffectInstance mobEffectInstance : list) {
@@ -238,14 +_,14 @@
.value()
.applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance1.getAmplifier(), 0.5);
.applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), 0.5);
} else {
- livingEntity.addEffect(new MobEffectInstance(mobEffectInstance1), this);
+ livingEntity.addEffect(new MobEffectInstance(mobEffectInstance1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit
- livingEntity.addEffect(new MobEffectInstance(mobEffectInstance), this);
+ livingEntity.addEffect(new MobEffectInstance(mobEffectInstance), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit
}
}
@@ -70,8 +70,8 @@
return;
}
@@ -253,7 +_,7 @@
if (this.durationOnUse != 0) {
@@ -255,7 +_,7 @@
if (this.durationOnUse != 0 && this.duration != -1) {
this.duration = this.duration + this.durationOnUse;
if (this.duration <= 0) {
- this.discard();

View File

@@ -9,3 +9,11 @@
}
firstPassenger.startRiding(newMob);
@@ -70,6 +_,7 @@
if (leashHolder != null) {
oldMob.dropLeash();
}
+ newMob.aware = oldMob.aware; // Paper - Fix nerfed slime when splitting
this.convertCommon(oldMob, newMob, conversionParams);
}

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/Display.java
+++ b/net/minecraft/world/entity/Display.java
@@ -213,7 +_,7 @@
if (tag.contains("transformation")) {
Transformation.EXTENDED_CODEC
.decode(NbtOps.INSTANCE, tag.get("transformation"))
- .resultOrPartial(Util.prefix("Display entity", LOGGER::error))
+ .result() // Paper - Hide text display error on spawn
.ifPresent(pair -> this.setTransformation(pair.getFirst()));
}

View File

@@ -0,0 +1,14 @@
--- a/net/minecraft/world/entity/EntityEquipment.java
+++ b/net/minecraft/world/entity/EntityEquipment.java
@@ -71,4 +_,11 @@
public void clear() {
this.items.replaceAll((equipmentSlot, itemStack) -> ItemStack.EMPTY);
}
+
+ // Paper start - EntityDeathEvent
+ // Needed to not set ItemStack.EMPTY to not existent slot.
+ public boolean has(final EquipmentSlot slot) {
+ return this.items.containsKey(slot);
+ }
+ // Paper end - EntityDeathEvent
}

View File

@@ -1,18 +1,17 @@
--- a/net/minecraft/world/entity/EntitySelector.java
+++ b/net/minecraft/world/entity/EntitySelector.java
@@ -16,6 +_,23 @@
@@ -17,6 +_,22 @@
public static final Predicate<Entity> NO_SPECTATORS = entity -> !entity.isSpectator();
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = NO_SPECTATORS.and(Entity::canBeCollidedWith);
public static final Predicate<Entity> CAN_BE_PICKED = NO_SPECTATORS.and(Entity::isPickable);
+ // Paper start - Ability to control player's insomnia and phantoms
+ public static Predicate<Player> IS_INSOMNIAC = (player) -> {
+ net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player;
+ int playerInsomniaTicks = serverPlayer.level().paperConfig().entities.behavior.playerInsomniaStartTicks;
+
+ int playerInsomniaTicks = player.level().paperConfig().entities.behavior.playerInsomniaStartTicks;
+ if (playerInsomniaTicks <= 0) {
+ return false;
+ }
+
+ net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player;
+ return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks;
+ };
+ // Paper end - Ability to control player's insomnia and phantoms
@@ -24,13 +23,14 @@
private EntitySelector() {
}
@@ -26,29 +_,34 @@
@@ -27,18 +_,24 @@
}
public static Predicate<Entity> pushableBy(Entity entity) {
+ // Paper start - Climbing should not bypass cramming gamerule
+ return pushable(entity, false);
+ }
+
+ public static Predicate<Entity> pushable(Entity entity, boolean ignoreClimbing) {
+ // Paper end - Climbing should not bypass cramming gamerule
Team team = entity.getTeam();
@@ -38,38 +38,15 @@
return (Predicate<Entity>)(collisionRule == Team.CollisionRule.NEVER
? Predicates.alwaysFalse()
: NO_SPECTATORS.and(
- pushedEntity -> {
pushedEntity -> {
- if (!pushedEntity.isPushable()) {
+ pushedEntity -> {
+ if (!pushedEntity.isCollidable(ignoreClimbing) || !pushedEntity.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(pushedEntity)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
+ return false;
+ } else if (!entity.level().isClientSide || pushedEntity instanceof Player && ((Player)pushedEntity).isLocalPlayer()) {
+ Team team1 = pushedEntity.getTeam();
+ Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
+ if (collisionRule1 == Team.CollisionRule.NEVER || (pushedEntity instanceof Player && !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions)) { // Paper - Configurable player collision
+ if (!pushedEntity.isCollidable(ignoreClimbing) || !pushedEntity.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(pushedEntity)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
return false;
- } else if (!entity.level().isClientSide || pushedEntity instanceof Player && ((Player)pushedEntity).isLocalPlayer()) {
- Team team1 = pushedEntity.getTeam();
- Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
} else if (!entity.level().isClientSide || pushedEntity instanceof Player player && player.isLocalPlayer()) {
Team team1 = pushedEntity.getTeam();
Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
- if (collisionRule1 == Team.CollisionRule.NEVER) {
- return false;
- } else {
- boolean flag = team != null && team.isAlliedTo(team1);
- return (collisionRule != Team.CollisionRule.PUSH_OWN_TEAM && collisionRule1 != Team.CollisionRule.PUSH_OWN_TEAM || !flag)
- && (collisionRule != Team.CollisionRule.PUSH_OTHER_TEAMS && collisionRule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag);
- }
} else {
- return false;
+ boolean flag = team != null && team.isAlliedTo(team1);
+ return (collisionRule != Team.CollisionRule.PUSH_OWN_TEAM && collisionRule1 != Team.CollisionRule.PUSH_OWN_TEAM || !flag)
+ && (collisionRule != Team.CollisionRule.PUSH_OTHER_TEAMS && collisionRule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag);
}
+ } else {
+ return false;
}
- ));
+ }
+ ));
}
public static Predicate<Entity> notRiding(Entity entity) {
+ if (collisionRule1 == Team.CollisionRule.NEVER || (pushedEntity instanceof Player && !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions)) { // Paper - Configurable player collision
return false;
} else {
boolean flag = team != null && team.isAlliedTo(team1);

View File

@@ -1,14 +1,6 @@
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -176,6 +_,7 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.entity.CreatureSpawnEvent;
import org.slf4j.Logger;
public class EntityType<T extends Entity> implements FeatureElement, EntityTypeTest<Entity, T> {
@@ -215,7 +_,7 @@
@@ -216,7 +_,7 @@
.fireImmune()
.sized(6.0F, 0.5F)
.clientTrackingRange(10)
@@ -17,19 +9,19 @@
);
public static final EntityType<Armadillo> ARMADILLO = register(
"armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10)
@@ -1132,6 +_,22 @@
@@ -1145,6 +_,22 @@
boolean shouldOffsetY,
boolean shouldOffsetYMore
) {
+ // CraftBukkit start
+ return this.spawn(level, spawnedFrom, player, pos, reason, shouldOffsetY, shouldOffsetYMore, reason == EntitySpawnReason.DISPENSER ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Paper - use correct spawn reason for dispenser spawn eggs
+ return this.spawn(level, spawnedFrom, owner, pos, reason, shouldOffsetY, shouldOffsetYMore, reason == EntitySpawnReason.DISPENSER ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Paper - use correct spawn reason for dispenser spawn eggs
+ }
+
+ @Nullable
+ public T spawn(
+ ServerLevel level,
+ @Nullable ItemStack spawnedFrom,
+ @Nullable Player player,
+ @Nullable LivingEntity owner,
+ BlockPos pos,
+ EntitySpawnReason reason,
+ boolean shouldOffsetY,
@@ -39,8 +31,8 @@
+ // CraftBukkit end
Consumer<T> consumer;
if (spawnedFrom != null) {
consumer = createDefaultStackConfig(level, spawnedFrom, player);
@@ -1139,7 +_,7 @@
consumer = createDefaultStackConfig(level, spawnedFrom, owner);
@@ -1152,7 +_,7 @@
consumer = entity -> {};
}
@@ -48,16 +40,16 @@
+ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, createSpawnReason); // CraftBukkit
}
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack spawnedFrom, @Nullable Player player) {
@@ -1159,19 +_,54 @@
Consumer<T> consumer, Level level, ItemStack spawnedFrom, @Nullable Player player
) {
CustomData customData = spawnedFrom.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
- return !customData.isEmpty() ? consumer.andThen(entity -> updateCustomEntityTag(level, player, entity, customData)) : consumer;
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack stack, @Nullable LivingEntity owner) {
@@ -1169,19 +_,56 @@
public static <T extends Entity> Consumer<T> appendCustomEntityStackConfig(Consumer<T> consumer, Level level, ItemStack stack, @Nullable LivingEntity owner) {
CustomData customData = stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
- return !customData.isEmpty() ? consumer.andThen(entity -> updateCustomEntityTag(level, owner, entity, customData)) : consumer;
+ // CraftBukkit start - SPIGOT-5665
+ return !customData.isEmpty() ? consumer.andThen(entity -> {
+ try {
+ updateCustomEntityTag(level, player, entity, customData);
+ updateCustomEntityTag(level, owner, entity, customData);
+ } catch (Throwable t) {
+ EntityType.LOGGER.warn("Error loading spawn egg NBT", t);
+ }
@@ -71,6 +63,7 @@
+ // CraftBukkit start
+ return this.spawn(level, pos, reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ @Nullable
+ public T spawn(ServerLevel level, BlockPos pos, EntitySpawnReason reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
+ return this.spawn(level, null, pos, reason, false, false, creatureSpawnReason);
@@ -82,12 +75,13 @@
+ // CraftBukkit start
+ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ @Nullable
+ public T spawn(ServerLevel level, @Nullable Consumer<T> consumer, BlockPos pos, EntitySpawnReason reason, boolean shouldOffsetY, boolean shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
+ // CraftBukkit end
+ // Paper start - PreCreatureSpawnEvent
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
+ io.papermc.paper.util.MCUtil.toLocation(level, pos),
+ org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level),
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this),
+ creatureSpawnReason
+ );
@@ -107,12 +101,12 @@
if (entity instanceof Mob mob) {
mob.playAmbientSound();
}
@@ -1225,6 +_,15 @@
EntityType<?> entityType = customData.parseEntityType(server.registryAccess(), Registries.ENTITY_TYPE);
if (entity.getType() == entityType) {
if (level.isClientSide || !entity.getType().onlyOpCanSetNbt() || player != null && server.getPlayerList().isOp(player.getGameProfile())) {
@@ -1237,6 +_,15 @@
if (level.isClientSide
|| !entity.getType().onlyOpCanSetNbt()
|| owner instanceof Player player && server.getPlayerList().isOp(player.getGameProfile())) {
+ // Paper start - filter out protected tags
+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
+ if (owner == null || !owner.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
+ customData = customData.update((compound) -> {
+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : level.paperConfig().entities.spawning.filteredEntityTagNbtPaths) {
+ tag.remove(compound);
@@ -123,33 +117,25 @@
customData.loadInto(entity);
}
}
@@ -1296,9 +_,19 @@
@@ -1308,9 +_,20 @@
}
public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason) {
+ // Paper start - Don't fire sync event during generation
+ return create(tag, level, spawnReason, false);
+ }
+
+ public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason, boolean generation) {
+ // Paper end - Don't fire sync event during generation
return Util.ifElse(
by(tag).map(entityType -> entityType.create(level, spawnReason)),
- entity -> entity.load(tag),
+ // Paper start - Don't fire sync event during generation
+ entity -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
+ entity.load(tag);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id"))
+ // Paper start - Don't fire sync event during generation
+ entity -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
+ entity.load(tag);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", tag.getStringOr("id", "[invalid]"))
);
}
@@ -1325,7 +_,7 @@
}
public static Optional<EntityType<?>> by(CompoundTag tag) {
- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(tag.getString("id")));
+ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(tag.getString("id"))); // Paper - Validate ResourceLocation
}
@Nullable

View File

@@ -1,102 +1,87 @@
--- a/net/minecraft/world/entity/ExperienceOrb.java
+++ b/net/minecraft/world/entity/ExperienceOrb.java
@@ -24,6 +_,14 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.event.player.PlayerExpCooldownChangeEvent;
+// CraftBukkit end
+
public class ExperienceOrb extends Entity {
private static final int LIFETIME = 6000;
private static final int ENTITY_SCAN_PERIOD = 20;
@@ -35,9 +_,63 @@
public int value;
public int count = 1;
@@ -41,9 +_,54 @@
@Nullable
private Player followingPlayer;
private final InterpolationHandler interpolation = new InterpolationHandler(this);
-
+ // Paper start
+ @javax.annotation.Nullable
+ @Nullable
+ public java.util.UUID sourceEntityId;
+ @javax.annotation.Nullable
+ @Nullable
+ public java.util.UUID triggerEntityId;
+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+
+ private void loadPaperNBT(CompoundTag tag) {
+ if (!tag.contains("Paper.ExpData", net.minecraft.nbt.Tag.TAG_COMPOUND)) {
+ CompoundTag expData = tag.getCompoundOrEmpty("Paper.ExpData");
+ if (expData.isEmpty()) {
+ return;
+ }
+ CompoundTag comp = tag.getCompound("Paper.ExpData");
+ if (comp.hasUUID("source")) {
+ this.sourceEntityId = comp.getUUID("source");
+ }
+ if (comp.hasUUID("trigger")) {
+ this.triggerEntityId = comp.getUUID("trigger");
+ }
+ if (comp.contains("reason")) {
+ String reason = comp.getString("reason");
+
+ this.sourceEntityId = expData.read("source", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ this.triggerEntityId = expData.read("trigger", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ expData.getString("reason").ifPresent(reason -> {
+ try {
+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
+ } catch (Exception e) {
+ this.level().getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
+ }
+ }
+ });
+ }
+ private void savePaperNBT(CompoundTag tag) {
+ CompoundTag comp = new CompoundTag();
+ if (this.sourceEntityId != null) {
+ comp.putUUID("source", this.sourceEntityId);
+ CompoundTag expData = new CompoundTag();
+ expData.storeNullable("source", net.minecraft.core.UUIDUtil.CODEC, this.sourceEntityId);
+ expData.storeNullable("trigger", net.minecraft.core.UUIDUtil.CODEC, this.triggerEntityId);
+ if (this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
+ expData.putString("reason", this.spawnReason.name());
+ }
+ if (this.triggerEntityId != null) {
+ comp.putUUID("trigger", triggerEntityId);
+ }
+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
+ comp.putString("reason", this.spawnReason.name());
+ }
+ tag.put("Paper.ExpData", comp);
+ tag.put("Paper.ExpData", expData);
+ }
+
+ @io.papermc.paper.annotation.DoNotUse
+ @Deprecated
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
public ExperienceOrb(Level level, double x, double y, double z, int value) {
+ this(level, x, y, z, value, null, null);
+ }
+
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @javax.annotation.Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @javax.annotation.Nullable Entity triggerId) {
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId) {
+ this(level, x, y, z, value, reason, triggerId, null);
+ }
+
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @javax.annotation.Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @javax.annotation.Nullable Entity triggerId, @javax.annotation.Nullable Entity sourceId) {
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
this(EntityType.EXPERIENCE_ORB, level);
+ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null;
+ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null;
+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+ // Paper end
this.setPos(x, y, z);
this.setYRot((float)(this.random.nextDouble() * 360.0));
this.setDeltaMovement(
@@ -67,6 +_,7 @@
@Override
public void tick() {
super.tick();
+ Player prevTarget = this.followingPlayer;// CraftBukkit - store old target
this.xo = this.getX();
this.yo = this.getY();
this.zo = this.getZ();
@@ -92,7 +_,22 @@
this.followingPlayer = null;
if (!this.level().isClientSide) {
this.setYRot((float)(this.random.nextDouble() * 360.0));
@@ -119,12 +_,13 @@
this.age++;
if (this.age >= 6000) {
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
}
private void followNearbyPlayer() {
+ Player prevTarget = this.followingPlayer; // CraftBukkit - store old target
if (this.followingPlayer == null || this.followingPlayer.isSpectator() || this.followingPlayer.distanceToSqr(this) > 64.0) {
Player nearestPlayer = this.level().getNearestPlayer(this, 8.0);
if (nearestPlayer != null && !nearestPlayer.isSpectator() && !nearestPlayer.isDeadOrDying()) {
@@ -134,7 +_,24 @@
}
}
- if (this.followingPlayer != null) {
+ // CraftBukkit start
+ boolean cancelled = false;
+ if (this.followingPlayer != prevTarget) {
+ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this, this.followingPlayer, (this.followingPlayer != null) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.FORGOT_TARGET);
+ org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(
+ this, this.followingPlayer, (this.followingPlayer != null) ? org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER : org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET
+ );
+ LivingEntity target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle();
+ cancelled = event.isCancelled();
+
@@ -112,26 +97,19 @@
Vec3 vec3 = new Vec3(
this.followingPlayer.getX() - this.getX(),
this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(),
@@ -120,7 +_,7 @@
this.age++;
if (this.age >= 6000) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
@@ -143,16 +_,25 @@
@@ -161,16 +_,27 @@
}
public static void award(ServerLevel level, Vec3 pos, int amount) {
+ // Paper start - add reasons for orbs
+ award(level, pos, amount, null, null, null);
+ }
+ public static void award(ServerLevel level, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) {
+
+ public static void award(ServerLevel level, Vec3 pos, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId) {
+ award(level, pos, amount, reason, triggerId, null);
+ }
+ public static void award(ServerLevel level, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) {
+
+ public static void award(ServerLevel level, Vec3 pos, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reasons for orbs
while (amount > 0) {
int experienceValue = getExperienceValue(amount);
@@ -148,7 +126,7 @@
AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0);
int randomInt = level.getRandom().nextInt(40);
List<ExperienceOrb> entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount));
@@ -175,9 +_,14 @@
@@ -193,9 +_,14 @@
}
private void merge(ExperienceOrb orb) {
@@ -160,36 +138,36 @@
this.count = this.count + orb.count;
this.age = Math.min(this.age, orb.age);
- orb.discard();
+ orb.discard(EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause
+ orb.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause
}
private void setUnderwaterMovement() {
@@ -202,7 +_,7 @@
@@ -220,7 +_,7 @@
this.markHurt();
this.health = (int)(this.health - amount);
if (this.health <= 0) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
}
return true;
@@ -213,32 +_,34 @@
@@ -231,32 +_,34 @@
public void addAdditionalSaveData(CompoundTag compound) {
compound.putShort("Health", (short)this.health);
compound.putShort("Age", (short)this.age);
- compound.putShort("Value", (short)this.value);
+ compound.putInt("Value", this.value); // Paper - save as Integer
- compound.putShort("Value", (short)this.getValue());
+ compound.putInt("Value", this.getValue()); // Paper - save as Integer
compound.putInt("Count", this.count);
+ this.savePaperNBT(compound); // Paper
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
this.health = compound.getShort("Health");
this.age = compound.getShort("Age");
- this.value = compound.getShort("Value");
+ this.value = compound.getInt("Value"); // Paper - load as Integer
this.count = Math.max(compound.getInt("Count"), 1);
this.health = compound.getShortOr("Health", (short)5);
this.age = compound.getShortOr("Age", (short)0);
- this.setValue(compound.getShortOr("Value", (short)0));
+ this.setValue(compound.getIntOr("Value", 0)); // Paper - load as Integer
this.count = compound.read("Count", ExtraCodecs.POSITIVE_INT).orElse(1);
+ this.loadPaperNBT(compound); // Paper
}
@@ -199,29 +177,29 @@
- if (entity.takeXpDelay == 0) {
- entity.takeXpDelay = 2;
+ if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent
+ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
+ entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
entity.take(this, 1);
int i = this.repairPlayerItems(serverPlayer, this.value);
int i = this.repairPlayerItems(serverPlayer, this.getValue());
if (i > 0) {
- entity.giveExperiencePoints(i);
+ entity.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entity, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object
+ entity.giveExperiencePoints(org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerExpChangeEvent(entity, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object
}
this.count--;
if (this.count == 0) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
}
}
}
@@ -252,10 +_,21 @@
@@ -270,9 +_,19 @@
ItemStack itemStack = randomItemWith.get().itemStack();
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemStack, value);
int min = Math.min(i, itemStack.getDamageValue());
+ // CraftBukkit start
+ // Paper start - mending event
+ final int consumedExperience = min > 0 ? min * value / i : 0;
+ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemStack, randomItemWith.get().inSlot(), min, consumedExperience);
+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(player, this, itemStack, randomItemWith.get().inSlot(), min, consumedExperience);
+ // Paper end - mending event
+ min = event.getRepairAmount();
+ if (event.isCancelled()) {
@@ -233,11 +211,9 @@
- int i1 = value - min * value / i;
+ int i1 = value - min * value / i; // Paper - diff on change - expand PlayerMendEvents
if (i1 > 0) {
+ // this.value = l; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls // Paper - the value field should not be mutated here because it doesn't take "count" into account
return this.repairPlayerItems(player, i1);
}
}
@@ -295,6 +_,24 @@
@@ -318,6 +_,24 @@
}
public static int getExperienceValue(int expValue) {

View File

@@ -0,0 +1,66 @@
--- a/net/minecraft/world/entity/InsideBlockEffectApplier.java
+++ b/net/minecraft/world/entity/InsideBlockEffectApplier.java
@@ -32,7 +_,7 @@
public static class StepBasedCollector implements InsideBlockEffectApplier {
private static final InsideBlockEffectType[] APPLY_ORDER = InsideBlockEffectType.values();
private static final int NO_STEP = -1;
- private final Set<InsideBlockEffectType> effectsInStep = EnumSet.noneOf(InsideBlockEffectType.class);
+ private final Map<InsideBlockEffectType, Consumer<Entity>> effectsInStep = new java.util.EnumMap<>(InsideBlockEffectType.class); // Paper - track position inside effect was triggered on
private final Map<InsideBlockEffectType, List<Consumer<Entity>>> beforeEffectsInStep = Util.makeEnumMap(
InsideBlockEffectType.class, insideBlockEffectType -> new ArrayList<>()
);
@@ -42,7 +_,8 @@
private final List<Consumer<Entity>> finalEffects = new ArrayList<>();
private int lastStep = -1;
- public void advanceStep(int step) {
+ public void advanceStep(int step, net.minecraft.core.BlockPos pos) { // Paper - track position inside effect was triggered on
+ this.currentBlockPos = pos; // Paper - track position inside effect was triggered on
if (this.lastStep != step) {
this.lastStep = step;
this.flushStep();
@@ -69,8 +_,8 @@
List<Consumer<Entity>> list = this.beforeEffectsInStep.get(insideBlockEffectType);
this.finalEffects.addAll(list);
list.clear();
- if (this.effectsInStep.remove(insideBlockEffectType)) {
- this.finalEffects.add(insideBlockEffectType.effect());
+ if (this.effectsInStep.remove(insideBlockEffectType) instanceof final Consumer<Entity> recordedEffect) { // Paper - track position inside effect was triggered on - better than null check to avoid diff.
+ this.finalEffects.add(recordedEffect); // Paper - track position inside effect was triggered on
}
List<Consumer<Entity>> list1 = this.afterEffectsInStep.get(insideBlockEffectType);
@@ -81,7 +_,7 @@
@Override
public void apply(InsideBlockEffectType type) {
- this.effectsInStep.add(type);
+ this.effectsInStep.put(type, recorded(type)); // Paper - track position inside effect was triggered on
}
@Override
@@ -93,5 +_,24 @@
public void runAfter(InsideBlockEffectType type, Consumer<Entity> effect) {
this.afterEffectsInStep.get(type).add(effect);
}
+
+ // Paper start - track position inside effect was triggered on
+ private net.minecraft.core.BlockPos currentBlockPos;
+
+ private Consumer<Entity> recorded(final InsideBlockEffectType type) {
+ return new RecordedEffect(this.currentBlockPos, type.effect());
+ }
+
+ record RecordedEffect(
+ net.minecraft.core.BlockPos blockPos,
+ InsideBlockEffectType.Applier applier
+ ) implements Consumer<Entity> {
+
+ @Override
+ public void accept(final Entity entity) {
+ this.applier.affect(entity, blockPos);
+ }
+ }
+ // Paper end - track position inside effect was triggered on
}
}

View File

@@ -0,0 +1,41 @@
--- a/net/minecraft/world/entity/InsideBlockEffectType.java
+++ b/net/minecraft/world/entity/InsideBlockEffectType.java
@@ -6,21 +_,34 @@
public enum InsideBlockEffectType {
FREEZE(entity -> {
entity.setIsInPowderSnow(true);
- if (entity.canFreeze()) {
+ if (entity.canFreeze() && !entity.freezeLocked) { // Paper - Freeze Tick Lock API
entity.setTicksFrozen(Math.min(entity.getTicksRequiredToFreeze(), entity.getTicksFrozen() + 1));
}
}),
FIRE_IGNITE(BaseFireBlock::fireIgnite),
- LAVA_IGNITE(Entity::lavaIgnite),
+ LAVA_IGNITE((entity, pos) -> entity.lavaIgnite(pos)), // Paper - track lava contact
EXTINGUISH(Entity::clearFire);
- private final Consumer<Entity> effect;
+ private final Applier effect; // Paper - track position inside effect was triggered on
private InsideBlockEffectType(final Consumer<Entity> effect) {
+ // Paper start - track position inside effect was triggered on
+ this((entity, block) -> effect.accept(entity));
+ }
+ private InsideBlockEffectType(final Applier effect) {
+ // Paper end - track position inside effect was triggered on
this.effect = effect;
}
- public Consumer<Entity> effect() {
+ public Applier effect() { // Paper - track position inside effect was triggered on
return this.effect;
}
+
+ // Paper start - track position inside effect was triggered on
+ // Use over biconsumer for less fqn spamming.
+ @FunctionalInterface
+ public interface Applier {
+ void affect(final Entity entity, final net.minecraft.core.BlockPos blockPos);
+ }
+ // Paper end - track position inside effect was triggered on
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/Interaction.java
+++ b/net/minecraft/world/entity/Interaction.java
@@ -130,9 +_,16 @@
@@ -100,9 +_,16 @@
@Override
public boolean skipAttackInteraction(Entity entity) {
if (entity instanceof Player player) {
@@ -14,7 +14,7 @@
this.attack = new Interaction.PlayerAction(player.getUUID(), this.level().getGameTime());
if (player instanceof ServerPlayer serverPlayer) {
- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, player.damageSources().generic(), 1.0F, 1.0F, false);
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, source, 1.0F, (float) event.getFinalDamage(), false); // CraftBukkit // Paper - use correct source and fix taken/dealt param order
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, source, 1.0F, (float) event.getFinalDamage(), false); // CraftBukkit
}
return !this.getResponse();

View File

@@ -1,17 +1,15 @@
--- a/net/minecraft/world/entity/ItemBasedSteering.java
+++ b/net/minecraft/world/entity/ItemBasedSteering.java
@@ -51,6 +_,14 @@
@@ -47,4 +_,12 @@
public int boostTimeTotal() {
return this.entityData.get(this.boostTimeAccessor);
}
+ // CraftBukkit add setBoostTicks(int)
+
+ // CraftBukkit start
+ public void setBoostTicks(int ticks) {
+ this.boosting = true;
+ this.boostTime = 0;
+ this.entityData.set(this.boostTimeAccessor, ticks);
+ }
+ // CraftBukkit end
+
public void addAdditionalSaveData(CompoundTag nbt) {
nbt.putBoolean("Saddle", this.hasSaddle());
}
}

View File

@@ -1,33 +1,18 @@
--- a/net/minecraft/world/entity/Leashable.java
+++ b/net/minecraft/world/entity/Leashable.java
@@ -56,7 +_,13 @@
@Nullable
private static Leashable.LeashData readLeashDataInternal(CompoundTag tag) {
if (tag.contains("leash", 10)) {
- return new Leashable.LeashData(Either.left(tag.getCompound("leash").getUUID("UUID")));
+ // Paper start
+ final CompoundTag leashTag = tag.getCompound("leash");
+ if (!leashTag.hasUUID("UUID")) {
+ return null;
+ }
+ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID")));
+ // Paper end
} else {
if (tag.contains("leash", 11)) {
Either<UUID, BlockPos> either = NbtUtils.readBlockPos(tag, "leash").<Either<UUID, BlockPos>>map(Either::right).orElse(null);
@@ -72,6 +_,11 @@
@@ -56,6 +_,11 @@
}
default void writeLeashData(CompoundTag tag, @Nullable Leashable.LeashData leashData) {
if (leashData != null) {
Either<UUID, BlockPos> either = leashData.delayedLeashInfo;
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
+ if (leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) {
+ return;
+ }
+ // CraftBukkit end
if (leashData.leashHolder instanceof LeashFenceKnotEntity leashFenceKnotEntity) {
either = Either.right(leashFenceKnotEntity.getPos());
} else if (leashData.leashHolder != null) {
@@ -104,7 +_,9 @@
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
+ if (leashData != null && leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) {
+ return;
+ }
+ // CraftBukkit end
tag.storeNullable("leash", Leashable.LeashData.CODEC, leashData);
}
@@ -75,7 +_,9 @@
}
if (entity.tickCount > 100) {
@@ -37,7 +22,7 @@
entity.setLeashData(null);
}
}
@@ -128,7 +_,9 @@
@@ -99,7 +_,9 @@
entity.onLeashRemoved();
if (entity.level() instanceof ServerLevel serverLevel) {
if (dropItem) {
@@ -47,7 +32,7 @@
}
if (broadcastPacket) {
@@ -146,7 +_,15 @@
@@ -117,7 +_,15 @@
if (leashData != null && leashData.leashHolder != null) {
if (!entity.isAlive() || !leashData.leashHolder.isAlive()) {
@@ -64,7 +49,7 @@
entity.dropLeash();
} else {
entity.removeLeash();
@@ -160,7 +_,7 @@
@@ -131,7 +_,7 @@
return;
}
@@ -73,7 +58,7 @@
entity.leashTooFarBehaviour();
} else if (f > 6.0) {
entity.elasticRangeLeashBehaviour(leashHolder, f);
@@ -177,7 +_,21 @@
@@ -148,7 +_,21 @@
}
default void leashTooFarBehaviour() {

View File

@@ -40,7 +40,7 @@
}
- if (this.life >= 0) {
+ if (this.life >= 0 && !this.isEffect) { // CraftBukkit - add !this.visualOnly // Paper - Properly handle lightning effects api
+ if (this.life >= 0 && !this.isEffect) { // Paper - Properly handle lightning effects api
if (!(this.level() instanceof ServerLevel)) {
this.level().setSkyFlashTime(2);
- } else if (!this.visualOnly) {
@@ -59,8 +59,8 @@
if (this.level().getBlockState(blockPos).isAir() && state.canSurvive(this.level(), blockPos)) {
- this.level().setBlockAndUpdate(blockPos, state);
- this.blocksSetOnFire++;
+ // CraftBukkit start - add "!visualOnly"
+ if (!this.visualOnly && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockPos, this).isCancelled()) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockPos, this).isCancelled()) {
+ this.level().setBlockAndUpdate(blockPos, state);
+ this.blocksSetOnFire++;
+ }
@@ -73,8 +73,8 @@
if (this.level().getBlockState(blockPos1).isAir() && state.canSurvive(this.level(), blockPos1)) {
- this.level().setBlockAndUpdate(blockPos1, state);
- this.blocksSetOnFire++;
+ // CraftBukkit start - add "!visualOnly"
+ if (!this.visualOnly && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockPos1, this).isCancelled()) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockPos1, this).isCancelled()) {
+ this.level().setBlockAndUpdate(blockPos1, state);
+ this.blocksSetOnFire++;
+ }

View File

@@ -1,19 +1,15 @@
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -84,6 +_,18 @@
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
@@ -83,6 +_,14 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.ticks.ContainerSingleItem;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.event.entity.EntityTransformEvent;
+import org.bukkit.event.entity.EntityUnleashEvent;
+import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason;
+// CraftBukkit end
+
public abstract class Mob extends LivingEntity implements EquipmentUser, Leashable, Targeting {
@@ -23,11 +19,11 @@
private final BodyRotationControl bodyRotationControl;
protected PathNavigation navigation;
public GoalSelector goalSelector;
+ @Nullable public net.minecraft.world.entity.ai.goal.FloatGoal goalFloat; // Paper - Allow nerfed mobs to jump and float
+ public @Nullable net.minecraft.world.entity.ai.goal.FloatGoal goalFloat; // Paper - Allow nerfed mobs to jump and float
public GoalSelector targetSelector;
@Nullable
private LivingEntity target;
@@ -131,6 +_,7 @@
@@ -126,6 +_,7 @@
private Leashable.LeashData leashData;
private BlockPos restrictCenter = BlockPos.ZERO;
private float restrictRadius = -1.0F;
@@ -35,7 +31,7 @@
protected Mob(EntityType<? extends Mob> entityType, Level level) {
super(entityType, level);
@@ -150,6 +_,12 @@
@@ -142,6 +_,12 @@
}
}
@@ -48,37 +44,36 @@
protected void registerGoals() {
}
@@ -230,7 +_,40 @@
@@ -222,7 +_,39 @@
}
public void setTarget(@Nullable LivingEntity target) {
+ // CraftBukkit start - fire event
+ this.setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true);
+ this.setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN);
+ }
+
+ public boolean setTarget(LivingEntity target, EntityTargetEvent.TargetReason reason, boolean fireEvent) {
+ public boolean setTarget(@Nullable LivingEntity target, @Nullable EntityTargetEvent.TargetReason reason) {
+ if (this.getTarget() == target) {
+ return false;
+ }
+ if (fireEvent) {
+ if (reason != null) {
+ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && this.getTarget() != null && target == null) {
+ reason = this.getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED;
+ }
+ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) {
+ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception());
+ }
+ CraftLivingEntity ctarget = null;
+ org.bukkit.craftbukkit.entity.CraftLivingEntity ctarget = null;
+ if (target != null) {
+ ctarget = (CraftLivingEntity) target.getBukkitEntity();
+ ctarget = (org.bukkit.craftbukkit.entity.CraftLivingEntity) target.getBukkitEntity();
+ }
+ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason);
+ this.level().getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ org.bukkit.event.entity.EntityTargetLivingEntityEvent event = new org.bukkit.event.entity.EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason);
+ if (!event.callEvent()) {
+ return false;
+ }
+
+ if (event.getTarget() != null) {
+ target = ((CraftLivingEntity) event.getTarget()).getHandle();
+ target = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle();
+ } else {
+ target = null;
+ }
@@ -89,20 +84,7 @@
}
@Override
@@ -354,6 +_,12 @@
return null;
}
+ // CraftBukkit start - Add delegate method
+ public SoundEvent getAmbientSound0() {
+ return this.getAmbientSound();
+ }
+ // CraftBukkit end
+
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
@@ -413,13 +_,25 @@
@@ -358,13 +_,22 @@
if (this.isNoAi()) {
compound.putBoolean("NoAI", this.isNoAi());
}
@@ -112,45 +94,30 @@
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
- this.setCanPickUpLoot(compound.getBoolean("CanPickUpLoot"));
- this.persistenceRequired = compound.getBoolean("PersistenceRequired");
- this.setCanPickUpLoot(compound.getBooleanOr("CanPickUpLoot", false));
- this.persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
+ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
+ if (compound.contains("CanPickUpLoot", 99)) {
+ boolean data = compound.getBoolean("CanPickUpLoot");
+ if (isLevelAtLeast(compound, 1) || data) {
+ this.setCanPickUpLoot(data);
+ }
+ boolean canPickUpLoot = compound.getBooleanOr("CanPickUpLoot", false);
+ if (isLevelAtLeast(compound, 1) || canPickUpLoot) {
+ this.setCanPickUpLoot(canPickUpLoot);
+ }
+
+ boolean data = compound.getBoolean("PersistenceRequired");
+ if (isLevelAtLeast(compound, 1) || data) {
+ this.persistenceRequired = data;
+ boolean persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
+ if (isLevelAtLeast(compound, 1) || persistenceRequired) {
+ this.persistenceRequired = persistenceRequired;
+ }
+ // CraftBukkit end
if (compound.contains("ArmorItems", 9)) {
ListTag list = compound.getList("ArmorItems", 10);
@@ -472,13 +_,18 @@
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
this.dropChances = compound.read("drop_chances", DropChances.CODEC, registryOps).orElse(DropChances.DEFAULT);
this.readLeashData(compound);
this.setLeftHanded(compound.getBoolean("LeftHanded"));
if (compound.contains("DeathLootTable", 8)) {
- this.lootTable = Optional.of(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(compound.getString("DeathLootTable"))));
+ this.lootTable = Optional.ofNullable(ResourceLocation.tryParse(compound.getString("DeathLootTable"))).map((rs) -> ResourceKey.create(Registries.LOOT_TABLE, rs)); // Paper - Validate ResourceLocation
} else {
this.lootTable = Optional.empty();
}
this.lootTableSeed = compound.getLong("DeathLootTableSeed");
this.setNoAi(compound.getBoolean("NoAI"));
+ // CraftBukkit start
+ if (compound.contains("Bukkit.Aware")) {
+ this.aware = compound.getBoolean("Bukkit.Aware");
+ }
+ // CraftBukkit end
@@ -372,6 +_,7 @@
this.lootTable = compound.read("DeathLootTable", LootTable.KEY_CODEC);
this.lootTableSeed = compound.getLongOr("DeathLootTableSeed", 0L);
this.setNoAi(compound.getBooleanOr("NoAI", false));
+ this.aware = compound.getBooleanOr("Bukkit.Aware", true); // CraftBukkit
}
@Override
@@ -540,6 +_,11 @@
@@ -433,6 +_,11 @@
&& !itemEntity.getItem().isEmpty()
&& !itemEntity.hasPickUpDelay()
&& this.wantsToPickUp(serverLevel, itemEntity.getItem())) {
@@ -162,7 +129,7 @@
this.pickUpItem(serverLevel, itemEntity);
}
}
@@ -554,18 +_,24 @@
@@ -447,18 +_,24 @@
protected void pickUpItem(ServerLevel level, ItemEntity entity) {
ItemStack item = entity.getItem();
@@ -184,32 +151,32 @@
+ return this.equipItemIfPossible(level, stack, null);
+ }
+
+ public ItemStack equipItemIfPossible(ServerLevel level, ItemStack stack, ItemEntity entity) {
+ public ItemStack equipItemIfPossible(ServerLevel level, ItemStack stack, @Nullable ItemEntity entity) {
+ // CraftBukkit end
EquipmentSlot equipmentSlotForItem = this.getEquipmentSlotForItem(stack);
ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem);
boolean canReplaceCurrentItem = this.canReplaceCurrentItem(stack, itemBySlot, equipmentSlotForItem);
@@ -575,10 +_,18 @@
canReplaceCurrentItem = itemBySlot.isEmpty();
}
- if (canReplaceCurrentItem && this.canHoldItem(stack)) {
+ // CraftBukkit start
+ boolean canPickup = canReplaceCurrentItem && this.canHoldItem(stack);
+ if (entity != null) {
+ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, !canPickup).isCancelled();
+ }
+ if (canPickup) {
+ // CraftBukkit end
double d = this.getEquipmentDropChance(equipmentSlotForItem);
if (!itemBySlot.isEmpty() && Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) {
+ this.forceDrops = true; // CraftBukkit
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // CraftBukkit
if (!this.isEquippableInSlot(stack, equipmentSlotForItem)) {
return ItemStack.EMPTY;
@@ -471,10 +_,18 @@
canReplaceCurrentItem = itemBySlot.isEmpty();
}
ItemStack itemStack = equipmentSlotForItem.limit(stack);
@@ -703,22 +_,29 @@
- if (canReplaceCurrentItem && this.canHoldItem(stack)) {
+ // CraftBukkit start
+ boolean canPickup = canReplaceCurrentItem && this.canHoldItem(stack);
+ if (entity != null) {
+ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, !canPickup).isCancelled();
+ }
+ if (canPickup) {
+ // CraftBukkit end
double d = this.dropChances.byEquipment(equipmentSlotForItem);
if (!itemBySlot.isEmpty() && Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) {
+ this.forceDrops = true; // CraftBukkit
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // CraftBukkit
}
ItemStack itemStack = equipmentSlotForItem.limit(stack);
@@ -591,22 +_,29 @@
@Override
public void checkDespawn() {
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
@@ -229,9 +196,9 @@
+ final io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DespawnRangePair despawnRangePair = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory());
+ final io.papermc.paper.configuration.type.DespawnRange.Shape shape = this.level().paperConfig().entities.spawning.despawnRangeShape;
+ final double dy = Math.abs(nearestPlayer.getY() - this.getY());
+ final double dySqr = Math.pow(dy, 2);
+ final double dxSqr = Math.pow(nearestPlayer.getX() - this.getX(), 2);
+ final double dzSqr = Math.pow(nearestPlayer.getZ() - this.getZ(), 2);
+ final double dySqr = Mth.square(dy);
+ final double dxSqr = Mth.square(nearestPlayer.getX() - this.getX());
+ final double dzSqr = Mth.square(nearestPlayer.getZ() - this.getZ());
+ final double distanceSquared = dxSqr + dzSqr + dySqr;
+ // Despawn if hard/soft limit is exceeded
+ if (despawnRangePair.hard().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy) && this.removeWhenFarAway(distanceSquared)) {
@@ -252,14 +219,14 @@
this.noActionTime = 0;
}
}
@@ -730,6 +_,15 @@
@@ -618,6 +_,15 @@
@Override
protected final void serverAiStep() {
this.noActionTime++;
+ // Paper start - Allow nerfed mobs to jump and float
+ if (!this.aware) {
+ if (goalFloat != null) {
+ if (goalFloat.canUse()) goalFloat.tick();
+ if (this.goalFloat != null) {
+ if (this.goalFloat.canUse()) this.goalFloat.tick();
+ this.getJumpControl().tick();
+ }
+ return;
@@ -268,41 +235,67 @@
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("sensing");
this.sensing.tick();
@@ -908,26 +_,40 @@
@Override
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
+ // Paper start - Fix silent equipment change
+ setItemSlot(slot, stack, false);
+ }
@@ -793,14 +_,69 @@
public boolean stillValid(Player player) {
return player.getVehicle() == Mob.this || player.canInteractWithEntity(Mob.this, 4.0);
}
+
+ @Override
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
+ // Paper end - Fix silent equipment change
this.verifyEquippedItem(stack);
switch (slot.getType()) {
case HAND:
- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
break;
case HUMANOID_ARMOR:
- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
break;
case ANIMAL_ARMOR:
ItemStack itemStack = this.bodyArmorItem;
this.bodyArmorItem = stack;
- this.onEquipItem(slot, itemStack, stack);
+ this.onEquipItem(slot, itemStack, stack, silent); // Paper - Fix silent equipment change
}
+ // Paper start
+ private final List<org.bukkit.entity.HumanEntity> viewers = new java.util.ArrayList<>();
+ private int maxStackSize = MAX_STACK;
+
+ @Override
+ public int getMaxStackSize() {
+ return this.maxStackSize;
+ }
+
+ @Override
+ public List<ItemStack> getContents() {
+ return java.util.Arrays.asList(this.getTheItem());
+ }
+
+ @Override
+ public void onOpen(final org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
+ this.viewers.add(player);
+ }
+
+ @Override
+ public void onClose(final org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
+ this.viewers.remove(player);
+ }
+
+ @Override
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
+ return this.viewers;
+ }
+
+ @Override
+ public @Nullable org.bukkit.inventory.InventoryHolder getOwner() {
+ if (Mob.this.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder inventoryHolder) {
+ return inventoryHolder;
+ }
+ return null;
+ }
+
+ @Override
+ public void setMaxStackSize(final int size) {
+ this.maxStackSize = size;
+ }
+
+ @Override
+ public org.bukkit.Location getLocation() {
+ return Mob.this.getBukkitEntity().getLocation();
+ }
+ // Paper end
};
}
+
+ // Paper start
+ protected boolean shouldSkipLoot(EquipmentSlot slot) { // method to avoid to fallback into the global mob loot logic (i.e fox)
+ protected boolean shouldSkipLoot(EquipmentSlot slot) { // method to avoid to fallback into the global mob loot logic (e.g. the fox)
+ return false;
+ }
+ // Paper end
+
@Override
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
super.dropCustomDeathLoot(level, damageSource, recentlyHit);
@@ -310,9 +303,9 @@
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ if (this.shouldSkipLoot(equipmentSlot)) continue; // Paper
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
float equipmentDropChance = this.getEquipmentDropChance(equipmentSlot);
if (equipmentDropChance != 0.0F) {
@@ -951,7 +_,13 @@
float f = this.dropChances.byEquipment(equipmentSlot);
if (f != 0.0F) {
@@ -820,7 +_,13 @@
}
this.spawnAtLocation(level, itemBySlot);
@@ -326,40 +319,39 @@
}
}
}
@@ -981,7 +_,9 @@
double d = this.getEquipmentDropChance(equipmentSlot);
if (d > 1.0) {
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
}
@@ -844,7 +_,9 @@
set.add(equipmentSlot);
} else if (this.dropChances.isPreserved(equipmentSlot)) {
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
}
}
@@ -1269,6 +_,22 @@
}
@@ -1122,6 +_,21 @@
public <T extends Mob> T convertTo(
EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion
) {
+ // Paper start - entity zap event - allow cancellation of conversion post creation
+ return this.convertTo(entityType, conversionParams, spawnReason, afterConversion, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ @Nullable
+ public <T extends Mob> T convertTo(
+ EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason creatureSpawnReason
+ EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion, @Nullable EntityTransformEvent.TransformReason transformReason, @Nullable CreatureSpawnEvent.SpawnReason creatureSpawnReason
+ ) {
+ // Paper start - entity zap event - allow cancellation of conversion post creation
+ return this.convertTo(entityType, conversionParams, spawnReason, e -> { afterConversion.finalizeConversion(e); return true; }, transformReason, creatureSpawnReason);
+ }
+ @Nullable
+ public <T extends Mob> T convertTo(
+ EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.CancellingAfterConversion<T> afterConversion, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason creatureSpawnReason
+ EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.CancellingAfterConversion<T> afterConversion, @Nullable EntityTransformEvent.TransformReason transformReason, @Nullable CreatureSpawnEvent.SpawnReason creatureSpawnReason
+ ) {
+ // Paper end - entity zap event - allow cancellation of conversion post creation
+ // CraftBukkit end
if (this.isRemoved()) {
return null;
} else {
@@ -1277,13 +_,23 @@
@@ -1130,13 +_,23 @@
return null;
} else {
conversionParams.type().convert(this, mob, conversionParams);
@@ -371,7 +363,7 @@
+ return mob;
+ }
+
+ if (CraftEventFactory.callEntityTransformEvent(this, mob, transformReason).isCancelled()) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, mob, transformReason).isCancelled()) {
+ return null;
+ }
+ // CraftBukkit end
@@ -386,29 +378,27 @@
}
return mob;
@@ -1293,7 +_,20 @@
@@ -1146,7 +_,18 @@
@Nullable
public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.AfterConversion<T> afterConversion) {
- return this.convertTo(entityType, coversionParams, EntitySpawnReason.CONVERSION, afterConversion);
+ // CraftBukkit start
+ // Paper start - entity zap event - allow cancellation of conversion post creation
+ return this.convertTo(entityType, coversionParams, afterConversion, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ @Nullable
+ public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.AfterConversion<T> afterConversion, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
+ // Paper start - entity zap event - allow cancellation of conversion post creation
+ public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.AfterConversion<T> afterConversion, @Nullable EntityTransformEvent.TransformReason transformReason, @Nullable CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
+ return this.convertTo(entityType, coversionParams, e -> { afterConversion.finalizeConversion(e); return true; }, transformReason, creatureSpawnReason);
+ }
+ @Nullable
+ public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.CancellingAfterConversion<T> afterConversion, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
+ // Paper start - entity zap event - allow cancellation of conversion post creation
+ public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.CancellingAfterConversion<T> afterConversion, @Nullable EntityTransformEvent.TransformReason transformReason, @Nullable CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
+ return this.convertTo(entityType, coversionParams, EntitySpawnReason.CONVERSION, afterConversion, transformReason, creatureSpawnReason);
+ // CraftBukkit end
+ // Paper end - entity zap event - allow cancellation of conversion post creation
}
@Nullable
@@ -1329,7 +_,17 @@
@@ -1182,7 +_,17 @@
public boolean startRiding(Entity entity, boolean force) {
boolean flag = super.startRiding(entity, force);
if (flag && this.isLeashed()) {
@@ -427,7 +417,7 @@
}
return flag;
@@ -1412,7 +_,7 @@
@@ -1270,7 +_,7 @@
float knockback = this.getKnockback(source, damageSource);
if (knockback > 0.0F && source instanceof LivingEntity livingEntity) {
livingEntity.knockback(

View File

@@ -1,43 +1,34 @@
--- a/net/minecraft/world/entity/NeutralMob.java
+++ b/net/minecraft/world/entity/NeutralMob.java
@@ -39,18 +_,11 @@
} else {
UUID uuid = tag.getUUID("AngryAt");
this.setPersistentAngerTarget(uuid);
- Entity entity = ((ServerLevel)level).getEntity(uuid);
- if (entity != null) {
- if (entity instanceof Mob mob) {
- this.setTarget(mob);
- this.setLastHurtByMob(mob);
- }
-
- if (entity instanceof Player player) {
- this.setTarget(player);
- this.setLastHurtByPlayer(player);
- }
- }
+ // Paper - Prevent entity loading causing async lookups; Moved diff to separate method
+ // If this entity already survived its first tick, e.g. is loaded and ticked in sync, actively
+ // tick the initial persistent anger.
+ // If not, let the first tick on the baseTick call the method later down the line.
+ if (this instanceof Entity entity && !entity.firstTick) this.tickInitialPersistentAnger(level);
}
@@ -35,9 +_,11 @@
if (level instanceof ServerLevel serverLevel) {
UUID uuid = tag.read("AngryAt", UUIDUtil.CODEC).orElse(null);
this.setPersistentAngerTarget(uuid);
- if ((uuid != null ? serverLevel.getEntity(uuid) : null) instanceof LivingEntity livingEntity) {
- this.setTarget(livingEntity);
- }
+ // Paper - Prevent entity loading causing async lookups; Moved diff to separate method
+ // If this entity already survived its first tick, e.g. is loaded and ticked in sync, actively
+ // tick the initial persistent anger.
+ // If not, let the first tick on the baseTick call the method later down the line.
+ if (this instanceof Entity entity && !entity.firstTick) this.tickInitialPersistentAnger(level);
}
}
@@ -104,7 +_,7 @@
@@ -90,7 +_,7 @@
default void stopBeingAngry() {
this.setLastHurtByMob(null);
this.setPersistentAngerTarget(null);
- this.setTarget(null);
+ this.setTarget(null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit
+ this.setTarget(null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // CraftBukkit
this.setRemainingPersistentAngerTime(0);
}
@@ -117,8 +_,33 @@
@@ -101,8 +_,24 @@
void setTarget(@Nullable LivingEntity livingEntity);
+ boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit
+ boolean setTarget(@Nullable LivingEntity livingEntity, @Nullable org.bukkit.event.entity.EntityTargetEvent.TargetReason reason); // CraftBukkit
+
boolean canAttack(LivingEntity entity);
@@ -52,17 +43,8 @@
+ return;
+ }
+
+ Entity entity = ((ServerLevel)level).getEntity(uuid);
+ if (entity != null) {
+ if (entity instanceof Mob mob) {
+ this.setTarget(mob, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, false); // CraftBukkit
+ this.setLastHurtByMob(mob);
+ }
+
+ if (entity instanceof Player player) {
+ this.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, false); // CraftBukkit
+ this.setLastHurtByPlayer(player);
+ }
+ if (level.getEntity(uuid) instanceof net.minecraft.world.entity.LivingEntity livingEntity) {
+ this.setTarget(livingEntity, null);
+ }
+ }
+ // Paper end - Prevent entity loading causing async lookups

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/OminousItemSpawner.java
+++ b/net/minecraft/world/entity/OminousItemSpawner.java
@@ -76,7 +_,7 @@
@@ -79,7 +_,7 @@
entity = this.spawnProjectile(serverLevel, projectileItem, item);
} else {
entity = new ItemEntity(serverLevel, this.getX(), this.getY(), this.getZ(), item);
@@ -9,7 +9,7 @@
}
serverLevel.levelEvent(3021, this.blockPosition(), 1);
@@ -90,7 +_,7 @@
@@ -93,7 +_,7 @@
ProjectileItem.DispenseConfig dispenseConfig = projectileItem.createDispenseConfig();
dispenseConfig.overrideDispenseEvent().ifPresent(i -> level.levelEvent(i, this.blockPosition(), 0));
Direction direction = Direction.DOWN;
@@ -18,7 +18,7 @@
projectileItem.asProjectile(level, this.position(), stack, direction),
level,
stack,
@@ -99,7 +_,7 @@
@@ -102,7 +_,7 @@
direction.getStepZ(),
dispenseConfig.power(),
dispenseConfig.uncertainty()

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/world/entity/TamableAnimal.java
+++ b/net/minecraft/world/entity/TamableAnimal.java
@@ -84,7 +_,7 @@
@@ -77,7 +_,7 @@
}
this.orderedToSit = compound.getBoolean("Sitting");
this.orderedToSit = compound.getBooleanOr("Sitting", false);
- this.setInSittingPose(this.orderedToSit);
+ this.setInSittingPose(this.orderedToSit, false); // Paper - Add EntityToggleSitEvent
}
@Override
@@ -95,8 +_,16 @@
@@ -88,8 +_,16 @@
@Override
public boolean handleLeashAtDistance(Entity leashHolder, float distance) {
if (this.isInSittingPose()) {
@@ -28,20 +28,21 @@
}
return false;
@@ -155,6 +_,12 @@
@@ -148,6 +_,13 @@
}
public void setInSittingPose(boolean sitting) {
+ // Paper start - Add EntityToggleSitEvent
+ this.setInSittingPose(sitting, true);
+ }
+
+ public void setInSittingPose(boolean sitting, boolean callEvent) {
+ if (callEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return;
+ // Paper end - Add EntityToggleSitEvent
byte b = this.entityData.get(DATA_FLAGS_ID);
if (sitting) {
this.entityData.set(DATA_FLAGS_ID, (byte)(b | 1));
@@ -227,7 +_,12 @@
@@ -230,7 +_,12 @@
if (this.level() instanceof ServerLevel serverLevel
&& serverLevel.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES)
&& this.getOwner() instanceof ServerPlayer serverPlayer) {
@@ -55,18 +56,18 @@
}
super.die(cause);
@@ -270,7 +_,14 @@
@@ -273,7 +_,14 @@
if (!this.canTeleportTo(new BlockPos(x, y, z))) {
return false;
} else {
- this.moveTo(x + 0.5, y, z + 0.5, this.getYRot(), this.getXRot());
- this.snapTo(x + 0.5, y, z + 0.5, this.getYRot(), this.getXRot());
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityTeleportEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(this, x + 0.5, y, z + 0.5);
+ if (event.isCancelled() || event.getTo() == null) { // Paper - prevent NP on null event to location
+ if (event.isCancelled() || event.getTo() == null) {
+ return false;
+ }
+ org.bukkit.Location to = event.getTo();
+ this.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
+ this.snapTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
+ // CraftBukkit end
this.navigation.stop();
return true;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
@@ -153,20 +_,20 @@
@@ -155,20 +_,20 @@
double baseValue = this.getBaseValue();
for (AttributeModifier attributeModifier : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_VALUE)) {

View File

@@ -1,7 +1,7 @@
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -162,4 +_,12 @@
}
@@ -148,4 +_,12 @@
.ifPresent(attributeInstance -> attributeInstance.load(compoundOrEmpty));
}
}
+

View File

@@ -3,15 +3,15 @@
@@ -38,7 +_,14 @@
.findFirst()
)
.ifPresent(profession -> {
- villager.setVillagerData(villager.getVillagerData().setProfession(profession));
.ifPresent(reference -> {
- villager.setVillagerData(villager.getVillagerData().withProfession(reference));
+ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed
+ org.bukkit.event.entity.VillagerCareerChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callVillagerCareerChangeEvent(villager, org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.minecraftToBukkit(profession), org.bukkit.event.entity.VillagerCareerChangeEvent.ChangeReason.EMPLOYED);
+ org.bukkit.event.entity.VillagerCareerChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callVillagerCareerChangeEvent(villager, org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.minecraftHolderToBukkit(reference), org.bukkit.event.entity.VillagerCareerChangeEvent.ChangeReason.EMPLOYED);
+ if (event.isCancelled()) {
+ return;
+ }
+
+ villager.setVillagerData(villager.getVillagerData().setProfession(org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession())));
+ villager.setVillagerData(villager.getVillagerData().withProfession(org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.bukkitToMinecraftHolder(event.getProfession())));
+ // CraftBukkit end
villager.refreshBrain(level);
});

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/ai/behavior/RamTarget.java
+++ b/net/minecraft/world/entity/ai/behavior/RamTarget.java
@@ -89,7 +_,7 @@
float f = 0.25F * (i - i1);
float f1 = Mth.clamp(owner.getSpeed() * 1.65F, 0.2F, 3.0F) + f;
float f2 = livingEntity.isDamageSourceBlocked(level.damageSources().mobAttack(owner)) ? 0.5F : 1.0F;
- livingEntity.knockback(f2 * f1 * this.getKnockbackForce.applyAsDouble(owner), this.ramDirection.x(), this.ramDirection.z());
+ livingEntity.knockback(f2 * f1 * this.getKnockbackForce.applyAsDouble(owner), this.ramDirection.x(), this.ramDirection.z(), owner, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
@@ -92,7 +_,7 @@
DamageSource damageSource1 = level.damageSources().mobAttack(owner);
float f3 = livingEntity.applyItemBlocking(level, damageSource1, f);
float f4 = f3 > 0.0F ? 0.5F : 1.0F;
- livingEntity.knockback(f4 * f2 * this.getKnockbackForce.applyAsDouble(owner), this.ramDirection.x(), this.ramDirection.z());
+ livingEntity.knockback(f4 * f2 * this.getKnockbackForce.applyAsDouble(owner), this.ramDirection.x(), this.ramDirection.z(), owner, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
this.finishRam(level, owner);
level.playSound(null, owner, this.getImpactSound.apply(owner), SoundSource.NEUTRAL, 1.0F, 1.0F);
} else if (this.hasRammedHornBreakingBlock(level, owner)) {

View File

@@ -1,18 +1,18 @@
--- a/net/minecraft/world/entity/ai/behavior/ResetProfession.java
+++ b/net/minecraft/world/entity/ai/behavior/ResetProfession.java
@@ -18,7 +_,14 @@
&& villagerData.getProfession() != VillagerProfession.NITWIT
&& villager.getVillagerXp() == 0
&& villagerData.getLevel() <= 1) {
- villager.setVillagerData(villager.getVillagerData().setProfession(VillagerProfession.NONE));
+ // CraftBukkit start
+ org.bukkit.event.entity.VillagerCareerChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callVillagerCareerChangeEvent(villager, org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), org.bukkit.event.entity.VillagerCareerChangeEvent.ChangeReason.LOSING_JOB);
+ if (event.isCancelled()) {
+ return false;
+ }
@@ -13,7 +_,14 @@
VillagerData villagerData = villager.getVillagerData();
boolean flag = !villagerData.profession().is(VillagerProfession.NONE) && !villagerData.profession().is(VillagerProfession.NITWIT);
if (flag && villager.getVillagerXp() == 0 && villagerData.level() <= 1) {
- villager.setVillagerData(villager.getVillagerData().withProfession(level.registryAccess(), VillagerProfession.NONE));
+ // CraftBukkit start
+ org.bukkit.event.entity.VillagerCareerChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callVillagerCareerChangeEvent(villager, org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.minecraftHolderToBukkit(level.registryAccess().getOrThrow(VillagerProfession.NONE)), org.bukkit.event.entity.VillagerCareerChangeEvent.ChangeReason.LOSING_JOB);
+ if (event.isCancelled()) {
+ return false;
+ }
+
+ villager.setVillagerData(villager.getVillagerData().setProfession(org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession())));
+ // CraftBukkit end
villager.refreshBrain(level);
return true;
} else {
+ villager.setVillagerData(villager.getVillagerData().withProfession(org.bukkit.craftbukkit.entity.CraftVillager.CraftProfession.bukkitToMinecraftHolder(event.getProfession())));
+ // CraftBukkit end
villager.refreshBrain(level);
return true;
} else {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
+++ b/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
@@ -42,7 +_,7 @@
@@ -45,7 +_,7 @@
Pair.of(1, new MoveToTargetSink()),
Pair.of(2, PoiCompetitorScan.create()),
Pair.of(3, new LookAndFollowTradingPlayerSink(speedModifier)),

View File

@@ -7,13 +7,13 @@
- parent.setAge(6000);
- partner.setAge(6000);
breedOffspring.setAge(-24000);
breedOffspring.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F);
+ // Paper - Move age setting down
breedOffspring.snapTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F);
- level.addFreshEntityWithPassengers(breedOffspring);
+ // CraftBukkit start - call EntityBreedEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(breedOffspring, parent, partner, null, null, 0).isCancelled()) {
+ return Optional.empty();
+ }
+ // Move age setting down
+ parent.setAge(6000);
+ partner.setAge(6000);
+ level.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);

View File

@@ -16,10 +16,10 @@
this.eatAnimationTick = Math.max(0, this.eatAnimationTick - 1);
if (this.eatAnimationTick == this.adjustedTickDelay(4)) {
BlockPos blockPos = this.mob.blockPosition();
- if (IS_TALL_GRASS.test(this.level.getBlockState(blockPos))) {
- if (IS_EDIBLE.test(this.level.getBlockState(blockPos))) {
- if (getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+ final BlockState blockState = this.level.getBlockState(blockPos); // Paper - fix wrong block state
+ if (IS_TALL_GRASS.test(blockState)) { // Paper - fix wrong block state
+ if (IS_EDIBLE.test(blockState)) { // Paper - fix wrong block state
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state
this.level.destroyBlock(blockPos, false);
}

View File

@@ -23,13 +23,13 @@
}
+ // Paper start - Mob goal api
+ private com.destroystokyo.paper.entity.ai.PaperVanillaGoal<?> vanillaGoal;
+ public <T extends org.bukkit.entity.Mob> com.destroystokyo.paper.entity.ai.Goal<T> asPaperVanillaGoal() {
+ if (this.vanillaGoal == null) {
+ this.vanillaGoal = new com.destroystokyo.paper.entity.ai.PaperVanillaGoal<>(this);
+ private com.destroystokyo.paper.entity.ai.PaperGoal<?> paperGoal;
+ public <T extends org.bukkit.entity.Mob> com.destroystokyo.paper.entity.ai.Goal<T> asPaperGoal() {
+ if (this.paperGoal == null) {
+ this.paperGoal = new com.destroystokyo.paper.entity.ai.PaperGoal<>(this);
+ }
+ //noinspection unchecked
+ return (com.destroystokyo.paper.entity.ai.Goal<T>) this.vanillaGoal;
+ return (com.destroystokyo.paper.entity.ai.Goal<T>) this.paperGoal;
+ }
+ // Paper end - Mob goal api
+

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java
+++ b/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java
@@ -20,7 +_,7 @@
@Override
public boolean canUse() {
if (!this.mob.isTame()) {
- return false;
+ return this.mob.isOrderedToSit() && this.mob.getTarget() == null; // CraftBukkit - Allow sitting for wild animals
} else if (this.mob.isInWaterOrBubble()) {
return false;
} else if (!this.mob.onGround()) {

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java
+++ b/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java
@@ -48,7 +_,7 @@
@@ -47,7 +_,7 @@
@Override
public void start() {
- this.golem.setTarget(this.potentialTarget);
+ this.golem.setTarget(this.potentialTarget, org.bukkit.event.entity.EntityTargetEvent.TargetReason.DEFEND_VILLAGE, true); // CraftBukkit - reason
+ this.golem.setTarget(this.potentialTarget, org.bukkit.event.entity.EntityTargetEvent.TargetReason.DEFEND_VILLAGE); // CraftBukkit - reason
super.start();
}
}

View File

@@ -5,7 +5,7 @@
@Override
public void start() {
- this.mob.setTarget(this.mob.getLastHurtByMob());
+ this.mob.setTarget(this.mob.getLastHurtByMob(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason
+ this.mob.setTarget(this.mob.getLastHurtByMob(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY); // CraftBukkit - reason
this.targetMob = this.mob.getTarget();
this.timestamp = this.mob.getLastHurtByMobTimestamp();
this.unseenMemoryTicks = 300;
@@ -14,6 +14,6 @@
protected void alertOther(Mob mob, LivingEntity target) {
- mob.setTarget(target);
+ mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit - reason
+ mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY); // CraftBukkit - reason
}
}

View File

@@ -5,7 +5,7 @@
@Override
public void start() {
- this.mob.setTarget(this.target);
+ this.mob.setTarget(this.target, this.target instanceof ServerPlayer ? org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER : org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY, true); // CraftBukkit - reason
+ this.mob.setTarget(this.target, this.target instanceof ServerPlayer ? org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER : org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); // CraftBukkit - reason
super.start();
}

View File

@@ -5,7 +5,7 @@
@Override
public void start() {
- this.mob.setTarget(this.ownerLastHurtBy);
+ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit - reason
+ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER); // CraftBukkit - reason
LivingEntity owner = this.tameAnimal.getOwner();
if (owner != null) {
this.timestamp = owner.getLastHurtByMobTimestamp();

View File

@@ -5,7 +5,7 @@
@Override
public void start() {
- this.mob.setTarget(this.ownerLastHurt);
+ this.mob.setTarget(this.ownerLastHurt, org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit - reason
+ this.mob.setTarget(this.ownerLastHurt, org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET); // CraftBukkit - reason
LivingEntity owner = this.tameAnimal.getOwner();
if (owner != null) {
this.timestamp = owner.getLastHurtMobTimestamp();

View File

@@ -5,7 +5,7 @@
}
- this.mob.setTarget(target);
+ this.mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY, true); // CraftBukkit
+ this.mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); // CraftBukkit
return true;
}
}
@@ -14,7 +14,7 @@
@Override
public void stop() {
- this.mob.setTarget(null);
+ this.mob.setTarget(null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit
+ this.mob.setTarget(null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // CraftBukkit
this.targetMob = null;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ai/gossip/GossipContainer.java
+++ b/net/minecraft/world/entity/ai/gossip/GossipContainer.java
@@ -216,6 +_,44 @@
@@ -220,6 +_,44 @@
public void remove(GossipType gossipType) {
this.entries.removeInt(gossipType);
}

View File

@@ -51,7 +51,7 @@
+ boolean copiedSet = false;
+ for (BlockPos possibleTarget : targets) {
+ if (!this.mob.level().getWorldBorder().isWithinBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(), // Paper - don't path out of world border
+ io.papermc.paper.util.MCUtil.toLocation(this.mob.level(), possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) {
+ org.bukkit.craftbukkit.util.CraftLocation.toBukkit(possibleTarget, this.mob.level()), target == null ? null : target.getBukkitEntity()).callEvent()) {
+ if (!copiedSet) {
+ copiedSet = true;
+ targets = new java.util.HashSet<>(targets);

View File

@@ -1,32 +1,19 @@
--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
+++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
@@ -16,6 +_,14 @@
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
+// CraftBukkit start
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+// CraftBukkit end
+
public class TemptingSensor extends Sensor<PathfinderMob> {
private static final TargetingConditions TEMPT_TARGETING = TargetingConditions.forNonCombat().ignoreLineOfSight();
private final Predicate<ItemStack> temptations;
@@ -38,7 +_,17 @@
@@ -38,7 +_,19 @@
.collect(Collectors.toList());
if (!list.isEmpty()) {
Player player = list.get(0);
- brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, player);
+ // CraftBukkit start
+ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, player, EntityTargetEvent.TargetReason.TEMPT);
+ org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(
+ entity, player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TEMPT
+ );
+ if (event.isCancelled()) {
+ return;
+ }
+ if (event.getTarget() instanceof HumanEntity) {
+ brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle());
+ if (event.getTarget() instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity target) {
+ brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, target.getHandle());
+ } else {
+ brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER);
+ }

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ai/village/VillageSiege.java
+++ b/net/minecraft/world/entity/ai/village/VillageSiege.java
@@ -101,11 +_,12 @@
@@ -95,11 +_,12 @@
zombie.finalizeSpawn(level, level.getCurrentDifficultyAt(zombie.blockPosition()), EntitySpawnReason.EVENT, null);
} catch (Exception var5) {
LOGGER.warn("Failed to create zombie for village siege at {}", vec3, var5);
@@ -8,7 +8,7 @@
return;
}
zombie.moveTo(vec3.x, vec3.y, vec3.z, level.random.nextFloat() * 360.0F, 0.0F);
zombie.snapTo(vec3.x, vec3.y, vec3.z, level.random.nextFloat() * 360.0F, 0.0F);
- level.addFreshEntityWithPassengers(zombie);
+ level.addFreshEntityWithPassengers(zombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ambient/Bat.java
+++ b/net/minecraft/world/entity/ambient/Bat.java
@@ -85,7 +_,7 @@
@@ -86,7 +_,7 @@
}
@Override
@@ -9,7 +9,7 @@
return false;
}
@@ -139,13 +_,13 @@
@@ -140,13 +_,13 @@
this.yHeadRot = this.random.nextInt(360);
}
@@ -25,7 +25,7 @@
this.setResting(false);
if (!isSilent) {
level.levelEvent(null, 1025, blockPos, 0);
@@ -178,7 +_,7 @@
@@ -179,7 +_,7 @@
float f1 = Mth.wrapDegrees(f - this.getYRot());
this.zza = 0.5F;
this.setYRot(this.getYRot() + f1);
@@ -34,7 +34,7 @@
this.setResting(true);
}
}
@@ -203,7 +_,7 @@
@@ -204,7 +_,7 @@
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/animal/Cow.java
+++ b/net/minecraft/world/entity/animal/Cow.java
@@ -88,8 +_,15 @@
--- a/net/minecraft/world/entity/animal/AbstractCow.java
+++ b/net/minecraft/world/entity/animal/AbstractCow.java
@@ -84,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, itemInHand, Items.MILK_BUCKET, hand);
+ org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(player.level(), player, this.blockPosition(), this.blockPosition(), null, itemInHand, Items.MILK_BUCKET, hand);
+ if (event.isCancelled()) {
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+ return InteractionResult.PASS;

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/entity/animal/Animal.java
+++ b/net/minecraft/world/entity/animal/Animal.java
@@ -39,6 +_,7 @@
public int inLove;
@@ -41,6 +_,7 @@
public int inLove = 0;
@Nullable
public UUID loveCause;
+ public ItemStack breedItem; // CraftBukkit - Add breedItem variable
+ public @Nullable ItemStack breedItem; // CraftBukkit - Add breedItem variable
protected Animal(EntityType<? extends Animal> entityType, Level level) {
super(entityType, level);
@@ -78,9 +_,13 @@
@@ -80,9 +_,13 @@
}
@Override
@@ -35,7 +35,7 @@
this.playEatingSound();
return InteractionResult.SUCCESS_SERVER;
}
@@ -176,11 +_,26 @@
@@ -176,8 +_,23 @@
return this.inLove <= 0;
}
@@ -45,6 +45,7 @@
+ // 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
@@ -59,17 +60,13 @@
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 +_,44 @@
@@ -220,23 +_,45 @@
if (breedOffspring != null) {
breedOffspring.setBaby(true);
breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
breedOffspring.snapTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
- this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring);
- level.addFreshEntityWithPassengers(breedOffspring);
+ // CraftBukkit start - call EntityBreedEvent
+ // 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);
@@ -79,29 +76,30 @@
+ return;
+ }
+ experience = entityBreedEvent.getExperience();
+
+ this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring, experience);
+ level.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);
+ // CraftBukkit end - call EntityBreedEvent
+ // CraftBukkit end - Call EntityBreedEvent
}
}
public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) {
- Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(animal.getLoveCause())).ifPresent(player -> {
+ // CraftBukkit start - call EntityBreedEvent
+ // CraftBukkit start - Call EntityBreedEvent
+ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1);
+ }
+
+ public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby, int experience) {
+ // CraftBukkit end - call EntityBreedEvent
+ // Paper start - call EntityBreedEvent
+ // CraftBukkit end - Call EntityBreedEvent
+ // Paper start - Call EntityBreedEvent
+ ServerPlayer player = this.getLoveCause();
+ if (player == null) player = animal.getLoveCause();
+ if (player != null) {
+ // Paper end - call EntityBreedEvent
+ // Paper end - Call EntityBreedEvent
player.awardStat(Stats.ANIMALS_BRED);
CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby);
- });
+ } // Paper - call EntityBreedEvent
+ } // Paper - Call EntityBreedEvent
this.setAge(6000);
animal.setAge(6000);
this.resetLove();
@@ -109,8 +107,8 @@
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));
+ if (experience > 0 && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - call EntityBreedEvent
+ level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, player, baby)); // Paper - call EntityBreedEvent, add spawn context
+ if (experience > 0 && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - Call EntityBreedEvent
+ level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, player, baby)); // Paper - Call EntityBreedEvent, add spawn context
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Bee.java
+++ b/net/minecraft/world/entity/animal/Bee.java
@@ -141,10 +_,26 @@
@@ -145,10 +_,26 @@
Bee.BeeGoToHiveGoal goToHiveGoal;
private Bee.BeeGoToKnownFlowerGoal goToKnownFlowerGoal;
private int underWaterTicks;
@@ -28,7 +28,7 @@
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(PathType.DANGER_FIRE, -1.0F);
this.setPathfindingMalus(PathType.WATER, -1.0F);
@@ -191,12 +_,19 @@
@@ -195,9 +_,18 @@
@Override
public void addAdditionalSaveData(CompoundTag compound) {
@@ -37,20 +37,17 @@
+ }
+
+ @Override
+ public void addAdditionalSaveData(CompoundTag compound, boolean includeAll) {
+ public void addAdditionalSaveData(CompoundTag compound, boolean saveAll) {
+ // 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 (saveAll) { // Paper
compound.storeNullable("hive_pos", BlockPos.CODEC, this.hivePos);
compound.storeNullable("flower_pos", BlockPos.CODEC, this.savedFlowerPos);
+ } // Paper
compound.putBoolean("HasNectar", this.hasNectar());
compound.putBoolean("HasStung", this.hasStung());
compound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive);
@@ -235,7 +_,7 @@
}
if (i > 0) {
@@ -59,7 +56,7 @@
}
}
@@ -492,7 +_,11 @@
@@ -490,7 +_,11 @@
if (this.hivePos == null) {
return null;
} else {
@@ -72,7 +69,7 @@
}
}
@@ -525,6 +_,7 @@
@@ -523,6 +_,7 @@
}
public void setRolling(boolean isRolling) {
@@ -80,7 +77,7 @@
this.setFlag(2, isRolling);
}
@@ -581,7 +_,7 @@
@@ -579,7 +_,7 @@
if (beeInteractionEffect != null) {
this.usePlayerItem(player, hand, itemInHand);
if (!this.level().isClientSide) {
@@ -89,7 +86,7 @@
}
return InteractionResult.SUCCESS;
@@ -650,8 +_,9 @@
@@ -648,8 +_,9 @@
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {
@@ -100,7 +97,7 @@
}
}
@@ -772,7 +_,7 @@
@@ -770,7 +_,7 @@
@VisibleForDebug
public class BeeGoToHiveGoal extends Bee.BaseBeeGoal {
public static final int MAX_TRAVELLING_TICKS = 2400;
@@ -109,7 +106,7 @@
private static final int MAX_BLACKLISTED_TARGETS = 3;
final List<BlockPos> blacklistedTargets = Lists.newArrayList();
@Nullable
@@ -888,7 +_,7 @@
@@ -886,7 +_,7 @@
public class BeeGoToKnownFlowerGoal extends Bee.BaseBeeGoal {
private static final int MAX_TRAVELLING_TICKS = 2400;
@@ -118,7 +115,7 @@
BeeGoToKnownFlowerGoal() {
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
@@ -986,7 +_,7 @@
@@ -983,7 +_,7 @@
}
}
@@ -127,16 +124,16 @@
Bee.this.level().levelEvent(2011, blockPos, 15);
Bee.this.level().setBlockAndUpdate(blockPos, blockState1);
Bee.this.incrementNumCropsGrownSincePollination();
@@ -1010,7 +_,7 @@
@@ -1007,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
+ mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY); // CraftBukkit - reason
}
}
}
@@ -1168,7 +_,7 @@
@@ -1165,7 +_,7 @@
Bee.this.dropFlower();
this.pollinating = false;
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Bucketable.java
+++ b/net/minecraft/world/entity/animal/Bucketable.java
@@ -88,9 +_,19 @@
@@ -71,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()) {
@@ -21,7 +21,7 @@
ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, bucketItemStack, false);
player.setItemInHand(hand, itemStack);
Level level = entity.level();
@@ -98,7 +_,7 @@
@@ -81,7 +_,7 @@
CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer)player, bucketItemStack);
}

View File

@@ -1,15 +1,6 @@
--- 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 @@
@@ -372,6 +_,11 @@
if (item instanceof DyeItem dyeItem) {
DyeColor dyeColor = dyeItem.getDyeColor();
if (dyeColor != this.getCollarColor()) {
@@ -21,7 +12,7 @@
if (!this.level().isClientSide()) {
this.setCollarColor(dyeColor);
itemInHand.consume(1, player);
@@ -371,7 +_,7 @@
@@ -384,7 +_,7 @@
if (!this.level().isClientSide()) {
this.usePlayerItem(player, hand, itemInHand);
FoodProperties foodProperties = itemInHand.get(DataComponents.FOOD);
@@ -30,7 +21,7 @@
this.playEatingSound();
}
@@ -433,7 +_,7 @@
@@ -446,7 +_,7 @@
}
private void tryToTame(Player player) {
@@ -39,32 +30,32 @@
this.tame(player);
this.setOrderedToSit(true);
this.level().broadcastEntityEvent(this, (byte)7);
@@ -567,15 +_,20 @@
@@ -580,15 +_,20 @@
.dropFromGiftLootTable(
getServerLevel(this.cat),
BuiltInLootTables.CAT_MORNING_GIFT,
- (serverLevel, itemStack) -> serverLevel.addFreshEntity(
- (level, stack) -> level.addFreshEntity(
- new ItemEntity(
+ (serverLevel, itemStack) -> {
+ // CraftBukkit start
+ ItemEntity item = new ItemEntity(
serverLevel,
+ // CraftBukkit start
+ (level, stack) -> {
+ final ItemEntity item = new ItemEntity(
level,
(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
stack
- )
- )
+ );
+ 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
+ level.addFreshEntity(item);
+ }
+ // CraftBukkit end
);
}
@@ -602,7 +_,7 @@
@@ -615,7 +_,7 @@
static class CatTemptGoal extends TemptGoal {
@Nullable

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Chicken.java
+++ b/net/minecraft/world/entity/animal/Chicken.java
@@ -91,10 +_,12 @@
@@ -111,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) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Dolphin.java
+++ b/net/minecraft/world/entity/animal/Dolphin.java
@@ -96,6 +_,13 @@
@@ -98,6 +_,13 @@
return EntityType.DOLPHIN.create(level, EntitySpawnReason.BREEDING);
}
@@ -14,7 +14,7 @@
@Override
public float getAgeScale() {
return this.isBaby() ? 0.65F : 1.0F;
@@ -196,7 +_,7 @@
@@ -182,7 +_,7 @@
@Override
public int getMaxAirSupply() {
@@ -23,7 +23,7 @@
}
@Override
@@ -229,11 +_,15 @@
@@ -215,11 +_,15 @@
if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) {
ItemStack item = entity.getItem();
if (this.canHoldItem(item)) {
@@ -40,7 +40,7 @@
}
}
}
@@ -497,7 +_,7 @@
@@ -486,7 +_,7 @@
@Override
public void start() {
@@ -49,7 +49,7 @@
}
@Override
@@ -516,7 +_,7 @@
@@ -505,7 +_,7 @@
}
if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) {
@@ -58,7 +58,7 @@
}
}
}
@@ -586,7 +_,7 @@
@@ -575,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
);

View File

@@ -1,15 +1,15 @@
--- 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"));
@@ -429,7 +_,7 @@
compound.read("Trusted", TRUSTED_LIST_CODEC).orElse(List.of()).forEach(this::addTrustedEntity);
this.setSleeping(compound.getBooleanOr("Sleeping", false));
this.setVariant(compound.read("Type", Fox.Variant.CODEC).orElse(Fox.Variant.DEFAULT));
- this.setSitting(compound.getBooleanOr("Sitting", false));
+ this.setSitting(compound.getBooleanOr("Sitting", false), false); // Paper - Add EntityToggleSitEvent
this.setIsCrouching(compound.getBooleanOr("Crouching", false));
if (this.level() instanceof ServerLevel) {
this.setTargetGoals();
@@ -425,6 +_,12 @@
@@ -446,6 +_,12 @@
}
public void setSitting(boolean sitting) {
@@ -22,7 +22,7 @@
this.setFlag(1, sitting);
}
@@ -484,19 +_,20 @@
@@ -505,19 +_,20 @@
itemEntity.setPickUpDelay(40);
itemEntity.setThrower(this);
this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F);
@@ -46,7 +46,7 @@
int count = item.getCount();
if (count > 1) {
this.dropItemStack(item.split(count - 1));
@@ -507,7 +_,7 @@
@@ -528,7 +_,7 @@
this.setItemSlot(EquipmentSlot.MAINHAND, item.split(1));
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
this.take(entity, item.getCount());
@@ -55,8 +55,23 @@
this.ticksSinceEaten = 0;
}
}
@@ -671,15 +_,33 @@
return this.getTrustedUUIDs().contains(uuid);
@@ -623,12 +_,12 @@
}
@Override
- public void setTarget(@Nullable LivingEntity livingEntity) {
+ public boolean setTarget(@Nullable LivingEntity livingEntity, @Nullable org.bukkit.event.entity.EntityTargetEvent.TargetReason reason) { // CraftBukkit
if (this.isDefending() && livingEntity == null) {
this.setDefending(false);
}
- super.setTarget(livingEntity);
+ return super.setTarget(livingEntity, reason); // CraftBukkit
}
void wakeUp() {
@@ -692,15 +_,33 @@
return this.getTrustedEntities().anyMatch(entityReference -> entityReference.matches(entity));
}
- @Override
@@ -93,13 +108,13 @@
}
public static boolean isPathClear(Fox fox, LivingEntity livingEntity) {
@@ -853,6 +_,18 @@
if (loveCause1 != null && loveCause != loveCause1) {
fox.addTrustedUUID(loveCause1.getUUID());
@@ -876,6 +_,19 @@
fox.addTrustedEntity(loveCause1);
}
+ // CraftBukkit start - call EntityBreedEvent
+ fox.setAge(-24000);
+ fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
+ fox.snapTo(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()) {
@@ -109,15 +124,16 @@
+ }
+ experience = entityBreedEvent.getExperience();
+ // CraftBukkit end - call EntityBreedEvent
+
if (serverPlayer != null) {
serverPlayer.awardStat(Stats.ANIMALS_BRED);
@@ -863,14 +_,12 @@
CriteriaTriggers.BRED_ANIMALS.trigger(serverPlayer, this.animal, this.partner, fox);
@@ -885,14 +_,12 @@
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);
- fox.snapTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
- serverLevel.addFreshEntityWithPassengers(fox);
+ serverLevel.addFreshEntityWithPassengers(fox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
this.level.broadcastEntityEvent(this.animal, (byte)18);
@@ -130,10 +146,10 @@
);
}
}
@@ -934,6 +_,7 @@
@@ -956,6 +_,7 @@
private void pickSweetBerries(BlockState state) {
int ageValue = state.getValue(SweetBerryBushBlock.AGE);
state.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(1));
state.setValue(SweetBerryBushBlock.AGE, 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);

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/world/entity/animal/IronGolem.java
+++ b/net/minecraft/world/entity/animal/IronGolem.java
@@ -104,7 +_,7 @@
@@ -105,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
+ this.setTarget((LivingEntity)entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION); // CraftBukkit - set reason
}
super.doPush(entity);
@@ -303,7 +_,7 @@
@@ -304,7 +_,7 @@
BlockPos blockPos = this.blockPosition();
BlockPos blockPos1 = blockPos.below();
BlockState blockState = level.getBlockState(blockPos1);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
@@ -110,7 +_,17 @@
@@ -116,7 +_,17 @@
return InteractionResult.SUCCESS;
} else if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) {
if (this.level() instanceof ServerLevel serverLevel) {
@@ -19,7 +19,7 @@
this.gameEvent(GameEvent.SHEAR, player);
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
}
@@ -163,15 +_,31 @@
@@ -169,15 +_,31 @@
@Override
public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears) {
@@ -40,11 +40,11 @@
+ 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 -> {
this.convertTo(EntityType.COW, ConversionParams.single(this, false, false), cow -> {
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)));
- this.dropFromShearingLootTable(level, BuiltInLootTables.SHEAR_MOOSHROOM, shears, (serverLevel, stack) -> {
- for (int i = 0; i < stack.getCount(); i++) {
- serverLevel.addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), stack.copyWithCount(1)));
- }
+ // Paper start - custom shear drops; moved drop generation to separate method
+ drops.forEach(drop -> {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Ocelot.java
+++ b/net/minecraft/world/entity/animal/Ocelot.java
@@ -125,7 +_,7 @@
@@ -126,7 +_,7 @@
@Override
public boolean removeWhenFarAway(double distanceToClosestPlayer) {
@@ -9,7 +9,7 @@
}
public static AttributeSupplier.Builder createAttributes() {
@@ -159,7 +_,7 @@
@@ -160,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) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Panda.java
+++ b/net/minecraft/world/entity/animal/Panda.java
@@ -127,6 +_,7 @@
@@ -128,6 +_,7 @@
}
public void sit(boolean sitting) {
@@ -8,7 +8,7 @@
this.setFlag(8, sitting);
}
@@ -516,24 +_,28 @@
@@ -517,24 +_,28 @@
for (Panda panda : level.getEntitiesOfClass(Panda.class, this.getBoundingBox().inflate(10.0))) {
if (!panda.isBaby() && panda.onGround() && !panda.isInWater() && panda.canPerformAction()) {
@@ -39,7 +39,7 @@
}
}
@@ -624,8 +_,9 @@
@@ -625,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()) {
@@ -50,7 +50,7 @@
} else {
if (!(this.level() instanceof ServerLevel serverLevel) || this.isSitting() || this.isInWater()) {
return InteractionResult.PASS;
@@ -635,7 +_,9 @@
@@ -636,7 +_,9 @@
this.eat(true);
ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND);
if (!itemBySlot.isEmpty() && !player.hasInfiniteMaterials()) {
@@ -60,16 +60,16 @@
}
this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(itemInHand.getItem(), 1));
@@ -861,7 +_,7 @@
@@ -858,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
+ mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY); // CraftBukkit
}
}
}
@@ -1090,7 +_,9 @@
@@ -1087,7 +_,9 @@
public void stop() {
ItemStack itemBySlot = Panda.this.getItemBySlot(EquipmentSlot.MAINHAND);
if (!itemBySlot.isEmpty()) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Parrot.java
+++ b/net/minecraft/world/entity/animal/Parrot.java
@@ -257,7 +_,7 @@
@@ -262,7 +_,7 @@
}
if (!this.level().isClientSide) {
@@ -9,7 +9,7 @@
this.tame(player);
this.level().broadcastEntityEvent(this, (byte)7);
} else {
@@ -278,7 +_,7 @@
@@ -283,7 +_,7 @@
}
} else {
this.usePlayerItem(player, hand, itemInHand);
@@ -18,7 +18,7 @@
if (player.isCreative() || !this.isInvulnerable()) {
this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE);
}
@@ -373,8 +_,8 @@
@@ -378,8 +_,8 @@
}
@Override
@@ -29,7 +29,7 @@
}
@Override
@@ -389,8 +_,13 @@
@@ -394,8 +_,13 @@
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Pufferfish.java
+++ b/net/minecraft/world/entity/animal/Pufferfish.java
@@ -95,24 +_,36 @@
@@ -96,24 +_,36 @@
public void tick() {
if (!this.level().isClientSide && this.isAlive() && this.isEffectiveAi()) {
if (this.inflateCounter > 0) {
@@ -37,7 +37,7 @@
this.deflateTimer++;
}
}
@@ -136,7 +_,7 @@
@@ -137,7 +_,7 @@
private void touch(ServerLevel level, Mob mob) {
int puffState = this.getPuffState();
if (mob.hurtServer(level, this.damageSources().mobAttack(this), 1 + puffState)) {
@@ -46,7 +46,7 @@
this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F);
}
}
@@ -151,7 +_,7 @@
@@ -152,7 +_,7 @@
serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F));
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Rabbit.java
+++ b/net/minecraft/world/entity/animal/Rabbit.java
@@ -88,7 +_,7 @@
@@ -95,7 +_,7 @@
super(entityType, level);
this.jumpControl = new Rabbit.RabbitJumpControl(this);
this.moveControl = new Rabbit.RabbitMoveControl(this);
@@ -9,7 +9,7 @@
}
@Override
@@ -561,9 +_,11 @@
@@ -588,9 +_,11 @@
if (this.canRaid && block instanceof CarrotBlock) {
int ageValue = blockState.getValue(CarrotBlock.AGE);
if (ageValue == 0) {
@@ -18,6 +18,6 @@
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.setBlock(blockPos, blockState.setValue(CarrotBlock.AGE, ageValue - 1), 2);
level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(this.rabbit));
level.levelEvent(2001, blockPos, Block.getId(blockState));

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
@@ -92,7 +_,7 @@
@@ -91,7 +_,7 @@
super.aiStep();
if (this.level() instanceof ServerLevel serverLevel) {
if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) {
@@ -9,16 +9,16 @@
}
if (!serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
@@ -107,7 +_,7 @@
@@ -106,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
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockPos, blockState, 3, this)) continue; // CraftBukkit
this.level().gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this, blockState));
}
}
@@ -135,7 +_,19 @@
@@ -134,7 +_,19 @@
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) {
if (this.level() instanceof ServerLevel serverLevel) {
@@ -39,7 +39,7 @@
this.gameEvent(GameEvent.SHEAR, player);
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
}
@@ -148,11 +_,29 @@
@@ -147,11 +_,29 @@
@Override
public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Turtle.java
+++ b/net/minecraft/world/entity/animal/Turtle.java
@@ -303,7 +_,9 @@
@@ -259,7 +_,9 @@
protected void ageBoundaryReached() {
super.ageBoundaryReached();
if (!this.isBaby() && this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
@@ -10,7 +10,7 @@
}
}
@@ -328,7 +_,7 @@
@@ -284,7 +_,7 @@
@Override
public void thunderHit(ServerLevel level, LightningBolt lightning) {
@@ -19,7 +19,7 @@
}
@Override
@@ -355,6 +_,10 @@
@@ -311,6 +_,10 @@
if (loveCause == null && this.partner.getLoveCause() != null) {
loveCause = this.partner.getLoveCause();
}
@@ -30,7 +30,7 @@
if (loveCause != null) {
loveCause.awardStat(Stats.ANIMALS_BRED);
@@ -368,7 +_,7 @@
@@ -324,7 +_,7 @@
this.partner.resetLove();
RandomSource random = this.animal.getRandom();
if (getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
@@ -39,34 +39,32 @@
}
}
}
@@ -392,7 +_,7 @@
@@ -347,7 +_,7 @@
&& (
this.turtle.hasEgg()
|| this.turtle.getRandom().nextInt(reducedTickDelay(700)) == 0
&& !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0)
|| this.turtle.getRandom().nextInt(reducedTickDelay(700)) == 0 && !this.turtle.homePos.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 @@
@@ -455,14 +_,20 @@
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
+ this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.blockPos, this.turtle.level())).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);
+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.blockPos.above(), this.turtle.level()), 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 - Turtle API
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
- BlockState blockState = Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1);
+ BlockState blockState = Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()); // Paper
level.setBlock(blockPos1, blockState, 3);
level.gameEvent(GameEvent.BLOCK_PLACE, blockPos1, GameEvent.Context.of(this.turtle, blockState));
+ } // CraftBukkit

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/WaterAnimal.java
+++ b/net/minecraft/world/entity/animal/WaterAnimal.java
@@ -70,6 +_,10 @@
@@ -72,6 +_,10 @@
) {
int seaLevel = level.getSeaLevel();
int i = seaLevel - 13;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/allay/Allay.java
+++ b/net/minecraft/world/entity/animal/allay/Allay.java
@@ -118,6 +_,7 @@
@@ -116,6 +_,7 @@
private float dancingAnimationTicks;
private float spinningAnimationTicks;
private float spinningAnimationTicks0;
@@ -8,7 +8,7 @@
public Allay(EntityType<? extends Allay> entityType, Level level) {
super(entityType, level);
@@ -131,6 +_,12 @@
@@ -129,6 +_,12 @@
);
}
@@ -21,7 +21,7 @@
@Override
protected Brain.Provider<Allay> brainProvider() {
return Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
@@ -252,7 +_,7 @@
@@ -248,7 +_,7 @@
public void aiStep() {
super.aiStep();
if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) {
@@ -30,7 +30,7 @@
}
if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) {
@@ -320,7 +_,12 @@
@@ -316,7 +_,12 @@
ItemStack itemInHand = player.getItemInHand(hand);
ItemStack itemInHand1 = this.getItemInHand(InteractionHand.MAIN_HAND);
if (this.isDancing() && itemInHand.is(ItemTags.DUPLICATES_ALLAYS) && this.canDuplicate()) {
@@ -44,7 +44,7 @@
this.level().broadcastEntityEvent(this, (byte)18);
this.level().playSound(player, this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F);
this.removeInteractionItem(player, itemInHand);
@@ -425,6 +_,7 @@
@@ -421,6 +_,7 @@
}
private boolean shouldStopDancing() {
@@ -52,24 +52,24 @@
return this.jukeboxPos == null
|| !this.jukeboxPos.closerToCenterThan(this.position(), GameEvent.JUKEBOX_PLAY.value().notificationRadius())
|| !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX);
@@ -489,7 +_,7 @@
.ifPresent(data -> this.vibrationData = data);
}
- this.duplicationCooldown = compound.getInt("DuplicationCooldown");
+ this.duplicationCooldown = compound.getLong("DuplicationCooldown"); // Paper - Load as long
this.entityData.set(DATA_CAN_DUPLICATE, compound.getBoolean("CanDuplicate"));
@@ -475,7 +_,7 @@
this.readInventoryFromTag(compound, this.registryAccess());
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
this.vibrationData = compound.read("listener", VibrationSystem.Data.CODEC, registryOps).orElseGet(VibrationSystem.Data::new);
- this.setDuplicationCooldown(compound.getIntOr("DuplicationCooldown", 0));
+ this.setDuplicationCooldown(compound.getLongOr("DuplicationCooldown", 0)); // Paper - Load as long
}
@@ -508,15 +_,17 @@
}
@Override
@@ -494,15 +_,17 @@
this.entityData.set(DATA_CAN_DUPLICATE, duplicationCooldown == 0L);
}
- public void duplicateAllay() {
+ @Nullable public Allay duplicateAllay() { // CraftBukkit - return allay
Allay allay = EntityType.ALLAY.create(this.level(), EntitySpawnReason.BREEDING);
if (allay != null) {
allay.moveTo(this.position());
allay.snapTo(this.position());
allay.setPersistenceRequired();
allay.resetDuplicationCooldown();
this.resetDuplicationCooldown();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
@@ -141,10 +_,12 @@
@@ -142,10 +_,12 @@
ArmadilloAi.updateActivity(this);
profilerFiller.pop();
if (this.isAlive() && !this.isBaby() && --this.scuteTime <= 0) {
@@ -13,7 +13,7 @@
this.scuteTime = this.pickNextScuteDropTime();
}
@@ -283,8 +_,11 @@
@@ -282,8 +_,11 @@
}
@Override
@@ -27,7 +27,7 @@
if (!this.isNoAi() && !this.isDeadOrDying()) {
if (damageSource.getEntity() instanceof LivingEntity) {
this.getBrain().setMemoryWithExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY, true, 80L);
@@ -295,6 +_,7 @@
@@ -294,6 +_,7 @@
this.rollOut();
}
}
@@ -35,7 +35,7 @@
}
@Override
@@ -313,7 +_,9 @@
@@ -312,7 +_,9 @@
return false;
} else {
if (this.level() instanceof ServerLevel serverLevel) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java
+++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
@@ -226,7 +_,7 @@
@@ -231,7 +_,7 @@
@Override
public int getMaxAirSupply() {
@@ -8,8 +8,8 @@
+ return this.maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
}
@Override
@@ -426,10 +_,10 @@
public Axolotl.Variant getVariant() {
@@ -449,10 +_,10 @@
if (effect == null || effect.endsWithin(2399)) {
int i = effect != null ? effect.getDuration() : 0;
int min = Math.min(2400, 100 + i);
@@ -17,12 +17,12 @@
+ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, min, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit
}
- player.removeEffect(MobEffects.DIG_SLOWDOWN);
+ player.removeEffect(MobEffects.DIG_SLOWDOWN, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // Paper - Add missing effect cause
- player.removeEffect(MobEffects.MINING_FATIGUE);
+ player.removeEffect(MobEffects.MINING_FATIGUE, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // Paper - Add missing effect cause
}
@Override
@@ -521,6 +_,13 @@
@@ -544,6 +_,13 @@
) {
return level.getBlockState(pos.below()).is(BlockTags.AXOLOTLS_SPAWNABLE_ON);
}
@@ -30,7 +30,7 @@
+ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
+ @Override
+ public int getDefaultMaxAirSupply() {
+ return Axolotl.AXOLOTL_TOTAL_AIR_SUPPLY;
+ return AXOLOTL_TOTAL_AIR_SUPPLY;
+ }
+ // CraftBukkit end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/camel/Camel.java
+++ b/net/minecraft/world/entity/animal/camel/Camel.java
@@ -386,12 +_,12 @@
@@ -398,12 +_,12 @@
} else {
boolean flag = this.getHealth() < this.getMaxHealth();
if (flag) {
@@ -15,7 +15,7 @@
}
boolean isBaby = this.isBaby();
@@ -451,9 +_,13 @@
@@ -463,9 +_,13 @@
}
@Override
@@ -31,7 +31,7 @@
}
@Override
@@ -554,7 +_,7 @@
@@ -566,7 +_,7 @@
}
public void sitDown() {
@@ -40,7 +40,7 @@
this.makeSound(SoundEvents.CAMEL_SIT);
this.setPose(Pose.SITTING);
this.gameEvent(GameEvent.ENTITY_ACTION);
@@ -563,7 +_,7 @@
@@ -575,7 +_,7 @@
}
public void standUp() {
@@ -49,7 +49,7 @@
this.makeSound(SoundEvents.CAMEL_STAND);
this.setPose(Pose.STANDING);
this.gameEvent(GameEvent.ENTITY_ACTION);
@@ -572,6 +_,7 @@
@@ -584,6 +_,7 @@
}
public void standUpInstantly() {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/frog/Frog.java
+++ b/net/minecraft/world/entity/animal/frog/Frog.java
@@ -270,7 +_,12 @@
@@ -287,7 +_,12 @@
@Override
public void spawnChildFromBreeding(ServerLevel level, Animal mate) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/frog/Tadpole.java
+++ b/net/minecraft/world/entity/animal/frog/Tadpole.java
@@ -62,6 +_,7 @@
@@ -63,6 +_,7 @@
MemoryModuleType.BREED_TARGET,
MemoryModuleType.IS_PANICKING
);
@@ -8,7 +8,7 @@
public Tadpole(EntityType<? extends AbstractFish> entityType, Level level) {
super(entityType, level);
@@ -113,7 +_,7 @@
@@ -114,7 +_,7 @@
@Override
public void aiStep() {
super.aiStep();
@@ -17,7 +17,7 @@
this.setAge(this.age + 1);
}
}
@@ -122,12 +_,14 @@
@@ -123,12 +_,14 @@
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
compound.putInt("Age", this.age);
@@ -27,12 +27,12 @@
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
this.setAge(compound.getInt("Age"));
+ this.ageLocked = compound.getBoolean("AgeLocked"); // Paper
this.setAge(compound.getIntOr("Age", 0));
+ this.ageLocked = compound.getBooleanOr("AgeLocked", false); // Paper
}
@Nullable
@@ -177,7 +_,12 @@
@@ -178,13 +_,19 @@
@Override
public void saveToBucketTag(ItemStack stack) {
Bucketable.saveDefaultDataToBucketTag(this, stack);
@@ -46,15 +46,14 @@
}
@Override
@@ -186,6 +_,7 @@
if (tag.contains("Age")) {
this.setAge(tag.getInt("Age"));
}
+ this.ageLocked = tag.getBoolean("AgeLocked"); // Paper
public void loadFromBucketTag(CompoundTag tag) {
Bucketable.loadDefaultDataFromBucketTag(this, tag);
tag.getInt("Age").ifPresent(this::setAge);
+ this.ageLocked = tag.getBooleanOr("AgeLocked", false); // Paper
}
@Override
@@ -217,6 +_,7 @@
@@ -216,6 +_,7 @@
}
private void ageUp(int offset) {
@@ -62,7 +61,7 @@
this.setAge(this.age + offset * 20);
}
@@ -229,12 +_,17 @@
@@ -228,12 +_,17 @@
private void ageUp() {
if (this.level() instanceof ServerLevel serverLevel) {

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
@@ -231,13 +_,22 @@
@@ -234,13 +_,22 @@
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, itemInHand, Items.MILK_BUCKET, hand);
+ org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(player.level(), player, this.blockPosition(), this.blockPosition(), null, itemInHand, Items.MILK_BUCKET, hand);
+
+ if (event.isCancelled()) {
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
@@ -25,7 +25,7 @@
this.playEatingSound();
}
@@ -349,8 +_,7 @@
@@ -352,8 +_,7 @@
double d1 = Mth.randomBetween(this.random, 0.3F, 0.7F);
double d2 = Mth.randomBetween(this.random, -0.2F, 0.2F);
ItemEntity itemEntity = new ItemEntity(this.level(), vec3.x(), vec3.y(), vec3.z(), itemStack, d, d1, d2);
@@ -35,7 +35,7 @@
}
}
@@ -381,4 +_,15 @@
@@ -384,4 +_,15 @@
) {
return level.getBlockState(pos.below()).is(BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
+++ b/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
@@ -69,6 +_,12 @@
@@ -70,6 +_,12 @@
super.dropEquipment(level);
if (this.hasChest()) {
this.spawnAtLocation(level, Blocks.CHEST);

View File

@@ -1,78 +1,14 @@
--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -77,6 +_,17 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.ticks.ContainerSingleItem;
+// CraftBukkit start
+import java.util.Arrays;
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.entity.EntityRegainHealthEvent;
+import org.bukkit.inventory.InventoryHolder;
+// CraftBukkit end
+
public abstract class AbstractHorse extends Animal implements ContainerListener, HasCustomInventoryScreen, OwnableEntity, PlayerRideableJumping, Saddleable {
public static final int EQUIPMENT_SLOT_OFFSET = 400;
public static final int CHEST_SLOT_OFFSET = 499;
@@ -145,7 +_,53 @@
public boolean stillValid(Player player) {
return player.getVehicle() == AbstractHorse.this || player.canInteractWithEntity(AbstractHorse.this, 4.0);
}
+
+ // CraftBukkit start - add fields and methods
+ public final List<HumanEntity> transaction = new java.util.ArrayList<>();
+ private int maxStack = MAX_STACK;
+
+ @Override
+ public List<ItemStack> getContents() {
+ return Arrays.asList(this.getTheItem());
+ }
+
+ @Override
+ public void onOpen(CraftHumanEntity player) {
+ this.transaction.add(player);
+ }
+
+ @Override
+ public void onClose(CraftHumanEntity player) {
+ this.transaction.remove(player);
+ }
+
+ @Override
+ public List<HumanEntity> getViewers() {
+ return this.transaction;
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ return this.maxStack;
+ }
+
+ @Override
+ public void setMaxStackSize(int size) {
+ this.maxStack = size;
+ }
+
+ @Override
+ public InventoryHolder getOwner() {
+ return (org.bukkit.entity.AbstractHorse) AbstractHorse.this.getBukkitEntity();
+ }
+
+ @Override
+ public Location getLocation() {
+ return AbstractHorse.this.getBukkitEntity().getLocation();
+ }
+ // CraftBukkit end
};
@@ -122,6 +_,7 @@
protected int gallopSoundCounter;
@Nullable
public EntityReference<LivingEntity> owner;
+ public int maxDomestication = 100; // CraftBukkit - store max domestication value
protected AbstractHorse(EntityType<? extends AbstractHorse> entityType, Level level) {
super(entityType, level);
@@ -284,7 +_,7 @@
@@ -250,7 +_,7 @@
}
@Override
@@ -81,25 +17,25 @@
return !this.isVehicle();
}
@@ -340,7 +_,7 @@
@@ -301,7 +_,7 @@
public void createInventory() {
SimpleContainer simpleContainer = this.inventory;
- this.inventory = new SimpleContainer(this.getInventorySize());
+ this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit
if (simpleContainer != null) {
simpleContainer.removeListener(this);
int min = Math.min(simpleContainer.getContainerSize(), this.inventory.getContainerSize());
@@ -448,7 +_,7 @@
@@ -395,7 +_,7 @@
}
public int getMaxTemper() {
- return 100;
+ return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100
+ return this.maxDomestication; // CraftBukkit - return stored max domestication instead
}
@Override
@@ -503,7 +_,7 @@
@@ -450,7 +_,7 @@
i1 = 5;
if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) {
flag = true;
@@ -108,7 +44,7 @@
}
} else if (stack.is(Items.GOLDEN_APPLE) || stack.is(Items.ENCHANTED_GOLDEN_APPLE)) {
f = 10.0F;
@@ -511,12 +_,12 @@
@@ -458,12 +_,12 @@
i1 = 10;
if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) {
flag = true;
@@ -119,20 +55,20 @@
if (this.getHealth() < this.getMaxHealth() && f > 0.0F) {
- this.heal(f);
+ this.heal(f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit
+ this.heal(f, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit
flag = true;
}
@@ -587,7 +_,7 @@
@@ -534,7 +_,7 @@
super.aiStep();
if (this.level() instanceof ServerLevel serverLevel && this.isAlive()) {
if (this.random.nextInt(900) == 0 && this.deathTime == 0) {
- this.heal(1.0F);
+ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
+ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
}
if (this.canEatGrass()) {
@@ -690,6 +_,16 @@
@@ -637,6 +_,16 @@
}
}
@@ -149,7 +85,7 @@
@Override
public InteractionResult mobInteract(Player player, InteractionHand hand) {
if (this.isVehicle() || this.isBaby()) {
@@ -727,6 +_,12 @@
@@ -674,6 +_,12 @@
this.setFlag(16, eating);
}
@@ -162,27 +98,23 @@
public void setStanding(boolean standing) {
if (standing) {
this.setEating(false);
@@ -838,6 +_,7 @@
if (this.getOwnerUUID() != null) {
compound.putUUID("Owner", this.getOwnerUUID());
@@ -785,6 +_,7 @@
if (this.owner != null) {
this.owner.store(compound, "Owner");
}
+ compound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // CraftBukkit
+ compound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // Paper - max domestication
}
if (!this.inventory.getItem(0).isEmpty()) {
compound.put("SaddleItem", this.inventory.getItem(0).save(this.registryAccess()));
@@ -862,6 +_,11 @@
if (uuid != null) {
this.setOwnerUUID(uuid);
}
+ // CraftBukkit start
+ if (compound.contains("Bukkit.MaxDomestication")) {
+ this.maxDomestication = compound.getInt("Bukkit.MaxDomestication");
+ }
+ // CraftBukkit end
@Override
@@ -795,6 +_,7 @@
this.setTemper(compound.getIntOr("Temper", 0));
this.setTamed(compound.getBooleanOr("Tame", false));
this.owner = EntityReference.readWithOldOwnerConversion(compound, "Owner", this.level());
+ this.maxDomestication = compound.getIntOr("Bukkit.MaxDomestication", this instanceof Llama ? 30 : 100); // Paper - max domestication
}
if (compound.contains("SaddleItem", 10)) {
ItemStack itemStack = ItemStack.parse(this.registryAccess(), compound.getCompound("SaddleItem")).orElse(ItemStack.EMPTY);
@@ -959,6 +_,17 @@
@Override
@@ -883,6 +_,17 @@
@Override
public void handleStartJump(int jumpPower) {
@@ -193,7 +125,7 @@
+ } else {
+ power = 0.4F + 0.4F * (float) jumpPower / 90.0F;
+ }
+ if (!CraftEventFactory.callHorseJumpEvent(this, power)) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callHorseJumpEvent(this, power)) {
+ return;
+ }
+ // CraftBukkit end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/horse/Llama.java
+++ b/net/minecraft/world/entity/animal/horse/Llama.java
@@ -71,17 +_,23 @@
@@ -76,17 +_,23 @@
@Nullable
private Llama caravanHead;
@Nullable
@@ -25,7 +25,7 @@
private void setStrength(int strength) {
this.entityData.set(DATA_STRENGTH_ID, Math.max(1, Math.min(5, strength)));
}
@@ -168,12 +_,12 @@
@@ -193,12 +_,12 @@
f = 10.0F;
if (this.isTamed() && this.getAge() == 0 && this.canFallInLove()) {
flag = true;
@@ -40,7 +40,7 @@
flag = true;
}
@@ -295,7 +_,7 @@
@@ -312,7 +_,7 @@
@Override
public int getMaxTemper() {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
+++ b/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
@@ -122,7 +_,7 @@
@@ -124,7 +_,7 @@
public void aiStep() {
super.aiStep();
if (this.isTrap() && this.trapTime++ >= 18000) {

View File

@@ -25,7 +25,7 @@
this.horse.setTamed(true);
@@ -39,11 +_,11 @@
if (lightningBolt != null) {
lightningBolt.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ());
lightningBolt.snapTo(this.horse.getX(), this.horse.getY(), this.horse.getZ());
lightningBolt.setVisualOnly(true);
- serverLevel.addFreshEntity(lightningBolt);
+ serverLevel.strikeLightning(lightningBolt, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRAP); // CraftBukkit

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java
+++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java
@@ -89,7 +_,7 @@
@@ -88,7 +_,7 @@
this.despawnDelay = this.isLeashedToWanderingTrader() ? ((WanderingTrader)this.getLeashHolder()).getDespawnDelay() - 1 : this.despawnDelay - 1;
if (this.despawnDelay <= 0) {
this.removeLeash();
@@ -9,12 +9,12 @@
}
}
}
@@ -148,7 +_,7 @@
@@ -147,7 +_,7 @@
@Override
public void start() {
- this.mob.setTarget(this.ownerLastHurtBy);
+ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit
+ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER); // CraftBukkit
Entity leashHolder = this.llama.getLeashHolder();
if (leashHolder instanceof WanderingTrader) {
this.timestamp = ((WanderingTrader)leashHolder).getLastHurtByMobTimestamp();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Sheep.java
+++ b/net/minecraft/world/entity/animal/Sheep.java
@@ -158,7 +_,19 @@
--- a/net/minecraft/world/entity/animal/sheep/Sheep.java
+++ b/net/minecraft/world/entity/animal/sheep/Sheep.java
@@ -161,7 +_,19 @@
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.SHEARS)) {
if (this.level() instanceof ServerLevel serverLevel && this.readyForShearing()) {
@@ -21,7 +21,7 @@
this.gameEvent(GameEvent.SHEAR, player);
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
return InteractionResult.SUCCESS_SERVER;
@@ -172,14 +_,28 @@
@@ -175,14 +_,28 @@
@Override
public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears) {
@@ -57,7 +57,7 @@
if (itemEntity != null) {
itemEntity.setDeltaMovement(
itemEntity.getDeltaMovement()
@@ -287,6 +_,7 @@
@@ -302,6 +_,7 @@
@Override
public void ate() {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/Wolf.java
+++ b/net/minecraft/world/entity/animal/Wolf.java
@@ -344,8 +_,9 @@
--- a/net/minecraft/world/entity/animal/wolf/Wolf.java
+++ b/net/minecraft/world/entity/animal/wolf/Wolf.java
@@ -400,16 +_,18 @@
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {
@@ -11,9 +11,6 @@
}
}
@@ -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
@@ -25,7 +22,7 @@
ItemStack bodyArmorItem = this.getBodyArmorItem();
int damageValue = bodyArmorItem.getDamageValue();
int maxDamage = bodyArmorItem.getMaxDamage();
@@ -378,6 +_,7 @@
@@ -429,6 +_,7 @@
);
}
}
@@ -33,7 +30,7 @@
}
private boolean canArmorAbsorb(DamageSource damageSource) {
@@ -388,7 +_,7 @@
@@ -439,7 +_,7 @@
protected void applyTamingSideEffects() {
if (this.isTame()) {
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(40.0);
@@ -42,7 +39,7 @@
} else {
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0);
}
@@ -408,7 +_,7 @@
@@ -459,7 +_,7 @@
this.usePlayerItem(player, hand, itemInHand);
FoodProperties foodProperties = itemInHand.get(DataComponents.FOOD);
float f = foodProperties != null ? foodProperties.nutrition() : 1.0F;
@@ -51,16 +48,16 @@
return InteractionResult.SUCCESS;
}
@@ -441,7 +_,7 @@
@@ -492,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
+ this.setTarget(null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // CraftBukkit - reason
return InteractionResult.SUCCESS.withoutItem();
}
@@ -453,7 +_,9 @@
@@ -504,7 +_,9 @@
ItemStack bodyArmorItem = this.getBodyArmorItem();
this.setBodyArmorItem(ItemStack.EMPTY);
if (this.level() instanceof ServerLevel serverLevel) {
@@ -70,7 +67,7 @@
}
return InteractionResult.SUCCESS;
@@ -461,6 +_,13 @@
@@ -512,6 +_,13 @@
DyeColor dyeColor = dyeItem.getDyeColor();
if (dyeColor != this.getCollarColor()) {
@@ -84,7 +81,7 @@
this.setCollarColor(dyeColor);
itemInHand.consume(1, player);
return InteractionResult.SUCCESS;
@@ -475,7 +_,7 @@
@@ -526,7 +_,7 @@
}
private void tryToTame(Player player) {

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
+++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
@@ -25,6 +_,7 @@
);
private static final EntityDataAccessor<Boolean> DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN);
private static final boolean DEFAULT_SHOW_BOTTOM = true;
public int time;
+ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals
public EndCrystal(EntityType<? extends EndCrystal> entityType, Level level) {
super(entityType, level);
@@ -56,9 +_,23 @@
@@ -56,21 +_,37 @@
if (this.level() instanceof ServerLevel) {
BlockPos blockPos = this.blockPosition();
if (((ServerLevel)this.level()).getDragonFight() != null && this.level().getBlockState(blockPos).isAir()) {
@@ -22,7 +22,7 @@
+
+ // Paper start - Fix invulnerable end crystals
+ if (this.level().paperConfig().unsupportedSettings.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) {
+ if (!java.util.Objects.equals(((ServerLevel) this.level()).uuid, this.getOriginWorld())
+ if (!java.util.Objects.equals(((ServerLevel) this.level()).uuid, this.originWorld)
+ || ((ServerLevel) this.level()).getDragonFight() == null
+ || ((ServerLevel) this.level()).getDragonFight().respawnStage == null
+ || ((ServerLevel) this.level()).getDragonFight().respawnStage.ordinal() > net.minecraft.world.level.dimension.end.DragonRespawnAnimation.SUMMONING_DRAGON.ordinal()) {
@@ -34,23 +34,21 @@
}
@Override
@@ -68,6 +_,7 @@
}
protected void addAdditionalSaveData(CompoundTag compound) {
compound.storeNullable("beam_target", BlockPos.CODEC, this.getBeamTarget());
compound.putBoolean("ShowBottom", this.showsBottom());
+ if (this.generatedByDragonFight) compound.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals
+ compound.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals
}
@Override
@@ -76,6 +_,7 @@
if (compound.contains("ShowBottom", 1)) {
this.setShowBottom(compound.getBoolean("ShowBottom"));
}
+ if (compound.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = compound.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals
protected void readAdditionalSaveData(CompoundTag compound) {
this.setBeamTarget(compound.read("beam_target", BlockPos.CODEC).orElse(null));
this.setShowBottom(compound.getBooleanOr("ShowBottom", true));
+ this.generatedByDragonFight = compound.getBooleanOr("Paper.GeneratedByDragonFight", false); // Paper - Fix invulnerable end crystals
}
@Override
@@ -96,10 +_,24 @@
@@ -91,10 +_,24 @@
return false;
} else {
if (!this.isRemoved()) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -86,6 +_,10 @@
@@ -87,6 +_,10 @@
private final Node[] nodes = new Node[24];
private final int[] nodeAdjacency = new int[24];
private final BinaryHeap openSet = new BinaryHeap();
@@ -11,7 +11,7 @@
public EnderDragon(EntityType<? extends EnderDragon> entityType, Level level) {
super(EntityType.ENDER_DRAGON, level);
@@ -101,6 +_,7 @@
@@ -102,6 +_,7 @@
this.setHealth(this.getMaxHealth());
this.noPhysics = true;
this.phaseManager = new EnderDragonPhaseManager(this);
@@ -19,7 +19,7 @@
}
public void setDragonFight(EndDragonFight dragonFight) {
@@ -119,6 +_,19 @@
@@ -120,6 +_,19 @@
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0);
}
@@ -39,7 +39,7 @@
@Override
public boolean isFlapping() {
float cos = Mth.cos(this.flapTime * (float) (Math.PI * 2));
@@ -210,7 +_,7 @@
@@ -211,7 +_,7 @@
}
Vec3 flyTargetLocation = currentPhase.getFlyTargetLocation();
@@ -48,7 +48,7 @@
double d = flyTargetLocation.x - this.getX();
double d1 = flyTargetLocation.y - this.getY();
double d2 = flyTargetLocation.z - this.getZ();
@@ -369,7 +_,12 @@
@@ -366,7 +_,12 @@
if (this.nearestCrystal.isRemoved()) {
this.nearestCrystal = null;
} else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) {
@@ -62,7 +62,7 @@
}
}
@@ -400,7 +_,7 @@
@@ -396,7 +_,7 @@
double d2 = entity.getX() - d;
double d3 = entity.getZ() - d1;
double max = Math.max(d2 * d2 + d3 * d3, 0.1);
@@ -71,7 +71,7 @@
if (!this.phaseManager.getCurrentPhase().isSitting() && livingEntity.getLastHurtByMobTimestamp() < entity.tickCount - 2) {
DamageSource damageSource = this.damageSources().mobAttack(this);
entity.hurtServer(level, damageSource, 5.0F);
@@ -433,6 +_,7 @@
@@ -429,6 +_,7 @@
int floor5 = Mth.floor(box.maxZ);
boolean flag = false;
boolean flag1 = false;
@@ -79,7 +79,7 @@
for (int i = floor; i <= floor3; i++) {
for (int i1 = floor1; i1 <= floor4; i1++) {
@@ -441,7 +_,11 @@
@@ -437,7 +_,11 @@
BlockState blockState = level.getBlockState(blockPos);
if (!blockState.isAir() && !blockState.is(BlockTags.DRAGON_TRANSPARENT)) {
if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockState.is(BlockTags.DRAGON_IMMUNE)) {
@@ -92,7 +92,7 @@
} else {
flag = true;
}
@@ -450,6 +_,58 @@
@@ -446,6 +_,58 @@
}
}
@@ -151,7 +151,7 @@
if (flag1) {
BlockPos blockPos1 = new BlockPos(
floor + this.random.nextInt(floor3 - floor + 1),
@@ -507,7 +_,15 @@
@@ -503,7 +_,15 @@
@Override
public void kill(ServerLevel level) {
@@ -168,7 +168,7 @@
this.gameEvent(GameEvent.ENTITY_DIE);
if (this.dragonFight != null) {
this.dragonFight.updateDragon(this);
@@ -529,18 +_,41 @@
@@ -525,18 +_,41 @@
this.level().addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + f, this.getY() + 2.0 + f1, this.getZ() + f2, 0.0, 0.0, 0.0);
}
@@ -186,7 +186,7 @@
- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- ExperienceOrb.award(serverLevel, this.position(), Mth.floor(i * 0.08F));
+ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp
+ ExperienceOrb.award(serverLevel, this.position(), Mth.floor(i * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper
+ ExperienceOrb.award(serverLevel, this.position(), Mth.floor(i * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, net.minecraft.Optionull.map(this.lastHurtByPlayer, lastHurtByPlayer -> lastHurtByPlayer.getEntity(this.level(), Player.class)), this); // Paper
}
if (this.dragonDeathTime == 1 && !this.isSilent()) {
@@ -213,14 +213,14 @@
}
}
@@ -553,15 +_,15 @@
@@ -549,15 +_,15 @@
}
if (this.dragonDeathTime == 200 && this.level() instanceof ServerLevel serverLevel1) {
- if (serverLevel1.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- ExperienceOrb.award(serverLevel1, this.position(), Mth.floor(i * 0.2F));
+ if (true) { // Paper - SPIGOT-2420: Already checked for the game rule when calculating the xp
+ ExperienceOrb.award(serverLevel1, this.position(), Mth.floor(i * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper
+ ExperienceOrb.award(serverLevel1, this.position(), Mth.floor(i * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, net.minecraft.Optionull.map(this.lastHurtByPlayer, lastHurtByPlayer -> lastHurtByPlayer.getEntity(this.level(), Player.class)), this); // Paper
}
if (this.dragonFight != null) {
@@ -232,7 +232,7 @@
this.gameEvent(GameEvent.ENTITY_DIE);
}
}
@@ -743,6 +_,7 @@
@@ -739,6 +_,7 @@
super.addAdditionalSaveData(compound);
compound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId());
compound.putInt("DragonDeathTime", this.dragonDeathTime);
@@ -240,20 +240,15 @@
}
@Override
@@ -755,6 +_,12 @@
if (compound.contains("DragonDeathTime")) {
this.dragonDeathTime = compound.getInt("DragonDeathTime");
}
+
+ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts
+ if (compound.contains("Bukkit.expToDrop")) {
+ this.expToDrop = compound.getInt("Bukkit.expToDrop");
+ }
+ // CraftBukkit end
@@ -746,6 +_,7 @@
super.readAdditionalSaveData(compound);
compound.getInt("DragonPhase").ifPresent(integer -> this.phaseManager.setPhase(EnderDragonPhase.getById(integer)));
this.dragonDeathTime = compound.getIntOr("DragonDeathTime", 0);
+ this.expToDrop = compound.getIntOr("Bukkit.expToDrop", 0); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts
}
@Override
@@ -795,7 +_,7 @@
@@ -786,7 +_,7 @@
EnderDragonPhase<? extends DragonPhaseInstance> phase = currentPhase.getPhase();
Vec3 viewVector;
if (phase == EnderDragonPhase.LANDING || phase == EnderDragonPhase.TAKEOFF) {
@@ -262,16 +257,16 @@
float max = Math.max((float)Math.sqrt(heightmapPos.distToCenterSqr(this.position())) / 4.0F, 1.0F);
float f = 6.0F / max;
float xRot = this.getXRot();
@@ -883,4 +_,19 @@
@@ -874,4 +_,19 @@
protected float sanitizeScale(float scale) {
return 1.0F;
}
+
+ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time.
+ @Override
+ public int getExpReward(ServerLevel worldserver, Entity entity) {
+ public int getExpReward(ServerLevel level, Entity entity) {
+ // CraftBukkit - Moved from #tickDeath method
+ boolean flag = worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT);
+ boolean flag = level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT);
+ int i = 500;
+
+ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) {

View File

@@ -1,9 +1,9 @@
--- a/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
+++ b/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
@@ -82,7 +_,13 @@
this.flame.setDuration(200);
@@ -83,7 +_,13 @@
this.flame.setParticle(ParticleTypes.DRAGON_BREATH);
this.flame.addEffect(new MobEffectInstance(MobEffects.HARM));
this.flame.setPotionDurationScale(0.25F);
this.flame.addEffect(new MobEffectInstance(MobEffects.INSTANT_DAMAGE));
+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper - EnderDragon Events
level.addFreshEntity(this.flame);
+ // Paper start - EnderDragon Events
@@ -14,7 +14,7 @@
}
}
@@ -95,7 +_,7 @@
@@ -96,7 +_,7 @@
@Override
public void end() {
if (this.flame != null) {

View File

@@ -5,7 +5,7 @@
DragonFireball dragonFireball = new DragonFireball(level, this.dragon, vec32.normalize());
+ dragonFireball.preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported
dragonFireball.moveTo(d2, d3, d4, 0.0F, 0.0F);
dragonFireball.snapTo(d2, d3, d4, 0.0F, 0.0F);
+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) dragonFireball.getBukkitEntity()).callEvent()) // Paper - EnderDragon Events
level.addFreshEntity(dragonFireball);
+ else dragonFireball.discard(null); // Paper - EnderDragon Events

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -69,6 +_,7 @@
@@ -70,6 +_,7 @@
private final int[] nextHeadUpdate = new int[2];
private final int[] idleHeadUpdates = new int[2];
private int destroyBlocksTick;
@@ -8,7 +8,7 @@
public final ServerBossEvent bossEvent = (ServerBossEvent)new ServerBossEvent(
this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS
)
@@ -260,15 +_,40 @@
@@ -261,15 +_,40 @@
int i = this.getInvulnerableTicks() - 1;
this.bossEvent.setProgress(1.0F - i / 220.0F);
if (i <= 0) {
@@ -52,7 +52,7 @@
}
} else {
super.customServerAiStep(level);
@@ -305,6 +_,7 @@
@@ -306,6 +_,7 @@
);
if (!nearbyEntities.isEmpty()) {
LivingEntity livingEntity1 = nearbyEntities.get(this.random.nextInt(nearbyEntities.size()));
@@ -60,7 +60,7 @@
this.setAlternativeTarget(ix, livingEntity1.getId());
}
}
@@ -334,6 +_,11 @@
@@ -335,6 +_,11 @@
)) {
BlockState blockState = level.getBlockState(blockPos);
if (canDestroy(blockState)) {
@@ -72,7 +72,7 @@
flag = level.destroyBlock(blockPos, true, this) || flag;
}
}
@@ -345,7 +_,7 @@
@@ -346,7 +_,7 @@
}
if (this.tickCount % 20 == 0) {
@@ -81,7 +81,7 @@
}
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
@@ -483,16 +_,16 @@
@@ -484,16 +_,16 @@
@Override
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
super.dropCustomDeathLoot(level, damageSource, recentlyHit);
@@ -101,7 +101,7 @@
} else {
this.noActionTime = 0;
}
@@ -547,12 +_,18 @@
@@ -548,12 +_,18 @@
@Override
public boolean canUsePortal(boolean allowPassengers) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -86,9 +_,17 @@
@@ -88,9 +_,17 @@
public Rotations rightArmPose = DEFAULT_RIGHT_ARM_POSE;
public Rotations leftLegPose = DEFAULT_LEFT_LEG_POSE;
public Rotations rightLegPose = DEFAULT_RIGHT_LEG_POSE;
@@ -18,7 +18,7 @@
}
public ArmorStand(Level level, double x, double y, double z) {
@@ -100,6 +_,13 @@
@@ -102,6 +_,13 @@
return createLivingAttributes().add(Attributes.STEP_HEIGHT, 0.0);
}
@@ -32,32 +32,22 @@
@Override
public void refreshDimensions() {
double x = this.getX();
@@ -159,14 +_,22 @@
@Override
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
+ // CraftBukkit start
+ this.setItemSlot(slot, stack, false);
+ }
+
+ @Override
+ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack, boolean silent) {
+ // CraftBukkit end
this.verifyEquippedItem(stack);
switch (slot.getType()) {
case HAND:
- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack, silent); // CraftBukkit
break;
case HUMANOID_ARMOR:
- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack, silent); // CraftBukkit
}
+ this.noTickEquipmentDirty = true; // Paper - Allow ArmorStands not to tick; Still update equipment
@@ -137,6 +_,14 @@
return slot != EquipmentSlot.BODY && slot != EquipmentSlot.SADDLE && !this.isDisabled(slot);
}
+ // Paper - Allow ArmorStands not to tick; Still update equipment
+ @Override
+ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack, boolean silent) {
+ super.setItemSlot(slot, stack, silent);
+ this.noTickEquipmentDirty = true;
+ }
+ // Paper - Allow ArmorStands not to tick; Still update equipment
+
@Override
@@ -196,6 +_,7 @@
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
@@ -150,6 +_,7 @@
}
compound.put("Pose", this.writePose());
@@ -65,20 +55,20 @@
}
@Override
@@ -226,6 +_,12 @@
this.setNoBasePlate(compound.getBoolean("NoBasePlate"));
this.setMarker(compound.getBoolean("Marker"));
@@ -163,6 +_,12 @@
this.setMarker(compound.getBooleanOr("Marker", false));
this.noPhysics = !this.hasPhysics();
this.readPose(compound.getCompoundOrEmpty("Pose"));
+ // Paper start - Allow ArmorStands not to tick
+ if (compound.contains("Paper.CanTickOverride")) {
+ this.canTick = compound.getBoolean("Paper.CanTickOverride");
+ compound.getBoolean("Paper.CanTickOverride").ifPresent(canTick -> {
+ this.canTick = canTick;
+ this.canTickSetByAPI = true;
+ }
+ });
+ // Paper end - Allow ArmorStands not to tick
CompoundTag compound2 = compound.getCompound("Pose");
this.readPose(compound2);
}
@@ -275,7 +_,7 @@
private void readPose(CompoundTag compound) {
@@ -204,7 +_,7 @@
}
@Override
@@ -87,7 +77,7 @@
return false;
}
@@ -285,6 +_,7 @@
@@ -214,6 +_,7 @@
@Override
protected void pushEntities() {
@@ -95,7 +85,7 @@
for (Entity entity : this.level().getEntities(this, this.getBoundingBox(), RIDABLE_MINECARTS)) {
if (this.distanceToSqr(entity) <= 0.2) {
entity.push(this);
@@ -357,7 +_,25 @@
@@ -286,7 +_,25 @@
return false;
} else if (itemBySlot.isEmpty() && (this.disabledSlots & 1 << slot.getFilterBit(16)) != 0) {
return false;
@@ -122,7 +112,7 @@
this.setItemSlot(slot, stack.copyWithCount(1));
return true;
} else if (stack.isEmpty() || stack.getCount() <= 1) {
@@ -370,6 +_,7 @@
@@ -299,6 +_,7 @@
this.setItemSlot(slot, stack.split(1));
return true;
}
@@ -130,7 +120,7 @@
}
@Override
@@ -379,15 +_,32 @@
@@ -308,15 +_,32 @@
} else if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && damageSource.getEntity() instanceof Mob) {
return false;
} else if (damageSource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) {
@@ -167,7 +157,7 @@
if (this.isOnFire()) {
this.causeDamage(level, damageSource, 0.15F);
} else {
@@ -396,9 +_,19 @@
@@ -325,9 +_,19 @@
return false;
} else if (damageSource.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) {
@@ -187,7 +177,7 @@
boolean isCanBreakArmorStand = damageSource.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND);
boolean isAlwaysKillsArmorStands = damageSource.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS);
if (!isCanBreakArmorStand && !isAlwaysKillsArmorStands) {
@@ -408,7 +_,7 @@
@@ -337,7 +_,7 @@
} else if (damageSource.isCreativePlayer()) {
this.playBrokenSound();
this.showBreakingParticles();
@@ -196,7 +186,7 @@
return true;
} else {
long gameTime = level.getGameTime();
@@ -417,9 +_,9 @@
@@ -346,9 +_,9 @@
this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity());
this.lastHit = gameTime;
} else {
@@ -208,10 +198,11 @@
}
return true;
@@ -472,28 +_,31 @@
@@ -400,31 +_,34 @@
float health = this.getHealth();
health -= damageAmount;
if (health <= 0.5F) {
this.brokenByAnything(level, damageSource);
- this.brokenByAnything(level, damageSource);
- this.kill(level);
+ // Paper start - avoid duplicate event call
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(level, damageSource);
@@ -239,28 +230,18 @@
- this.dropAllDeathLoot(level, damageSource);
+ // this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved down
for (int i = 0; i < this.handItems.size(); i++) {
ItemStack itemStack = this.handItems.get(i);
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY);
if (!itemStack.isEmpty()) {
- Block.popResource(this.level(), this.blockPosition().above(), itemStack);
+ this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
this.handItems.set(i, ItemStack.EMPTY);
}
}
@@ -501,10 +_,11 @@
for (int ix = 0; ix < this.armorItems.size(); ix++) {
ItemStack itemStack = this.armorItems.get(ix);
if (!itemStack.isEmpty()) {
- Block.popResource(this.level(), this.blockPosition().above(), itemStack);
+ this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
this.armorItems.set(ix, ItemStack.EMPTY);
+ this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly}
}
}
+ return this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved from above // Paper
}
private void playBrokenSound() {
@@ -539,7 +_,28 @@
@@ -458,7 +_,28 @@
@Override
public void tick() {
@@ -273,7 +254,7 @@
+
+ if (this.noTickEquipmentDirty) {
+ this.noTickEquipmentDirty = false;
+ this.detectEquipmentUpdatesPublic();
+ this.detectEquipmentUpdates();
+ }
+
+ return;
@@ -289,14 +270,14 @@
Rotations rotations = this.entityData.get(DATA_HEAD_POSE);
if (!this.headPose.equals(rotations)) {
this.setHeadPose(rotations);
@@ -587,9 +_,32 @@
@@ -506,9 +_,32 @@
return this.isSmall();
}
+ // CraftBukkit start
+ @Override
+ public boolean shouldDropExperience() {
+ return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop
+ return true; // MC-157395, SPIGOT-5193 even small armor stands should drop
+ }
+ // CraftBukkit end
+
@@ -323,7 +304,7 @@
this.gameEvent(GameEvent.ENTITY_DIE);
}
@@ -653,31 +_,37 @@
@@ -572,31 +_,37 @@
public void setHeadPose(Rotations headPose) {
this.headPose = headPose;
this.entityData.set(DATA_HEAD_POSE, headPose);
@@ -361,7 +342,7 @@
}
public Rotations getHeadPose() {
@@ -809,4 +_,13 @@
@@ -728,4 +_,13 @@
public boolean canBeSeenByAnyone() {
return !this.isInvisible() && !this.isMarker();
}

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -49,6 +_,7 @@
private static final float HEIGHT = 0.75F;
@@ -56,6 +_,7 @@
private static final boolean DEFAULT_FIXED = false;
public float dropChance = 1.0F;
public boolean fixed;
public boolean fixed = false;
+ public @Nullable MapId cachedMapId; // Paper - Perf: Cache map ids on item frames
public ItemFrame(EntityType<? extends ItemFrame> entityType, Level level) {
super(entityType, level);
@@ -88,6 +_,12 @@
@@ -97,6 +_,12 @@
@Override
protected AABB calculateBoundingBox(BlockPos pos, Direction direction) {
@@ -21,7 +21,7 @@
float f = 0.46875F;
Vec3 vec3 = Vec3.atCenterOf(pos).relative(direction, -0.46875);
Direction.Axis axis = direction.getAxis();
@@ -118,9 +_,9 @@
@@ -127,9 +_,9 @@
}
@Override
@@ -33,7 +33,7 @@
}
}
@@ -149,6 +_,18 @@
@@ -158,6 +_,18 @@
if (this.isInvulnerableToBase(damageSource)) {
return false;
} else if (this.shouldDamageDropItem(damageSource)) {
@@ -52,7 +52,7 @@
this.dropItem(level, damageSource.getEntity(), false);
this.gameEvent(GameEvent.BLOCK_CHANGE, damageSource.getEntity());
this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F);
@@ -234,6 +_,14 @@
@@ -243,6 +_,14 @@
return this.getEntityData().get(DATA_ITEM);
}
@@ -67,7 +67,7 @@
@Nullable
public MapId getFramedMapId(ItemStack stack) {
return stack.get(DataComponents.MAP_ID);
@@ -248,13 +_,19 @@
@@ -257,13 +_,19 @@
}
public void setItem(ItemStack stack, boolean updateNeighbours) {
@@ -88,7 +88,7 @@
this.playSound(this.getAddItemSound(), 1.0F, 1.0F);
}
@@ -280,6 +_,7 @@
@@ -289,6 +_,7 @@
}
private void onItemChanged(ItemStack item) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/decoration/Painting.java
+++ b/net/minecraft/world/entity/decoration/Painting.java
@@ -129,21 +_,31 @@
@@ -146,21 +_,31 @@
@Override
protected AABB calculateBoundingBox(BlockPos pos, Direction direction) {

View File

@@ -1,18 +1,6 @@
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -49,6 +_,11 @@
import net.minecraft.world.phys.Vec3;
import org.slf4j.Logger;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
+
public class FallingBlockEntity extends Entity {
private static final Logger LOGGER = LogUtils.getLogger();
public BlockState blockState = Blocks.SAND.defaultBlockState();
@@ -62,6 +_,7 @@
@@ -69,6 +_,7 @@
public CompoundTag blockData;
public boolean forceTickAfterTeleportToDuplicate;
protected static final EntityDataAccessor<BlockPos> DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
@@ -20,20 +8,20 @@
public FallingBlockEntity(EntityType<? extends FallingBlockEntity> entityType, Level level) {
super(entityType, level);
@@ -89,6 +_,7 @@
? blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false))
: blockState
@@ -94,6 +_,7 @@
pos.getZ() + 0.5,
blockState.hasProperty(BlockStateProperties.WATERLOGGED) ? blockState.setValue(BlockStateProperties.WATERLOGGED, false) : blockState
);
+ if (!CraftEventFactory.callEntityChangeBlockEvent(fallingBlockEntity, pos, blockState.getFluidState().createLegacyBlock())) return fallingBlockEntity; // CraftBukkit
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(fallingBlockEntity, pos, blockState.getFluidState().createLegacyBlock())) return fallingBlockEntity; // CraftBukkit
level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3);
level.addFreshEntity(fallingBlockEntity);
return fallingBlockEntity;
@@ -139,13 +_,22 @@
@@ -144,13 +_,22 @@
@Override
public void tick() {
if (this.blockState.isAir()) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
Block block = this.blockState.getBlock();
this.time++;
@@ -45,14 +33,14 @@
+ if (this.dropItem && this.level() instanceof final ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
+ this.spawnAtLocation(serverLevel, block);
+ }
+ this.discard(EntityRemoveEvent.Cause.OUT_OF_WORLD);
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.OUT_OF_WORLD);
+ return;
+ }
+ // Paper end - Configurable falling blocks height nerf
this.handlePortal();
if (this.level() instanceof ServerLevel serverLevel && (this.isAlive() || this.forceTickAfterTeleportToDuplicate)) {
BlockPos blockPos = this.blockPosition();
@@ -166,12 +_,12 @@
@@ -171,12 +_,12 @@
}
if (!this.onGround() && !flag1) {
@@ -63,17 +51,17 @@
}
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
}
} else {
BlockState blockState = this.level().getBlockState(blockPos);
@@ -189,12 +_,18 @@
this.blockState = this.blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(true));
@@ -194,12 +_,18 @@
this.blockState = this.blockState.setValue(BlockStateProperties.WATERLOGGED, true);
}
+ // CraftBukkit start
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockPos, this.blockState)) {
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // SPIGOT-6586 called before the event in previous versions
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockPos, this.blockState)) {
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // SPIGOT-6586 called before the event in previous versions
+ return;
+ }
+ // CraftBukkit end
@@ -83,22 +71,22 @@
.chunkMap
.broadcast(this, new ClientboundBlockUpdatePacket(blockPos, this.level().getBlockState(blockPos)));
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
if (block instanceof Fallable) {
((Fallable)block).onLand(this.level(), blockPos, this.blockState, blockState, this);
}
@@ -218,19 +_,19 @@
@@ -220,19 +_,19 @@
}
}
} else if (this.dropItem && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
this.callOnBrokenAfterFall(block, blockPos);
this.spawnAtLocation(serverLevel, block);
}
} else {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
if (this.dropItem && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
this.callOnBrokenAfterFall(block, blockPos);
this.spawnAtLocation(serverLevel, block);
@@ -106,11 +94,11 @@
}
} else {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
this.callOnBrokenAfterFall(block, blockPos);
}
}
@@ -290,6 +_,7 @@
@@ -293,6 +_,7 @@
}
compound.putBoolean("CancelDrop", this.cancelDrop);
@@ -118,29 +106,18 @@
}
@Override
@@ -308,7 +_,7 @@
this.dropItem = compound.getBoolean("DropItem");
}
- if (compound.contains("TileEntityData", 10)) {
+ if (compound.contains("TileEntityData", 10) && !(this.level().paperConfig().entities.spawning.filterBadTileEntityNbtFromFallingBlocks && this.blockState.getBlock() instanceof net.minecraft.world.level.block.GameMasterBlock)) { // Paper - Filter bad block entity nbt data from falling blocks
this.blockData = compound.getCompound("TileEntityData").copy();
}
@@ -316,6 +_,12 @@
if (this.blockState.isAir()) {
this.blockState = Blocks.SAND.defaultBlockState();
}
+
+ // Paper start - Expand FallingBlock API
+ if (compound.contains("Paper.AutoExpire")) {
+ this.autoExpire = compound.getBoolean("Paper.AutoExpire");
+ }
+ // Paper end - Expand FallingBlock API
@@ -305,8 +_,9 @@
this.fallDamagePerDistance = compound.getFloatOr("FallHurtAmount", 0.0F);
this.fallDamageMax = compound.getIntOr("FallHurtMax", 40);
this.dropItem = compound.getBooleanOr("DropItem", true);
- this.blockData = compound.getCompound("TileEntityData").map(CompoundTag::copy).orElse(null);
+ this.blockData = compound.getCompound("TileEntityData").map(blockData -> this.level().paperConfig().entities.spawning.filterBadTileEntityNbtFromFallingBlocks && this.blockState.getBlock() instanceof net.minecraft.world.level.block.GameMasterBlock ? null : blockData).map(CompoundTag::copy).orElse(null); // Paper - Filter bad block entity nbt data from falling blocks
this.cancelDrop = compound.getBooleanOr("CancelDrop", false);
+ this.autoExpire = compound.getBooleanOr("Paper.AutoExpire", true); // Paper - Expand FallingBlock API
}
public void setHurtsEntities(float fallDamagePerDistance, int fallDamageMax) {
@@ -372,7 +_,7 @@
@@ -363,7 +_,7 @@
ResourceKey<Level> resourceKey1 = this.level().dimension();
boolean flag = (resourceKey1 == Level.END || resourceKey == Level.END) && resourceKey1 != resourceKey;
Entity entity = super.teleport(teleportTransition);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -49,6 +_,9 @@
@@ -56,6 +_,9 @@
@Nullable
public UUID target;
public final float bobOffs;
@@ -10,7 +10,7 @@
public ItemEntity(EntityType<? extends ItemEntity> entityType, Level level) {
super(entityType, level);
@@ -57,7 +_,12 @@
@@ -64,7 +_,12 @@
}
public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack) {
@@ -24,7 +24,7 @@
}
public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack, double deltaX, double deltaY, double deltaZ) {
@@ -119,7 +_,7 @@
@@ -126,7 +_,7 @@
@Override
public void tick() {
if (this.getItem().isEmpty()) {
@@ -33,7 +33,7 @@
} else {
super.tick();
if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
@@ -147,11 +_,15 @@
@@ -154,11 +_,15 @@
}
}
@@ -44,14 +44,14 @@
float f = 0.98F;
- if (this.onGround()) {
+ // Paper start - Friction API
+ if (frictionState == net.kyori.adventure.util.TriState.FALSE) {
+ if (this.frictionState == net.kyori.adventure.util.TriState.FALSE) {
+ f = 1F;
+ } else if (this.onGround()) {
+ // Paper end - Friction API
f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F;
}
@@ -184,8 +_,14 @@
@@ -191,8 +_,14 @@
}
}
@@ -68,7 +68,7 @@
}
}
}
@@ -210,9 +_,18 @@
@@ -217,9 +_,18 @@
private void mergeWithNeighbours() {
if (this.isMergable()) {
@@ -88,7 +88,7 @@
this.tryToMerge(itemEntity);
if (this.isRemoved()) {
break;
@@ -224,14 +_,14 @@
@@ -231,7 +_,7 @@
private boolean isMergable() {
ItemStack item = this.getItem();
@@ -97,15 +97,7 @@
}
private void tryToMerge(ItemEntity itemEntity) {
ItemStack item = this.getItem();
ItemStack item1 = itemEntity.getItem();
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
- if (item1.getCount() < item.getCount()) {
+ if (true || item1.getCount() < item.getCount()) { // Spigot
merge(this, item, itemEntity, item1);
} else {
merge(itemEntity, item1, this, item);
@@ -257,11 +_,16 @@
@@ -264,11 +_,16 @@
}
private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemEntity originEntity, ItemStack originStack) {
@@ -123,7 +115,7 @@
}
}
@@ -289,12 +_,17 @@
@@ -296,12 +_,17 @@
} else if (!this.getItem().canBeHurtBy(damageSource)) {
return false;
} else {
@@ -142,9 +134,9 @@
}
return true;
@@ -322,6 +_,11 @@
if (!this.getItem().isEmpty()) {
compound.put("Item", this.getItem().save(this.registryAccess()));
@@ -324,6 +_,11 @@
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
compound.store("Item", ItemStack.CODEC, registryOps, this.getItem());
}
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
@@ -154,28 +146,28 @@
}
@Override
@@ -347,9 +_,19 @@
} else {
this.setItem(ItemStack.EMPTY);
}
@@ -336,8 +_,19 @@
this.cachedThrower = null;
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
this.setItem(compound.read("Item", ItemStack.CODEC, registryOps).orElse(ItemStack.EMPTY));
+
+ // Paper start - Friction API
+ if (compound.contains("Paper.FrictionState")) {
+ String fs = compound.getString("Paper.FrictionState");
+ compound.getString("Paper.FrictionState").ifPresent(frictionState -> {
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ this.frictionState = net.kyori.adventure.util.TriState.valueOf(frictionState);
+ } catch (Exception ignored) {
+ com.mojang.logging.LogUtils.getLogger().error("Unknown friction state {} for {}", fs, this);
+ com.mojang.logging.LogUtils.getLogger().error("Unknown friction state {} for {}", frictionState, this);
+ }
+ }
+ });
+ // Paper end - Friction API
+
if (this.getItem().isEmpty()) {
- this.discard();
+ this.discard(null); // CraftBukkit - add Bukkit remove cause
}
}
@@ -359,10 +_,73 @@
@@ -347,10 +_,73 @@
ItemStack item = this.getItem();
Item item1 = item.getItem();
int count = item.getCount();
@@ -250,7 +242,7 @@
item.setCount(count);
}
@@ -400,6 +_,7 @@
@@ -388,6 +_,7 @@
public void setItem(ItemStack stack) {
this.getEntityData().set(DATA_ITEM, stack);
@@ -258,7 +250,7 @@
}
@Override
@@ -453,7 +_,7 @@
@@ -441,7 +_,7 @@
public void makeFakeItem() {
this.setNeverPickUp();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/net/minecraft/world/entity/item/PrimedTnt.java
@@ -27,6 +_,12 @@
@@ -29,6 +_,12 @@
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.portal.TeleportTransition;
@@ -13,15 +13,15 @@
public class PrimedTnt extends Entity implements TraceableEntity {
private static final EntityDataAccessor<Integer> DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<BlockState> DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE);
@@ -50,6 +_,7 @@
@@ -53,6 +_,7 @@
public LivingEntity owner;
private boolean usedPortal;
public float explosionPower = 4.0F;
+ public boolean isIncendiary = false; // CraftBukkit - add field
+ public boolean isIncendiary = false; // CraftBukkit
public PrimedTnt(EntityType<? extends PrimedTnt> entityType, Level level) {
super(entityType, level);
@@ -59,7 +_,7 @@
@@ -62,7 +_,7 @@
public PrimedTnt(Level level, double x, double y, double z, @Nullable LivingEntity owner) {
this(EntityType.TNT, level);
this.setPos(x, y, z);
@@ -30,7 +30,7 @@
this.setDeltaMovement(-Math.sin(d) * 0.02, 0.2F, -Math.cos(d) * 0.02);
this.setFuse(80);
this.xo = x;
@@ -91,10 +_,17 @@
@@ -94,10 +_,17 @@
@Override
public void tick() {
@@ -48,7 +48,7 @@
this.setDeltaMovement(this.getDeltaMovement().scale(0.98));
if (this.onGround()) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7));
@@ -103,19 +_,49 @@
@@ -106,20 +_,50 @@
int i = this.getFuse() - 1;
this.setFuse(i);
if (i <= 0) {
@@ -90,27 +90,28 @@
}
private void explode() {
+ // CraftBukkit start
+ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
+ if (event.isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
this.level()
.explode(
this,
@@ -124,8 +_,8 @@
this.getX(),
this.getY(0.0625),
this.getZ(),
- this.explosionPower,
- false,
+ event.getRadius(), // CraftBukkit
+ event.getFire(), // CraftBukkit
Level.ExplosionInteraction.TNT
);
}
@@ -200,4 +_,11 @@
if (this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_TNT_EXPLODES)) {
+ // CraftBukkit start
+ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
+ if (event.isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
this.level()
.explode(
this,
@@ -128,8 +_,8 @@
this.getX(),
this.getY(0.0625),
this.getZ(),
- this.explosionPower,
- false,
+ event.getRadius(), // CraftBukkit
+ event.getFire(), // CraftBukkit
Level.ExplosionInteraction.TNT
);
}
@@ -202,4 +_,11 @@
public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
return false;
}

View File

@@ -48,7 +48,7 @@
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
+ 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 shoot bow event, add arrow stack to event
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;
@@ -63,17 +63,18 @@
}
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
@@ -222,11 +_,23 @@
@@ -222,11 +_,22 @@
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
-
- @Override
- public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) {
- super.onEquipItem(slot, oldItem, newItem);
+ this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - shouldBurnInDay API
+ }
+
+ // Paper start - shouldBurnInDay API
+ @Override
+ public void addAdditionalSaveData(final net.minecraft.nbt.CompoundTag nbt) {
@@ -81,12 +82,12 @@
+ 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
+
+ // Paper start - silent equipping
+ @Override
+ public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem, boolean silent) {
+ super.onEquipItem(slot, oldItem, newItem, silent);
+ // Paper end - silent equipping
if (!this.level().isClientSide) {
this.reassessWeaponGoal();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Bogged.java
+++ b/net/minecraft/world/entity/monster/Bogged.java
@@ -72,7 +_,19 @@
@@ -73,7 +_,19 @@
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) {
if (this.level() instanceof ServerLevel serverLevel) {
@@ -21,11 +21,11 @@
this.gameEvent(GameEvent.SHEAR, player);
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
}
@@ -125,15 +_,33 @@
@@ -126,15 +_,33 @@
@Override
public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears) {
+ // Paper start - custom shear drops
+ // Paper start - custom shear drops
+ this.shear(level, soundSource, shears, this.generateDefaultDrops(level, shears));
+ }
+
@@ -40,7 +40,7 @@
+
+ @Override
+ public void shear(ServerLevel level, SoundSource soundSource, ItemStack shears, java.util.List<ItemStack> drops) {
+ // Paper end - custom shear drops
+ // Paper end - custom shear drops
level.playSound(null, this, SoundEvents.BOGGED_SHEAR, soundSource, 1.0F, 1.0F);
- this.spawnShearedMushrooms(level, shears);
+ this.spawnShearedMushrooms(level, shears, drops); // Paper - custom shear drops

View File

@@ -1,23 +1,37 @@
--- a/net/minecraft/world/entity/monster/Creeper.java
+++ b/net/minecraft/world/entity/monster/Creeper.java
@@ -49,6 +_,7 @@
@@ -53,6 +_,7 @@
public int maxSwell = 30;
public int explosionRadius = 3;
private int droppedSkulls;
+ public Entity entityIgniter; // CraftBukkit
+ public @Nullable Entity entityIgniter; // CraftBukkit
public Creeper(EntityType<? extends Creeper> entityType, Level level) {
super(entityType, level);
@@ -121,7 +_,7 @@
}
if (compound.getBoolean("ignited")) {
@@ -116,7 +_,7 @@
this.maxSwell = compound.getShortOr("Fuse", (short)30);
this.explosionRadius = compound.getByteOr("ExplosionRadius", (byte)3);
if (compound.getBooleanOr("ignited", false)) {
- this.ignite();
+ this.entityData.set(DATA_IS_IGNITED, true); // Paper - set directly to avoid firing event
}
}
@@ -204,8 +_,19 @@
@@ -149,10 +_,11 @@
}
@Override
- public void setTarget(@Nullable LivingEntity target) {
+ public boolean setTarget(@Nullable LivingEntity target, @Nullable org.bukkit.event.entity.EntityTargetEvent.TargetReason reason) { // CraftBukkit
if (!(target instanceof Goat)) {
- super.setTarget(target);
+ return super.setTarget(target, reason); // CraftBukkit
}
+ return false; // CraftBukkit
}
@Override
@@ -199,9 +_,20 @@
@Override
public void thunderHit(ServerLevel level, LightningBolt lightning) {
super.thunderHit(level, lightning);
@@ -28,16 +42,17 @@
+ // CraftBukkit end
this.entityData.set(DATA_IS_POWERED, true);
}
+ // CraftBukkit start
+ public void setPowered(boolean powered) {
+ this.entityData.set(Creeper.DATA_IS_POWERED, powered);
+ this.entityData.set(DATA_IS_POWERED, powered);
+ }
+ // CraftBukkit end
+
@Override
protected InteractionResult mobInteract(Player player, InteractionHand hand) {
@@ -215,8 +_,9 @@
ItemStack itemInHand = player.getItemInHand(hand);
@@ -210,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) {
@@ -48,7 +63,7 @@
itemInHand.shrink(1);
} else {
itemInHand.hurtAndBreak(1, player, getSlotForHand(hand));
@@ -232,18 +_,29 @@
@@ -227,18 +_,29 @@
public void explodeCreeper() {
if (this.level() instanceof ServerLevel serverLevel) {
float f = this.isPowered() ? 2.0F : 1.0F;
@@ -81,7 +96,7 @@
areaEffectCloud.setRadius(2.5F);
areaEffectCloud.setRadiusOnUse(-0.5F);
areaEffectCloud.setWaitTime(10);
@@ -254,16 +_,27 @@
@@ -250,16 +_,27 @@
areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance));
}
@@ -92,7 +107,7 @@
+ }
+ }
+
+ // Paper start - CreeperIgniteEvent
+ // Paper start - Call 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);
@@ -101,7 +116,7 @@
+ }
+ }
+ }
+ // Paper end - CreeperIgniteEvent
+ // Paper end - Call CreeperIgniteEvent
public boolean isIgnited() {
return this.entityData.get(DATA_IS_IGNITED);
@@ -109,7 +124,7 @@
public void ignite() {
- this.entityData.set(DATA_IS_IGNITED, true);
+ setIgnited(true); // Paper - CreeperIgniteEvent
+ setIgnited(true); // Paper - Call CreeperIgniteEvent
}
public boolean canDropMobsSkull() {

View File

@@ -3,7 +3,7 @@
@@ -65,7 +_,7 @@
super.customServerAiStep(level);
if ((this.tickCount + this.getId()) % 1200 == 0) {
MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2);
MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.MINING_FATIGUE, 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(

View File

@@ -1,23 +1,21 @@
--- a/net/minecraft/world/entity/monster/EnderMan.java
+++ b/net/minecraft/world/entity/monster/EnderMan.java
@@ -117,7 +_,23 @@
@@ -116,9 +_,20 @@
.add(Attributes.STEP_HEIGHT, 1.0);
}
@Override
public void setTarget(@Nullable LivingEntity livingEntity) {
- super.setTarget(livingEntity);
+ // CraftBukkit start - fire event
+ this.setTarget(livingEntity, 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 livingEntity, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) {
+ if (!super.setTarget(livingEntity, reason, fireEvent)) {
@Override
- public void setTarget(@Nullable LivingEntity livingEntity) {
- super.setTarget(livingEntity);
+ // CraftBukkit start - fire event
+ public boolean setTarget(@Nullable LivingEntity livingEntity, @Nullable org.bukkit.event.entity.EntityTargetEvent.TargetReason reason) {
+ if (!super.setTarget(livingEntity, reason)) {
+ return false;
+ }
+ livingEntity = this.getTarget();
@@ -25,7 +23,7 @@
AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED);
if (livingEntity == null) {
this.targetChangeTime = 0;
@@ -131,6 +_,7 @@
@@ -132,6 +_,7 @@
attribute.addTransientModifier(SPEED_MODIFIER_ATTACKING);
}
}
@@ -33,22 +31,23 @@
}
@Override
@@ -212,6 +_,14 @@
@@ -207,6 +_,15 @@
}
boolean isBeingStaredBy(Player player) {
+ // Paper start - EndermanAttackPlayerEvent
+ final boolean shouldAttack = isBeingStaredBy0(player);
+ final boolean shouldAttack = this.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) {
+
+ 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 @@
@@ -246,7 +_,7 @@
float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue();
if (lightLevelDependentMagicValue > 0.5F
&& level.canSeeSky(this.blockPosition())
@@ -57,9 +56,9 @@
this.setTarget(null);
this.teleport();
}
@@ -372,11 +_,13 @@
@@ -369,11 +_,13 @@
} else {
boolean flag1 = flag && this.hurtWithCleanWater(level, damageSource, (ThrownPotion)damageSource.getDirectEntity(), amount);
boolean flag = abstractThrownPotion1 != null && this.hurtWithCleanWater(level, damageSource, abstractThrownPotion1, amount);
+ if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent
for (int i = 0; i < 64; i++) {
@@ -69,9 +68,9 @@
}
+ } // Paper - EndermanEscapeEvent
return flag1;
return flag;
}
@@ -401,6 +_,16 @@
@@ -398,6 +_,16 @@
this.entityData.set(DATA_STARED_AT, true);
}
@@ -88,7 +87,7 @@
@Override
public boolean requiresCustomPersistence() {
return super.requiresCustomPersistence() || this.getCarriedBlock() != null;
@@ -460,16 +_,19 @@
@@ -457,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);
@@ -109,7 +108,7 @@
}
}
}
@@ -567,7 +_,7 @@
@@ -564,7 +_,7 @@
} else {
if (this.target != null && !this.enderman.isPassenger()) {
if (this.enderman.isBeingStaredBy((Player)this.target)) {
@@ -118,7 +117,7 @@
this.enderman.teleport();
}
@@ -606,15 +_,18 @@
@@ -603,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);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Endermite.java
+++ b/net/minecraft/world/entity/monster/Endermite.java
@@ -121,7 +_,7 @@
@@ -122,7 +_,7 @@
}
if (this.life >= 2400) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Ghast.java
+++ b/net/minecraft/world/entity/monster/Ghast.java
@@ -63,6 +_,12 @@
@@ -64,6 +_,12 @@
return this.explosionPower;
}
@@ -13,7 +13,7 @@
@Override
protected boolean shouldDespawnInPeaceful() {
return true;
@@ -277,6 +_,7 @@
@@ -276,6 +_,7 @@
}
LargeFireball largeFireball = new LargeFireball(level, this.ghast, vec3.normalize(), this.ghast.getExplosionPower());

View File

@@ -1,8 +1,8 @@
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -47,6 +_,11 @@
Vec3 moveTargetPoint = Vec3.ZERO;
public BlockPos anchorPoint = BlockPos.ZERO;
@@ -48,6 +_,11 @@
@Nullable
public BlockPos anchorPoint;
Phantom.AttackPhase attackPhase = Phantom.AttackPhase.CIRCLE;
+ // Paper start
+ @Nullable
@@ -12,7 +12,7 @@
public Phantom(EntityType<? extends Phantom> entityType, Level level) {
super(entityType, level);
@@ -141,7 +_,7 @@
@@ -142,7 +_,7 @@
@Override
public void aiStep() {
@@ -21,42 +21,35 @@
this.igniteForSeconds(8.0F);
}
@@ -165,6 +_,15 @@
}
this.setPhantomSize(compound.getInt("Size"));
+
@@ -163,6 +_,10 @@
super.readAdditionalSaveData(compound);
this.anchorPoint = compound.read("anchor_pos", BlockPos.CODEC).orElse(null);
this.setPhantomSize(compound.getIntOr("size", 0));
+ // Paper start
+ if (compound.hasUUID("Paper.SpawningEntity")) {
+ this.spawningEntity = compound.getUUID("Paper.SpawningEntity");
+ }
+ if (compound.contains("Paper.ShouldBurnInDay")) {
+ this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
+ }
+ this.spawningEntity = compound.read("Paper.SpawningEntity", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true);
+ // Paper end
}
@Override
@@ -174,6 +_,12 @@
compound.putInt("AY", this.anchorPoint.getY());
compound.putInt("AZ", this.anchorPoint.getZ());
compound.putInt("Size", this.getPhantomSize());
@@ -170,6 +_,10 @@
super.addAdditionalSaveData(compound);
compound.storeNullable("anchor_pos", BlockPos.CODEC, this.anchorPoint);
compound.putInt("size", this.getPhantomSize());
+ // Paper start
+ if (this.spawningEntity != null) {
+ compound.putUUID("Paper.SpawningEntity", this.spawningEntity);
+ }
+ compound.storeNullable("Paper.SpawningEntity", net.minecraft.core.UUIDUtil.CODEC, this.spawningEntity);
+ compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
+ // Paper end
}
@Override
@@ -247,7 +_,8 @@
@@ -243,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
+ Phantom.this.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER); // CraftBukkit - reason
return true;
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Ravager.java
+++ b/net/minecraft/world/entity/monster/Ravager.java
@@ -151,12 +_,19 @@
@@ -154,12 +_,19 @@
BlockState blockState = serverLevel.getBlockState(blockPos);
Block block = blockState.getBlock();
if (block instanceof LeavesBlock) {
@@ -20,7 +20,7 @@
}
}
@@ -257,7 +_,7 @@
@@ -260,7 +_,7 @@
double d = entity.getX() - this.getX();
double d1 = entity.getZ() - this.getZ();
double max = Math.max(d * d + d1 * d1, 0.001);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Shulker.java
+++ b/net/minecraft/world/entity/monster/Shulker.java
@@ -274,7 +_,13 @@
@@ -277,7 +_,13 @@
@Override
public void stopRiding() {
@@ -15,7 +15,7 @@
if (this.level().isClientSide) {
this.clientOldAttachPosition = this.blockPosition();
}
@@ -387,6 +_,14 @@
@@ -390,6 +_,14 @@
&& this.level().getWorldBorder().isWithinBounds(blockPos1)
&& this.level().noCollision(this, new AABB(blockPos1).deflate(1.0E-6))) {
Direction direction = this.findAttachableSurface(blockPos1);
@@ -30,16 +30,16 @@
if (direction != null) {
this.unRide();
this.setAttachFace(direction);
@@ -453,7 +_,12 @@
@@ -454,7 +_,12 @@
if (shulker != null) {
shulker.setVariant(this.getVariant());
shulker.moveTo(vec3);
shulker.snapTo(vec3);
- this.level().addFreshEntity(shulker);
+ // Paper start - Shulker duplicate event
+ // Paper start - Call ShulkerDuplicateEvent
+ 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
+ // Paper end - Call ShulkerDuplicateEvent
+ this.level().addFreshEntity(shulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Skeleton.java
+++ b/net/minecraft/world/entity/monster/Skeleton.java
@@ -89,11 +_,17 @@
@@ -93,11 +_,17 @@
}
protected void doFreezeConversion() {

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/entity/monster/Slime.java
+++ b/net/minecraft/world/entity/monster/Slime.java
@@ -56,6 +_,7 @@
@@ -57,6 +_,7 @@
public float squish;
public float oSquish;
private boolean wasOnGround;
private boolean wasOnGround = false;
+ private boolean canWander = true; // Paper - Slime pathfinder events
public Slime(EntityType<? extends Slime> entityType, Level level) {
super(entityType, level);
@@ -110,6 +_,7 @@
@@ -111,6 +_,7 @@
super.addAdditionalSaveData(compound);
compound.putInt("Size", this.getSize() - 1);
compound.putBoolean("wasOnGround", this.wasOnGround);
@@ -16,47 +16,37 @@
}
@Override
@@ -117,6 +_,11 @@
this.setSize(compound.getInt("Size") + 1, false);
@@ -118,6 +_,7 @@
this.setSize(compound.getIntOr("Size", 0) + 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
this.wasOnGround = compound.getBooleanOr("wasOnGround", false);
+ this.canWander = compound.getBooleanOr("Paper.canWander", true); // Paper
}
public boolean isTiny() {
@@ -197,6 +_,13 @@
@@ -197,7 +_,7 @@
}
@Override
public void remove(Entity.RemovalReason reason) {
+ // CraftBukkit start - add Bukkit remove cause
+ this.remove(reason, null);
+ }
+
+ @Override
+ public void remove(Entity.RemovalReason reason, org.bukkit.event.entity.EntityRemoveEvent.Cause eventCause) {
+ // CraftBukkit end
- public void remove(Entity.RemovalReason reason) {
+ public void remove(Entity.RemovalReason reason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause eventCause) { // CraftBukkit - add Bukkit remove cause
int size = this.getSize();
if (!this.level().isClientSide && size > 1 && this.isDeadOrDying()) {
float width = this.getDimensions(this.getPose()).width();
@@ -204,18 +_,45 @@
@@ -205,18 +_,43 @@
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) {
+ if (event.callEvent() && event.getCount() > 0) {
+ i1 = event.getCount();
+ } else {
+ super.remove(reason, eventCause); // CraftBukkit - add Bukkit remove cause
+ return;
+ }
+ java.util.List<net.minecraft.world.entity.LivingEntity> slimes = new java.util.ArrayList<>(i1);
+
+ java.util.List<LivingEntity> slimes = new java.util.ArrayList<>(i1);
+ // CraftBukkit end
for (int i2 = 0; i2 < i1; i2++) {
@@ -64,9 +54,8 @@
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);
mob.snapTo(this.getX() + f1, this.getY() + 0.5, this.getZ() + f2, this.random.nextFloat() * 360.0F, 0.0F);
- });
- }
+ // CraftBukkit start
@@ -78,11 +67,11 @@
+ }
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) {
+ super.remove(reason, eventCause); // CraftBukkit - add Bukkit remove cause
+ super.remove(reason, eventCause); // add Bukkit remove cause
+ return;
+ }
+ for (LivingEntity living : slimes) {
+ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason
+ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT);
+ }
+ // CraftBukkit end
}
@@ -92,29 +81,29 @@
}
@Override
@@ -281,9 +_,13 @@
@@ -282,9 +_,13 @@
return checkMobSpawnRules(entityType, level, spawnReason, pos, random);
}
+ // Paper start - Replace rules for Height in Swamp Biome
+ // Paper start - Replace rules for Height in Swamp Biomes
+ final double maxHeightSwamp = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.maximum;
+ final double minHeightSwamp = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.minimum;
+ // Paper end
+ // Paper end - Replace rules for Height in Swamp Biomes
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
+ && pos.getY() > minHeightSwamp // Paper - Replace rules for Height in Swamp Biomes
+ && pos.getY() < maxHeightSwamp // Paper - Replace rules for Height in Swamp Biomes
&& random.nextFloat() < 0.5F
&& random.nextFloat() < level.getMoonBrightness()
&& level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
@@ -295,8 +_,11 @@
@@ -296,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
+ boolean flag = level.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel) level).getSeed(), level.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // 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) {
@@ -122,7 +111,7 @@
return checkMobSpawnRules(entityType, level, spawnReason, pos, random);
}
}
@@ -355,6 +_,16 @@
@@ -356,6 +_,16 @@
return super.getDefaultDimensions(pose).scale(this.getSize());
}
@@ -139,7 +128,7 @@
static class SlimeAttackGoal extends Goal {
private final Slime slime;
private int growTiredTimer;
@@ -367,7 +_,16 @@
@@ -368,7 +_,16 @@
@Override
public boolean canUse() {
LivingEntity target = this.slime.getTarget();
@@ -157,7 +146,7 @@
}
@Override
@@ -379,7 +_,16 @@
@@ -380,7 +_,16 @@
@Override
public boolean canContinueToUse() {
LivingEntity target = this.slime.getTarget();
@@ -175,7 +164,7 @@
}
@Override
@@ -398,6 +_,13 @@
@@ -399,6 +_,13 @@
slimeMoveControl.setDirection(this.slime.getYRot(), this.slime.isDealsDamage());
}
}
@@ -189,7 +178,7 @@
}
static class SlimeFloatGoal extends Goal {
@@ -411,7 +_,7 @@
@@ -412,7 +_,7 @@
@Override
public boolean canUse() {
@@ -198,7 +187,7 @@
}
@Override
@@ -441,7 +_,7 @@
@@ -442,7 +_,7 @@
@Override
public boolean canUse() {
@@ -207,7 +196,7 @@
}
@Override
@@ -519,7 +_,7 @@
@@ -520,7 +_,7 @@
@Override
public boolean canUse() {
@@ -216,7 +205,7 @@
&& (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION))
&& this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
}
@@ -529,6 +_,11 @@
@@ -530,6 +_,11 @@
if (--this.nextRandomizeTime <= 0) {
this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
this.chosenDegrees = this.slime.getRandom().nextInt(360);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java
+++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java
@@ -208,6 +_,11 @@
@@ -209,6 +_,11 @@
public void tick() {
this.attackWarmupDelay--;
if (this.attackWarmupDelay == 0) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Strider.java
+++ b/net/minecraft/world/entity/monster/Strider.java
@@ -309,7 +_,14 @@
@@ -295,7 +_,14 @@
|| blockStateOnLegacy.is(BlockTags.STRIDER_WARM_BLOCKS)
|| this.getFluidHeight(FluidTags.LAVA) > 0.0;
boolean flag1 = this.getVehicle() instanceof Strider strider && strider.isSuffocating();

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/world/entity/monster/Vex.java
+++ b/net/minecraft/world/entity/monster/Vex.java
@@ -296,7 +_,7 @@
@@ -286,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
+ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET); // CraftBukkit
super.start();
}
}
@@ -355,7 +_,10 @@
@@ -345,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);

Some files were not shown because too many files have changed in this diff Show More