Paper/patches/server/0079-EntityPathfindEvent.patch
Spottedleaf 01a13871de
Rewrite chunk system (#8177)
Patch documentation to come

Issues with the old system that are fixed now:
- World generation does not scale with cpu cores effectively.
- Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps.
- Unreliable prioritisation of chunk gen/load calls that block the main thread.
- Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved.
- Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal.
- Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles.

The above list is not complete. The patch documentation will complete it.

New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil.

Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft.

The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 01:02:51 -07:00

150 lines
7.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 28 Mar 2016 21:22:26 -0400
Subject: [PATCH] EntityPathfindEvent
Fires when an Entity decides to start moving to a location.
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
index 0b2e10a0f508448d9e7d003e6c822f0a56d4022f..27cd393e81f6ef9b5690c051624d8d2af50acd34 100644
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
@@ -35,7 +35,7 @@ public class FlyingPathNavigation extends PathNavigation {
@Override
public Path createPath(Entity entity, int distance) {
- return this.createPath(entity.blockPosition(), distance);
+ return this.createPath(entity.blockPosition(), entity, distance); // Paper - Forward target entity
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
index 27b072943328aca4489a9565bda700e7e7dcbb6a..f0248d839255763005ba333b0bfcf691407fb69b 100644
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
@@ -39,14 +39,14 @@ public class GroundPathNavigation extends PathNavigation {
}
@Override
- public Path createPath(BlockPos target, int distance) {
+ public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper
if (this.level.getBlockState(target).isAir()) {
BlockPos blockPos;
for(blockPos = target.below(); blockPos.getY() > this.level.getMinBuildHeight() && this.level.getBlockState(blockPos).isAir(); blockPos = blockPos.below()) {
}
if (blockPos.getY() > this.level.getMinBuildHeight()) {
- return super.createPath(blockPos.above(), distance);
+ return super.createPath(blockPos.above(), entity, distance); // Paper
}
while(blockPos.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(blockPos).isAir()) {
@@ -57,19 +57,19 @@ public class GroundPathNavigation extends PathNavigation {
}
if (!this.level.getBlockState(target).getMaterial().isSolid()) {
- return super.createPath(target, distance);
+ return super.createPath(target, entity, distance); // Paper
} else {
BlockPos blockPos2;
for(blockPos2 = target.above(); blockPos2.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(blockPos2).getMaterial().isSolid(); blockPos2 = blockPos2.above()) {
}
- return super.createPath(blockPos2, distance);
+ return super.createPath(blockPos2, entity, distance); // Paper
}
}
@Override
public Path createPath(Entity entity, int distance) {
- return this.createPath(entity.blockPosition(), distance);
+ return this.createPath(entity.blockPosition(), entity, distance); // Paper - Forward target entity
}
private int getSurfaceY() {
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
index eaf1653b14e5fdacae38abe75260a64d0ffbfc1d..30f58f1829d1b500ee49b543e3c15e5bfe63fade 100644
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java
@@ -108,7 +108,13 @@ public abstract class PathNavigation {
@Nullable
public Path createPath(BlockPos target, int distance) {
- return this.createPath(ImmutableSet.of(target), 8, false, distance);
+ // Paper start - add target entity parameter
+ 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
}
@Nullable
@@ -118,7 +124,7 @@ public abstract class PathNavigation {
@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
}
@Nullable
@@ -128,6 +134,16 @@ public abstract class PathNavigation {
@Nullable
protected Path createPath(Set<BlockPos> positions, int range, boolean useHeadPos, int distance, float followRange) {
+ 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
if (positions.isEmpty()) {
return null;
} else if (this.mob.getY() < (double)this.level.getMinBuildHeight()) {
@@ -137,6 +153,23 @@ public abstract class PathNavigation {
} else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) {
return this.path;
} else {
+ // Paper start - Pathfind event
+ boolean copiedSet = false;
+ for (BlockPos possibleTarget : positions) {
+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(),
+ net.minecraft.server.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
this.level.getProfiler().push("pathfind");
BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition();
int i = (int)(followRange + (float)range);
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
index d11e9f4f7ae5f2666d67878309b4a1359ef90e39..de1f178fa18ae3ff3c73bc59b10eb39857800bf9 100644
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
@@ -16,9 +16,9 @@ public class WallClimberNavigation extends GroundPathNavigation {
}
@Override
- public Path createPath(BlockPos target, int distance) {
+ public Path createPath(BlockPos target, @Nullable Entity entity, int distance) { // Paper
this.pathToPosition = target;
- return super.createPath(target, distance);
+ return super.createPath(target, entity, distance); // Paper
}
@Override