Move patches to unapplied
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
--- a/net/minecraft/world/entity/AgeableMob.java
|
||||
+++ b/net/minecraft/world/entity/AgeableMob.java
|
||||
@@ -21,12 +21,38 @@
|
||||
protected int age;
|
||||
protected int forcedAge;
|
||||
protected int forcedAgeTimer;
|
||||
+ public boolean ageLocked; // CraftBukkit
|
||||
|
||||
protected AgeableMob(EntityType<? extends AgeableMob> type, Level world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
+ // Spigot start
|
||||
@Override
|
||||
+ public void inactiveTick()
|
||||
+ {
|
||||
+ super.inactiveTick();
|
||||
+ if ( this.level().isClientSide || this.ageLocked )
|
||||
+ { // CraftBukkit
|
||||
+ this.refreshDimensions();
|
||||
+ } else
|
||||
+ {
|
||||
+ int i = this.getAge();
|
||||
+
|
||||
+ if ( i < 0 )
|
||||
+ {
|
||||
+ ++i;
|
||||
+ this.setAge( i );
|
||||
+ } else if ( i > 0 )
|
||||
+ {
|
||||
+ --i;
|
||||
+ this.setAge( i );
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+
|
||||
+ @Override
|
||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData entityData) {
|
||||
if (entityData == null) {
|
||||
entityData = new AgeableMob.AgeableMobGroupData(true);
|
||||
@@ -60,6 +86,7 @@
|
||||
}
|
||||
|
||||
public void ageUp(int age, boolean overGrow) {
|
||||
+ if (this.ageLocked) return; // Paper - Honor ageLock
|
||||
int j = this.getAge();
|
||||
int k = j;
|
||||
|
||||
@@ -104,6 +131,7 @@
|
||||
super.addAdditionalSaveData(nbt);
|
||||
nbt.putInt("Age", this.getAge());
|
||||
nbt.putInt("ForcedAge", this.forcedAge);
|
||||
+ nbt.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,6 +139,7 @@
|
||||
super.readAdditionalSaveData(nbt);
|
||||
this.setAge(nbt.getInt("Age"));
|
||||
this.forcedAge = nbt.getInt("ForcedAge");
|
||||
+ this.ageLocked = nbt.getBoolean("AgeLocked"); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,7 +154,7 @@
|
||||
@Override
|
||||
public void aiStep() {
|
||||
super.aiStep();
|
||||
- if (this.level().isClientSide) {
|
||||
+ if (this.level().isClientSide || this.ageLocked) { // CraftBukkit
|
||||
if (this.forcedAgeTimer > 0) {
|
||||
if (this.forcedAgeTimer % 4 == 0) {
|
||||
this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D);
|
||||
@@ -0,0 +1,160 @@
|
||||
--- a/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
@@ -33,6 +33,12 @@
|
||||
import net.minecraft.world.level.material.PushReaction;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.entity.LivingEntity;
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class AreaEffectCloud extends Entity implements TraceableEntity {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -54,7 +60,7 @@
|
||||
public float radiusOnUse;
|
||||
public float radiusPerTick;
|
||||
@Nullable
|
||||
- private LivingEntity owner;
|
||||
+ private net.minecraft.world.entity.LivingEntity owner;
|
||||
@Nullable
|
||||
public UUID ownerUUID;
|
||||
|
||||
@@ -145,7 +151,19 @@
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
+ // Spigot start - copied from below
|
||||
@Override
|
||||
+ public void inactiveTick() {
|
||||
+ super.inactiveTick();
|
||||
+
|
||||
+ if (this.tickCount >= this.waitTime + this.duration) {
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+
|
||||
+ @Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
Level world = this.level();
|
||||
@@ -200,7 +218,7 @@
|
||||
|
||||
private void serverTick(ServerLevel world) {
|
||||
if (this.tickCount >= this.waitTime + this.duration) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
} else {
|
||||
boolean flag = this.isWaiting();
|
||||
boolean flag1 = this.tickCount < this.waitTime;
|
||||
@@ -215,7 +233,7 @@
|
||||
if (this.radiusPerTick != 0.0F) {
|
||||
f += this.radiusPerTick;
|
||||
if (f < 0.5F) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -244,16 +262,17 @@
|
||||
}
|
||||
|
||||
list.addAll(this.potionContents.customEffects());
|
||||
- List<LivingEntity> list1 = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox());
|
||||
+ List<net.minecraft.world.entity.LivingEntity> list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, this.getBoundingBox());
|
||||
|
||||
if (!list1.isEmpty()) {
|
||||
Iterator iterator1 = list1.iterator();
|
||||
|
||||
+ List<LivingEntity> entities = new java.util.ArrayList<LivingEntity>(); // CraftBukkit
|
||||
while (iterator1.hasNext()) {
|
||||
- LivingEntity entityliving = (LivingEntity) iterator1.next();
|
||||
+ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator1.next();
|
||||
|
||||
if (!this.victims.containsKey(entityliving) && entityliving.isAffectedByPotions()) {
|
||||
- Stream stream = list.stream();
|
||||
+ Stream<MobEffectInstance> stream = list.stream(); // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(entityliving);
|
||||
if (!stream.noneMatch(entityliving::canBeAffected)) {
|
||||
@@ -262,6 +281,19 @@
|
||||
double d2 = d0 * d0 + d1 * d1;
|
||||
|
||||
if (d2 <= (double) (f * f)) {
|
||||
+ // CraftBukkit start
|
||||
+ entities.add((LivingEntity) entityliving.getBukkitEntity());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ {
|
||||
+ org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities);
|
||||
+ if (!event.isCancelled()) {
|
||||
+ for (LivingEntity entity : event.getAffectedEntities()) {
|
||||
+ if (entity instanceof CraftLivingEntity) {
|
||||
+ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) entity).getHandle();
|
||||
+ // CraftBukkit end
|
||||
this.victims.put(entityliving, this.tickCount + this.reapplicationDelay);
|
||||
Iterator iterator2 = list.iterator();
|
||||
|
||||
@@ -271,14 +303,14 @@
|
||||
if (((MobEffect) mobeffect1.getEffect().value()).isInstantenous()) {
|
||||
((MobEffect) mobeffect1.getEffect().value()).applyInstantenousEffect(world, this, this.getOwner(), entityliving, mobeffect1.getAmplifier(), 0.5D);
|
||||
} else {
|
||||
- entityliving.addEffect(new MobEffectInstance(mobeffect1), this);
|
||||
+ entityliving.addEffect(new MobEffectInstance(mobeffect1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
if (this.radiusOnUse != 0.0F) {
|
||||
f += this.radiusOnUse;
|
||||
if (f < 0.5F) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -288,7 +320,7 @@
|
||||
if (this.durationOnUse != 0) {
|
||||
this.duration += this.durationOnUse;
|
||||
if (this.duration <= 0) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -336,14 +368,14 @@
|
||||
this.waitTime = waitTime;
|
||||
}
|
||||
|
||||
- public void setOwner(@Nullable LivingEntity owner) {
|
||||
+ public void setOwner(@Nullable net.minecraft.world.entity.LivingEntity owner) {
|
||||
this.owner = owner;
|
||||
this.ownerUUID = owner == null ? null : owner.getUUID();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
- public LivingEntity getOwner() {
|
||||
+ public net.minecraft.world.entity.LivingEntity getOwner() {
|
||||
if (this.owner != null && !this.owner.isRemoved()) {
|
||||
return this.owner;
|
||||
} else {
|
||||
@@ -353,10 +385,10 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
Entity entity = worldserver.getEntity(this.ownerUUID);
|
||||
- LivingEntity entityliving;
|
||||
+ net.minecraft.world.entity.LivingEntity entityliving;
|
||||
|
||||
- if (entity instanceof LivingEntity) {
|
||||
- LivingEntity entityliving1 = (LivingEntity) entity;
|
||||
+ if (entity instanceof net.minecraft.world.entity.LivingEntity) {
|
||||
+ net.minecraft.world.entity.LivingEntity entityliving1 = (net.minecraft.world.entity.LivingEntity) entity;
|
||||
|
||||
entityliving = entityliving1;
|
||||
} else {
|
||||
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/ConversionParams.java
|
||||
+++ b/net/minecraft/world/entity/ConversionParams.java
|
||||
@@ -12,4 +12,11 @@
|
||||
public interface AfterConversion<T extends Mob> {
|
||||
void finalizeConversion(T convertedEntity);
|
||||
}
|
||||
+
|
||||
+ // Paper start - entity zap event - allow conversion to be cancelled during finalization
|
||||
+ @FunctionalInterface
|
||||
+ public interface CancellingAfterConversion<T extends Mob> {
|
||||
+ boolean finalizeConversionOrCancel(final T convertedEntity);
|
||||
+ }
|
||||
+ // Paper start - entity zap event - allow conversion to be cancelled during finalization
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/world/entity/ConversionType.java
|
||||
+++ b/net/minecraft/world/entity/ConversionType.java
|
||||
@@ -4,6 +4,7 @@
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
+import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
@@ -11,6 +12,8 @@
|
||||
import net.minecraft.world.entity.monster.Zombie;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public enum ConversionType {
|
||||
|
||||
@@ -31,7 +34,7 @@
|
||||
while (iterator.hasNext()) {
|
||||
entity1 = (Entity) iterator.next();
|
||||
entity1.stopRiding();
|
||||
- entity1.remove(Entity.RemovalReason.DISCARDED);
|
||||
+ entity1.remove(Entity.RemovalReason.DISCARDED, EntityRemoveEvent.Cause.TRANSFORMATION); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
|
||||
entity.startRiding(newEntity);
|
||||
@@ -64,7 +67,7 @@
|
||||
newEntity.hurtTime = oldEntity.hurtTime;
|
||||
newEntity.yBodyRot = oldEntity.yBodyRot;
|
||||
newEntity.setOnGround(oldEntity.onGround());
|
||||
- Optional optional = oldEntity.getSleepingPos();
|
||||
+ Optional<BlockPos> optional = oldEntity.getSleepingPos(); // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(newEntity);
|
||||
optional.ifPresent(newEntity::setSleepingPos);
|
||||
@@ -156,7 +159,7 @@
|
||||
newEntity.setNoGravity(oldEntity.isNoGravity());
|
||||
newEntity.setPortalCooldown(oldEntity.getPortalCooldown());
|
||||
newEntity.setSilent(oldEntity.isSilent());
|
||||
- Set set = oldEntity.getTags();
|
||||
+ Set<String> set = oldEntity.getTags(); // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(newEntity);
|
||||
set.forEach(newEntity::addTag);
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/Display.java
|
||||
+++ b/net/minecraft/world/entity/Display.java
|
||||
@@ -903,7 +903,7 @@
|
||||
b = loadFlag(b, nbt, "default_background", (byte)4);
|
||||
Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC
|
||||
.decode(NbtOps.INSTANCE, nbt.get("alignment"))
|
||||
- .resultOrPartial(Util.prefix("Display entity", Display.LOGGER::error))
|
||||
+ .result() // Paper - Hide text display error on spawn
|
||||
.map(Pair::getFirst);
|
||||
if (optional.isPresent()) {
|
||||
b = switch ((Display.TextDisplay.Align)optional.get()) {
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
--- a/net/minecraft/world/entity/EntitySelector.java
|
||||
+++ b/net/minecraft/world/entity/EntitySelector.java
|
||||
@@ -27,8 +27,25 @@
|
||||
};
|
||||
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
|
||||
public static final Predicate<Entity> CAN_BE_PICKED = EntitySelector.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;
|
||||
|
||||
+ if (playerInsomniaTicks <= 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ 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
|
||||
+
|
||||
private EntitySelector() {}
|
||||
+ // Paper start - Affects Spawning API
|
||||
+ public static final Predicate<Entity> PLAYER_AFFECTS_SPAWNING = (entity) -> {
|
||||
+ return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning;
|
||||
+ };
|
||||
+ // Paper end - Affects Spawning API
|
||||
|
||||
public static Predicate<Entity> withinDistance(double x, double y, double z, double max) {
|
||||
double d4 = max * max;
|
||||
@@ -39,13 +56,18 @@
|
||||
}
|
||||
|
||||
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
|
||||
PlayerTeam scoreboardteam = entity.getTeam();
|
||||
Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteam == null ? Team.CollisionRule.ALWAYS : scoreboardteam.getCollisionRule();
|
||||
|
||||
return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> {
|
||||
- if (!entity1.isPushable()) {
|
||||
+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
|
||||
return false;
|
||||
- } else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) {
|
||||
+ } else if (entity1 instanceof Player && entity instanceof Player && !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions) { // Paper - Configurable player collision
|
||||
return false;
|
||||
} else {
|
||||
PlayerTeam scoreboardteam1 = entity1.getTeam();
|
||||
@@ -0,0 +1,179 @@
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -176,6 +176,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> {
|
||||
@@ -191,7 +192,7 @@
|
||||
return Items.ACACIA_CHEST_BOAT;
|
||||
}), MobCategory.MISC).noLootTable().sized(1.375F, 0.5625F).eyeHeight(0.5625F).clientTrackingRange(10));
|
||||
public static final EntityType<Allay> ALLAY = EntityType.register("allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).eyeHeight(0.36F).ridingOffset(0.04F).clientTrackingRange(8).updateInterval(2));
|
||||
- public static final EntityType<AreaEffectCloud> AREA_EFFECT_CLOUD = EntityType.register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).noLootTable().fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE));
|
||||
+ public static final EntityType<AreaEffectCloud> AREA_EFFECT_CLOUD = EntityType.register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).noLootTable().fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds
|
||||
public static final EntityType<Armadillo> ARMADILLO = EntityType.register("armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10));
|
||||
public static final EntityType<ArmorStand> ARMOR_STAND = EntityType.register("armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).eyeHeight(1.7775F).clientTrackingRange(10));
|
||||
public static final EntityType<Arrow> ARROW = EntityType.register("arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).noLootTable().sized(0.5F, 0.5F).eyeHeight(0.13F).clientTrackingRange(4).updateInterval(20));
|
||||
@@ -399,7 +400,7 @@
|
||||
return ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.withDefaultNamespace(id));
|
||||
}
|
||||
|
||||
- private static <T extends Entity> EntityType<T> register(String id, EntityType.Builder<T> type) {
|
||||
+ private static <T extends Entity> EntityType<T> register(String id, EntityType.Builder type) { // CraftBukkit - decompile error
|
||||
return EntityType.register(EntityType.vanillaEntityId(id), type);
|
||||
}
|
||||
|
||||
@@ -431,16 +432,23 @@
|
||||
|
||||
@Nullable
|
||||
public T spawn(ServerLevel world, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, EntitySpawnReason spawnReason, boolean alignPosition, boolean invertY) {
|
||||
- Consumer consumer;
|
||||
+ // CraftBukkit start
|
||||
+ return this.spawn(world, stack, player, pos, spawnReason, alignPosition, invertY, spawnReason == 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
|
||||
+ }
|
||||
|
||||
- if (stack != null) {
|
||||
- consumer = EntityType.createDefaultStackConfig(world, stack, player);
|
||||
+ @Nullable
|
||||
+ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // CraftBukkit end
|
||||
+ Consumer<T> consumer; // CraftBukkit - decompile error
|
||||
+
|
||||
+ if (itemstack != null) {
|
||||
+ consumer = EntityType.createDefaultStackConfig(worldserver, itemstack, entityhuman);
|
||||
} else {
|
||||
consumer = (entity) -> {
|
||||
};
|
||||
}
|
||||
|
||||
- return this.spawn(world, consumer, pos, spawnReason, alignPosition, invertY);
|
||||
+ return this.spawn(worldserver, consumer, blockposition, entityspawnreason, flag, flag1, spawnReason); // CraftBukkit
|
||||
}
|
||||
|
||||
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level world, ItemStack stack, @Nullable Player player) {
|
||||
@@ -464,21 +472,50 @@
|
||||
CustomData customdata = (CustomData) stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
|
||||
|
||||
return !customdata.isEmpty() ? chained.andThen((entity) -> {
|
||||
- EntityType.updateCustomEntityTag(world, player, entity, customdata);
|
||||
+ try { EntityType.updateCustomEntityTag(world, player, entity, customdata); } catch (Throwable t) { EntityType.LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665
|
||||
}) : chained;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T spawn(ServerLevel world, BlockPos pos, EntitySpawnReason reason) {
|
||||
- return this.spawn(world, (Consumer) null, pos, reason, false, false);
|
||||
+ // CraftBukkit start
|
||||
+ return this.spawn(world, pos, reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
+ public T spawn(ServerLevel worldserver, BlockPos blockposition, EntitySpawnReason entityspawnreason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ return this.spawn(worldserver, (Consumer<T>) null, blockposition, entityspawnreason, false, false, spawnReason); // CraftBukkit - decompile error
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
public T spawn(ServerLevel world, @Nullable Consumer<T> afterConsumer, BlockPos pos, EntitySpawnReason reason, boolean alignPosition, boolean invertY) {
|
||||
- T t0 = this.create(world, afterConsumer, pos, reason, alignPosition, invertY);
|
||||
+ // CraftBukkit start
|
||||
+ return this.spawn(world, afterConsumer, pos, reason, alignPosition, invertY, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public T spawn(ServerLevel worldserver, @Nullable Consumer<T> consumer, BlockPos blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // 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(worldserver, blockposition),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this),
|
||||
+ spawnReason
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
+ T t0 = this.create(worldserver, consumer, blockposition, entityspawnreason, flag, flag1);
|
||||
|
||||
if (t0 != null) {
|
||||
- world.addFreshEntityWithPassengers(t0);
|
||||
+ // CraftBukkit start
|
||||
+ worldserver.addFreshEntityWithPassengers(t0, spawnReason);
|
||||
+ if (t0.isRemoved()) {
|
||||
+ return null; // Don't return an entity when CreatureSpawnEvent is canceled
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (t0 instanceof Mob) {
|
||||
Mob entityinsentient = (Mob) t0;
|
||||
|
||||
@@ -542,6 +579,15 @@
|
||||
|
||||
if (entity.getType() == entitytypes) {
|
||||
if (world.isClientSide || !entity.getType().onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) {
|
||||
+ // Paper start - filter out protected tags
|
||||
+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
|
||||
+ nbt = nbt.update((compound) -> {
|
||||
+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : world.paperConfig().entities.spawning.filteredEntityTagNbtPaths) {
|
||||
+ tag.remove(compound);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ // Paper end - filter out protected tags
|
||||
nbt.loadInto(entity);
|
||||
}
|
||||
}
|
||||
@@ -613,9 +659,15 @@
|
||||
}
|
||||
|
||||
public static Optional<Entity> create(CompoundTag nbt, Level world, EntitySpawnReason reason) {
|
||||
+ // Paper start - Don't fire sync event during generation
|
||||
+ return create(nbt, world, reason, false);
|
||||
+ }
|
||||
+ public static Optional<Entity> create(CompoundTag nbt, Level world, EntitySpawnReason reason, boolean generation) {
|
||||
+ // Paper end - Don't fire sync event during generation
|
||||
return Util.ifElse(EntityType.by(nbt).map((entitytypes) -> {
|
||||
return entitytypes.create(world, reason);
|
||||
}), (entity) -> {
|
||||
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
|
||||
entity.load(nbt);
|
||||
}, () -> {
|
||||
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
|
||||
@@ -638,7 +690,7 @@
|
||||
}
|
||||
|
||||
public static Optional<EntityType<?>> by(CompoundTag nbt) {
|
||||
- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(nbt.getString("id")));
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(nbt.getString("id"))); // Paper - Validate ResourceLocation
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -657,7 +709,7 @@
|
||||
}
|
||||
|
||||
return entity;
|
||||
- }).orElse((Object) null);
|
||||
+ }).orElse(null); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public static Stream<Entity> loadEntitiesRecursive(final List<? extends Tag> entityNbtList, final Level world, final EntitySpawnReason reason) {
|
||||
@@ -718,7 +770,7 @@
|
||||
|
||||
@Nullable
|
||||
public T tryCast(Entity obj) {
|
||||
- return obj.getType() == this ? obj : null;
|
||||
+ return obj.getType() == this ? (T) obj : null; // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -791,7 +843,7 @@
|
||||
this.canSpawnFarFromPlayer = spawnGroup == MobCategory.CREATURE || spawnGroup == MobCategory.MISC;
|
||||
}
|
||||
|
||||
- public static <T extends Entity> EntityType.Builder<T> of(EntityType.EntityFactory<T> factory, MobCategory spawnGroup) {
|
||||
+ public static <T extends Entity> EntityType.Builder<T> of(EntityType.EntityFactory factory, MobCategory spawnGroup) { // CraftBukkit - decompile error
|
||||
return new EntityType.Builder<>(factory, spawnGroup);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
--- a/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -24,6 +24,13 @@
|
||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||
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 {
|
||||
|
||||
@@ -37,9 +44,63 @@
|
||||
public int value;
|
||||
public int count;
|
||||
private Player followingPlayer;
|
||||
+ // Paper start
|
||||
+ @javax.annotation.Nullable
|
||||
+ public java.util.UUID sourceEntityId;
|
||||
+ @javax.annotation.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)) {
|
||||
+ 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");
|
||||
+ 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);
|
||||
+ }
|
||||
+ 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);
|
||||
+ }
|
||||
+
|
||||
+ @io.papermc.paper.annotation.DoNotUse
|
||||
+ @Deprecated
|
||||
public ExperienceOrb(Level world, double x, double y, double z, int amount) {
|
||||
+ this(world, x, y, z, amount, null, null);
|
||||
+ }
|
||||
+
|
||||
+ public ExperienceOrb(Level world, double x, double y, double z, int amount, @javax.annotation.Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @javax.annotation.Nullable Entity triggerId) {
|
||||
+ this(world, x, y, z, amount, reason, triggerId, null);
|
||||
+ }
|
||||
+
|
||||
+ public ExperienceOrb(Level world, double x, double y, double z, int amount, @javax.annotation.Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @javax.annotation.Nullable Entity triggerId, @javax.annotation.Nullable Entity sourceId) {
|
||||
this(EntityType.EXPERIENCE_ORB, world);
|
||||
+ 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.0D));
|
||||
this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D);
|
||||
@@ -68,6 +129,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();
|
||||
@@ -93,7 +155,22 @@
|
||||
this.followingPlayer = null;
|
||||
}
|
||||
|
||||
- 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);
|
||||
+ LivingEntity target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle();
|
||||
+ cancelled = event.isCancelled();
|
||||
+
|
||||
+ if (cancelled) {
|
||||
+ this.followingPlayer = prevTarget;
|
||||
+ } else {
|
||||
+ this.followingPlayer = (target instanceof Player) ? (Player) target : null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (this.followingPlayer != null && !cancelled) {
|
||||
+ // CraftBukkit end
|
||||
Vec3 vec3d = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ());
|
||||
double d0 = vec3d.lengthSqr();
|
||||
|
||||
@@ -121,7 +198,7 @@
|
||||
|
||||
++this.age;
|
||||
if (this.age >= 6000) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,18 +227,27 @@
|
||||
}
|
||||
|
||||
public static void award(ServerLevel world, Vec3 pos, int amount) {
|
||||
+ // Paper start - add reasons for orbs
|
||||
+ award(world, pos, amount, null, null, null);
|
||||
+ }
|
||||
+ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) {
|
||||
+ award(world, pos, amount, reason, triggerId, null);
|
||||
+ }
|
||||
+ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) {
|
||||
+ // Paper end - add reasons for orbs
|
||||
while (amount > 0) {
|
||||
int j = ExperienceOrb.getExperienceValue(amount);
|
||||
|
||||
amount -= j;
|
||||
if (!ExperienceOrb.tryMergeToExisting(world, pos, j)) {
|
||||
- world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j));
|
||||
+ world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j, reason, triggerId, sourceId)); // Paper - add reason
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean tryMergeToExisting(ServerLevel world, Vec3 pos, int amount) {
|
||||
+ // Paper - TODO some other event for this kind of merge
|
||||
AABB axisalignedbb = AABB.ofSize(pos, 1.0D, 1.0D, 1.0D);
|
||||
int j = world.getRandom().nextInt(40);
|
||||
List<ExperienceOrb> list = world.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), axisalignedbb, (entityexperienceorb) -> {
|
||||
@@ -188,9 +274,14 @@
|
||||
}
|
||||
|
||||
private void merge(ExperienceOrb other) {
|
||||
+ // Paper start - call orb merge event
|
||||
+ if (!new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) this.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) other.getBukkitEntity()).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - call orb merge event
|
||||
this.count += other.count;
|
||||
this.age = Math.min(this.age, other.age);
|
||||
- other.discard();
|
||||
+ other.discard(EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
|
||||
private void setUnderwaterMovement() {
|
||||
@@ -215,7 +306,7 @@
|
||||
this.markHurt();
|
||||
this.health = (int) ((float) this.health - amount);
|
||||
if (this.health <= 0) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -226,33 +317,35 @@
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
nbt.putShort("Health", (short) this.health);
|
||||
nbt.putShort("Age", (short) this.age);
|
||||
- nbt.putShort("Value", (short) this.value);
|
||||
+ nbt.putInt("Value", this.value); // Paper - save as Integer
|
||||
nbt.putInt("Count", this.count);
|
||||
+ this.savePaperNBT(nbt); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
this.health = nbt.getShort("Health");
|
||||
this.age = nbt.getShort("Age");
|
||||
- this.value = nbt.getShort("Value");
|
||||
+ this.value = nbt.getInt("Value"); // Paper - load as Integer
|
||||
this.count = Math.max(nbt.getInt("Count"), 1);
|
||||
+ this.loadPaperNBT(nbt); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerTouch(Player player) {
|
||||
if (player instanceof ServerPlayer entityplayer) {
|
||||
- if (player.takeXpDelay == 0) {
|
||||
- player.takeXpDelay = 2;
|
||||
+ if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(entityplayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent
|
||||
+ player.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(player, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
|
||||
player.take(this, 1);
|
||||
int i = this.repairPlayerItems(entityplayer, this.value);
|
||||
|
||||
if (i > 0) {
|
||||
- player.giveExperiencePoints(i);
|
||||
+ player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,12 +359,23 @@
|
||||
ItemStack itemstack = ((EnchantedItemInUse) optional.get()).itemStack();
|
||||
int j = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemstack, amount);
|
||||
int k = Math.min(j, itemstack.getDamageValue());
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - mending event
|
||||
+ final int consumedExperience = k > 0 ? k * amount / j : 0;
|
||||
+ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, optional.get().inSlot(), k, consumedExperience);
|
||||
+ // Paper end - mending event
|
||||
+ k = event.getRepairAmount();
|
||||
+ if (event.isCancelled()) {
|
||||
+ return amount;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
itemstack.setDamageValue(itemstack.getDamageValue() - k);
|
||||
if (k > 0) {
|
||||
- int l = amount - k * amount / j;
|
||||
+ int l = amount - k * amount / j; // Paper - diff on change - expand PlayerMendEvents
|
||||
|
||||
if (l > 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, l);
|
||||
}
|
||||
}
|
||||
@@ -291,6 +395,24 @@
|
||||
}
|
||||
|
||||
public static int getExperienceValue(int value) {
|
||||
+ // CraftBukkit start
|
||||
+ if (value > 162670129) return value - 100000;
|
||||
+ if (value > 81335063) return 81335063;
|
||||
+ if (value > 40667527) return 40667527;
|
||||
+ if (value > 20333759) return 20333759;
|
||||
+ if (value > 10166857) return 10166857;
|
||||
+ if (value > 5083423) return 5083423;
|
||||
+ if (value > 2541701) return 2541701;
|
||||
+ if (value > 1270849) return 1270849;
|
||||
+ if (value > 635413) return 635413;
|
||||
+ if (value > 317701) return 317701;
|
||||
+ if (value > 158849) return 158849;
|
||||
+ if (value > 79423) return 79423;
|
||||
+ if (value > 39709) return 39709;
|
||||
+ if (value > 19853) return 19853;
|
||||
+ if (value > 9923) return 9923;
|
||||
+ if (value > 4957) return 4957;
|
||||
+ // CraftBukkit end
|
||||
return value >= 2477 ? 2477 : (value >= 1237 ? 1237 : (value >= 617 ? 617 : (value >= 307 ? 307 : (value >= 149 ? 149 : (value >= 73 ? 73 : (value >= 37 ? 37 : (value >= 17 ? 17 : (value >= 7 ? 7 : (value >= 3 ? 3 : 1)))))))));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
--- a/net/minecraft/world/entity/Interaction.java
|
||||
+++ b/net/minecraft/world/entity/Interaction.java
|
||||
@@ -27,6 +27,12 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.world.damagesource.DamageSource;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityDamageEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class Interaction extends Entity implements Attackable, Targeting {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -65,7 +71,7 @@
|
||||
this.setHeight(nbt.getFloat("height"));
|
||||
}
|
||||
|
||||
- DataResult dataresult;
|
||||
+ DataResult<com.mojang.datafixers.util.Pair<Interaction.PlayerAction, net.minecraft.nbt.Tag>> dataresult; // CraftBukkit - decompile error
|
||||
Logger logger;
|
||||
|
||||
if (nbt.contains("attack")) {
|
||||
@@ -145,9 +151,16 @@
|
||||
@Override
|
||||
public boolean skipAttackInteraction(Entity attacker) {
|
||||
if (attacker instanceof Player entityhuman) {
|
||||
+ // CraftBukkit start
|
||||
+ DamageSource source = entityhuman.damageSources().playerAttack(entityhuman);
|
||||
+ EntityDamageEvent event = CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.attack = new Interaction.PlayerAction(entityhuman.getUUID(), this.level().getGameTime());
|
||||
if (entityhuman instanceof ServerPlayer entityplayer) {
|
||||
- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, entityhuman.damageSources().generic(), 1.0F, 1.0F, false);
|
||||
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, entityhuman.damageSources().generic(), 1.0F, (float) event.getFinalDamage(), false); // CraftBukkit // Paper - use correct source and fix taken/dealt param order
|
||||
}
|
||||
|
||||
return !this.getResponse();
|
||||
@@ -0,0 +1,17 @@
|
||||
--- a/net/minecraft/world/entity/ItemBasedSteering.java
|
||||
+++ b/net/minecraft/world/entity/ItemBasedSteering.java
|
||||
@@ -53,6 +53,14 @@
|
||||
return (Integer) this.entityData.get(this.boostTimeAccessor);
|
||||
}
|
||||
|
||||
+ // CraftBukkit add setBoostTicks(int)
|
||||
+ 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());
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
--- a/net/minecraft/world/entity/Leashable.java
|
||||
+++ b/net/minecraft/world/entity/Leashable.java
|
||||
@@ -15,6 +15,10 @@
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.Level;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityUnleashEvent;
|
||||
+import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason;
|
||||
+// CraftBukkit end
|
||||
|
||||
public interface Leashable {
|
||||
|
||||
@@ -45,7 +49,7 @@
|
||||
|
||||
default void setDelayedLeashHolderId(int unresolvedLeashHolderId) {
|
||||
this.setLeashData(new Leashable.LeashData(unresolvedLeashHolderId));
|
||||
- Leashable.dropLeash((Entity) this, false, false);
|
||||
+ Leashable.dropLeash((Entity & Leashable) this, false, false); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
default void readLeashData(CompoundTag nbt) {
|
||||
@@ -61,10 +65,16 @@
|
||||
@Nullable
|
||||
private static Leashable.LeashData readLeashDataInternal(CompoundTag nbt) {
|
||||
if (nbt.contains("leash", 10)) {
|
||||
- return new Leashable.LeashData(Either.left(nbt.getCompound("leash").getUUID("UUID")));
|
||||
+ // Paper start
|
||||
+ final CompoundTag leashTag = nbt.getCompound("leash");
|
||||
+ if (!leashTag.hasUUID("UUID")) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID")));
|
||||
+ // Paper end
|
||||
} else {
|
||||
if (nbt.contains("leash", 11)) {
|
||||
- Either<UUID, BlockPos> either = (Either) NbtUtils.readBlockPos(nbt, "leash").map(Either::right).orElse((Object) null);
|
||||
+ Either<UUID, BlockPos> either = (Either) NbtUtils.readBlockPos(nbt, "leash").map(Either::right).orElse(null); // CraftBukkit - decompile error
|
||||
|
||||
if (either != null) {
|
||||
return new Leashable.LeashData(either);
|
||||
@@ -79,6 +89,11 @@
|
||||
if (leashData != null) {
|
||||
Either<UUID, BlockPos> either = leashData.delayedLeashInfo;
|
||||
Entity entity = leashData.leashHolder;
|
||||
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
|
||||
+ if (entity != null && entity.pluginRemoved) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (entity instanceof LeashFenceKnotEntity) {
|
||||
LeashFenceKnotEntity entityleash = (LeashFenceKnotEntity) entity;
|
||||
@@ -121,7 +136,9 @@
|
||||
}
|
||||
|
||||
if (entity.tickCount > 100) {
|
||||
+ entity.forceDrops = true; // CraftBukkit
|
||||
entity.spawnAtLocation(worldserver, (ItemLike) Items.LEAD);
|
||||
+ entity.forceDrops = false; // CraftBukkit
|
||||
((Leashable) entity).setLeashData((Leashable.LeashData) null);
|
||||
}
|
||||
}
|
||||
@@ -130,11 +147,11 @@
|
||||
}
|
||||
|
||||
default void dropLeash() {
|
||||
- Leashable.dropLeash((Entity) this, true, true);
|
||||
+ Leashable.dropLeash((Entity & Leashable) this, true, true); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
default void removeLeash() {
|
||||
- Leashable.dropLeash((Entity) this, true, false);
|
||||
+ Leashable.dropLeash((Entity & Leashable) this, true, false); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
default void onLeashRemoved() {}
|
||||
@@ -151,7 +168,9 @@
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
if (dropItem) {
|
||||
+ entity.forceDrops = true; // CraftBukkit
|
||||
entity.spawnAtLocation(worldserver, (ItemLike) Items.LEAD);
|
||||
+ entity.forceDrops = false; // CraftBukkit
|
||||
}
|
||||
|
||||
if (sendPacket) {
|
||||
@@ -171,7 +190,11 @@
|
||||
|
||||
if (leashable_a != null && leashable_a.leashHolder != null) {
|
||||
if (!entity.isAlive() || !leashable_a.leashHolder.isAlive()) {
|
||||
- if (world.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ final EntityUnleashEvent event = new EntityUnleashEvent(entity.getBukkitEntity(), (!entity.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, world.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS) && !entity.pluginRemoved);
|
||||
+ event.callEvent();
|
||||
+ if (event.isDropLeash()) { // CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin
|
||||
+ // Paper end - Expand EntityUnleashEvent
|
||||
((Leashable) entity).dropLeash();
|
||||
} else {
|
||||
((Leashable) entity).removeLeash();
|
||||
@@ -187,7 +210,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
- if ((double) f > 10.0D) {
|
||||
+ if ((double) f > entity.level().paperConfig().misc.maxLeashDistance.or(LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
|
||||
((Leashable) entity).leashTooFarBehaviour();
|
||||
} else if ((double) f > 6.0D) {
|
||||
((Leashable) entity).elasticRangeLeashBehaviour(entity1, f);
|
||||
@@ -205,13 +228,27 @@
|
||||
}
|
||||
|
||||
default void leashTooFarBehaviour() {
|
||||
- this.dropLeash();
|
||||
+ // CraftBukkit start
|
||||
+ boolean dropLeash = true; // Paper
|
||||
+ if (this instanceof Entity entity) {
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ final EntityUnleashEvent event = new EntityUnleashEvent(entity.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true);
|
||||
+ if (!event.callEvent()) return;
|
||||
+ dropLeash = event.isDropLeash();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (dropLeash) {
|
||||
+ this.dropLeash();
|
||||
+ } else {
|
||||
+ this.removeLeash();
|
||||
+ }
|
||||
+ // Paper end - Expand EntityUnleashEvent
|
||||
}
|
||||
|
||||
default void closeRangeLeashBehaviour(Entity entity) {}
|
||||
|
||||
default void elasticRangeLeashBehaviour(Entity leashHolder, float distance) {
|
||||
- Leashable.legacyElasticRangeLeashBehaviour((Entity) this, leashHolder, distance);
|
||||
+ Leashable.legacyElasticRangeLeashBehaviour((Entity & Leashable) this, leashHolder, distance); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
private static <E extends Entity & Leashable> void legacyElasticRangeLeashBehaviour(E entity, Entity leashHolder, float distance) {
|
||||
@@ -223,7 +260,7 @@
|
||||
}
|
||||
|
||||
default void setLeashedTo(Entity leashHolder, boolean sendPacket) {
|
||||
- this.setLeashedTo((Entity) this, leashHolder, sendPacket);
|
||||
+ Leashable.setLeashedTo((Entity & Leashable) this, leashHolder, sendPacket); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
private static <E extends Entity & Leashable> void setLeashedTo(E entity, Entity leashHolder, boolean sendPacket) {
|
||||
@@ -254,7 +291,7 @@
|
||||
|
||||
@Nullable
|
||||
default Entity getLeashHolder() {
|
||||
- return Leashable.getLeashHolder((Entity) this);
|
||||
+ return Leashable.getLeashHolder((Entity & Leashable) this); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -0,0 +1,160 @@
|
||||
--- a/net/minecraft/world/entity/LightningBolt.java
|
||||
+++ b/net/minecraft/world/entity/LightningBolt.java
|
||||
@@ -30,6 +30,10 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
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;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class LightningBolt extends Entity {
|
||||
|
||||
@@ -44,6 +48,7 @@
|
||||
private ServerPlayer cause;
|
||||
private final Set<Entity> hitEntities = Sets.newHashSet();
|
||||
private int blocksSetOnFire;
|
||||
+ public boolean isEffect; // Paper - Properly handle lightning effects api
|
||||
|
||||
public LightningBolt(EntityType<? extends LightningBolt> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -82,7 +87,7 @@
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
- if (this.life == 2) {
|
||||
+ if (!this.isEffect && this.life == 2) { // Paper - Properly handle lightning effects api
|
||||
if (this.level().isClientSide()) {
|
||||
this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F, false);
|
||||
this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F, false);
|
||||
@@ -94,7 +99,7 @@
|
||||
}
|
||||
|
||||
this.powerLightningRod();
|
||||
- LightningBolt.clearCopperOnLightningStrike(this.level(), this.getStrikePosition());
|
||||
+ LightningBolt.clearCopperOnLightningStrike(this.level(), this.getStrikePosition(), this); // Paper - Call EntityChangeBlockEvent
|
||||
this.gameEvent(GameEvent.LIGHTNING_STRIKE);
|
||||
}
|
||||
}
|
||||
@@ -120,7 +125,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
} else if (this.life < -this.random.nextInt(10)) {
|
||||
--this.flashes;
|
||||
this.life = 1;
|
||||
@@ -129,7 +134,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- if (this.life >= 0) {
|
||||
+ if (this.life >= 0 && !this.isEffect) { // CraftBukkit - add !this.visualOnly // Paper - Properly handle lightning effects api
|
||||
if (!(this.level() instanceof ServerLevel)) {
|
||||
this.level().setSkyFlashTime(2);
|
||||
} else if (!this.visualOnly) {
|
||||
@@ -158,7 +163,7 @@
|
||||
}
|
||||
|
||||
private void spawnFire(int spreadAttempts) {
|
||||
- if (!this.visualOnly) {
|
||||
+ if (!this.visualOnly && !this.isEffect) { // Paper - Properly handle lightning effects api
|
||||
Level world = this.level();
|
||||
|
||||
if (world instanceof ServerLevel) {
|
||||
@@ -169,8 +174,12 @@
|
||||
BlockState iblockdata = BaseFireBlock.getState(this.level(), blockposition);
|
||||
|
||||
if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) {
|
||||
- this.level().setBlockAndUpdate(blockposition, iblockdata);
|
||||
- ++this.blocksSetOnFire;
|
||||
+ // CraftBukkit start - add "!visualOnly"
|
||||
+ if (!this.visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) {
|
||||
+ this.level().setBlockAndUpdate(blockposition, iblockdata);
|
||||
+ ++this.blocksSetOnFire;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
for (int j = 0; j < spreadAttempts; ++j) {
|
||||
@@ -178,8 +187,12 @@
|
||||
|
||||
iblockdata = BaseFireBlock.getState(this.level(), blockposition1);
|
||||
if (this.level().getBlockState(blockposition1).isAir() && iblockdata.canSurvive(this.level(), blockposition1)) {
|
||||
- this.level().setBlockAndUpdate(blockposition1, iblockdata);
|
||||
- ++this.blocksSetOnFire;
|
||||
+ // CraftBukkit start - add "!visualOnly"
|
||||
+ if (!this.visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition1, this).isCancelled()) {
|
||||
+ this.level().setBlockAndUpdate(blockposition1, iblockdata);
|
||||
+ ++this.blocksSetOnFire;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +203,7 @@
|
||||
|
||||
}
|
||||
|
||||
- private static void clearCopperOnLightningStrike(Level world, BlockPos pos) {
|
||||
+ private static void clearCopperOnLightningStrike(Level world, BlockPos pos, Entity lightning) { // Paper - Call EntityChangeBlockEvent
|
||||
BlockState iblockdata = world.getBlockState(pos);
|
||||
BlockPos blockposition1;
|
||||
BlockState iblockdata1;
|
||||
@@ -204,24 +217,29 @@
|
||||
}
|
||||
|
||||
if (iblockdata1.getBlock() instanceof WeatheringCopper) {
|
||||
- world.setBlockAndUpdate(blockposition1, WeatheringCopper.getFirst(world.getBlockState(blockposition1)));
|
||||
+ // Paper start - Call EntityChangeBlockEvent
|
||||
+ BlockState newBlock = WeatheringCopper.getFirst(world.getBlockState(blockposition1));
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(lightning, blockposition1, newBlock)) {
|
||||
+ world.setBlockAndUpdate(blockposition1, newBlock);
|
||||
+ }
|
||||
+ // Paper end - Call EntityChangeBlockEvent
|
||||
BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable();
|
||||
int i = world.random.nextInt(3) + 3;
|
||||
|
||||
for (int j = 0; j < i; ++j) {
|
||||
int k = world.random.nextInt(8) + 1;
|
||||
|
||||
- LightningBolt.randomWalkCleaningCopper(world, blockposition1, blockposition_mutableblockposition, k);
|
||||
+ LightningBolt.randomWalkCleaningCopper(world, blockposition1, blockposition_mutableblockposition, k, lightning); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- private static void randomWalkCleaningCopper(Level world, BlockPos pos, BlockPos.MutableBlockPos mutablePos, int count) {
|
||||
+ private static void randomWalkCleaningCopper(Level world, BlockPos pos, BlockPos.MutableBlockPos mutablePos, int count, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
|
||||
mutablePos.set(pos);
|
||||
|
||||
for (int j = 0; j < count; ++j) {
|
||||
- Optional<BlockPos> optional = LightningBolt.randomStepCleaningCopper(world, mutablePos);
|
||||
+ Optional<BlockPos> optional = LightningBolt.randomStepCleaningCopper(world, mutablePos, lightning); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
|
||||
|
||||
if (optional.isEmpty()) {
|
||||
break;
|
||||
@@ -232,7 +250,7 @@
|
||||
|
||||
}
|
||||
|
||||
- private static Optional<BlockPos> randomStepCleaningCopper(Level world, BlockPos pos) {
|
||||
+ private static Optional<BlockPos> randomStepCleaningCopper(Level world, BlockPos pos, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
|
||||
Iterator iterator = BlockPos.randomInCube(world.random, 10, pos, 1).iterator();
|
||||
|
||||
BlockPos blockposition1;
|
||||
@@ -247,8 +265,10 @@
|
||||
iblockdata = world.getBlockState(blockposition1);
|
||||
} while (!(iblockdata.getBlock() instanceof WeatheringCopper));
|
||||
|
||||
+ BlockPos blockposition1Final = blockposition1; // CraftBukkit - decompile error
|
||||
WeatheringCopper.getPrevious(iblockdata).ifPresent((iblockdata1) -> {
|
||||
- world.setBlockAndUpdate(blockposition1, iblockdata1);
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(lightning, blockposition1Final, iblockdata1)) // Paper - call EntityChangeBlockEvent
|
||||
+ world.setBlockAndUpdate(blockposition1Final, iblockdata1); // CraftBukkit - decompile error
|
||||
});
|
||||
world.levelEvent(3002, blockposition1, -1);
|
||||
return Optional.of(blockposition1);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,472 @@
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -84,6 +84,17 @@
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+// 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 {
|
||||
|
||||
@@ -112,6 +123,7 @@
|
||||
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 GoalSelector targetSelector;
|
||||
@Nullable
|
||||
private LivingEntity target;
|
||||
@@ -132,6 +144,8 @@
|
||||
private BlockPos restrictCenter;
|
||||
private float restrictRadius;
|
||||
|
||||
+ public boolean aware = true; // CraftBukkit
|
||||
+
|
||||
protected Mob(EntityType<? extends Mob> type, Level world) {
|
||||
super(type, world);
|
||||
this.handItems = NonNullList.withSize(2, ItemStack.EMPTY);
|
||||
@@ -157,8 +171,14 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
this.registerGoals();
|
||||
}
|
||||
+
|
||||
+ }
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void setPersistenceRequired(boolean persistenceRequired) {
|
||||
+ this.persistenceRequired = persistenceRequired;
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
protected void registerGoals() {}
|
||||
|
||||
@@ -264,13 +284,44 @@
|
||||
|
||||
@Nullable
|
||||
protected final LivingEntity getTargetFromBrain() {
|
||||
- return (LivingEntity) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null);
|
||||
+ return (LivingEntity) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public void setTarget(@Nullable LivingEntity target) {
|
||||
- this.target = target;
|
||||
+ // CraftBukkit start - fire event
|
||||
+ this.setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true);
|
||||
}
|
||||
|
||||
+ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) {
|
||||
+ if (this.getTarget() == entityliving) return false;
|
||||
+ if (fireEvent) {
|
||||
+ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && this.getTarget() != null && entityliving == 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;
|
||||
+ if (entityliving != null) {
|
||||
+ ctarget = (CraftLivingEntity) entityliving.getBukkitEntity();
|
||||
+ }
|
||||
+ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason);
|
||||
+ this.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (event.getTarget() != null) {
|
||||
+ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle();
|
||||
+ } else {
|
||||
+ entityliving = null;
|
||||
+ }
|
||||
+ }
|
||||
+ this.target = entityliving;
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public boolean canAttackType(EntityType<?> type) {
|
||||
return type != EntityType.GHAST;
|
||||
@@ -399,6 +450,12 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - Add delegate method
|
||||
+ public SoundEvent getAmbientSound0() {
|
||||
+ return this.getAmbientSound();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
super.addAdditionalSaveData(nbt);
|
||||
@@ -473,13 +530,25 @@
|
||||
nbt.putBoolean("NoAI", this.isNoAi());
|
||||
}
|
||||
|
||||
+ nbt.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
super.readAdditionalSaveData(nbt);
|
||||
- this.setCanPickUpLoot(nbt.getBoolean("CanPickUpLoot"));
|
||||
- this.persistenceRequired = nbt.getBoolean("PersistenceRequired");
|
||||
+ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
|
||||
+ if (nbt.contains("CanPickUpLoot", 99)) {
|
||||
+ boolean data = nbt.getBoolean("CanPickUpLoot");
|
||||
+ if (isLevelAtLeast(nbt, 1) || data) {
|
||||
+ this.setCanPickUpLoot(data);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ boolean data = nbt.getBoolean("PersistenceRequired");
|
||||
+ if (isLevelAtLeast(nbt, 1) || data) {
|
||||
+ this.persistenceRequired = data;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ListTag nbttaglist;
|
||||
CompoundTag nbttagcompound1;
|
||||
int i;
|
||||
@@ -540,13 +609,18 @@
|
||||
this.readLeashData(nbt);
|
||||
this.setLeftHanded(nbt.getBoolean("LeftHanded"));
|
||||
if (nbt.contains("DeathLootTable", 8)) {
|
||||
- this.lootTable = Optional.of(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("DeathLootTable"))));
|
||||
+ this.lootTable = Optional.ofNullable(ResourceLocation.tryParse(nbt.getString("DeathLootTable"))).map((rs) -> ResourceKey.create(Registries.LOOT_TABLE, rs)); // Paper - Validate ResourceLocation
|
||||
} else {
|
||||
this.lootTable = Optional.empty();
|
||||
}
|
||||
|
||||
this.lootTableSeed = nbt.getLong("DeathLootTableSeed");
|
||||
this.setNoAi(nbt.getBoolean("NoAI"));
|
||||
+ // CraftBukkit start
|
||||
+ if (nbt.contains("Bukkit.Aware")) {
|
||||
+ this.aware = nbt.getBoolean("Bukkit.Aware");
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -608,6 +682,11 @@
|
||||
ItemEntity entityitem = (ItemEntity) iterator.next();
|
||||
|
||||
if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(worldserver, entityitem.getItem())) {
|
||||
+ // Paper start - Item#canEntityPickup
|
||||
+ if (!entityitem.canMobPickup) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end - Item#canEntityPickup
|
||||
this.pickUpItem(worldserver, entityitem);
|
||||
}
|
||||
}
|
||||
@@ -623,23 +702,29 @@
|
||||
|
||||
protected void pickUpItem(ServerLevel world, ItemEntity itemEntity) {
|
||||
ItemStack itemstack = itemEntity.getItem();
|
||||
- ItemStack itemstack1 = this.equipItemIfPossible(world, itemstack.copy());
|
||||
+ ItemStack itemstack1 = this.equipItemIfPossible(world, itemstack.copy(), itemEntity); // CraftBukkit - add item
|
||||
|
||||
if (!itemstack1.isEmpty()) {
|
||||
this.onItemPickup(itemEntity);
|
||||
this.take(itemEntity, itemstack1.getCount());
|
||||
itemstack.shrink(itemstack1.getCount());
|
||||
if (itemstack.isEmpty()) {
|
||||
- itemEntity.discard();
|
||||
+ itemEntity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ItemStack equipItemIfPossible(ServerLevel world, ItemStack stack) {
|
||||
- EquipmentSlot enumitemslot = this.getEquipmentSlotForItem(stack);
|
||||
+ // CraftBukkit start - add item
|
||||
+ return this.equipItemIfPossible(world, stack, null);
|
||||
+ }
|
||||
+
|
||||
+ public ItemStack equipItemIfPossible(ServerLevel worldserver, ItemStack itemstack, ItemEntity entityitem) {
|
||||
+ // CraftBukkit end
|
||||
+ EquipmentSlot enumitemslot = this.getEquipmentSlotForItem(itemstack);
|
||||
ItemStack itemstack1 = this.getItemBySlot(enumitemslot);
|
||||
- boolean flag = this.canReplaceCurrentItem(stack, itemstack1, enumitemslot);
|
||||
+ boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1, enumitemslot);
|
||||
|
||||
if (enumitemslot.isArmor() && !flag) {
|
||||
enumitemslot = EquipmentSlot.MAINHAND;
|
||||
@@ -647,14 +732,22 @@
|
||||
flag = itemstack1.isEmpty();
|
||||
}
|
||||
|
||||
- if (flag && this.canHoldItem(stack)) {
|
||||
+ // CraftBukkit start
|
||||
+ boolean canPickup = flag && this.canHoldItem(itemstack);
|
||||
+ if (entityitem != null) {
|
||||
+ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled();
|
||||
+ }
|
||||
+ if (canPickup) {
|
||||
+ // CraftBukkit end
|
||||
double d0 = (double) this.getEquipmentDropChance(enumitemslot);
|
||||
|
||||
if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) {
|
||||
- this.spawnAtLocation(world, itemstack1);
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
+ this.spawnAtLocation(worldserver, itemstack1);
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
}
|
||||
|
||||
- ItemStack itemstack2 = enumitemslot.limit(stack);
|
||||
+ ItemStack itemstack2 = enumitemslot.limit(itemstack);
|
||||
|
||||
this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack2);
|
||||
return itemstack2;
|
||||
@@ -768,25 +861,29 @@
|
||||
@Override
|
||||
public void checkDespawn() {
|
||||
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
} else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) {
|
||||
- Player entityhuman = this.level().getNearestPlayer(this, -1.0D);
|
||||
+ Player entityhuman = this.level().findNearbyPlayer(this, -1.0D, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper - Affects Spawning API
|
||||
|
||||
if (entityhuman != null) {
|
||||
- double d0 = entityhuman.distanceToSqr((Entity) this);
|
||||
- int i = this.getType().getCategory().getDespawnDistance();
|
||||
- int j = i * i;
|
||||
-
|
||||
- if (d0 > (double) j && this.removeWhenFarAway(d0)) {
|
||||
- this.discard();
|
||||
+ // Paper start - Configurable despawn distances
|
||||
+ 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(entityhuman.getY() - this.getY());
|
||||
+ final double dySqr = Math.pow(dy, 2);
|
||||
+ final double dxSqr = Math.pow(entityhuman.getX() - this.getX(), 2);
|
||||
+ final double dzSqr = Math.pow(entityhuman.getZ() - this.getZ(), 2);
|
||||
+ 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)) {
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
-
|
||||
- int k = this.getType().getCategory().getNoDespawnDistance();
|
||||
- int l = k * k;
|
||||
-
|
||||
- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) {
|
||||
- this.discard();
|
||||
- } else if (d0 < (double) l) {
|
||||
+ if (despawnRangePair.soft().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy)) {
|
||||
+ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && this.removeWhenFarAway(distanceSquared)) {
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
+ }
|
||||
+ } else {
|
||||
+ // Paper end - Configurable despawn distances
|
||||
this.noActionTime = 0;
|
||||
}
|
||||
}
|
||||
@@ -799,6 +896,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();
|
||||
+ this.getJumpControl().tick();
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Allow nerfed mobs to jump and float
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
gameprofilerfiller.push("sensing");
|
||||
@@ -994,23 +1100,36 @@
|
||||
|
||||
@Override
|
||||
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
|
||||
+ // Paper start - Fix silent equipment change
|
||||
+ setItemSlot(slot, stack, false);
|
||||
+ }
|
||||
+
|
||||
+ @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, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack);
|
||||
+ this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
|
||||
break;
|
||||
case HUMANOID_ARMOR:
|
||||
- this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack);
|
||||
+ this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
|
||||
break;
|
||||
case ANIMAL_ARMOR:
|
||||
ItemStack itemstack1 = this.bodyArmorItem;
|
||||
|
||||
this.bodyArmorItem = stack;
|
||||
- this.onEquipItem(slot, itemstack1, stack);
|
||||
+ this.onEquipItem(slot, itemstack1, stack, silent); // Paper - Fix silent equipment change
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ protected boolean shouldSkipLoot(EquipmentSlot slot) { // method to avoid to fallback into the global mob loot logic (i.e fox)
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {
|
||||
super.dropCustomDeathLoot(world, source, causedByPlayer);
|
||||
@@ -1018,6 +1137,7 @@
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
EquipmentSlot enumitemslot = (EquipmentSlot) iterator.next();
|
||||
+ if (this.shouldSkipLoot(enumitemslot)) continue; // Paper
|
||||
ItemStack itemstack = this.getItemBySlot(enumitemslot);
|
||||
float f = this.getEquipmentDropChance(enumitemslot);
|
||||
|
||||
@@ -1042,7 +1162,13 @@
|
||||
}
|
||||
|
||||
this.spawnAtLocation(world, itemstack);
|
||||
+ if (this.clearEquipmentSlots) { // Paper
|
||||
this.setItemSlot(enumitemslot, ItemStack.EMPTY);
|
||||
+ // Paper start
|
||||
+ } else {
|
||||
+ this.clearedEquipmentSlots.add(enumitemslot);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1338,7 +1464,7 @@
|
||||
if (itemstack.getItem() instanceof SpawnEggItem) {
|
||||
if (this.level() instanceof ServerLevel) {
|
||||
SpawnEggItem itemmonsteregg = (SpawnEggItem) itemstack.getItem();
|
||||
- Optional<Mob> optional = itemmonsteregg.spawnOffspringFromSpawnEgg(player, this, this.getType(), (ServerLevel) this.level(), this.position(), itemstack);
|
||||
+ Optional<Mob> optional = itemmonsteregg.spawnOffspringFromSpawnEgg(player, this, (EntityType<? extends Mob>) this.getType(), (ServerLevel) this.level(), this.position(), itemstack); // CraftBukkit - decompile error
|
||||
|
||||
optional.ifPresent((entityinsentient) -> {
|
||||
this.onOffspringSpawnedFromEgg(player, entityinsentient);
|
||||
@@ -1389,28 +1515,51 @@
|
||||
return this.restrictRadius != -1.0F;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
@Nullable
|
||||
public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams context, EntitySpawnReason reason, ConversionParams.AfterConversion<T> finalizer) {
|
||||
+ return this.convertTo(entityType, context, reason, finalizer, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public <T extends Mob> T convertTo(EntityType<T> entitytypes, ConversionParams conversionparams, EntitySpawnReason entityspawnreason, ConversionParams.AfterConversion<T> conversionparams_a, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // Paper start - entity zap event - allow cancellation of conversion post creation
|
||||
+ return this.convertTo(entitytypes, conversionparams, entityspawnreason, e -> { conversionparams_a.finalizeConversion(e); return true; }, transformReason, spawnReason);
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ public <T extends Mob> T convertTo(EntityType<T> entitytypes, ConversionParams conversionparams, EntitySpawnReason entityspawnreason, ConversionParams.CancellingAfterConversion<T> conversionparams_a, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // Paper end - entity zap event - allow cancellation of conversion post creation
|
||||
+ // CraftBukkit end
|
||||
if (this.isRemoved()) {
|
||||
return null;
|
||||
} else {
|
||||
- T t0 = (Mob) entityType.create(this.level(), reason);
|
||||
+ T t0 = entitytypes.create(this.level(), EntitySpawnReason.CONVERSION); // CraftBukkit - decompile error
|
||||
|
||||
if (t0 == null) {
|
||||
return null;
|
||||
} else {
|
||||
- context.type().convert(this, t0, context);
|
||||
- finalizer.finalizeConversion(t0);
|
||||
+ conversionparams.type().convert(this, t0, conversionparams);
|
||||
+ if (!conversionparams_a.finalizeConversionOrCancel(t0)) return null; // Paper - entity zap event - return null if conversion was cancelled
|
||||
Level world = this.level();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ if (transformReason == null) {
|
||||
+ // Special handling for slime split and pig lightning
|
||||
+ return t0;
|
||||
+ }
|
||||
+
|
||||
+ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
- worldserver.addFreshEntity(t0);
|
||||
+ worldserver.addFreshEntity(t0, spawnReason); // CraftBukkit
|
||||
}
|
||||
|
||||
- if (context.type().shouldDiscardAfterConversion()) {
|
||||
- this.discard();
|
||||
+ if (conversionparams.type().shouldDiscardAfterConversion()) {
|
||||
+ this.discard(EntityRemoveEvent.Cause.TRANSFORMATION); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
|
||||
return t0;
|
||||
@@ -1420,10 +1569,22 @@
|
||||
|
||||
@Nullable
|
||||
public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams context, ConversionParams.AfterConversion<T> finalizer) {
|
||||
- return this.convertTo(entityType, context, EntitySpawnReason.CONVERSION, finalizer);
|
||||
+ // CraftBukkit start
|
||||
+ return this.convertTo(entityType, context, finalizer, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
+ public <T extends Mob> T convertTo(EntityType<T> entitytypes, ConversionParams conversionparams, ConversionParams.AfterConversion<T> conversionparams_a, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // Paper start - entity zap event - allow cancellation of conversion post creation
|
||||
+ return this.convertTo(entitytypes, conversionparams, e -> { conversionparams_a.finalizeConversion(e); return true; }, transformReason, spawnReason);
|
||||
+ }
|
||||
+ public <T extends Mob> T convertTo(EntityType<T> entitytypes, ConversionParams conversionparams, ConversionParams.CancellingAfterConversion<T> conversionparams_a, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // Paper start - entity zap event - allow cancellation of conversion post creation
|
||||
+ return this.convertTo(entitytypes, conversionparams, EntitySpawnReason.CONVERSION, conversionparams_a, transformReason, spawnReason);
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
@Override
|
||||
public Leashable.LeashData getLeashData() {
|
||||
return this.leashData;
|
||||
@@ -1458,7 +1619,15 @@
|
||||
boolean flag1 = super.startRiding(entity, force);
|
||||
|
||||
if (flag1 && this.isLeashed()) {
|
||||
- this.dropLeash();
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN, true);
|
||||
+ if (!event.callEvent()) { return flag1; }
|
||||
+ if (event.isDropLeash()) {
|
||||
+ this.dropLeash();
|
||||
+ } else {
|
||||
+ this.removeLeash();
|
||||
+ }
|
||||
+ // Paper end - Expand EntityUnleashEvent
|
||||
}
|
||||
|
||||
return flag1;
|
||||
@@ -1542,7 +1711,7 @@
|
||||
|
||||
if (f1 > 0.0F && target instanceof LivingEntity) {
|
||||
entityliving = (LivingEntity) target;
|
||||
- entityliving.knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)));
|
||||
+ entityliving.knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
--- a/net/minecraft/world/entity/NeutralMob.java
|
||||
+++ b/net/minecraft/world/entity/NeutralMob.java
|
||||
@@ -8,6 +8,9 @@
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.Level;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public interface NeutralMob {
|
||||
|
||||
@@ -42,24 +45,11 @@
|
||||
UUID uuid = nbt.getUUID("AngryAt");
|
||||
|
||||
this.setPersistentAngerTarget(uuid);
|
||||
- Entity entity = ((ServerLevel) world).getEntity(uuid);
|
||||
-
|
||||
- if (entity != null) {
|
||||
- if (entity instanceof Mob) {
|
||||
- Mob entityinsentient = (Mob) entity;
|
||||
-
|
||||
- this.setTarget(entityinsentient);
|
||||
- this.setLastHurtByMob(entityinsentient);
|
||||
- }
|
||||
-
|
||||
- if (entity instanceof Player) {
|
||||
- Player entityhuman = (Player) entity;
|
||||
-
|
||||
- this.setTarget(entityhuman);
|
||||
- this.setLastHurtByPlayer(entityhuman);
|
||||
- }
|
||||
-
|
||||
- }
|
||||
+ // 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(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +104,7 @@
|
||||
default void stopBeingAngry() {
|
||||
this.setLastHurtByMob((LivingEntity) null);
|
||||
this.setPersistentAngerTarget((UUID) null);
|
||||
- this.setTarget((LivingEntity) null);
|
||||
+ this.setTarget((LivingEntity) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit
|
||||
this.setRemainingPersistentAngerTime(0);
|
||||
}
|
||||
|
||||
@@ -127,8 +117,34 @@
|
||||
|
||||
void setTarget(@Nullable LivingEntity target);
|
||||
|
||||
+ boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit
|
||||
+
|
||||
boolean canAttack(LivingEntity target);
|
||||
|
||||
@Nullable
|
||||
LivingEntity getTarget();
|
||||
+
|
||||
+ // Paper start - Prevent entity loading causing async lookups
|
||||
+ // Update last hurt when ticking
|
||||
+ default void tickInitialPersistentAnger(Level level) {
|
||||
+ UUID target = getPersistentAngerTarget();
|
||||
+ if (target == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ Entity entity = ((ServerLevel) level).getEntity(target);
|
||||
+
|
||||
+ if (entity != null) {
|
||||
+ if (entity instanceof Mob mob) {
|
||||
+ this.setTarget(mob, EntityTargetEvent.TargetReason.UNKNOWN, false); // CraftBukkit
|
||||
+ this.setLastHurtByMob(mob);
|
||||
+ }
|
||||
+
|
||||
+ if (entity instanceof Player player) {
|
||||
+ this.setTarget(player, EntityTargetEvent.TargetReason.UNKNOWN, false); // CraftBukkit
|
||||
+ this.setLastHurtByPlayer(player);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Prevent entity loading causing async lookups
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
--- a/net/minecraft/world/entity/OminousItemSpawner.java
|
||||
+++ b/net/minecraft/world/entity/OminousItemSpawner.java
|
||||
@@ -76,7 +76,7 @@
|
||||
entity = this.spawnProjectile(serverLevel, projectileItem, itemStack);
|
||||
} else {
|
||||
entity = new ItemEntity(serverLevel, this.getX(), this.getY(), this.getZ(), itemStack);
|
||||
- serverLevel.addFreshEntity(entity);
|
||||
+ serverLevel.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.OMINOUS_ITEM_SPAWNER); // Paper - fixes and addition to spawn reason API
|
||||
}
|
||||
|
||||
serverLevel.levelEvent(3021, this.blockPosition(), 1);
|
||||
@@ -90,7 +90,7 @@
|
||||
ProjectileItem.DispenseConfig dispenseConfig = item.createDispenseConfig();
|
||||
dispenseConfig.overrideDispenseEvent().ifPresent(dispenseEvent -> world.levelEvent(dispenseEvent, this.blockPosition(), 0));
|
||||
Direction direction = Direction.DOWN;
|
||||
- Projectile projectile = Projectile.spawnProjectileUsingShoot(
|
||||
+ Projectile projectile = Projectile.spawnProjectileUsingShootDelayed( // Paper - fixes and addition to spawn reason API
|
||||
item.asProjectile(world, this.position(), stack, direction),
|
||||
world,
|
||||
stack,
|
||||
@@ -99,7 +99,7 @@
|
||||
(double)direction.getStepZ(),
|
||||
dispenseConfig.power(),
|
||||
dispenseConfig.uncertainty()
|
||||
- );
|
||||
+ ).spawn(org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.OMINOUS_ITEM_SPAWNER); // Paper - fixes and addition to spawn reason API
|
||||
projectile.setOwner(this);
|
||||
return projectile;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/world/entity/PathfinderMob.java
|
||||
+++ b/net/minecraft/world/entity/PathfinderMob.java
|
||||
@@ -10,6 +10,9 @@
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityUnleashEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class PathfinderMob extends Mob {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
--- a/net/minecraft/world/entity/Shearable.java
|
||||
+++ b/net/minecraft/world/entity/Shearable.java
|
||||
@@ -5,7 +5,15 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public interface Shearable {
|
||||
+ default void shear(ServerLevel world, SoundSource soundCategory, ItemStack shears, java.util.List<net.minecraft.world.item.ItemStack> drops) { this.shear(world, soundCategory, shears); } // Paper - Add drops to shear events
|
||||
void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears);
|
||||
|
||||
boolean readyForShearing();
|
||||
+ net.minecraft.world.level.Level level(); // Shearable API - expose default level needed for shearing.
|
||||
+
|
||||
+ // Paper start - custom shear drops; ensure all implementing entities override this
|
||||
+ default java.util.List<net.minecraft.world.item.ItemStack> generateDefaultDrops(final ServerLevel serverLevel, final ItemStack shears) {
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ // Paper end - custom shear drops
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
--- a/net/minecraft/world/entity/TamableAnimal.java
|
||||
+++ b/net/minecraft/world/entity/TamableAnimal.java
|
||||
@@ -27,6 +27,11 @@
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityTeleportEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class TamableAnimal extends Animal implements OwnableEntity {
|
||||
|
||||
@@ -85,7 +90,7 @@
|
||||
}
|
||||
|
||||
this.orderedToSit = nbt.getBoolean("Sitting");
|
||||
- this.setInSittingPose(this.orderedToSit);
|
||||
+ this.setInSittingPose(this.orderedToSit, false); // Paper - Add EntityToggleSitEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,8 +101,16 @@
|
||||
@Override
|
||||
public boolean handleLeashAtDistance(Entity leashHolder, float distance) {
|
||||
if (this.isInSittingPose()) {
|
||||
- if (distance > 10.0F) {
|
||||
- this.dropLeash();
|
||||
+ if (distance > (float) this.level().paperConfig().misc.maxLeashDistance.or(Leashable.LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(this.getBukkitEntity(), org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.DISTANCE, true);
|
||||
+ if (!event.callEvent()) return false;
|
||||
+ if (event.isDropLeash()) {
|
||||
+ this.dropLeash();
|
||||
+ } else {
|
||||
+ this.removeLeash();
|
||||
+ }
|
||||
+ // Paper end - Expand EntityUnleashEvent
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -161,6 +174,12 @@
|
||||
}
|
||||
|
||||
public void setInSittingPose(boolean inSittingPose) {
|
||||
+ // Paper start - Add EntityToggleSitEvent
|
||||
+ this.setInSittingPose(inSittingPose, true);
|
||||
+ }
|
||||
+ public void setInSittingPose(boolean inSittingPose, boolean callEvent) {
|
||||
+ if (callEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), inSittingPose).callEvent()) return;
|
||||
+ // Paper end - Add EntityToggleSitEvent
|
||||
byte b0 = (Byte) this.entityData.get(TamableAnimal.DATA_FLAGS_ID);
|
||||
|
||||
if (inSittingPose) {
|
||||
@@ -244,7 +263,12 @@
|
||||
if (entityliving instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entityliving;
|
||||
|
||||
- entityplayer.sendSystemMessage(this.getCombatTracker().getDeathMessage());
|
||||
+ // Paper start - Add TameableDeathMessageEvent
|
||||
+ io.papermc.paper.event.entity.TameableDeathMessageEvent event = new io.papermc.paper.event.entity.TameableDeathMessageEvent((org.bukkit.entity.Tameable) getBukkitEntity(), io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getCombatTracker().getDeathMessage()));
|
||||
+ if (event.callEvent()) {
|
||||
+ entityplayer.sendSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.deathMessage()));
|
||||
+ }
|
||||
+ // Paper end - Add TameableDeathMessageEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,7 +319,14 @@
|
||||
if (!this.canTeleportTo(new BlockPos(x, y, z))) {
|
||||
return false;
|
||||
} else {
|
||||
- this.moveTo((double) x + 0.5D, (double) y, (double) z + 0.5D, this.getYRot(), this.getXRot());
|
||||
+ // CraftBukkit start
|
||||
+ EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this, (double) x + 0.5D, (double) y, (double) z + 0.5D);
|
||||
+ if (event.isCancelled() || event.getTo() == null) { // Paper - prevent NP on null event to location
|
||||
+ return false;
|
||||
+ }
|
||||
+ Location to = event.getTo();
|
||||
+ this.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
|
||||
+ // CraftBukkit end
|
||||
this.navigation.stop();
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||
@@ -153,20 +153,20 @@
|
||||
double d = this.getBaseValue();
|
||||
|
||||
for (AttributeModifier attributeModifier : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_VALUE)) {
|
||||
- d += attributeModifier.amount();
|
||||
+ d += attributeModifier.amount(); // Paper - destroy speed API - diff on change
|
||||
}
|
||||
|
||||
double e = d;
|
||||
|
||||
for (AttributeModifier attributeModifier2 : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_MULTIPLIED_BASE)) {
|
||||
- e += d * attributeModifier2.amount();
|
||||
+ e += d * attributeModifier2.amount(); // Paper - destroy speed API - diff on change
|
||||
}
|
||||
|
||||
for (AttributeModifier attributeModifier3 : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL)) {
|
||||
- e *= 1.0 + attributeModifier3.amount();
|
||||
+ e *= 1.0 + attributeModifier3.amount(); // Paper - destroy speed API - diff on change
|
||||
}
|
||||
|
||||
- return this.attribute.value().sanitizeValue(e);
|
||||
+ return attribute.value().sanitizeValue(e); // Paper - destroy speed API - diff on change
|
||||
}
|
||||
|
||||
private Collection<AttributeModifier> getModifiersOrEmpty(AttributeModifier.Operation operation) {
|
||||
@@ -0,0 +1,15 @@
|
||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
@@ -162,4 +162,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper - start - living entity allow attribute registration
|
||||
+ public void registerAttribute(Holder<Attribute> attributeBase) {
|
||||
+ AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute);
|
||||
+ attributes.put(attributeBase, attributeModifiable);
|
||||
+ }
|
||||
+ // Paper - end - living entity allow attribute registration
|
||||
+
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
--- a/net/minecraft/world/entity/ai/attributes/Attributes.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/Attributes.java
|
||||
@@ -1,3 +1,4 @@
|
||||
+// mc-dev import
|
||||
package net.minecraft.world.entity.ai.attributes;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
@@ -9,7 +10,7 @@
|
||||
|
||||
public static final Holder<Attribute> ARMOR = Attributes.register("armor", (new RangedAttribute("attribute.name.armor", 0.0D, 0.0D, 30.0D)).setSyncable(true));
|
||||
public static final Holder<Attribute> ARMOR_TOUGHNESS = Attributes.register("armor_toughness", (new RangedAttribute("attribute.name.armor_toughness", 0.0D, 0.0D, 20.0D)).setSyncable(true));
|
||||
- public static final Holder<Attribute> ATTACK_DAMAGE = Attributes.register("attack_damage", new RangedAttribute("attribute.name.attack_damage", 2.0D, 0.0D, 2048.0D));
|
||||
+ public static final Holder<Attribute> ATTACK_DAMAGE = Attributes.register("attack_damage", new RangedAttribute("attribute.name.attack_damage", 2.0D, 0.0D, org.spigotmc.SpigotConfig.attackDamage));
|
||||
public static final Holder<Attribute> ATTACK_KNOCKBACK = Attributes.register("attack_knockback", new RangedAttribute("attribute.name.attack_knockback", 0.0D, 0.0D, 5.0D));
|
||||
public static final Holder<Attribute> ATTACK_SPEED = Attributes.register("attack_speed", (new RangedAttribute("attribute.name.attack_speed", 4.0D, 0.0D, 1024.0D)).setSyncable(true));
|
||||
public static final Holder<Attribute> BLOCK_BREAK_SPEED = Attributes.register("block_break_speed", (new RangedAttribute("attribute.name.block_break_speed", 1.0D, 0.0D, 1024.0D)).setSyncable(true));
|
||||
@@ -24,11 +25,11 @@
|
||||
public static final Holder<Attribute> JUMP_STRENGTH = Attributes.register("jump_strength", (new RangedAttribute("attribute.name.jump_strength", 0.41999998688697815D, 0.0D, 32.0D)).setSyncable(true));
|
||||
public static final Holder<Attribute> KNOCKBACK_RESISTANCE = Attributes.register("knockback_resistance", new RangedAttribute("attribute.name.knockback_resistance", 0.0D, 0.0D, 1.0D));
|
||||
public static final Holder<Attribute> LUCK = Attributes.register("luck", (new RangedAttribute("attribute.name.luck", 0.0D, -1024.0D, 1024.0D)).setSyncable(true));
|
||||
- public static final Holder<Attribute> MAX_ABSORPTION = Attributes.register("max_absorption", (new RangedAttribute("attribute.name.max_absorption", 0.0D, 0.0D, 2048.0D)).setSyncable(true));
|
||||
- public static final Holder<Attribute> MAX_HEALTH = Attributes.register("max_health", (new RangedAttribute("attribute.name.max_health", 20.0D, 1.0D, 1024.0D)).setSyncable(true));
|
||||
+ public static final Holder<Attribute> MAX_ABSORPTION = Attributes.register("max_absorption", (new RangedAttribute("attribute.name.max_absorption", 0.0D, 0.0D, org.spigotmc.SpigotConfig.maxAbsorption)).setSyncable(true));
|
||||
+ public static final Holder<Attribute> MAX_HEALTH = Attributes.register("max_health", (new RangedAttribute("attribute.name.max_health", 20.0D, 1.0D, org.spigotmc.SpigotConfig.maxHealth)).setSyncable(true));
|
||||
public static final Holder<Attribute> MINING_EFFICIENCY = Attributes.register("mining_efficiency", (new RangedAttribute("attribute.name.mining_efficiency", 0.0D, 0.0D, 1024.0D)).setSyncable(true));
|
||||
public static final Holder<Attribute> MOVEMENT_EFFICIENCY = Attributes.register("movement_efficiency", (new RangedAttribute("attribute.name.movement_efficiency", 0.0D, 0.0D, 1.0D)).setSyncable(true));
|
||||
- public static final Holder<Attribute> MOVEMENT_SPEED = Attributes.register("movement_speed", (new RangedAttribute("attribute.name.movement_speed", 0.7D, 0.0D, 1024.0D)).setSyncable(true));
|
||||
+ public static final Holder<Attribute> MOVEMENT_SPEED = Attributes.register("movement_speed", (new RangedAttribute("attribute.name.movement_speed", 0.7D, 0.0D, org.spigotmc.SpigotConfig.movementSpeed)).setSyncable(true));
|
||||
public static final Holder<Attribute> OXYGEN_BONUS = Attributes.register("oxygen_bonus", (new RangedAttribute("attribute.name.oxygen_bonus", 0.0D, 0.0D, 1024.0D)).setSyncable(true));
|
||||
public static final Holder<Attribute> SAFE_FALL_DISTANCE = Attributes.register("safe_fall_distance", (new RangedAttribute("attribute.name.safe_fall_distance", 3.0D, -1024.0D, 1024.0D)).setSyncable(true));
|
||||
public static final Holder<Attribute> SCALE = Attributes.register("scale", (new RangedAttribute("attribute.name.scale", 1.0D, 0.0625D, 16.0D)).setSyncable(true).setSentiment(Attribute.Sentiment.NEUTRAL));
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
@@ -70,6 +70,7 @@
|
||||
return false;
|
||||
} else {
|
||||
mutableLong.setValue(time + 20L + (long)world.getRandom().nextInt(20));
|
||||
+ if (entity.getNavigation().isStuck()) mutableLong.add(200); // Paper - Perf: Wait an additional 10s to check again if they're stuck
|
||||
PoiManager poiManager = world.getPoiManager();
|
||||
long2ObjectMap.long2ObjectEntrySet().removeIf(entry -> !entry.getValue().isStillValid(time));
|
||||
Predicate<BlockPos> predicate2 = pos -> {
|
||||
@@ -0,0 +1,31 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java
|
||||
@@ -9,6 +9,12 @@
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftVillager;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.VillagerCareerChangeEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class AssignProfessionFromJobSite {
|
||||
|
||||
public AssignProfessionFromJobSite() {}
|
||||
@@ -37,7 +43,14 @@
|
||||
return villagerprofession.heldJobSite().test(holder);
|
||||
}).findFirst();
|
||||
}).ifPresent((villagerprofession) -> {
|
||||
- entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(villagerprofession));
|
||||
+ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed
|
||||
+ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(villagerprofession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession())));
|
||||
+ // CraftBukkit end
|
||||
entityvillager.refreshBrain(worldserver);
|
||||
});
|
||||
return true;
|
||||
@@ -0,0 +1,37 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
|
||||
@@ -7,6 +7,12 @@
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class BabyFollowAdult {
|
||||
|
||||
@@ -25,9 +31,20 @@
|
||||
if (!entityageable.isBaby()) {
|
||||
return false;
|
||||
} else {
|
||||
- AgeableMob entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor);
|
||||
+ LivingEntity entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type
|
||||
|
||||
if (entityageable.closerThan(entityageable1, (double) (executionRange.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) executionRange.getMinValue())) {
|
||||
+ // CraftBukkit start
|
||||
+ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (event.getTarget() == null) {
|
||||
+ memoryaccessor.erase();
|
||||
+ return true;
|
||||
+ }
|
||||
+ entityageable1 = ((CraftLivingEntity) event.getTarget()).getHandle();
|
||||
+ // CraftBukkit end
|
||||
WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityageable1, false), (Float) speed.apply(entityageable), executionRange.getMinValue() - 1);
|
||||
|
||||
memoryaccessor1.set(new EntityTracker(entityageable1, true));
|
||||
@@ -0,0 +1,40 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/Behavior.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/Behavior.java
|
||||
@@ -14,6 +14,9 @@
|
||||
private long endTimestamp;
|
||||
private final int minDuration;
|
||||
private final int maxDuration;
|
||||
+ // Paper start - configurable behavior tick rate and timings
|
||||
+ private final String configKey;
|
||||
+ // Paper end - configurable behavior tick rate and timings
|
||||
|
||||
public Behavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState) {
|
||||
this(requiredMemoryState, 60);
|
||||
@@ -27,6 +30,14 @@
|
||||
this.minDuration = minRunTime;
|
||||
this.maxDuration = maxRunTime;
|
||||
this.entryCondition = requiredMemoryState;
|
||||
+ // Paper start - configurable behavior tick rate and timings
|
||||
+ String key = io.papermc.paper.util.MappingEnvironment.reobf() ? io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()) : this.getClass().getName();
|
||||
+ int lastSeparator = key.lastIndexOf('.');
|
||||
+ if (lastSeparator != -1) {
|
||||
+ key = key.substring(lastSeparator + 1);
|
||||
+ }
|
||||
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
||||
+ // Paper end - configurable behavior tick rate and timings
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,6 +47,12 @@
|
||||
|
||||
@Override
|
||||
public final boolean tryStart(ServerLevel world, E entity, long time) {
|
||||
+ // Paper start - configurable behavior tick rate and timings
|
||||
+ int tickRate = java.util.Objects.requireNonNullElse(world.paperConfig().tickRates.behavior.get(entity.getType(), this.configKey), -1);
|
||||
+ if (tickRate > -1 && time < this.endTimestamp + tickRate) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - configurable behavior tick rate and timings
|
||||
if (this.hasRequiredMemories(entity) && this.checkExtraStartConditions(world, entity)) {
|
||||
this.status = Behavior.Status.RUNNING;
|
||||
int i = this.minDuration + world.getRandom().nextInt(this.maxDuration + 1 - this.minDuration);
|
||||
@@ -0,0 +1,64 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
public static void lookAtEntity(LivingEntity entity, LivingEntity target) {
|
||||
- entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new EntityTracker(target, true)));
|
||||
+ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new EntityTracker(target, true))); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
private static void setWalkAndLookTargetMemoriesToEachOther(LivingEntity first, LivingEntity second, float speed, int completionRange) {
|
||||
@@ -79,8 +79,8 @@
|
||||
public static void setWalkAndLookTargetMemories(LivingEntity entity, PositionTracker target, float speed, int completionRange) {
|
||||
WalkTarget memorytarget = new WalkTarget(target, speed, completionRange);
|
||||
|
||||
- entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) target);
|
||||
- entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) memorytarget);
|
||||
+ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, target); // CraftBukkit - decompile error
|
||||
+ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, memorytarget); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 targetLocation) {
|
||||
@@ -90,6 +90,7 @@
|
||||
}
|
||||
|
||||
public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 targetLocation, Vec3 velocityFactor, float yOffset) {
|
||||
+ if (stack.isEmpty()) return; // CraftBukkit - SPIGOT-4940: no empty loot
|
||||
double d0 = entity.getEyeY() - (double) yOffset;
|
||||
ItemEntity entityitem = new ItemEntity(entity.level(), entity.getX(), d0, entity.getZ(), stack);
|
||||
|
||||
@@ -99,12 +100,19 @@
|
||||
vec3d2 = vec3d2.normalize().multiply(velocityFactor.x, velocityFactor.y, velocityFactor.z);
|
||||
entityitem.setDeltaMovement(vec3d2);
|
||||
entityitem.setDefaultPickUpDelay();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(entity.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
|
||||
+ entityitem.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
entity.level().addFreshEntity(entityitem);
|
||||
}
|
||||
|
||||
public static SectionPos findSectionClosestToVillage(ServerLevel world, SectionPos center, int radius) {
|
||||
int j = world.sectionsToVillage(center);
|
||||
- Stream stream = SectionPos.cube(center, radius).filter((sectionposition1) -> {
|
||||
+ Stream<SectionPos> stream = SectionPos.cube(center, radius).filter((sectionposition1) -> { // CraftBukkit - decompile error
|
||||
return world.sectionsToVillage(sectionposition1) < j;
|
||||
});
|
||||
|
||||
@@ -161,10 +169,10 @@
|
||||
|
||||
return optional.map((uuid) -> {
|
||||
return ((ServerLevel) entity.level()).getEntity(uuid);
|
||||
- }).map((entity) -> {
|
||||
+ }).map((entity1) -> { // Paper - remap fix
|
||||
LivingEntity entityliving1;
|
||||
|
||||
- if (entity instanceof LivingEntity entityliving2) {
|
||||
+ if (entity1 instanceof LivingEntity entityliving2) { // Paper - remap fix
|
||||
entityliving1 = entityliving2;
|
||||
} else {
|
||||
entityliving1 = null;
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/GateBehavior.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/GateBehavior.java
|
||||
@@ -18,7 +18,7 @@
|
||||
private final Set<MemoryModuleType<?>> exitErasedMemories;
|
||||
private final GateBehavior.OrderPolicy orderPolicy;
|
||||
private final GateBehavior.RunningPolicy runningPolicy;
|
||||
- private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>();
|
||||
+ private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>(false); // Paper - Fix Concurrency issue in ShufflingList during worldgen
|
||||
private Behavior.Status status = Behavior.Status.STOPPED;
|
||||
|
||||
public GateBehavior(
|
||||
@@ -0,0 +1,24 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
|
||||
@@ -28,6 +28,21 @@
|
||||
ItemEntity entityitem = (ItemEntity) behaviorbuilder_b.get(memoryaccessor2);
|
||||
|
||||
if (behaviorbuilder_b.tryGet(memoryaccessor3).isEmpty() && startCondition.test(entityliving) && entityitem.closerThan(entityliving, (double) radius) && entityliving.level().getWorldBorder().isWithinBounds(entityitem.blockPosition()) && entityliving.canPickUpLoot()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (entityliving instanceof net.minecraft.world.entity.animal.allay.Allay) {
|
||||
+ org.bukkit.event.entity.EntityTargetEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetEvent(entityliving, entityitem, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!(event.getTarget() instanceof org.bukkit.craftbukkit.entity.CraftItem)) { // Paper - only erase allay memory on non-item targets
|
||||
+ memoryaccessor2.erase();
|
||||
+ return false; // Paper - only erase allay memory on non-item targets
|
||||
+ }
|
||||
+
|
||||
+ entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityitem, false), speed, 0);
|
||||
|
||||
memoryaccessor.set(new EntityTracker(entityitem, true));
|
||||
@@ -0,0 +1,63 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
@@ -22,10 +22,15 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
+import net.minecraft.world.level.gameevent.GameEvent;
|
||||
+
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CropBlock;
|
||||
import net.minecraft.world.level.block.FarmBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
-import net.minecraft.world.level.gameevent.GameEvent;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class HarvestFarmland extends Behavior<Villager> {
|
||||
|
||||
@@ -82,8 +87,8 @@
|
||||
|
||||
protected void start(ServerLevel worldserver, Villager entityvillager, long i) {
|
||||
if (i > this.nextOkStartTime && this.aboveFarmlandPos != null) {
|
||||
- entityvillager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BlockPosTracker(this.aboveFarmlandPos)));
|
||||
- entityvillager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1)));
|
||||
+ entityvillager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BlockPosTracker(this.aboveFarmlandPos))); // CraftBukkit - decompile error
|
||||
+ entityvillager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
}
|
||||
@@ -103,7 +108,9 @@
|
||||
Block block1 = world.getBlockState(this.aboveFarmlandPos.below()).getBlock();
|
||||
|
||||
if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata)) {
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(entity, this.aboveFarmlandPos, iblockdata.getFluidState().createLegacyBlock())) { // CraftBukkit // Paper - fix wrong block state
|
||||
world.destroyBlock(this.aboveFarmlandPos, true, entity);
|
||||
+ } // CraftBukkit
|
||||
}
|
||||
|
||||
if (iblockdata.isAir() && block1 instanceof FarmBlock && entity.hasFarmSeeds()) {
|
||||
@@ -120,9 +127,11 @@
|
||||
BlockItem itemblock = (BlockItem) item;
|
||||
BlockState iblockdata1 = itemblock.getBlock().defaultBlockState();
|
||||
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(entity, this.aboveFarmlandPos, iblockdata1)) { // CraftBukkit
|
||||
world.setBlockAndUpdate(this.aboveFarmlandPos, iblockdata1);
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(entity, iblockdata1));
|
||||
flag = true;
|
||||
+ } // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +151,8 @@
|
||||
this.aboveFarmlandPos = this.getValidFarmland(world);
|
||||
if (this.aboveFarmlandPos != null) {
|
||||
this.nextOkStartTime = time + 20L;
|
||||
- entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1)));
|
||||
- entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BlockPosTracker(this.aboveFarmlandPos)));
|
||||
+ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error
|
||||
+ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BlockPosTracker(this.aboveFarmlandPos))); // CraftBukkit - decompile error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
|
||||
@@ -61,6 +61,13 @@
|
||||
DoorBlock blockdoor = (DoorBlock) iblockdata.getBlock();
|
||||
|
||||
if (!blockdoor.isOpen(iblockdata)) {
|
||||
+ // CraftBukkit start - entities opening doors
|
||||
+ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition));
|
||||
+ entityliving.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
blockdoor.setOpen(entityliving, worldserver, iblockdata, blockposition, true);
|
||||
}
|
||||
|
||||
@@ -76,6 +83,13 @@
|
||||
DoorBlock blockdoor1 = (DoorBlock) iblockdata1.getBlock();
|
||||
|
||||
if (!blockdoor1.isOpen(iblockdata1)) {
|
||||
+ // CraftBukkit start - entities opening doors
|
||||
+ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition1));
|
||||
+ entityliving.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
blockdoor1.setOpen(entityliving, worldserver, iblockdata1, blockposition1, true);
|
||||
optional = InteractWithDoor.rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition1);
|
||||
}
|
||||
@@ -129,7 +143,7 @@
|
||||
}
|
||||
|
||||
private static boolean areOtherMobsComingThroughDoor(LivingEntity entity, BlockPos pos, Optional<List<LivingEntity>> otherMobs) {
|
||||
- return otherMobs.isEmpty() ? false : ((List) otherMobs.get()).stream().filter((entityliving1) -> {
|
||||
+ return otherMobs.isEmpty() ? false : (otherMobs.get()).stream().filter((entityliving1) -> { // CraftBukkit - decompile error
|
||||
return entityliving1.getType() == entity.getType();
|
||||
}).filter((entityliving1) -> {
|
||||
return pos.closerToCenterThan(entityliving1.position(), 2.0D);
|
||||
@@ -0,0 +1,73 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java
|
||||
@@ -13,6 +13,7 @@
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
@@ -30,6 +31,10 @@
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class PrepareRamNearestTarget<E extends PathfinderMob> extends Behavior<E> {
|
||||
|
||||
@@ -63,6 +68,13 @@
|
||||
return this.ramTargeting.test(worldserver, entitycreature, entityliving);
|
||||
});
|
||||
}).ifPresent((entityliving) -> {
|
||||
+ // CraftBukkit start
|
||||
+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entitycreature, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
|
||||
+ if (event.isCancelled() || event.getTarget() == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle();
|
||||
+ // CraftBukkit end
|
||||
this.chooseRamPosition(entitycreature, entityliving);
|
||||
});
|
||||
}
|
||||
@@ -72,7 +84,7 @@
|
||||
|
||||
if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RAM_TARGET)) {
|
||||
world.broadcastEntityEvent(entity, (byte) 59);
|
||||
- behaviorcontroller.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, (Object) this.getCooldownOnFail.applyAsInt(entity));
|
||||
+ behaviorcontroller.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, this.getCooldownOnFail.applyAsInt(entity)); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,8 +95,8 @@
|
||||
|
||||
protected void tick(ServerLevel worldserver, E e0, long i) {
|
||||
if (!this.ramCandidate.isEmpty()) {
|
||||
- e0.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0)));
|
||||
- e0.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new EntityTracker(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget(), true)));
|
||||
+ e0.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0))); // CraftBukkit - decompile error
|
||||
+ e0.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new EntityTracker(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget(), true))); // CraftBukkit - decompile error
|
||||
boolean flag = !((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget().blockPosition().equals(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition());
|
||||
|
||||
if (flag) {
|
||||
@@ -101,7 +113,7 @@
|
||||
}
|
||||
|
||||
if (i - (Long) this.reachedRamPositionTimestamp.get() >= (long) this.ramPrepareTime) {
|
||||
- e0.getBrain().setMemory(MemoryModuleType.RAM_TARGET, (Object) this.getEdgeOfBlock(blockposition, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition()));
|
||||
+ e0.getBrain().setMemory(MemoryModuleType.RAM_TARGET, this.getEdgeOfBlock(blockposition, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition())); // CraftBukkit - decompile error
|
||||
worldserver.playSound((Player) null, (Entity) e0, (SoundEvent) this.getPrepareRamSound.apply(e0), SoundSource.NEUTRAL, 1.0F, e0.getVoicePitch());
|
||||
this.ramCandidate = Optional.empty();
|
||||
}
|
||||
@@ -153,7 +165,7 @@
|
||||
}
|
||||
|
||||
PathNavigation navigationabstract = entity.getNavigation();
|
||||
- Stream stream = list.stream();
|
||||
+ Stream<BlockPos> stream = list.stream(); // CraftBukkit - decompile error
|
||||
BlockPos blockposition1 = entity.blockPosition();
|
||||
|
||||
Objects.requireNonNull(blockposition1);
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/RamTarget.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/RamTarget.java
|
||||
@@ -89,7 +89,7 @@
|
||||
float f = 0.25F * (float)(i - j);
|
||||
float g = Mth.clamp(entity.getSpeed() * 1.65F, 0.2F, 3.0F) + f;
|
||||
float h = livingEntity.isDamageSourceBlocked(world.damageSources().mobAttack(entity)) ? 0.5F : 1.0F;
|
||||
- livingEntity.knockback((double)(h * g) * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z());
|
||||
+ livingEntity.knockback(h * g * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z(), entity, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
|
||||
this.finishRam(world, entity);
|
||||
world.playSound(null, entity, this.getImpactSound.apply(entity), SoundSource.NEUTRAL, 1.0F, 1.0F);
|
||||
} else if (this.hasRammedHornBreakingBlock(world, entity)) {
|
||||
@@ -0,0 +1,31 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/ResetProfession.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/ResetProfession.java
|
||||
@@ -6,6 +6,12 @@
|
||||
import net.minecraft.world.entity.npc.VillagerData;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftVillager;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.VillagerCareerChangeEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ResetProfession {
|
||||
|
||||
public ResetProfession() {}
|
||||
@@ -17,7 +23,14 @@
|
||||
VillagerData villagerdata = entityvillager.getVillagerData();
|
||||
|
||||
if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && entityvillager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) {
|
||||
- entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(VillagerProfession.NONE));
|
||||
+ // CraftBukkit start
|
||||
+ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), VillagerCareerChangeEvent.ChangeReason.LOSING_JOB);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession())));
|
||||
+ // CraftBukkit end
|
||||
entityvillager.refreshBrain(worldserver);
|
||||
return true;
|
||||
} else {
|
||||
@@ -0,0 +1,44 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/ShufflingList.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/ShufflingList.java
|
||||
@@ -16,12 +16,25 @@
|
||||
public class ShufflingList<U> implements Iterable<U> {
|
||||
protected final List<ShufflingList.WeightedEntry<U>> entries;
|
||||
private final RandomSource random = RandomSource.create();
|
||||
+ private final boolean isUnsafe; // Paper - Fix Concurrency issue in ShufflingList during worldgen
|
||||
|
||||
public ShufflingList() {
|
||||
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen
|
||||
+ this(true);
|
||||
+ }
|
||||
+ public ShufflingList(boolean isUnsafe) {
|
||||
+ this.isUnsafe = isUnsafe;
|
||||
+ // Paper end - Fix Concurrency issue in ShufflingList during worldgen
|
||||
this.entries = Lists.newArrayList();
|
||||
}
|
||||
|
||||
private ShufflingList(List<ShufflingList.WeightedEntry<U>> list) {
|
||||
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen
|
||||
+ this(list, true);
|
||||
+ }
|
||||
+ private ShufflingList(List<ShufflingList.WeightedEntry<U>> list, boolean isUnsafe) {
|
||||
+ this.isUnsafe = isUnsafe;
|
||||
+ // Paper end - Fix Concurrency issue in ShufflingList during worldgen
|
||||
this.entries = Lists.newArrayList(list);
|
||||
}
|
||||
|
||||
@@ -35,9 +48,12 @@
|
||||
}
|
||||
|
||||
public ShufflingList<U> shuffle() {
|
||||
- this.entries.forEach(entry -> entry.setRandom(this.random.nextFloat()));
|
||||
- this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
|
||||
- return this;
|
||||
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen
|
||||
+ List<ShufflingList.WeightedEntry<U>> list = this.isUnsafe ? Lists.newArrayList(this.entries) : this.entries;
|
||||
+ list.forEach(entry -> entry.setRandom(this.random.nextFloat()));
|
||||
+ list.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
|
||||
+ return this.isUnsafe ? new ShufflingList<>(list, this.isUnsafe) : this;
|
||||
+ // Paper end - Fix Concurrency issue in ShufflingList during worldgen
|
||||
}
|
||||
|
||||
public Stream<U> stream() {
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
@@ -42,7 +42,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- BlockState blockState = world.getBlockState(globalPos.pos());
|
||||
+ BlockState blockState = world.getBlockStateIfLoaded(globalPos.pos()); // Paper - Prevent sync chunk loads when villagers try to find beds
|
||||
+ if (blockState == null) { return false; } // Paper - Prevent sync chunk loads when villagers try to find beds
|
||||
return globalPos.pos().closerToCenterThan(entity.position(), 2.0) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
import java.util.Optional;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class StartAttacking {
|
||||
|
||||
@@ -34,6 +39,17 @@
|
||||
if (!entityinsentient.canAttack(entityliving)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (event.getTarget() == null) {
|
||||
+ memoryaccessor.erase();
|
||||
+ return true;
|
||||
+ }
|
||||
+ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle();
|
||||
+ // CraftBukkit end
|
||||
memoryaccessor.set(entityliving);
|
||||
memoryaccessor1.erase();
|
||||
return true;
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java
|
||||
@@ -7,6 +7,12 @@
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class StopAttackingIfTargetInvalid {
|
||||
|
||||
private static final int TIMEOUT_TO_GET_WITHIN_ATTACK_RANGE = 200;
|
||||
@@ -40,6 +46,30 @@
|
||||
if (entityinsentient.canAttack(entityliving) && (!shouldForgetIfTargetUnreachable || !StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !condition.test(worldserver, entityliving)) {
|
||||
return true;
|
||||
} else {
|
||||
+ // Paper start - better track target change reason
|
||||
+ final EntityTargetEvent.TargetReason reason;
|
||||
+ if (!entityinsentient.canAttack(entityliving)) {
|
||||
+ reason = EntityTargetEvent.TargetReason.TARGET_INVALID;
|
||||
+ } else if (shouldForgetIfTargetUnreachable && StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) {
|
||||
+ reason = EntityTargetEvent.TargetReason.FORGOT_TARGET;
|
||||
+ } else if (!entityliving.isAlive()) {
|
||||
+ reason = EntityTargetEvent.TargetReason.TARGET_DIED;
|
||||
+ } else if (entityliving.level() != entityinsentient.level()) {
|
||||
+ reason = EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL;
|
||||
+ } else {
|
||||
+ reason = EntityTargetEvent.TargetReason.TARGET_INVALID;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+ // CraftBukkit start
|
||||
+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, null, reason); // Paper
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (event.getTarget() != null) {
|
||||
+ entityinsentient.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle());
|
||||
+ return true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
callback.accept(worldserver, entityinsentient, entityliving);
|
||||
memoryaccessor.erase();
|
||||
return true;
|
||||
@@ -0,0 +1,15 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/TryLaySpawnOnWaterNearLand.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/TryLaySpawnOnWaterNearLand.java
|
||||
@@ -39,6 +39,12 @@
|
||||
if (worldserver.getBlockState(blockposition2).isAir()) {
|
||||
BlockState iblockdata = frogSpawn.defaultBlockState();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityliving, blockposition2, iblockdata)) {
|
||||
+ memoryaccessor2.erase();
|
||||
+ return true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
worldserver.setBlock(blockposition2, iblockdata, 3);
|
||||
worldserver.gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition2, GameEvent.Context.of(entityliving, iblockdata));
|
||||
worldserver.playSound((Player) null, (Entity) entityliving, SoundEvents.FROG_LAY_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
|
||||
@@ -42,7 +42,7 @@
|
||||
Pair.of(1, new MoveToTargetSink()),
|
||||
Pair.of(2, PoiCompetitorScan.create()),
|
||||
Pair.of(3, new LookAndFollowTradingPlayerSink(speed)),
|
||||
- Pair.of(5, GoToWantedItem.create(speed, false, 4)),
|
||||
+ Pair.of(5, GoToWantedItem.create(villager -> !villager.isSleeping(), speed, false, 4)), // Paper - Fix MC-157464
|
||||
Pair.of(
|
||||
6,
|
||||
AcquirePoi.create(
|
||||
@@ -0,0 +1,42 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java
|
||||
@@ -17,6 +17,10 @@
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiTypes;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class VillagerMakeLove extends Behavior<Villager> {
|
||||
|
||||
@@ -114,11 +118,17 @@
|
||||
if (entityvillager2 == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
- parent.setAge(6000);
|
||||
- partner.setAge(6000);
|
||||
entityvillager2.setAge(-24000);
|
||||
entityvillager2.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F);
|
||||
- world.addFreshEntityWithPassengers(entityvillager2);
|
||||
+ // CraftBukkit start - call EntityBreedEvent
|
||||
+ if (CraftEventFactory.callEntityBreedEvent(entityvillager2, parent, partner, null, null, 0).isCancelled()) {
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Move age setting down
|
||||
+ parent.setAge(6000);
|
||||
+ partner.setAge(6000);
|
||||
+ world.addFreshEntityWithPassengers(entityvillager2, CreatureSpawnEvent.SpawnReason.BREEDING);
|
||||
+ // CraftBukkit end
|
||||
world.broadcastEntityEvent(entityvillager2, (byte) 12);
|
||||
return Optional.of(entityvillager2);
|
||||
}
|
||||
@@ -127,6 +137,6 @@
|
||||
private void giveBedToChild(ServerLevel world, Villager child, BlockPos pos) {
|
||||
GlobalPos globalpos = GlobalPos.of(world.dimension(), pos);
|
||||
|
||||
- child.getBrain().setMemory(MemoryModuleType.HOME, (Object) globalpos);
|
||||
+ child.getBrain().setMemory(MemoryModuleType.HOME, globalpos); // CraftBukkit - decompile error
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/WorkAtComposter.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/WorkAtComposter.java
|
||||
@@ -86,7 +86,9 @@
|
||||
simpleContainer.removeItemType(Items.WHEAT, m);
|
||||
ItemStack itemStack = simpleContainer.addItem(new ItemStack(Items.BREAD, l));
|
||||
if (!itemStack.isEmpty()) {
|
||||
+ villager.forceDrops = true; // Paper - Add missing forceDrop toggles
|
||||
villager.spawnAtLocation(world, itemStack, 0.5F);
|
||||
+ villager.forceDrops = false; // Paper - Add missing forceDrop toggles
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/warden/Digging.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/warden/Digging.java
|
||||
@@ -10,6 +10,10 @@
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus;
|
||||
import net.minecraft.world.entity.monster.warden.Warden;
|
||||
|
||||
+// CraftBukkit start - imports
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class Digging<E extends Warden> extends Behavior<E> {
|
||||
|
||||
public Digging(int duration) {
|
||||
@@ -37,7 +41,7 @@
|
||||
|
||||
protected void stop(ServerLevel worldserver, E e0, long i) {
|
||||
if (e0.getRemovalReason() == null) {
|
||||
- e0.remove(Entity.RemovalReason.DISCARDED);
|
||||
+ e0.remove(Entity.RemovalReason.DISCARDED, EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - Add bukkit remove cause
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java
|
||||
@@ -83,7 +83,7 @@
|
||||
if (target.hurtServer(world, world.damageSources().sonicBoom(entity), 10.0F)) {
|
||||
double d = 0.5 * (1.0 - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
|
||||
double e = 2.5 * (1.0 - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
|
||||
- target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e);
|
||||
+ target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e, entity); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
@@ -72,9 +72,16 @@
|
||||
}
|
||||
|
||||
if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) {
|
||||
+ // CraftBukkit start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos, this.mob.level().getFluidState(this.doorPos).createLegacyBlock()).isCancelled()) { // Paper - fix wrong block state
|
||||
+ this.start();
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ final net.minecraft.world.level.block.state.BlockState oldState = this.mob.level().getBlockState(this.doorPos); // Paper - fix MC-263999
|
||||
this.mob.level().removeBlock(this.doorPos, false);
|
||||
this.mob.level().levelEvent(1021, this.doorPos, 0);
|
||||
- this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos)));
|
||||
+ this.mob.level().levelEvent(2001, this.doorPos, Block.getId(oldState)); // Paper - fix MC-263999
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
@@ -11,6 +11,10 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.predicate.BlockStatePredicate;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class EatBlockGoal extends Goal {
|
||||
|
||||
private static final int EAT_ANIMATION_TICKS = 40;
|
||||
@@ -27,6 +31,11 @@
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
+ // Paper start - Fix MC-210802
|
||||
+ if (!((net.minecraft.server.level.ServerLevel) this.level).chunkSource.chunkMap.anyPlayerCloseEnoughForSpawning(this.mob.chunkPosition())) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.mob.getRandom().nextInt(this.mob.isBaby() ? 50 : 1000) != 0) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -63,8 +72,9 @@
|
||||
if (this.eatAnimationTick == this.adjustedTickDelay(4)) {
|
||||
BlockPos blockposition = this.mob.blockPosition();
|
||||
|
||||
- if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) {
|
||||
- if (getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ final BlockState blockState = this.level.getBlockState(blockposition); // Paper - fix wrong block state
|
||||
+ if (EatBlockGoal.IS_TALL_GRASS.test(blockState)) { // Paper - fix wrong block state
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state
|
||||
this.level.destroyBlock(blockposition, false);
|
||||
}
|
||||
|
||||
@@ -73,7 +83,7 @@
|
||||
BlockPos blockposition1 = blockposition.below();
|
||||
|
||||
if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) {
|
||||
- if (getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.DIRT.defaultBlockState(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state
|
||||
this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState()));
|
||||
this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/FloatGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/FloatGoal.java
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
public FloatGoal(Mob mob) {
|
||||
this.mob = mob;
|
||||
+ if (mob.getCommandSenderWorld().paperConfig().entities.behavior.spawnerNerfedMobsShouldJump) mob.goalFloat = this; // Paper - Allow nerfed mobs to jump and float
|
||||
this.setFlags(EnumSet.of(Goal.Flag.JUMP));
|
||||
mob.getNavigation().setCanFloat(true);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
|
||||
@@ -72,7 +72,7 @@
|
||||
public void tick() {
|
||||
boolean bl = this.tamable.shouldTryTeleportToOwner();
|
||||
if (!bl) {
|
||||
- this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamable.getMaxHeadXRot());
|
||||
+ if (this.tamable.distanceToSqr(this.owner) <= 16 * 16) this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamable.getMaxHeadXRot()); // Paper - Limit pet look distance
|
||||
}
|
||||
|
||||
if (--this.timeToRecalcPath <= 0) {
|
||||
@@ -0,0 +1,39 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/Goal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/Goal.java
|
||||
@@ -46,6 +46,16 @@
|
||||
return this.flags;
|
||||
}
|
||||
|
||||
+ // Paper start - Mob Goal API
|
||||
+ public boolean hasFlag(final Goal.Flag flag) {
|
||||
+ return this.flags.contains(flag);
|
||||
+ }
|
||||
+
|
||||
+ public void addFlag(final Goal.Flag flag) {
|
||||
+ this.flags.add(flag);
|
||||
+ }
|
||||
+ // Paper end - Mob Goal API
|
||||
+
|
||||
protected int adjustedTickDelay(int ticks) {
|
||||
return this.requiresUpdateEveryTick() ? ticks : reducedTickDelay(ticks);
|
||||
}
|
||||
@@ -62,7 +72,19 @@
|
||||
return (ServerLevel)world;
|
||||
}
|
||||
|
||||
+ // 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);
|
||||
+ }
|
||||
+ //noinspection unchecked
|
||||
+ return (com.destroystokyo.paper.entity.ai.Goal<T>) this.vanillaGoal;
|
||||
+ }
|
||||
+ // Paper end - Mob goal api
|
||||
+
|
||||
public static enum Flag {
|
||||
+ UNKNOWN_BEHAVIOR, // Paper - add UNKNOWN_BEHAVIOR
|
||||
MOVE,
|
||||
LOOK,
|
||||
JUMP,
|
||||
@@ -0,0 +1,55 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
@@ -21,6 +21,10 @@
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
|
||||
@@ -97,6 +101,11 @@
|
||||
}
|
||||
|
||||
if (this.ticksSinceReachedGoal > 60) {
|
||||
+ // CraftBukkit start - Step on eggs
|
||||
+ if (!CraftEventFactory.callEntityInteractEvent(this.removerMob, CraftBlock.at(world, blockposition1))) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
world.removeBlock(blockposition1, false);
|
||||
if (!world.isClientSide) {
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
@@ -118,7 +127,9 @@
|
||||
|
||||
@Nullable
|
||||
private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) {
|
||||
- if (world.getBlockState(pos).is(this.blockToRemove)) {
|
||||
+ net.minecraft.world.level.block.state.BlockState block = world.getBlockStateIfLoaded(pos); // Paper - Prevent AI rules from loading chunks
|
||||
+ if (block == null) return null; // Paper - Prevent AI rules from loading chunks
|
||||
+ if (block.is(this.blockToRemove)) { // Paper - Prevent AI rules from loading chunks
|
||||
return pos;
|
||||
} else {
|
||||
BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()};
|
||||
@@ -128,7 +139,8 @@
|
||||
for (int j = 0; j < i; ++j) {
|
||||
BlockPos blockposition1 = ablockposition1[j];
|
||||
|
||||
- if (world.getBlockState(blockposition1).is(this.blockToRemove)) {
|
||||
+ net.minecraft.world.level.block.state.BlockState block2 = world.getBlockStateIfLoaded(blockposition1); // Paper - Prevent AI rules from loading chunks
|
||||
+ if (block2 != null && block2.is(this.blockToRemove)) { // Paper - Prevent AI rules from loading chunks
|
||||
return blockposition1;
|
||||
}
|
||||
}
|
||||
@@ -139,7 +151,7 @@
|
||||
|
||||
@Override
|
||||
protected boolean isValidTarget(LevelReader world, BlockPos pos) {
|
||||
- ChunkAccess ichunkaccess = world.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false);
|
||||
+ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper - Prevent AI rules from loading chunks
|
||||
|
||||
return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java
|
||||
@@ -6,6 +6,10 @@
|
||||
import net.minecraft.world.entity.animal.horse.AbstractHorse;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class RunAroundLikeCrazyGoal extends Goal {
|
||||
|
||||
@@ -63,7 +67,7 @@
|
||||
int i = this.horse.getTemper();
|
||||
int j = this.horse.getMaxTemper();
|
||||
|
||||
- if (j > 0 && this.horse.getRandom().nextInt(j) < i) {
|
||||
+ if (j > 0 && this.horse.getRandom().nextInt(j) < i && !CraftEventFactory.callEntityTameEvent(this.horse, ((CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent
|
||||
this.horse.tameWithName(entityhuman);
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java
|
||||
@@ -22,7 +22,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()) {
|
||||
@@ -0,0 +1,17 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/SwellGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/SwellGoal.java
|
||||
@@ -21,7 +21,14 @@
|
||||
return this.creeper.getSwellDir() > 0 || livingEntity != null && this.creeper.distanceToSqr(livingEntity) < 9.0;
|
||||
}
|
||||
|
||||
+ // Paper start - Fix MC-179072
|
||||
@Override
|
||||
+ public boolean canContinueToUse() {
|
||||
+ return !net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(this.creeper.getTarget()) && canUse();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ @Override
|
||||
public void start() {
|
||||
this.creeper.getNavigation().stop();
|
||||
this.target = this.creeper.getTarget();
|
||||
@@ -0,0 +1,44 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
@@ -8,9 +8,15 @@
|
||||
import net.minecraft.world.entity.PathfinderMob;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
|
||||
-import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class TemptGoal extends Goal {
|
||||
|
||||
private static final TargetingConditions TEMPT_TARGETING = TargetingConditions.forNonCombat().ignoreLineOfSight();
|
||||
@@ -23,7 +29,7 @@
|
||||
private double pRotX;
|
||||
private double pRotY;
|
||||
@Nullable
|
||||
- protected Player player;
|
||||
+ protected LivingEntity player; // CraftBukkit
|
||||
private int calmDown;
|
||||
private boolean isRunning;
|
||||
private final Predicate<ItemStack> items;
|
||||
@@ -47,6 +53,15 @@
|
||||
return false;
|
||||
} else {
|
||||
this.player = getServerLevel((Entity) this.mob).getNearestPlayer(this.targetingConditions.range(this.mob.getAttributeValue(Attributes.TEMPT_RANGE)), this.mob);
|
||||
+ // CraftBukkit start
|
||||
+ if (this.player != null) {
|
||||
+ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, EntityTargetEvent.TargetReason.TEMPT);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ this.player = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return this.player != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java
|
||||
@@ -61,7 +61,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
|
||||
super.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/target/HurtByTargetGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/target/HurtByTargetGoal.java
|
||||
@@ -67,7 +67,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.targetMob = this.mob.getTarget();
|
||||
this.timestamp = this.mob.getLastHurtByMobTimestamp();
|
||||
this.unseenMemoryTicks = 300;
|
||||
@@ -114,6 +114,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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
|
||||
@@ -70,7 +70,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
|
||||
super.start();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/target/OwnerHurtByTargetGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/target/OwnerHurtByTargetGoal.java
|
||||
@@ -38,7 +38,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
|
||||
LivingEntity entityliving = this.tameAnimal.getOwner();
|
||||
|
||||
if (entityliving != null) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/target/OwnerHurtTargetGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/target/OwnerHurtTargetGoal.java
|
||||
@@ -38,7 +38,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
|
||||
LivingEntity entityliving = this.tameAnimal.getOwner();
|
||||
|
||||
if (entityliving != null) {
|
||||
@@ -0,0 +1,30 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/target/TargetGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/target/TargetGoal.java
|
||||
@@ -10,6 +10,9 @@
|
||||
import net.minecraft.world.level.pathfinder.Node;
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class TargetGoal extends Goal {
|
||||
|
||||
@@ -69,7 +72,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- this.mob.setTarget(entityliving);
|
||||
+ this.mob.setTarget(entityliving, EntityTargetEvent.TargetReason.CLOSEST_ENTITY, true); // CraftBukkit
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -89,7 +92,7 @@
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
- this.mob.setTarget((LivingEntity) null);
|
||||
+ this.mob.setTarget((LivingEntity) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit
|
||||
this.targetMob = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/world/entity/ai/gossip/GossipContainer.java
|
||||
+++ b/net/minecraft/world/entity/ai/gossip/GossipContainer.java
|
||||
@@ -216,6 +216,43 @@
|
||||
public void remove(GossipType gossipType) {
|
||||
this.entries.removeInt(gossipType);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Add villager reputation API
|
||||
+ private static final GossipType[] TYPES = GossipType.values();
|
||||
+ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() {
|
||||
+ Map<com.destroystokyo.paper.entity.villager.ReputationType, Integer> map = new java.util.EnumMap<>(com.destroystokyo.paper.entity.villager.ReputationType.class);
|
||||
+ for (Object2IntMap.Entry<GossipType> type : this.entries.object2IntEntrySet()) {
|
||||
+ map.put(toApi(type.getKey()), type.getIntValue());
|
||||
+ }
|
||||
+
|
||||
+ return new com.destroystokyo.paper.entity.villager.Reputation(map);
|
||||
+ }
|
||||
+
|
||||
+ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) {
|
||||
+ for (GossipType type : TYPES) {
|
||||
+ com.destroystokyo.paper.entity.villager.ReputationType api = toApi(type);
|
||||
+
|
||||
+ if (rep.hasReputationSet(api)) {
|
||||
+ int reputation = rep.getReputation(api);
|
||||
+ if (reputation == 0) {
|
||||
+ this.entries.removeInt(type);
|
||||
+ } else {
|
||||
+ this.entries.put(type, reputation);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static com.destroystokyo.paper.entity.villager.ReputationType toApi(GossipType type) {
|
||||
+ return switch (type) {
|
||||
+ case MAJOR_NEGATIVE -> com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE;
|
||||
+ case MINOR_NEGATIVE -> com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE;
|
||||
+ case MINOR_POSITIVE -> com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE;
|
||||
+ case MAJOR_POSITIVE -> com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE;
|
||||
+ case TRADING -> com.destroystokyo.paper.entity.villager.ReputationType.TRADING;
|
||||
+ };
|
||||
+ }
|
||||
+ // Paper end - Add villager reputation API
|
||||
}
|
||||
|
||||
static record GossipEntry(UUID target, GossipType type, int value) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
@Override
|
||||
public Path createPath(Entity entity, int distance) {
|
||||
- return this.createPath(entity.blockPosition(), distance);
|
||||
+ return this.createPath(entity.blockPosition(), entity, distance); // Paper - EntityPathfindEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Path createPath(BlockPos target, int distance) {
|
||||
+ public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper - EntityPathfindEvent
|
||||
LevelChunk levelChunk = this.level
|
||||
.getChunkSource()
|
||||
.getChunkNow(SectionPos.blockToSectionCoord(target.getX()), SectionPos.blockToSectionCoord(target.getZ()));
|
||||
@@ -56,7 +56,7 @@
|
||||
}
|
||||
|
||||
if (mutableBlockPos.getY() > this.level.getMinY()) {
|
||||
- return super.createPath(mutableBlockPos.above(), distance);
|
||||
+ return super.createPath(mutableBlockPos.above(), entity, distance); // Paper - EntityPathfindEvent
|
||||
}
|
||||
|
||||
mutableBlockPos.setY(target.getY() + 1);
|
||||
@@ -69,7 +69,7 @@
|
||||
}
|
||||
|
||||
if (!levelChunk.getBlockState(target).isSolid()) {
|
||||
- return super.createPath(target, distance);
|
||||
+ return super.createPath(target, entity, distance); // Paper - EntityPathfindEvent
|
||||
} else {
|
||||
BlockPos.MutableBlockPos mutableBlockPos2 = target.mutable().move(Direction.UP);
|
||||
|
||||
@@ -77,14 +77,14 @@
|
||||
mutableBlockPos2.move(Direction.UP);
|
||||
}
|
||||
|
||||
- return super.createPath(mutableBlockPos2.immutable(), distance);
|
||||
+ return super.createPath(mutableBlockPos2.immutable(), entity, distance); // Paper - EntityPathfindEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createPath(Entity entity, int distance) {
|
||||
- return this.createPath(entity.blockPosition(), distance);
|
||||
+ return this.createPath(entity.blockPosition(), entity, distance); // Paper - EntityPathfindEvent
|
||||
}
|
||||
|
||||
private int getSurfaceY() {
|
||||
@@ -0,0 +1,104 @@
|
||||
--- a/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
@@ -125,8 +125,14 @@
|
||||
|
||||
@Nullable
|
||||
public Path createPath(BlockPos target, int distance) {
|
||||
- return this.createPath(ImmutableSet.of(target), 8, false, distance);
|
||||
+ // Paper start - EntityPathfindEvent
|
||||
+ return this.createPath(target, null, distance);
|
||||
}
|
||||
+ @Nullable
|
||||
+ public Path createPath(BlockPos target, @Nullable Entity entity, int distance) {
|
||||
+ return this.createPath(ImmutableSet.of(target), entity, 8, false, distance);
|
||||
+ // Paper end - EntityPathfindEvent
|
||||
+ }
|
||||
|
||||
@Nullable
|
||||
public Path createPath(BlockPos target, int minDistance, int maxDistance) {
|
||||
@@ -135,7 +141,7 @@
|
||||
|
||||
@Nullable
|
||||
public Path createPath(Entity entity, int distance) {
|
||||
- return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance);
|
||||
+ return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper - EntityPathfindEvent
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -145,6 +151,17 @@
|
||||
|
||||
@Nullable
|
||||
protected Path createPath(Set<BlockPos> positions, int range, boolean useHeadPos, int distance, float followRange) {
|
||||
+ // Paper start - EntityPathfindEvent
|
||||
+ return this.createPath(positions, null, range, useHeadPos, distance, followRange);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ protected Path createPath(Set<BlockPos> positions, @Nullable Entity target, int range, boolean useHeadPos, int distance) {
|
||||
+ return this.createPath(positions, target, range, useHeadPos, distance, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE));
|
||||
+ }
|
||||
+
|
||||
+ @Nullable protected Path createPath(Set<BlockPos> positions, @Nullable Entity target, int range, boolean useHeadPos, int distance, float followRange) {
|
||||
+ // Paper end - EntityPathfindEvent
|
||||
if (positions.isEmpty()) {
|
||||
return null;
|
||||
} else if (this.mob.getY() < (double)this.level.getMinY()) {
|
||||
@@ -154,6 +171,23 @@
|
||||
} else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) {
|
||||
return this.path;
|
||||
} else {
|
||||
+ // Paper start - EntityPathfindEvent
|
||||
+ boolean copiedSet = false;
|
||||
+ for (BlockPos possibleTarget : positions) {
|
||||
+ if (!this.mob.getCommandSenderWorld().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()) {
|
||||
+ if (!copiedSet) {
|
||||
+ copiedSet = true;
|
||||
+ positions = new java.util.HashSet<>(positions);
|
||||
+ }
|
||||
+ // note: since we copy the set this remove call is safe, since we're iterating over the old copy
|
||||
+ positions.remove(possibleTarget);
|
||||
+ if (positions.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - EntityPathfindEvent
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push("pathfind");
|
||||
BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition();
|
||||
@@ -175,13 +209,33 @@
|
||||
return this.moveTo(this.createPath(x, y, z, 1), speed);
|
||||
}
|
||||
|
||||
+ // Paper start - Perf: Optimise pathfinding
|
||||
+ private int lastFailure = 0;
|
||||
+ private int pathfindFailures = 0;
|
||||
+ // Paper end - Perf: Optimise pathfinding
|
||||
+
|
||||
public boolean moveTo(double x, double y, double z, int distance, double speed) {
|
||||
return this.moveTo(this.createPath(x, y, z, distance), speed);
|
||||
}
|
||||
|
||||
public boolean moveTo(Entity entity, double speed) {
|
||||
+ // Paper start - Perf: Optimise pathfinding
|
||||
+ if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimise pathfinding
|
||||
Path path = this.createPath(entity, 1);
|
||||
- return path != null && this.moveTo(path, speed);
|
||||
+ // Paper start - Perf: Optimise pathfinding
|
||||
+ if (path != null && this.moveTo(path, speed)) {
|
||||
+ this.lastFailure = 0;
|
||||
+ this.pathfindFailures = 0;
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ this.pathfindFailures++;
|
||||
+ this.lastFailure = net.minecraft.server.MinecraftServer.currentTick;
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimise pathfinding
|
||||
}
|
||||
|
||||
public boolean moveTo(@Nullable Path path, double speed) {
|
||||
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
|
||||
@@ -16,9 +16,9 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Path createPath(BlockPos target, int distance) {
|
||||
+ public Path createPath(BlockPos target, @Nullable Entity entity, int distance) { // Paper - EntityPathfindEvent
|
||||
this.pathToPosition = target;
|
||||
- return super.createPath(target, distance);
|
||||
+ return super.createPath(target, entity, distance); // Paper - EntityPathfindEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,34 @@
|
||||
--- a/net/minecraft/world/entity/ai/sensing/Sensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/Sensor.java
|
||||
@@ -29,8 +29,19 @@
|
||||
.ignoreInvisibilityTesting();
|
||||
private final int scanRate;
|
||||
private long timeToTick;
|
||||
+ // Paper start - configurable sensor tick rate and timings
|
||||
+ private final String configKey;
|
||||
+ // Paper end
|
||||
|
||||
public Sensor(int senseInterval) {
|
||||
+ // Paper start - configurable sensor tick rate and timings
|
||||
+ String key = io.papermc.paper.util.MappingEnvironment.reobf() ? io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()) : this.getClass().getName();
|
||||
+ int lastSeparator = key.lastIndexOf('.');
|
||||
+ if (lastSeparator != -1) {
|
||||
+ key = key.substring(lastSeparator + 1);
|
||||
+ }
|
||||
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
||||
+ // Paper end
|
||||
this.scanRate = senseInterval;
|
||||
this.timeToTick = (long)RANDOM.nextInt(senseInterval);
|
||||
}
|
||||
@@ -41,8 +52,10 @@
|
||||
|
||||
public final void tick(ServerLevel world, E entity) {
|
||||
if (--this.timeToTick <= 0L) {
|
||||
- this.timeToTick = (long)this.scanRate;
|
||||
+ // Paper start - configurable sensor tick rate and timings
|
||||
+ this.timeToTick = java.util.Objects.requireNonNullElse(world.paperConfig().tickRates.sensor.get(entity.getType(), this.configKey), this.scanRate);
|
||||
this.updateTargetingConditionRanges(entity);
|
||||
+ // Paper end
|
||||
this.doTick(world, entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
@@ -19,6 +19,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();
|
||||
@@ -31,7 +39,7 @@
|
||||
protected void doTick(ServerLevel world, PathfinderMob entity) {
|
||||
Brain<?> behaviorcontroller = entity.getBrain();
|
||||
TargetingConditions pathfindertargetcondition = TemptingSensor.TEMPT_TARGETING.copy().range((double) ((float) entity.getAttributeValue(Attributes.TEMPT_RANGE)));
|
||||
- Stream stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> {
|
||||
+ Stream<net.minecraft.server.level.ServerPlayer> stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { // CraftBukkit - decompile error
|
||||
return pathfindertargetcondition.test(world, entity, entityplayer);
|
||||
}).filter(this::playerHoldingTemptation).filter((entityplayer) -> {
|
||||
return !entity.hasPassenger((Entity) entityplayer);
|
||||
@@ -43,7 +51,17 @@
|
||||
if (!list.isEmpty()) {
|
||||
Player entityhuman = (Player) list.get(0);
|
||||
|
||||
- behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, (Object) entityhuman);
|
||||
+ // CraftBukkit start
|
||||
+ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityhuman, EntityTargetEvent.TargetReason.TEMPT);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (event.getTarget() instanceof HumanEntity) {
|
||||
+ behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle());
|
||||
+ } else {
|
||||
+ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
} else {
|
||||
behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
--- a/net/minecraft/world/entity/ai/village/VillageSiege.java
|
||||
+++ b/net/minecraft/world/entity/ai/village/VillageSiege.java
|
||||
@@ -117,11 +117,12 @@
|
||||
entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), EntitySpawnReason.EVENT, (SpawnGroupData) null);
|
||||
} catch (Exception exception) {
|
||||
VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception);
|
||||
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - ServerExceptionEvent
|
||||
return;
|
||||
}
|
||||
|
||||
entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, world.random.nextFloat() * 360.0F, 0.0F);
|
||||
- world.addFreshEntityWithPassengers(entityzombie);
|
||||
+ world.addFreshEntityWithPassengers(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
--- a/net/minecraft/world/entity/ambient/Bat.java
|
||||
+++ b/net/minecraft/world/entity/ambient/Bat.java
|
||||
@@ -29,6 +29,9 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Bat extends AmbientCreature {
|
||||
|
||||
@@ -88,7 +91,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public boolean isPushable() {
|
||||
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -144,13 +147,13 @@
|
||||
this.yHeadRot = (float) this.random.nextInt(360);
|
||||
}
|
||||
|
||||
- if (world.getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null) {
|
||||
+ if (world.getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent
|
||||
this.setResting(false);
|
||||
if (!flag) {
|
||||
world.levelEvent((Player) null, 1025, blockposition, 0);
|
||||
}
|
||||
}
|
||||
- } else {
|
||||
+ } else if (CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent
|
||||
this.setResting(false);
|
||||
if (!flag) {
|
||||
world.levelEvent((Player) null, 1025, blockposition, 0);
|
||||
@@ -177,7 +180,7 @@
|
||||
|
||||
this.zza = 0.5F;
|
||||
this.setYRot(this.getYRot() + f1);
|
||||
- if (this.random.nextInt(100) == 0 && world.getBlockState(blockposition1).isRedstoneConductor(world, blockposition1)) {
|
||||
+ if (this.random.nextInt(100) == 0 && world.getBlockState(blockposition1).isRedstoneConductor(world, blockposition1) && CraftEventFactory.handleBatToggleSleepEvent(this, false)) { // CraftBukkit - Call BatToggleSleepEvent
|
||||
this.setResting(true);
|
||||
}
|
||||
}
|
||||
@@ -202,7 +205,7 @@
|
||||
if (this.isInvulnerableTo(world, source)) {
|
||||
return false;
|
||||
} else {
|
||||
- if (this.isResting()) {
|
||||
+ if (this.isResting() && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent
|
||||
this.setResting(false);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/animal/AbstractSchoolingFish.java
|
||||
+++ b/net/minecraft/world/entity/animal/AbstractSchoolingFish.java
|
||||
@@ -51,6 +51,7 @@
|
||||
}
|
||||
|
||||
public void stopFollowing() {
|
||||
+ if (this.leader == null) return; // Avoid NPE, plugins can now set the leader and certain fish goals might cause this method to be called
|
||||
this.leader.removeFollower();
|
||||
this.leader = null;
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
--- a/net/minecraft/world/entity/animal/Animal.java
|
||||
+++ b/net/minecraft/world/entity/animal/Animal.java
|
||||
@@ -35,12 +35,20 @@
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityBreedEvent;
|
||||
+import org.bukkit.event.entity.EntityDamageEvent;
|
||||
+import org.bukkit.event.entity.EntityEnterLoveModeEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public abstract class Animal extends AgeableMob {
|
||||
|
||||
protected static final int PARENT_AGE_AFTER_BREEDING = 6000;
|
||||
public int inLove;
|
||||
@Nullable
|
||||
public UUID loveCause;
|
||||
+ public ItemStack breedItem; // CraftBukkit - Add breedItem variable
|
||||
|
||||
protected Animal(EntityType<? extends Animal> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -82,9 +90,15 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void actuallyHurt(ServerLevel world, DamageSource source, float amount) {
|
||||
+ // CraftBukkit start - void -> boolean
|
||||
+ public boolean actuallyHurt(ServerLevel worldserver, DamageSource damagesource, float f, EntityDamageEvent event) {
|
||||
+ boolean damageResult = super.actuallyHurt(worldserver, damagesource, f, event);
|
||||
+ if (!damageResult) {
|
||||
+ return false;
|
||||
+ }
|
||||
this.resetLove();
|
||||
- super.actuallyHurt(world, source, amount);
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,8 +158,9 @@
|
||||
int i = this.getAge();
|
||||
|
||||
if (!this.level().isClientSide && i == 0 && this.canFallInLove()) {
|
||||
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
|
||||
this.playEatingSound();
|
||||
return InteractionResult.SUCCESS_SERVER;
|
||||
}
|
||||
@@ -187,11 +202,26 @@
|
||||
return this.inLove <= 0;
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Fix EntityBreedEvent copying
|
||||
public void setInLove(@Nullable Player player) {
|
||||
- this.inLove = 600;
|
||||
+ // Paper start - Fix EntityBreedEvent copying
|
||||
+ this.setInLove(player, null);
|
||||
+ }
|
||||
+ public void setInLove(@Nullable Player player, @Nullable ItemStack breedItemCopy) {
|
||||
+ if (breedItemCopy != null) this.breedItem = breedItemCopy;
|
||||
+ // Paper end - Fix EntityBreedEvent copying
|
||||
+ // CraftBukkit start
|
||||
+ EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600);
|
||||
+ if (entityEnterLoveModeEvent.isCancelled()) {
|
||||
+ this.breedItem = null; // Paper - Fix EntityBreedEvent copying; clear if cancelled
|
||||
+ return;
|
||||
+ }
|
||||
+ this.inLove = entityEnterLoveModeEvent.getTicksInLove();
|
||||
+ // CraftBukkit end
|
||||
if (player != null) {
|
||||
this.loveCause = player.getUUID();
|
||||
}
|
||||
+ // Paper - Fix EntityBreedEvent copying; set breed item in better place
|
||||
|
||||
this.level().broadcastEntityEvent(this, (byte) 18);
|
||||
}
|
||||
@@ -233,25 +263,48 @@
|
||||
if (entityageable != null) {
|
||||
entityageable.setBaby(true);
|
||||
entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
|
||||
- this.finalizeSpawnChildFromBreeding(world, other, entityageable);
|
||||
- world.addFreshEntityWithPassengers(entityageable);
|
||||
+ // CraftBukkit start - call EntityBreedEvent
|
||||
+ ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> {
|
||||
+ return Optional.ofNullable(other.getLoveCause());
|
||||
+ }).orElse(null);
|
||||
+ int experience = this.getRandom().nextInt(7) + 1;
|
||||
+ EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, other, breeder, this.breedItem, experience);
|
||||
+ if (entityBreedEvent.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ experience = entityBreedEvent.getExperience();
|
||||
+ this.finalizeSpawnChildFromBreeding(world, other, entityageable, experience);
|
||||
+ world.addFreshEntityWithPassengers(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
|
||||
public void finalizeSpawnChildFromBreeding(ServerLevel world, Animal other, @Nullable AgeableMob baby) {
|
||||
- Optional.ofNullable(this.getLoveCause()).or(() -> {
|
||||
- return Optional.ofNullable(other.getLoveCause());
|
||||
- }).ifPresent((entityplayer) -> {
|
||||
+ // CraftBukkit start
|
||||
+ this.finalizeSpawnChildFromBreeding(world, other, baby, this.getRandom().nextInt(7) + 1);
|
||||
+ }
|
||||
+
|
||||
+ public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entityanimal, @Nullable AgeableMob entityageable, int experience) {
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start
|
||||
+ ServerPlayer entityplayer = this.getLoveCause();
|
||||
+ if (entityplayer == null) entityplayer = entityanimal.getLoveCause();
|
||||
+ if (entityplayer != null) {
|
||||
+ // Paper end
|
||||
entityplayer.awardStat(Stats.ANIMALS_BRED);
|
||||
- CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, other, baby);
|
||||
- });
|
||||
+ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, entityanimal, entityageable);
|
||||
+ } // Paper
|
||||
this.setAge(6000);
|
||||
- other.setAge(6000);
|
||||
+ entityanimal.setAge(6000);
|
||||
this.resetLove();
|
||||
- other.resetLove();
|
||||
- world.broadcastEntityEvent(this, (byte) 18);
|
||||
- if (world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1));
|
||||
+ entityanimal.resetLove();
|
||||
+ worldserver.broadcastEntityEvent(this, (byte) 18);
|
||||
+ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
+ // CraftBukkit start - use event experience
|
||||
+ if (experience > 0) {
|
||||
+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
--- a/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -92,6 +92,11 @@
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
|
||||
@@ -149,7 +154,22 @@
|
||||
public Bee(EntityType<? extends Bee> type, Level world) {
|
||||
super(type, world);
|
||||
this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
|
||||
- this.moveControl = new FlyingMoveControl(this, 20, true);
|
||||
+ // Paper start - Fix MC-167279
|
||||
+ class BeeFlyingMoveControl extends FlyingMoveControl {
|
||||
+ public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) {
|
||||
+ super(entity, maxPitchChange, noGravity);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void tick() {
|
||||
+ if (this.mob.getY() <= Bee.this.level().getMinY()) {
|
||||
+ this.mob.setNoGravity(false);
|
||||
+ }
|
||||
+ super.tick();
|
||||
+ }
|
||||
+ }
|
||||
+ this.moveControl = new BeeFlyingMoveControl(this, 20, true);
|
||||
+ // Paper end - Fix MC-167279
|
||||
this.lookControl = new Bee.BeeLookControl(this);
|
||||
this.setPathfindingMalus(PathType.DANGER_FIRE, -1.0F);
|
||||
this.setPathfindingMalus(PathType.WATER, -1.0F);
|
||||
@@ -198,21 +218,28 @@
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
- super.addAdditionalSaveData(nbt);
|
||||
- if (this.hasHive()) {
|
||||
- nbt.put("hive_pos", NbtUtils.writeBlockPos(this.getHivePos()));
|
||||
+ // CraftBukkit start - selectively save data
|
||||
+ this.addAdditionalSaveData(nbt, true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) {
|
||||
+ // CraftBukkit end
|
||||
+ super.addAdditionalSaveData(nbttagcompound);
|
||||
+ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive
|
||||
+ nbttagcompound.put("hive_pos", NbtUtils.writeBlockPos(this.getHivePos()));
|
||||
}
|
||||
|
||||
- if (this.hasSavedFlowerPos()) {
|
||||
- nbt.put("flower_pos", NbtUtils.writeBlockPos(this.getSavedFlowerPos()));
|
||||
+ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower
|
||||
+ nbttagcompound.put("flower_pos", NbtUtils.writeBlockPos(this.getSavedFlowerPos()));
|
||||
}
|
||||
|
||||
- nbt.putBoolean("HasNectar", this.hasNectar());
|
||||
- nbt.putBoolean("HasStung", this.hasStung());
|
||||
- nbt.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive);
|
||||
- nbt.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown);
|
||||
- nbt.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination);
|
||||
- this.addPersistentAngerSaveData(nbt);
|
||||
+ nbttagcompound.putBoolean("HasNectar", this.hasNectar());
|
||||
+ nbttagcompound.putBoolean("HasStung", this.hasStung());
|
||||
+ nbttagcompound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive);
|
||||
+ nbttagcompound.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown);
|
||||
+ nbttagcompound.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination);
|
||||
+ this.addPersistentAngerSaveData(nbttagcompound);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -223,8 +250,8 @@
|
||||
this.ticksWithoutNectarSinceExitingHive = nbt.getInt("TicksSincePollination");
|
||||
this.stayOutOfHiveCountdown = nbt.getInt("CannotEnterHiveTicks");
|
||||
this.numCropsGrownSincePollination = nbt.getInt("CropsGrownSincePollination");
|
||||
- this.hivePos = (BlockPos) NbtUtils.readBlockPos(nbt, "hive_pos").orElse((Object) null);
|
||||
- this.savedFlowerPos = (BlockPos) NbtUtils.readBlockPos(nbt, "flower_pos").orElse((Object) null);
|
||||
+ this.hivePos = (BlockPos) NbtUtils.readBlockPos(nbt, "hive_pos").orElse(null); // CraftBukkit - decompile error
|
||||
+ this.savedFlowerPos = (BlockPos) NbtUtils.readBlockPos(nbt, "flower_pos").orElse(null); // CraftBukkit - decompile error
|
||||
this.readPersistentAngerSaveData(this.level(), nbt);
|
||||
}
|
||||
|
||||
@@ -248,7 +275,7 @@
|
||||
}
|
||||
|
||||
if (b0 > 0) {
|
||||
- entityliving.addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this);
|
||||
+ entityliving.addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +533,12 @@
|
||||
|
||||
@Nullable
|
||||
BeehiveBlockEntity getBeehiveBlockEntity() {
|
||||
- return this.hivePos == null ? null : (this.isTooFarAway(this.hivePos) ? null : (BeehiveBlockEntity) this.level().getBlockEntity(this.hivePos, BlockEntityType.BEEHIVE).orElse((Object) null));
|
||||
+ // Paper start - move over logic to accommodate isTooFarAway with chunk load check
|
||||
+ if (this.hivePos != null && !this.isTooFarAway(this.hivePos) && this.level().getChunkIfLoadedImmediately(this.hivePos.getX() >> 4, this.hivePos.getZ() >> 4) != null) {
|
||||
+ return (BeehiveBlockEntity) this.level().getBlockEntity(this.hivePos, BlockEntityType.BEEHIVE).orElse(null);
|
||||
+ }
|
||||
+ return null;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
boolean isHiveValid() {
|
||||
@@ -533,11 +565,13 @@
|
||||
this.setFlag(4, hasStung);
|
||||
}
|
||||
|
||||
+ public net.kyori.adventure.util.TriState rollingOverride = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Rolling override
|
||||
public boolean isRolling() {
|
||||
return this.getFlag(2);
|
||||
}
|
||||
|
||||
public void setRolling(boolean nearTarget) {
|
||||
+ nearTarget = rollingOverride.toBooleanOrElse(nearTarget); // Paper - Rolling override
|
||||
this.setFlag(2, nearTarget);
|
||||
}
|
||||
|
||||
@@ -602,7 +636,7 @@
|
||||
if (mobeffect != null) {
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
if (!this.level().isClientSide) {
|
||||
- this.addEffect(mobeffect);
|
||||
+ this.addEffect(mobeffect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // Paper - Add missing effect cause
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -671,8 +705,14 @@
|
||||
if (this.isInvulnerableTo(world, source)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start - Only stop pollinating if entity was damaged
|
||||
+ boolean result = super.hurtServer(world, source, amount);
|
||||
+ if (!result) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.beePollinateGoal.stopPollinating();
|
||||
- return super.hurtServer(world, source, amount);
|
||||
+ return result; // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,7 +974,7 @@
|
||||
Bee.this.dropFlower();
|
||||
this.pollinating = false;
|
||||
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
|
||||
- } else {
|
||||
+ } else if (Bee.this.savedFlowerPos != null) { // Paper - add null check since API can manipulate this
|
||||
Vec3 vec3d = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, 0.6000000238418579D, 0.0D);
|
||||
|
||||
if (vec3d.distanceTo(Bee.this.position()) > 1.0D) {
|
||||
@@ -1082,7 +1122,7 @@
|
||||
|
||||
BeeGoToHiveGoal() {
|
||||
super();
|
||||
- this.travellingTicks = Bee.this.level().random.nextInt(10);
|
||||
+ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues
|
||||
this.blacklistedTargets = Lists.newArrayList();
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
|
||||
}
|
||||
@@ -1196,7 +1236,7 @@
|
||||
|
||||
BeeGoToKnownFlowerGoal() {
|
||||
super();
|
||||
- this.travellingTicks = Bee.this.level().random.nextInt(10);
|
||||
+ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
|
||||
}
|
||||
|
||||
@@ -1301,7 +1341,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- if (iblockdata1 != null) {
|
||||
+ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata1)) { // CraftBukkit
|
||||
Bee.this.level().levelEvent(2011, blockposition, 15);
|
||||
Bee.this.level().setBlockAndUpdate(blockposition, iblockdata1);
|
||||
Bee.this.incrementNumCropsGrownSincePollination();
|
||||
@@ -1378,7 +1418,7 @@
|
||||
@Override
|
||||
protected void alertOther(Mob mob, LivingEntity target) {
|
||||
if (mob instanceof Bee && this.mob.hasLineOfSight(target)) {
|
||||
- mob.setTarget(target);
|
||||
+ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1387,7 +1427,7 @@
|
||||
private static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal<Player> {
|
||||
|
||||
BeeBecomeAngryTargetGoal(Bee bee) {
|
||||
- Objects.requireNonNull(bee);
|
||||
+ // Objects.requireNonNull(entitybee); // CraftBukkit - decompile error
|
||||
super(bee, Player.class, 10, true, false, bee::isAngryAt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/world/entity/animal/Bucketable.java
|
||||
+++ b/net/minecraft/world/entity/animal/Bucketable.java
|
||||
@@ -16,6 +16,11 @@
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.Level;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+import org.bukkit.event.player.PlayerBucketEntityEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public interface Bucketable {
|
||||
|
||||
@@ -93,10 +98,21 @@
|
||||
ItemStack itemstack = player.getItemInHand(hand);
|
||||
|
||||
if (itemstack.getItem() == Items.WATER_BUCKET && entity.isAlive()) {
|
||||
- entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F);
|
||||
+ // CraftBukkit start
|
||||
+ // t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down
|
||||
ItemStack itemstack1 = ((Bucketable) entity).getBucketItemStack();
|
||||
|
||||
((Bucketable) entity).saveToBucketTag(itemstack1);
|
||||
+
|
||||
+ PlayerBucketEntityEvent playerBucketFishEvent = CraftEventFactory.callPlayerFishBucketEvent(entity, player, itemstack, itemstack1, hand);
|
||||
+ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket());
|
||||
+ if (playerBucketFishEvent.isCancelled()) {
|
||||
+ ((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
|
||||
+ entity.resendPossiblyDesyncedEntityData((ServerPlayer) player); // Paper
|
||||
+ return Optional.of(InteractionResult.FAIL);
|
||||
+ }
|
||||
+ entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F);
|
||||
+ // CraftBukkit end
|
||||
ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false);
|
||||
|
||||
player.setItemInHand(hand, itemstack2);
|
||||
@@ -106,7 +122,7 @@
|
||||
CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) player, itemstack1);
|
||||
}
|
||||
|
||||
- entity.discard();
|
||||
+ entity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
|
||||
return Optional.of(InteractionResult.SUCCESS);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
@@ -0,0 +1,96 @@
|
||||
--- a/net/minecraft/world/entity/animal/Cat.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cat.java
|
||||
@@ -174,10 +174,10 @@
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
super.readAdditionalSaveData(nbt);
|
||||
- Optional optional = Optional.ofNullable(ResourceLocation.tryParse(nbt.getString("variant"))).map((minecraftkey) -> {
|
||||
+ Optional<ResourceKey<CatVariant>> optional = Optional.ofNullable(ResourceLocation.tryParse(nbt.getString("variant"))).map((minecraftkey) -> { // CraftBukkit - decompile error
|
||||
return ResourceKey.create(Registries.CAT_VARIANT, minecraftkey);
|
||||
});
|
||||
- Registry iregistry = BuiltInRegistries.CAT_VARIANT;
|
||||
+ Registry<CatVariant> iregistry = BuiltInRegistries.CAT_VARIANT; // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(iregistry);
|
||||
optional.flatMap(iregistry::get).ifPresent(this::setVariant);
|
||||
@@ -365,7 +365,7 @@
|
||||
BuiltInRegistries.CAT_VARIANT.getRandomElementOf(tagkey, world.getRandom()).ifPresent(this::setVariant);
|
||||
ServerLevel worldserver = world.getLevel();
|
||||
|
||||
- if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) {
|
||||
+ if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK, world).isValid()) { // Paper - Fix swamp hut cat generation deadlock
|
||||
this.setVariant((Holder) BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.ALL_BLACK));
|
||||
this.setPersistenceRequired();
|
||||
}
|
||||
@@ -386,6 +386,13 @@
|
||||
DyeColor enumcolor = itemdye.getDyeColor();
|
||||
|
||||
if (enumcolor != this.getCollarColor()) {
|
||||
+ // Paper start - Add EntityDyeEvent and CollarColorable interface
|
||||
+ final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) enumcolor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
|
||||
+ if (!event.callEvent()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ enumcolor = DyeColor.byId(event.getColor().getWoolData());
|
||||
+ // Paper end - Add EntityDyeEvent and CollarColorable interface
|
||||
if (!this.level().isClientSide()) {
|
||||
this.setCollarColor(enumcolor);
|
||||
itemstack.consume(1, player);
|
||||
@@ -399,7 +406,7 @@
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
FoodProperties foodinfo = (FoodProperties) itemstack.get(DataComponents.FOOD);
|
||||
|
||||
- this.heal(foodinfo != null ? (float) foodinfo.nutrition() : 1.0F);
|
||||
+ this.heal(foodinfo != null ? (float) foodinfo.nutrition() : 1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper - Add missing regain reason
|
||||
this.playEatingSound();
|
||||
}
|
||||
|
||||
@@ -462,7 +469,7 @@
|
||||
}
|
||||
|
||||
private void tryToTame(Player player) {
|
||||
- if (this.random.nextInt(3) == 0) {
|
||||
+ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
|
||||
this.tame(player);
|
||||
this.setOrderedToSit(true);
|
||||
this.level().broadcastEntityEvent(this, (byte) 7);
|
||||
@@ -480,7 +487,7 @@
|
||||
private static class CatTemptGoal extends TemptGoal {
|
||||
|
||||
@Nullable
|
||||
- private Player selectedPlayer;
|
||||
+ private LivingEntity selectedPlayer; // CraftBukkit
|
||||
private final Cat cat;
|
||||
|
||||
public CatTemptGoal(Cat cat, double speed, Predicate<ItemStack> foodPredicate, boolean canBeScared) {
|
||||
@@ -614,7 +621,15 @@
|
||||
this.cat.randomTeleport((double) (blockposition_mutableblockposition.getX() + randomsource.nextInt(11) - 5), (double) (blockposition_mutableblockposition.getY() + randomsource.nextInt(5) - 2), (double) (blockposition_mutableblockposition.getZ() + randomsource.nextInt(11) - 5), false);
|
||||
blockposition_mutableblockposition.set(this.cat.blockPosition());
|
||||
this.cat.dropFromGiftLootTable(getServerLevel((Entity) this.cat), BuiltInLootTables.CAT_MORNING_GIFT, (worldserver, itemstack) -> {
|
||||
- worldserver.addFreshEntity(new ItemEntity(worldserver, (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack));
|
||||
+ // CraftBukkit start
|
||||
+ ItemEntity entityitem = new ItemEntity(worldserver, (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack);
|
||||
+ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
|
||||
+ entityitem.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ worldserver.addFreshEntity(entityitem);
|
||||
+ // CraftBukkit end
|
||||
});
|
||||
}
|
||||
|
||||
@@ -645,10 +660,10 @@
|
||||
private final Cat cat;
|
||||
|
||||
public CatAvoidEntityGoal(Cat cat, Class<T> fleeFromType, float distance, double slowSpeed, double fastSpeed) {
|
||||
- Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR;
|
||||
+ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error
|
||||
|
||||
- Objects.requireNonNull(predicate);
|
||||
- super(cat, fleeFromType, distance, slowSpeed, fastSpeed, predicate::test);
|
||||
+ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error
|
||||
+ super(cat, fleeFromType, distance, slowSpeed, fastSpeed, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error
|
||||
this.cat = cat;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
--- a/net/minecraft/world/entity/animal/Chicken.java
|
||||
+++ b/net/minecraft/world/entity/animal/Chicken.java
|
||||
@@ -99,10 +99,12 @@
|
||||
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
if (this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) {
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
if (this.dropFromGiftLootTable(worldserver, BuiltInLootTables.CHICKEN_LAY, this::spawnAtLocation)) {
|
||||
this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
|
||||
this.gameEvent(GameEvent.ENTITY_PLACE);
|
||||
}
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
|
||||
this.eggTime = this.random.nextInt(6000) + 6000;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
--- a/net/minecraft/world/entity/animal/Cow.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cow.java
|
||||
@@ -30,6 +30,11 @@
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.player.PlayerBucketFillEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Cow extends Animal {
|
||||
|
||||
@@ -92,8 +97,17 @@
|
||||
ItemStack itemstack = player.getItemInHand(hand);
|
||||
|
||||
if (itemstack.is(Items.BUCKET) && !this.isBaby()) {
|
||||
+ // CraftBukkit start - Got milk?
|
||||
+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F);
|
||||
- ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, Items.MILK_BUCKET.getDefaultInstance());
|
||||
+ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
|
||||
|
||||
player.setItemInHand(hand, itemstack1);
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -0,0 +1,87 @@
|
||||
--- a/net/minecraft/world/entity/animal/Dolphin.java
|
||||
+++ b/net/minecraft/world/entity/animal/Dolphin.java
|
||||
@@ -61,9 +61,20 @@
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Dolphin extends AgeableWaterCreature {
|
||||
|
||||
+ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
|
||||
+ @Override
|
||||
+ public int getDefaultMaxAirSupply() {
|
||||
+ return Dolphin.TOTAL_AIR_SUPPLY;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
private static final EntityDataAccessor<BlockPos> TREASURE_POS = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BLOCK_POS);
|
||||
private static final EntityDataAccessor<Boolean> GOT_FISH = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final EntityDataAccessor<Integer> MOISTNESS_LEVEL = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.INT);
|
||||
@@ -200,7 +211,7 @@
|
||||
|
||||
@Override
|
||||
public int getMaxAirSupply() {
|
||||
- return 4800;
|
||||
+ return this.maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -234,11 +245,17 @@
|
||||
ItemStack itemstack = itemEntity.getItem();
|
||||
|
||||
if (this.canHoldItem(itemstack)) {
|
||||
+ // CraftBukkit start - call EntityPickupItemEvent
|
||||
+ if (CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, false).isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ itemstack = itemEntity.getItem(); // CraftBukkit- update ItemStack from event
|
||||
+ // CraftBukkit start
|
||||
this.onItemPickup(itemEntity);
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, itemstack);
|
||||
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
|
||||
this.take(itemEntity, itemstack.getCount());
|
||||
- itemEntity.discard();
|
||||
+ itemEntity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +349,7 @@
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
- protected SoundEvent getDeathSound() {
|
||||
+ public SoundEvent getDeathSound() { // Paper - decompile error
|
||||
return SoundEvents.DOLPHIN_DEATH;
|
||||
}
|
||||
|
||||
@@ -495,7 +512,7 @@
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin);
|
||||
+ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -514,7 +531,7 @@
|
||||
}
|
||||
|
||||
if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) {
|
||||
- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin);
|
||||
+ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit
|
||||
}
|
||||
|
||||
}
|
||||
@@ -587,7 +604,7 @@
|
||||
float f2 = 0.02F * Dolphin.this.random.nextFloat();
|
||||
|
||||
entityitem.setDeltaMovement((double) (0.3F * -Mth.sin(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.cos(f1) * f2), (double) (0.3F * Mth.sin(Dolphin.this.getXRot() * 0.017453292F) * 1.5F), (double) (0.3F * Mth.cos(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.sin(f1) * f2));
|
||||
- Dolphin.this.level().addFreshEntity(entityitem);
|
||||
+ Dolphin.this.spawnAtLocation(getServerLevel(Dolphin.this), entityitem); // Paper - Call EntityDropItemEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
--- a/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -90,6 +90,9 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Fox extends Animal implements VariantHolder<Fox.Variant> {
|
||||
|
||||
@@ -416,7 +419,7 @@
|
||||
|
||||
this.setSleeping(nbt.getBoolean("Sleeping"));
|
||||
this.setVariant(Fox.Variant.byName(nbt.getString("Type")));
|
||||
- this.setSitting(nbt.getBoolean("Sitting"));
|
||||
+ this.setSitting(nbt.getBoolean("Sitting"), false); // Paper - Add EntityToggleSitEvent
|
||||
this.setIsCrouching(nbt.getBoolean("Crouching"));
|
||||
if (this.level() instanceof ServerLevel) {
|
||||
this.setTargetGoals();
|
||||
@@ -429,6 +432,12 @@
|
||||
}
|
||||
|
||||
public void setSitting(boolean sitting) {
|
||||
+ // Paper start - Add EntityToggleSitEvent
|
||||
+ this.setSitting(sitting, true);
|
||||
+ }
|
||||
+ public void setSitting(boolean sitting, boolean fireEvent) {
|
||||
+ if (fireEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return;
|
||||
+ // Paper end - Add EntityToggleSitEvent
|
||||
this.setFlag(1, sitting);
|
||||
}
|
||||
|
||||
@@ -489,21 +498,22 @@
|
||||
entityitem.setPickUpDelay(40);
|
||||
entityitem.setThrower(this);
|
||||
this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F);
|
||||
- this.level().addFreshEntity(entityitem);
|
||||
+ this.spawnAtLocation((net.minecraft.server.level.ServerLevel) this.level(), entityitem); // Paper - Call EntityDropItemEvent
|
||||
}
|
||||
}
|
||||
|
||||
private void dropItemStack(ItemStack stack) {
|
||||
ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), stack);
|
||||
|
||||
- this.level().addFreshEntity(entityitem);
|
||||
+ this.spawnAtLocation((net.minecraft.server.level.ServerLevel) this.level(), entityitem); // Paper - Call EntityDropItemEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pickUpItem(ServerLevel world, ItemEntity itemEntity) {
|
||||
ItemStack itemstack = itemEntity.getItem();
|
||||
|
||||
- if (this.canHoldItem(itemstack)) {
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent
|
||||
+ itemstack = itemEntity.getItem(); // CraftBukkit - update ItemStack from event
|
||||
int i = itemstack.getCount();
|
||||
|
||||
if (i > 1) {
|
||||
@@ -515,7 +525,7 @@
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, itemstack.split(1));
|
||||
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
|
||||
this.take(itemEntity, itemstack.getCount());
|
||||
- itemEntity.discard();
|
||||
+ itemEntity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
|
||||
this.ticksSinceEaten = 0;
|
||||
}
|
||||
|
||||
@@ -685,16 +695,38 @@
|
||||
return this.getTrustedUUIDs().contains(uuid);
|
||||
}
|
||||
|
||||
+ // Paper start - handle the bitten item separately like vanilla
|
||||
@Override
|
||||
- protected void dropAllDeathLoot(ServerLevel world, DamageSource damageSource) {
|
||||
+ protected boolean shouldSkipLoot(EquipmentSlot slot) {
|
||||
+ return slot == EquipmentSlot.MAINHAND;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ @Override
|
||||
+ // Paper start - Cancellable death event
|
||||
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(ServerLevel world, DamageSource damageSource) {
|
||||
ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
|
||||
- if (!itemstack.isEmpty()) {
|
||||
+ boolean releaseMouth = false;
|
||||
+ if (!itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Fix MC-153010
|
||||
this.spawnAtLocation(world, itemstack);
|
||||
+ releaseMouth = true;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(world, damageSource);
|
||||
+
|
||||
+ // Below is code to drop
|
||||
+
|
||||
+ if (deathEvent == null || deathEvent.isCancelled()) {
|
||||
+ return deathEvent;
|
||||
+ }
|
||||
+
|
||||
+ if (releaseMouth) {
|
||||
+ // Paper end - Cancellable death event
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
- super.dropAllDeathLoot(world, damageSource);
|
||||
+ return deathEvent; // Paper - Cancellable death event
|
||||
}
|
||||
|
||||
public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) {
|
||||
@@ -853,6 +885,16 @@
|
||||
if (entityplayer1 != null && entityplayer != entityplayer1) {
|
||||
entityfox.addTrustedUUID(entityplayer1.getUUID());
|
||||
}
|
||||
+ // CraftBukkit start - call EntityBreedEvent
|
||||
+ entityfox.setAge(-24000);
|
||||
+ entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
|
||||
+ int experience = this.animal.getRandom().nextInt(7) + 1;
|
||||
+ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityfox, this.animal, this.partner, entityplayer, this.animal.breedItem, experience);
|
||||
+ if (entityBreedEvent.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ experience = entityBreedEvent.getExperience();
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (entityplayer2 != null) {
|
||||
entityplayer2.awardStat(Stats.ANIMALS_BRED);
|
||||
@@ -863,12 +905,14 @@
|
||||
this.partner.setAge(6000);
|
||||
this.animal.resetLove();
|
||||
this.partner.resetLove();
|
||||
- entityfox.setAge(-24000);
|
||||
- entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
|
||||
- worldserver.addFreshEntityWithPassengers(entityfox);
|
||||
+ worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
|
||||
this.level.broadcastEntityEvent(this.animal, (byte) 18);
|
||||
if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1));
|
||||
+ // CraftBukkit start - use event experience
|
||||
+ if (experience > 0) {
|
||||
+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1264,6 +1308,11 @@
|
||||
int i = (Integer) state.getValue(SweetBerryBushBlock.AGE);
|
||||
|
||||
state.setValue(SweetBerryBushBlock.AGE, 1);
|
||||
+ // CraftBukkit start - call EntityChangeBlockEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1))) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
int j = 1 + Fox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0);
|
||||
ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
|
||||
@@ -1494,7 +1543,7 @@
|
||||
}
|
||||
|
||||
public static Fox.Variant byName(String name) {
|
||||
- return (Fox.Variant) Fox.Variant.CODEC.byName(name, (Enum) Fox.Variant.RED);
|
||||
+ return (Fox.Variant) Fox.Variant.CODEC.byName(name, Fox.Variant.RED); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public static Fox.Variant byId(int id) {
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/world/entity/animal/IronGolem.java
|
||||
+++ b/net/minecraft/world/entity/animal/IronGolem.java
|
||||
@@ -98,7 +98,7 @@
|
||||
@Override
|
||||
protected void doPush(Entity entity) {
|
||||
if (entity instanceof Enemy && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) {
|
||||
- this.setTarget((LivingEntity) entity);
|
||||
+ this.setTarget((LivingEntity) entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason
|
||||
}
|
||||
|
||||
super.doPush(entity);
|
||||
@@ -319,7 +319,7 @@
|
||||
BlockPos blockposition1 = blockposition.below();
|
||||
BlockState iblockdata = world.getBlockState(blockposition1);
|
||||
|
||||
- if (!iblockdata.entityCanStandOn(world, blockposition1, this)) {
|
||||
+ if (!iblockdata.entityCanStandOn(world, blockposition1, this) && !this.level().paperConfig().entities.spawning.ironGolemsCanSpawnInAir) { // Paper - Add option to allow iron golems to spawn in air
|
||||
return false;
|
||||
} else {
|
||||
for (int i = 1; i < 3; ++i) {
|
||||
@@ -0,0 +1,85 @@
|
||||
--- a/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
@@ -42,6 +42,13 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.entity.EntityDropItemEvent;
|
||||
+import org.bukkit.event.entity.EntityTransformEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class MushroomCow extends Cow implements Shearable, VariantHolder<MushroomCow.Variant> {
|
||||
|
||||
@@ -120,7 +127,19 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
- this.shear(worldserver, SoundSource.PLAYERS, itemstack);
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(worldserver, itemstack);
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
+ // Paper end - custom shear drops
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ this.shear(worldserver, SoundSource.PLAYERS, itemstack, drops); // Paper - custom shear drops
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
}
|
||||
@@ -158,16 +177,32 @@
|
||||
|
||||
@Override
|
||||
public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(world, shearedSoundCategory, shears, this.generateDefaultDrops(world, shears));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops(final ServerLevel serverLevel, final ItemStack shears) {
|
||||
+ final java.util.List<ItemStack> drops = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
|
||||
+ this.dropFromShearingLootTable(serverLevel, BuiltInLootTables.SHEAR_MOOSHROOM, shears, (ignored, stack) -> {
|
||||
+ for (int i = 0; i < stack.getCount(); ++i) drops.add(stack.copyWithCount(1));
|
||||
+ });
|
||||
+ return drops;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears, java.util.List<ItemStack> drops) {
|
||||
+ // Paper end - custom shear drops
|
||||
world.playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
this.convertTo(EntityType.COW, ConversionParams.single(this, false, false), (entitycow) -> {
|
||||
world.sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D);
|
||||
- this.dropFromShearingLootTable(world, BuiltInLootTables.SHEAR_MOOSHROOM, shears, (worldserver1, itemstack1) -> {
|
||||
- for (int i = 0; i < itemstack1.getCount(); ++i) {
|
||||
- worldserver1.addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), itemstack1.copyWithCount(1)));
|
||||
- }
|
||||
-
|
||||
+ // Paper start - custom shear drops; moved drop generation to separate method
|
||||
+ drops.forEach(drop -> {
|
||||
+ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), drop);
|
||||
+ this.spawnAtLocation(world, entityitem);
|
||||
+ // Paper end - custom shear drops; moved drop generation to separate method
|
||||
});
|
||||
- });
|
||||
+ }, EntityTransformEvent.TransformReason.SHEARED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -263,7 +298,7 @@
|
||||
}
|
||||
|
||||
static MushroomCow.Variant byName(String name) {
|
||||
- return (MushroomCow.Variant) MushroomCow.Variant.CODEC.byName(name, (Enum) MushroomCow.Variant.RED);
|
||||
+ return (MushroomCow.Variant) MushroomCow.Variant.CODEC.byName(name, MushroomCow.Variant.RED); // CraftBukkit - decompile error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
--- a/net/minecraft/world/entity/animal/Ocelot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Ocelot.java
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
@Override
|
||||
public boolean removeWhenFarAway(double distanceSquared) {
|
||||
- return !this.isTrusting() && this.tickCount > 2400;
|
||||
+ return !this.isTrusting() && this.tickCount > 2400 && !this.hasCustomName() && !this.isLeashed(); // Paper - honor name and leash
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
@@ -167,7 +167,7 @@
|
||||
if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemstack) && player.distanceToSqr((Entity) this) < 9.0D) {
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
if (!this.level().isClientSide) {
|
||||
- if (this.random.nextInt(3) == 0) {
|
||||
+ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check
|
||||
this.setTrusting(true);
|
||||
this.spawnTrustingParticles(true);
|
||||
this.level().broadcastEntityEvent(this, (byte) 41);
|
||||
@@ -298,10 +298,10 @@
|
||||
private final Ocelot ocelot;
|
||||
|
||||
public OcelotAvoidEntityGoal(Ocelot ocelot, Class<T> fleeFromType, float distance, double slowSpeed, double fastSpeed) {
|
||||
- Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR;
|
||||
+ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error
|
||||
|
||||
- Objects.requireNonNull(predicate);
|
||||
- super(ocelot, fleeFromType, distance, slowSpeed, fastSpeed, predicate::test);
|
||||
+ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error
|
||||
+ super(ocelot, fleeFromType, distance, slowSpeed, fastSpeed, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error
|
||||
this.ocelot = ocelot;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
--- a/net/minecraft/world/entity/animal/Panda.java
|
||||
+++ b/net/minecraft/world/entity/animal/Panda.java
|
||||
@@ -68,6 +68,11 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
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.EntityTargetEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Panda extends Animal {
|
||||
|
||||
@@ -129,6 +134,7 @@
|
||||
}
|
||||
|
||||
public void sit(boolean sitting) {
|
||||
+ if (!new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; // Paper - Add EntityToggleSitEvent
|
||||
this.setFlag(8, sitting);
|
||||
}
|
||||
|
||||
@@ -525,7 +531,9 @@
|
||||
Panda entitypanda = (Panda) iterator.next();
|
||||
|
||||
if (!entitypanda.isBaby() && entitypanda.onGround() && !entitypanda.isInWater() && entitypanda.canPerformAction()) {
|
||||
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - Entity Jump API
|
||||
entitypanda.jumpFromGround();
|
||||
+ } else { this.setJumping(false); } // Paper - Entity Jump API; setJumping(false) stops a potential loop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +541,9 @@
|
||||
|
||||
if (world1 instanceof ServerLevel worldserver) {
|
||||
if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
|
||||
this.dropFromGiftLootTable(worldserver, BuiltInLootTables.PANDA_SNEEZE, this::spawnAtLocation);
|
||||
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,14 +551,14 @@
|
||||
|
||||
@Override
|
||||
protected void pickUpItem(ServerLevel world, ItemEntity itemEntity) {
|
||||
- if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.canPickUpAndEat(itemEntity)) {
|
||||
+ if (!CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, !(this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.canPickUpAndEat(itemEntity))).isCancelled()) { // CraftBukkit
|
||||
this.onItemPickup(itemEntity);
|
||||
ItemStack itemstack = itemEntity.getItem();
|
||||
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, itemstack);
|
||||
this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
|
||||
this.take(itemEntity, itemstack.getCount());
|
||||
- itemEntity.discard();
|
||||
+ itemEntity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
|
||||
}
|
||||
@@ -643,8 +653,9 @@
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
this.ageUp((int) ((float) (-this.getAge() / 20) * 0.1F), true);
|
||||
} else if (!this.level().isClientSide && this.getAge() == 0 && this.canFallInLove()) {
|
||||
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
|
||||
} else {
|
||||
Level world = this.level();
|
||||
|
||||
@@ -657,7 +668,9 @@
|
||||
ItemStack itemstack1 = this.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
|
||||
if (!itemstack1.isEmpty() && !player.hasInfiniteMaterials()) {
|
||||
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
|
||||
this.spawnAtLocation(worldserver, itemstack1);
|
||||
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
|
||||
}
|
||||
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(itemstack.getItem(), 1));
|
||||
@@ -772,7 +785,7 @@
|
||||
}
|
||||
|
||||
public static Panda.Gene byName(String name) {
|
||||
- return (Panda.Gene) Panda.Gene.CODEC.byName(name, (Enum) Panda.Gene.NORMAL);
|
||||
+ return (Panda.Gene) Panda.Gene.CODEC.byName(name, Panda.Gene.NORMAL); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public static Panda.Gene getRandom(RandomSource random) {
|
||||
@@ -876,10 +889,10 @@
|
||||
private final Panda panda;
|
||||
|
||||
public PandaAvoidGoal(Panda panda, Class<T> fleeFromType, float distance, double slowSpeed, double fastSpeed) {
|
||||
- Predicate predicate = EntitySelector.NO_SPECTATORS;
|
||||
+ // Predicate predicate = IEntitySelector.NO_SPECTATORS;
|
||||
|
||||
- Objects.requireNonNull(predicate);
|
||||
- super(panda, fleeFromType, distance, slowSpeed, fastSpeed, predicate::test);
|
||||
+ // Objects.requireNonNull(predicate);
|
||||
+ super(panda, fleeFromType, distance, slowSpeed, fastSpeed, EntitySelector.NO_SPECTATORS::test);
|
||||
this.panda = panda;
|
||||
}
|
||||
|
||||
@@ -935,7 +948,9 @@
|
||||
ItemStack itemstack = Panda.this.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
|
||||
if (!itemstack.isEmpty()) {
|
||||
+ Panda.this.forceDrops = true; // Paper - Add missing forceDrop toggles
|
||||
Panda.this.spawnAtLocation(getServerLevel(Panda.this.level()), itemstack);
|
||||
+ Panda.this.forceDrops = false; // Paper - Add missing forceDrop toggles
|
||||
Panda.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
||||
int i = Panda.this.isLazy() ? Panda.this.random.nextInt(50) + 10 : Panda.this.random.nextInt(150) + 10;
|
||||
|
||||
@@ -1116,7 +1131,7 @@
|
||||
@Override
|
||||
protected void alertOther(Mob mob, LivingEntity target) {
|
||||
if (mob instanceof Panda && mob.isAggressive()) {
|
||||
- mob.setTarget(target);
|
||||
+ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
--- a/net/minecraft/world/entity/animal/Parrot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Parrot.java
|
||||
@@ -248,7 +248,7 @@
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
- if (this.random.nextInt(10) == 0) {
|
||||
+ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
|
||||
this.tame(player);
|
||||
this.level().broadcastEntityEvent(this, (byte) 7);
|
||||
} else {
|
||||
@@ -269,7 +269,7 @@
|
||||
}
|
||||
} else {
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
- this.addEffect(new MobEffectInstance(MobEffects.POISON, 900));
|
||||
+ this.addEffect(new MobEffectInstance(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit
|
||||
if (player.isCreative() || !this.isInvulnerable()) {
|
||||
this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE);
|
||||
}
|
||||
@@ -362,8 +362,8 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public boolean isPushable() {
|
||||
- return true;
|
||||
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
|
||||
+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -378,8 +378,14 @@
|
||||
if (this.isInvulnerableTo(world, source)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ boolean result = super.hurtServer(world, source, amount);
|
||||
+ if (!result) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.setOrderedToSit(false);
|
||||
- return super.hurtServer(world, source, amount);
|
||||
+ return result; // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
--- a/net/minecraft/world/entity/animal/Pig.java
|
||||
+++ b/net/minecraft/world/entity/animal/Pig.java
|
||||
@@ -49,6 +49,10 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
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;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Pig extends Animal implements ItemSteerable, Saddleable {
|
||||
|
||||
@@ -247,7 +251,14 @@
|
||||
}
|
||||
|
||||
entitypigzombie1.setPersistenceRequired();
|
||||
- });
|
||||
+ // CraftBukkit start
|
||||
+ }, null, null);
|
||||
+ if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ world.addFreshEntity(entitypigzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING);
|
||||
+ this.discard(EntityRemoveEvent.Cause.TRANSFORMATION); // CraftBukkit - add Bukkit remove cause
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (entitypigzombie == null) {
|
||||
super.thunderHit(world, lightning);
|
||||
@@ -0,0 +1,60 @@
|
||||
--- a/net/minecraft/world/entity/animal/Pufferfish.java
|
||||
+++ b/net/minecraft/world/entity/animal/Pufferfish.java
|
||||
@@ -102,25 +102,39 @@
|
||||
public void tick() {
|
||||
if (!this.level().isClientSide && this.isAlive() && this.isEffectiveAi()) {
|
||||
if (this.inflateCounter > 0) {
|
||||
+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent
|
||||
if (this.getPuffState() == 0) {
|
||||
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent
|
||||
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_UP);
|
||||
this.setPuffState(1);
|
||||
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
|
||||
} else if (this.inflateCounter > 40 && this.getPuffState() == 1) {
|
||||
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent
|
||||
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_UP);
|
||||
this.setPuffState(2);
|
||||
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
|
||||
}
|
||||
|
||||
+ if (increase) { // Paper - Add PufferFishStateChangeEvent
|
||||
++this.inflateCounter;
|
||||
+ } // Paper - Add PufferFishStateChangeEvent
|
||||
} else if (this.getPuffState() != 0) {
|
||||
+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent
|
||||
if (this.deflateTimer > 60 && this.getPuffState() == 2) {
|
||||
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent
|
||||
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_OUT);
|
||||
this.setPuffState(1);
|
||||
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
|
||||
} else if (this.deflateTimer > 100 && this.getPuffState() == 1) {
|
||||
+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent
|
||||
this.makeSound(SoundEvents.PUFFER_FISH_BLOW_OUT);
|
||||
this.setPuffState(0);
|
||||
+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent
|
||||
}
|
||||
|
||||
+ if (increase) { // Paper - Add PufferFishStateChangeEvent
|
||||
++this.deflateTimer;
|
||||
+ } // Paper - Add PufferFishStateChangeEvent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +169,7 @@
|
||||
int i = this.getPuffState();
|
||||
|
||||
if (target.hurtServer(world, this.damageSources().mobAttack(this), (float) (1 + i))) {
|
||||
- target.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this);
|
||||
+ target.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
|
||||
this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
@@ -171,7 +185,7 @@
|
||||
entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F));
|
||||
}
|
||||
|
||||
- player.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this);
|
||||
+ player.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
--- a/net/minecraft/world/entity/animal/Rabbit.java
|
||||
+++ b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
@@ -65,6 +65,9 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
||||
|
||||
@@ -90,7 +93,6 @@
|
||||
super(type, world);
|
||||
this.jumpControl = new Rabbit.RabbitJumpControl(this);
|
||||
this.moveControl = new Rabbit.RabbitMoveControl(this);
|
||||
- this.setSpeedModifier(0.0D);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -577,9 +579,19 @@
|
||||
int i = (Integer) iblockdata.getValue(CarrotBlock.AGE);
|
||||
|
||||
if (i == 0) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 2);
|
||||
world.destroyBlock(blockposition, true, this.rabbit);
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.setValue(CarrotBlock.AGE, i - 1))) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
world.setBlock(blockposition, (BlockState) iblockdata.setValue(CarrotBlock.AGE, i - 1), 2);
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of((Entity) this.rabbit));
|
||||
world.levelEvent(2001, blockposition, Block.getId(iblockdata));
|
||||
@@ -0,0 +1,90 @@
|
||||
--- a/net/minecraft/world/entity/animal/Sheep.java
|
||||
+++ b/net/minecraft/world/entity/animal/Sheep.java
|
||||
@@ -41,7 +41,6 @@
|
||||
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
-import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -49,6 +48,12 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
+import net.minecraft.world.item.DyeColor;
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.world.item.Item;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.SheepRegrowWoolEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Sheep extends Animal implements Shearable {
|
||||
|
||||
@@ -160,7 +165,19 @@
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
if (this.readyForShearing()) {
|
||||
- this.shear(worldserver, SoundSource.PLAYERS, itemstack);
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(worldserver, itemstack);
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
+ // Paper end - custom shear drops
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ this.shear(worldserver, SoundSource.PLAYERS, itemstack, drops); // Paper - custom shear drops
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
return InteractionResult.SUCCESS_SERVER;
|
||||
@@ -175,10 +192,29 @@
|
||||
|
||||
@Override
|
||||
public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(world, shearedSoundCategory, shears, this.generateDefaultDrops(world, shears));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops(final ServerLevel serverLevel, final ItemStack shears) {
|
||||
+ final java.util.List<ItemStack> drops = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
|
||||
+ this.dropFromShearingLootTable(serverLevel, BuiltInLootTables.SHEAR_SHEEP, shears, (ignored, stack) -> {
|
||||
+ for (int i = 0; i < stack.getCount(); ++i) drops.add(stack.copyWithCount(1));
|
||||
+ });
|
||||
+ return drops;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears, java.util.List<ItemStack> drops) {
|
||||
+ final ServerLevel worldserver1 = world; // Named for lambda consumption
|
||||
+ // Paper end - custom shear drops
|
||||
world.playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
- this.dropFromShearingLootTable(world, BuiltInLootTables.SHEAR_SHEEP, shears, (worldserver1, itemstack1) -> {
|
||||
- for (int i = 0; i < itemstack1.getCount(); ++i) {
|
||||
- ItemEntity entityitem = this.spawnAtLocation(worldserver1, itemstack1.copyWithCount(1), 1.0F);
|
||||
+ drops.forEach(itemstack1 -> { // Paper - custom drops - loop in generated default drops
|
||||
+ if (true) { // Paper - custom drops - loop in generated default drops
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
+ ItemEntity entityitem = this.spawnAtLocation(worldserver1, itemstack1, 1.0F); // Paper - custom drops - copy already done above
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
|
||||
if (entityitem != null) {
|
||||
entityitem.setDeltaMovement(entityitem.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F)));
|
||||
@@ -276,6 +312,12 @@
|
||||
|
||||
@Override
|
||||
public void ate() {
|
||||
+ // CraftBukkit start
|
||||
+ SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity());
|
||||
+ this.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) return;
|
||||
+ // CraftBukkit end
|
||||
super.ate();
|
||||
this.setSheared(false);
|
||||
if (this.isBaby()) {
|
||||
@@ -0,0 +1,21 @@
|
||||
--- a/net/minecraft/world/entity/animal/ShoulderRidingEntity.java
|
||||
+++ b/net/minecraft/world/entity/animal/ShoulderRidingEntity.java
|
||||
@@ -5,6 +5,9 @@
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.TamableAnimal;
|
||||
import net.minecraft.world.level.Level;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class ShoulderRidingEntity extends TamableAnimal {
|
||||
|
||||
@@ -21,7 +24,7 @@
|
||||
nbttagcompound.putString("id", this.getEncodeId());
|
||||
this.saveWithoutId(nbttagcompound);
|
||||
if (player.setEntityOnShoulder(nbttagcompound)) {
|
||||
- this.discard();
|
||||
+ this.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -0,0 +1,86 @@
|
||||
--- a/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
@@ -42,6 +42,9 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob {
|
||||
|
||||
@@ -100,7 +103,7 @@
|
||||
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) {
|
||||
- this.hurtServer(worldserver, this.damageSources().onFire(), 1.0F);
|
||||
+ this.hurtServer(worldserver, this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING
|
||||
}
|
||||
|
||||
if (!worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
@@ -116,7 +119,11 @@
|
||||
BlockPos blockposition = new BlockPos(j, k, l);
|
||||
|
||||
if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) {
|
||||
- this.level().setBlockAndUpdate(blockposition, iblockdata);
|
||||
+ // CraftBukkit start
|
||||
+ if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.level().gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this, iblockdata));
|
||||
}
|
||||
}
|
||||
@@ -153,7 +160,19 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
- this.shear(worldserver, SoundSource.PLAYERS, itemstack);
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(worldserver, itemstack);
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
+ // Paper end - custom shear drops
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ this.shear(worldserver, SoundSource.PLAYERS, itemstack, drops); // Paper - custom shear drops
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
}
|
||||
@@ -166,10 +185,29 @@
|
||||
|
||||
@Override
|
||||
public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(world, shearedSoundCategory, shears, this.generateDefaultDrops(world, shears));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops(final ServerLevel serverLevel, final ItemStack shears) {
|
||||
+ final java.util.List<ItemStack> drops = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
|
||||
+ this.dropFromShearingLootTable(serverLevel, BuiltInLootTables.SHEAR_SNOW_GOLEM, shears, (ignored, stack) -> {
|
||||
+ drops.add(stack);
|
||||
+ });
|
||||
+ return drops;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears, java.util.List<ItemStack> drops) {
|
||||
+ final ServerLevel worldserver1 = world; // Named for lambda consumption
|
||||
+ // Paper end - custom shear drops
|
||||
world.playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
this.setPumpkin(false);
|
||||
- this.dropFromShearingLootTable(world, BuiltInLootTables.SHEAR_SNOW_GOLEM, shears, (worldserver1, itemstack1) -> {
|
||||
+ drops.forEach(itemstack1 -> { // Paper - custom shear drops
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
this.spawnAtLocation(worldserver1, itemstack1, this.getEyeHeight());
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/animal/Squid.java
|
||||
+++ b/net/minecraft/world/entity/animal/Squid.java
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
public Squid(EntityType<? extends Squid> type, Level world) {
|
||||
super(type, world);
|
||||
- this.random.setSeed((long)this.getId());
|
||||
+ //this.random.setSeed((long)this.getId()); // Paper - Share random for entities to make them more random
|
||||
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
--- a/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -310,7 +310,9 @@
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
this.spawnAtLocation(worldserver, Items.TURTLE_SCUTE, 1);
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -339,7 +341,7 @@
|
||||
|
||||
@Override
|
||||
public void thunderHit(ServerLevel world, LightningBolt lightning) {
|
||||
- this.hurtServer(world, this.damageSources().lightningBolt(), Float.MAX_VALUE);
|
||||
+ this.hurtServer(world, this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -446,6 +448,10 @@
|
||||
if (entityplayer == null && this.partner.getLoveCause() != null) {
|
||||
entityplayer = this.partner.getLoveCause();
|
||||
}
|
||||
+ // Paper start - Add EntityFertilizeEggEvent event
|
||||
+ io.papermc.paper.event.entity.EntityFertilizeEggEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this.animal, this.partner);
|
||||
+ if (event.isCancelled()) return;
|
||||
+ // Paper end - Add EntityFertilizeEggEvent event
|
||||
|
||||
if (entityplayer != null) {
|
||||
entityplayer.awardStat(Stats.ANIMALS_BRED);
|
||||
@@ -460,7 +466,7 @@
|
||||
RandomSource randomsource = this.animal.getRandom();
|
||||
|
||||
if (getServerLevel((Level) this.level).getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1));
|
||||
+ if (event.getExperience() > 0) this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), event.getExperience(), org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper - Add EntityFertilizeEggEvent event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -492,16 +498,21 @@
|
||||
|
||||
if (!this.turtle.isInWater() && this.isReachedTarget()) {
|
||||
if (this.turtle.layEggCounter < 1) {
|
||||
- this.turtle.setLayingEgg(true);
|
||||
+ this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos)).callEvent()); // Paper - Turtle API
|
||||
} else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) {
|
||||
Level world = this.turtle.level();
|
||||
|
||||
+ // Paper start - Turtle API
|
||||
+ int eggCount = this.turtle.random.nextInt(4) + 1;
|
||||
+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos.above()), eggCount);
|
||||
+ if (layEggEvent.callEvent() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()))) {
|
||||
world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F);
|
||||
BlockPos blockposition1 = this.blockPos.above();
|
||||
- BlockState iblockdata = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1);
|
||||
+ BlockState iblockdata = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()); // Paper
|
||||
|
||||
world.setBlock(blockposition1, iblockdata, 3);
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata));
|
||||
+ } // CraftBukkit
|
||||
this.turtle.setHasEgg(false);
|
||||
this.turtle.setLayingEgg(false);
|
||||
this.turtle.setInLoveTime(600);
|
||||
@@ -567,7 +578,7 @@
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D)));
|
||||
+ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper - Turtle API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,13 @@
|
||||
--- a/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
+++ b/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
@@ -70,6 +70,10 @@
|
||||
) {
|
||||
int i = world.getSeaLevel();
|
||||
int j = i - 13;
|
||||
+ // Paper start - Make water animal spawn height configurable
|
||||
+ i = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(i);
|
||||
+ j = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(j);
|
||||
+ // Paper end - Make water animal spawn height configurable
|
||||
return pos.getY() >= j && pos.getY() <= i && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
--- a/net/minecraft/world/entity/animal/Wolf.java
|
||||
+++ b/net/minecraft/world/entity/animal/Wolf.java
|
||||
@@ -85,6 +85,12 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityDamageEvent;
|
||||
+import org.bukkit.event.entity.EntityRegainHealthEvent;
|
||||
+import org.bukkit.event.entity.EntityTargetEvent;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder<Holder<WolfVariant>> {
|
||||
|
||||
@@ -345,8 +351,14 @@
|
||||
if (this.isInvulnerableTo(world, source)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ boolean result = super.hurtServer(world, source, amount);
|
||||
+ if (!result) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.setOrderedToSit(false);
|
||||
- return super.hurtServer(world, source, amount);
|
||||
+ return result; // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,21 +368,27 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void actuallyHurt(ServerLevel world, DamageSource source, float amount) {
|
||||
- if (!this.canArmorAbsorb(source)) {
|
||||
- super.actuallyHurt(world, source, amount);
|
||||
+ public boolean actuallyHurt(ServerLevel worldserver, DamageSource damagesource, float f, EntityDamageEvent event) { // CraftBukkit - void -> boolean
|
||||
+ if (!this.canArmorAbsorb(damagesource)) {
|
||||
+ return super.actuallyHurt(worldserver, damagesource, f, event); // CraftBukkit
|
||||
} else {
|
||||
+ // CraftBukkit start - SPIGOT-7815: if the damage was cancelled, no need to run the wolf armor behaviour
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack itemstack = this.getBodyArmorItem();
|
||||
int i = itemstack.getDamageValue();
|
||||
int j = itemstack.getMaxDamage();
|
||||
|
||||
- itemstack.hurtAndBreak(Mth.ceil(amount), this, EquipmentSlot.BODY);
|
||||
+ itemstack.hurtAndBreak(Mth.ceil(f), this, EquipmentSlot.BODY);
|
||||
if (Crackiness.WOLF_ARMOR.byDamage(i, j) != Crackiness.WOLF_ARMOR.byDamage(this.getBodyArmorItem())) {
|
||||
this.playSound(SoundEvents.WOLF_ARMOR_CRACK);
|
||||
- world.sendParticles(new ItemParticleOption(ParticleTypes.ITEM, Items.ARMADILLO_SCUTE.getDefaultInstance()), this.getX(), this.getY() + 1.0D, this.getZ(), 20, 0.2D, 0.1D, 0.2D, 0.1D);
|
||||
+ worldserver.sendParticles(new ItemParticleOption(ParticleTypes.ITEM, Items.ARMADILLO_SCUTE.getDefaultInstance()), this.getX(), this.getY() + 1.0D, this.getZ(), 20, 0.2D, 0.1D, 0.2D, 0.1D);
|
||||
}
|
||||
|
||||
}
|
||||
+ return true; // CraftBukkit // Paper - return false ONLY if event was cancelled
|
||||
}
|
||||
|
||||
private boolean canArmorAbsorb(DamageSource source) {
|
||||
@@ -381,7 +399,7 @@
|
||||
protected void applyTamingSideEffects() {
|
||||
if (this.isTame()) {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(40.0D);
|
||||
- this.setHealth(40.0F);
|
||||
+ this.setHealth(this.getMaxHealth()); // CraftBukkit - 40.0 -> getMaxHealth()
|
||||
} else {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0D);
|
||||
}
|
||||
@@ -404,7 +422,7 @@
|
||||
FoodProperties foodinfo = (FoodProperties) itemstack.get(DataComponents.FOOD);
|
||||
float f = foodinfo != null ? (float) foodinfo.nutrition() : 1.0F;
|
||||
|
||||
- this.heal(2.0F * f);
|
||||
+ this.heal(2.0F * f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
if (item instanceof DyeItem) {
|
||||
@@ -414,6 +432,14 @@
|
||||
DyeColor enumcolor = itemdye.getDyeColor();
|
||||
|
||||
if (enumcolor != this.getCollarColor()) {
|
||||
+ // Paper start - Add EntityDyeEvent and CollarColorable interface
|
||||
+ final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) enumcolor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
|
||||
+ if (!event.callEvent()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ enumcolor = DyeColor.byId(event.getColor().getWoolData());
|
||||
+ // Paper end - Add EntityDyeEvent and CollarColorable interface
|
||||
+
|
||||
this.setCollarColor(enumcolor);
|
||||
itemstack.consume(1, player);
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -440,7 +466,9 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
this.spawnAtLocation(worldserver, itemstack1);
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -459,7 +487,7 @@
|
||||
this.setOrderedToSit(!this.isOrderedToSit());
|
||||
this.jumping = false;
|
||||
this.navigation.stop();
|
||||
- this.setTarget((LivingEntity) null);
|
||||
+ this.setTarget((LivingEntity) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason
|
||||
return InteractionResult.SUCCESS.withoutItem();
|
||||
} else {
|
||||
return enuminteractionresult;
|
||||
@@ -477,7 +505,8 @@
|
||||
}
|
||||
|
||||
private void tryToTame(Player player) {
|
||||
- if (this.random.nextInt(3) == 0) {
|
||||
+ // CraftBukkit - added event call and isCancelled check.
|
||||
+ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) {
|
||||
this.tame(player);
|
||||
this.navigation.stop();
|
||||
this.setTarget((LivingEntity) null);
|
||||
@@ -0,0 +1,102 @@
|
||||
--- a/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
+++ b/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
@@ -103,6 +103,7 @@
|
||||
private float dancingAnimationTicks;
|
||||
private float spinningAnimationTicks;
|
||||
private float spinningAnimationTicks0;
|
||||
+ public boolean forceDancing = false; // CraftBukkit
|
||||
|
||||
public Allay(EntityType<? extends Allay> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -114,6 +115,12 @@
|
||||
this.dynamicJukeboxListener = new DynamicGameEventListener<>(new Allay.JukeboxListener(this.vibrationUser.getPositionSource(), ((GameEvent) GameEvent.JUKEBOX_PLAY.value()).notificationRadius()));
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void setCanDuplicate(boolean canDuplicate) {
|
||||
+ this.entityData.set(Allay.DATA_CAN_DUPLICATE, canDuplicate);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
protected Brain.Provider<Allay> brainProvider() {
|
||||
return Brain.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES);
|
||||
@@ -126,7 +133,7 @@
|
||||
|
||||
@Override
|
||||
public Brain<Allay> getBrain() {
|
||||
- return super.getBrain();
|
||||
+ return (Brain<Allay>) super.getBrain(); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
@@ -233,7 +240,7 @@
|
||||
public void aiStep() {
|
||||
super.aiStep();
|
||||
if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) {
|
||||
- this.heal(1.0F);
|
||||
+ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
|
||||
}
|
||||
|
||||
if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) {
|
||||
@@ -303,7 +310,12 @@
|
||||
ItemStack itemstack1 = this.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
|
||||
if (this.isDancing() && itemstack.is(ItemTags.DUPLICATES_ALLAYS) && this.canDuplicate()) {
|
||||
- this.duplicateAllay();
|
||||
+ // CraftBukkit start - handle cancel duplication
|
||||
+ Allay allay = this.duplicateAllay();
|
||||
+ if (allay == null) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.level().broadcastEntityEvent(this, (byte) 18);
|
||||
this.level().playSound(player, (Entity) this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F);
|
||||
this.removeInteractionItem(player, itemstack);
|
||||
@@ -314,7 +326,7 @@
|
||||
this.setItemInHand(InteractionHand.MAIN_HAND, itemstack2);
|
||||
this.removeInteractionItem(player, itemstack);
|
||||
this.level().playSound(player, (Entity) this, SoundEvents.ALLAY_ITEM_GIVEN, SoundSource.NEUTRAL, 2.0F, 1.0F);
|
||||
- this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, (Object) player.getUUID());
|
||||
+ this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, player.getUUID()); // CraftBukkit - decompile error
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!itemstack1.isEmpty() && hand == InteractionHand.MAIN_HAND && itemstack.isEmpty()) {
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
||||
@@ -415,6 +427,7 @@
|
||||
}
|
||||
|
||||
private boolean shouldStopDancing() {
|
||||
+ if (this.forceDancing) {return false;} // CraftBukkit
|
||||
return this.jukeboxPos == null || !this.jukeboxPos.closerToCenterThan(this.position(), (double) ((GameEvent) GameEvent.JUKEBOX_PLAY.value()).notificationRadius()) || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX);
|
||||
}
|
||||
|
||||
@@ -486,7 +499,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
- this.duplicationCooldown = (long) nbt.getInt("DuplicationCooldown");
|
||||
+ this.duplicationCooldown = nbt.getLong("DuplicationCooldown"); // Paper - Load as long
|
||||
this.entityData.set(Allay.DATA_CAN_DUPLICATE, nbt.getBoolean("CanDuplicate"));
|
||||
}
|
||||
|
||||
@@ -506,7 +519,7 @@
|
||||
|
||||
}
|
||||
|
||||
- public void duplicateAllay() {
|
||||
+ public Allay duplicateAllay() { // CraftBukkit - return allay
|
||||
Allay allay = (Allay) EntityType.ALLAY.create(this.level(), EntitySpawnReason.BREEDING);
|
||||
|
||||
if (allay != null) {
|
||||
@@ -514,9 +527,9 @@
|
||||
allay.setPersistenceRequired();
|
||||
allay.resetDuplicationCooldown();
|
||||
this.resetDuplicationCooldown();
|
||||
- this.level().addFreshEntity(allay);
|
||||
+ this.level().addFreshEntity(allay, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DUPLICATION); // CraftBukkit - reason for duplicated allay
|
||||
}
|
||||
-
|
||||
+ return allay; // CraftBukkit
|
||||
}
|
||||
|
||||
public void resetDuplicationCooldown() {
|
||||
@@ -0,0 +1,81 @@
|
||||
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
@@ -47,6 +47,9 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityDamageEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Armadillo extends Animal {
|
||||
|
||||
@@ -135,16 +138,18 @@
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
gameprofilerfiller.push("armadilloBrain");
|
||||
- this.brain.tick(world, this);
|
||||
+ ((Brain<Armadillo>) this.brain).tick(world, this); // CraftBukkit - decompile error
|
||||
gameprofilerfiller.pop();
|
||||
gameprofilerfiller.push("armadilloActivityUpdate");
|
||||
ArmadilloAi.updateActivity(this);
|
||||
gameprofilerfiller.pop();
|
||||
if (this.isAlive() && !this.isBaby() && --this.scuteTime <= 0) {
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
if (this.dropFromGiftLootTable(world, BuiltInLootTables.ARMADILLO_SHED, this::spawnAtLocation)) {
|
||||
this.playSound(SoundEvents.ARMADILLO_SCUTE_DROP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
|
||||
this.gameEvent(GameEvent.ENTITY_PLACE);
|
||||
}
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
|
||||
this.scuteTime = this.pickNextScuteDropTime();
|
||||
}
|
||||
@@ -291,19 +296,25 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void actuallyHurt(ServerLevel world, DamageSource source, float amount) {
|
||||
- super.actuallyHurt(world, source, amount);
|
||||
+ // CraftBukkit start - void -> boolean
|
||||
+ public boolean actuallyHurt(ServerLevel worldserver, DamageSource damagesource, float f, EntityDamageEvent event) {
|
||||
+ boolean damageResult = super.actuallyHurt(worldserver, damagesource, f, event);
|
||||
+ if (!damageResult) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (!this.isNoAi() && !this.isDeadOrDying()) {
|
||||
- if (source.getEntity() instanceof LivingEntity) {
|
||||
+ if (damagesource.getEntity() instanceof LivingEntity) {
|
||||
this.getBrain().setMemoryWithExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY, true, 80L);
|
||||
if (this.canStayRolledUp()) {
|
||||
this.rollUp();
|
||||
}
|
||||
- } else if (source.is(DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES)) {
|
||||
+ } else if (damagesource.is(DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES)) {
|
||||
this.rollOut();
|
||||
}
|
||||
|
||||
}
|
||||
+ return true; // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -327,7 +338,9 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
+ this.forceDrops = true; // CraftBukkit
|
||||
this.spawnAtLocation(worldserver, new ItemStack(Items.ARMADILLO_SCUTE));
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
this.gameEvent(GameEvent.ENTITY_INTERACT);
|
||||
this.playSound(SoundEvents.ARMADILLO_BRUSH);
|
||||
}
|
||||
@@ -431,7 +444,7 @@
|
||||
}
|
||||
|
||||
public static Armadillo.ArmadilloState fromName(String name) {
|
||||
- return (Armadillo.ArmadilloState) Armadillo.ArmadilloState.CODEC.byName(name, (Enum) Armadillo.ArmadilloState.IDLE);
|
||||
+ return (Armadillo.ArmadilloState) Armadillo.ArmadilloState.CODEC.byName(name, Armadillo.ArmadilloState.IDLE); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,52 @@
|
||||
--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
+++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
@@ -67,10 +67,17 @@
|
||||
|
||||
public class Axolotl extends Animal implements VariantHolder<Axolotl.Variant>, Bucketable {
|
||||
|
||||
+ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
|
||||
+ @Override
|
||||
+ public int getDefaultMaxAirSupply() {
|
||||
+ return Axolotl.AXOLOTL_TOTAL_AIR_SUPPLY;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
public static final int TOTAL_PLAYDEAD_TIME = 200;
|
||||
private static final int POSE_ANIMATION_TICKS = 10;
|
||||
protected static final ImmutableList<? extends SensorType<? extends Sensor<? super Axolotl>>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS);
|
||||
- protected static final ImmutableList<? extends MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING});
|
||||
+ // CraftBukkit - decompile error
|
||||
+ protected static final ImmutableList<? extends MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.<MemoryModuleType<?>>of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING});
|
||||
private static final EntityDataAccessor<Integer> DATA_VARIANT = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Boolean> DATA_PLAYING_DEAD = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final EntityDataAccessor<Boolean> FROM_BUCKET = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.BOOLEAN);
|
||||
@@ -210,7 +217,7 @@
|
||||
|
||||
@Override
|
||||
public int getMaxAirSupply() {
|
||||
- return 6000;
|
||||
+ return this.maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -414,10 +421,10 @@
|
||||
int i = mobeffect != null ? mobeffect.getDuration() : 0;
|
||||
int j = Math.min(2400, 100 + i);
|
||||
|
||||
- player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this);
|
||||
+ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 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
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -464,7 +471,7 @@
|
||||
|
||||
@Override
|
||||
public Brain<Axolotl> getBrain() {
|
||||
- return super.getBrain();
|
||||
+ return (Brain<Axolotl>) super.getBrain(); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,81 @@
|
||||
--- a/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
+++ b/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
@@ -49,6 +49,9 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityDamageEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class Camel extends AbstractHorse {
|
||||
|
||||
@@ -143,7 +146,7 @@
|
||||
ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
|
||||
gameprofilerfiller.push("camelBrain");
|
||||
- Brain<?> behaviorcontroller = this.getBrain();
|
||||
+ Brain<Camel> behaviorcontroller = (Brain<Camel>) this.getBrain(); // CraftBukkit - decompile error
|
||||
|
||||
behaviorcontroller.tick(world, this);
|
||||
gameprofilerfiller.pop();
|
||||
@@ -386,13 +389,13 @@
|
||||
boolean flag = this.getHealth() < this.getMaxHealth();
|
||||
|
||||
if (flag) {
|
||||
- this.heal(2.0F);
|
||||
+ this.heal(2.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper - Add missing regain reason
|
||||
}
|
||||
|
||||
boolean flag1 = this.isTamed() && this.getAge() == 0 && this.canFallInLove();
|
||||
|
||||
if (flag1) {
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
|
||||
}
|
||||
|
||||
boolean flag2 = this.isBaby();
|
||||
@@ -454,9 +457,15 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void actuallyHurt(ServerLevel world, DamageSource source, float amount) {
|
||||
+ // CraftBukkit start - void -> boolean
|
||||
+ public boolean actuallyHurt(ServerLevel worldserver, DamageSource damagesource, float f, EntityDamageEvent event) {
|
||||
+ boolean damageResult = super.actuallyHurt(worldserver, damagesource, f, event);
|
||||
+ if (!damageResult) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.standUpInstantly();
|
||||
- super.actuallyHurt(world, source, amount);
|
||||
+ return true; // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -563,7 +572,7 @@
|
||||
}
|
||||
|
||||
public void sitDown() {
|
||||
- if (!this.isCamelSitting()) {
|
||||
+ if (!this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), true).callEvent()) { // Paper - Add EntityToggleSitEvent
|
||||
this.makeSound(SoundEvents.CAMEL_SIT);
|
||||
this.setPose(Pose.SITTING);
|
||||
this.gameEvent(GameEvent.ENTITY_ACTION);
|
||||
@@ -572,7 +581,7 @@
|
||||
}
|
||||
|
||||
public void standUp() {
|
||||
- if (this.isCamelSitting()) {
|
||||
+ if (this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) { // Paper - Add EntityToggleSitEvent
|
||||
this.makeSound(SoundEvents.CAMEL_STAND);
|
||||
this.setPose(Pose.STANDING);
|
||||
this.gameEvent(GameEvent.ENTITY_ACTION);
|
||||
@@ -581,6 +590,7 @@
|
||||
}
|
||||
|
||||
public void standUpInstantly() {
|
||||
+ if (this.isCamelSitting() && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) return; // Paper - Add EntityToggleSitEvent
|
||||
this.setPose(Pose.STANDING);
|
||||
this.gameEvent(GameEvent.ENTITY_ACTION);
|
||||
this.resetLastPoseChangeTickToFullStand(this.level().getGameTime());
|
||||
@@ -0,0 +1,16 @@
|
||||
--- a/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
@@ -270,7 +270,12 @@
|
||||
|
||||
@Override
|
||||
public void spawnChildFromBreeding(ServerLevel world, Animal other) {
|
||||
- this.finalizeSpawnChildFromBreeding(world, other, null);
|
||||
+ // Paper start - Add EntityFertilizeEggEvent event
|
||||
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
|
||||
+ if (result.isCancelled()) return;
|
||||
+
|
||||
+ this.finalizeSpawnChildFromBreeding(world, other, null, result.getExperience()); // Paper - use craftbukkit call that takes experience amount
|
||||
+ // Paper end - Add EntityFertilizeEggEvent event
|
||||
this.getBrain().setMemory(MemoryModuleType.IS_PREGNANT, Unit.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
--- a/net/minecraft/world/entity/animal/frog/ShootTongue.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/ShootTongue.java
|
||||
@@ -19,6 +19,9 @@
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ShootTongue extends Behavior<Frog> {
|
||||
|
||||
@@ -64,7 +67,7 @@
|
||||
|
||||
BehaviorUtils.lookAtEntity(frog, entityliving);
|
||||
frog.setTongueTarget(entityliving);
|
||||
- frog.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(entityliving.position(), 2.0F, 0)));
|
||||
+ frog.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(entityliving.position(), 2.0F, 0))); // CraftBukkit - decompile error
|
||||
this.calculatePathCounter = 10;
|
||||
this.state = ShootTongue.State.MOVE_TO_TARGET;
|
||||
}
|
||||
@@ -85,7 +88,7 @@
|
||||
if (entity.isAlive()) {
|
||||
frog.doHurtTarget(world, entity);
|
||||
if (!entity.isAlive()) {
|
||||
- entity.remove(Entity.RemovalReason.KILLED);
|
||||
+ entity.remove(Entity.RemovalReason.KILLED, EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +109,7 @@
|
||||
this.eatAnimationTimer = 0;
|
||||
this.state = ShootTongue.State.CATCH_ANIMATION;
|
||||
} else if (this.calculatePathCounter <= 0) {
|
||||
- frog.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(entityliving.position(), 2.0F, 0)));
|
||||
+ frog.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(entityliving.position(), 2.0F, 0))); // CraftBukkit - decompile error
|
||||
this.calculatePathCounter = 10;
|
||||
} else {
|
||||
--this.calculatePathCounter;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user