net/minecraft/world/entity/ai/behavior/

This commit is contained in:
Owen1212055
2024-12-14 17:25:17 -05:00
parent 4707f46b25
commit d096e6baaf
34 changed files with 324 additions and 560 deletions

View File

@@ -1,10 +0,0 @@
--- 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 -> {

View File

@@ -1,31 +0,0 @@
--- 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;

View File

@@ -1,37 +0,0 @@
--- 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));

View File

@@ -1,40 +0,0 @@
--- 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);

View File

@@ -1,64 +0,0 @@
--- 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;

View File

@@ -1,11 +0,0 @@
--- 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(

View File

@@ -1,24 +0,0 @@
--- 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));

View File

@@ -1,63 +0,0 @@
--- 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
}
}
}

View File

@@ -1,39 +0,0 @@
--- 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);

View File

@@ -1,73 +0,0 @@
--- 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);

View File

@@ -1,11 +0,0 @@
--- 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)) {

View File

@@ -1,31 +0,0 @@
--- 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 {

View File

@@ -1,44 +0,0 @@
--- 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() {

View File

@@ -1,12 +0,0 @@
--- 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);
}
}

View File

@@ -1,36 +0,0 @@
--- 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;

View File

@@ -1,46 +0,0 @@
--- 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;

View File

@@ -1,15 +0,0 @@
--- 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);

View File

@@ -1,11 +0,0 @@
--- 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(

View File

@@ -1,42 +0,0 @@
--- 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
}
}

View File

@@ -1,12 +0,0 @@
--- 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
}
}
}