Added pathfinder thread pool

This commit is contained in:
Felix Cravic 2020-08-09 21:56:01 +02:00
parent 55aeac7530
commit 644c1d9a71
5 changed files with 52 additions and 26 deletions

View File

@ -64,6 +64,9 @@ public class MinecraftServer {
public static final String THREAD_NAME_TICK = "Ms-Tick";
public static final String THREAD_NAME_PATHFINDER = "Ms-PathFinding";
public static final int THREAD_COUNT_PATHFINDER = 2;
public static final String THREAD_NAME_PACKET_WRITER = "Ms-PacketWriterPool";
public static final int THREAD_COUNT_PACKET_WRITER = 2;

View File

@ -27,6 +27,7 @@ public class BenchmarkManager {
threadMXBean.setThreadCpuTimeEnabled(true);
threads.add(THREAD_NAME_MAIN_UPDATE);
threads.add(THREAD_NAME_PATHFINDER);
threads.add(THREAD_NAME_PACKET_WRITER);
threads.add(THREAD_NAME_BLOCK_BATCH);
threads.add(THREAD_NAME_SCHEDULER);

View File

@ -7,6 +7,7 @@ import net.minestom.server.attribute.Attribute;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.entity.ai.TargetSelector;
import net.minestom.server.entity.pathfinding.PFPathingEntity;
import net.minestom.server.entity.pathfinding.PathfinderManager;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.item.ArmorEquipEvent;
import net.minestom.server.instance.Chunk;
@ -31,6 +32,8 @@ import java.util.function.Supplier;
public abstract class EntityCreature extends LivingEntity {
private static final PathfinderManager PATHFINDER_MANAGER = new PathfinderManager();
private PFPathingEntity pathingEntity = new PFPathingEntity(this);
private HydrazinePathFinder pathFinder;
private PathObject path;
@ -51,7 +54,6 @@ public abstract class EntityCreature extends LivingEntity {
private ItemStack leggings;
private ItemStack boots;
// Lock used for the pathfinder
private ReentrantLock pathLock = new ReentrantLock();
@ -121,19 +123,25 @@ public abstract class EntityCreature extends LivingEntity {
// Path finding
{
this.pathLock.lock();
path = pathFinder.updatePathFor(pathingEntity);
if (path != null) {
final float speed = getAttributeValue(Attribute.MOVEMENT_SPEED);
final Position targetPosition = pathingEntity.getTargetPosition();
moveTowards(targetPosition, speed);
} else {
if (pathPosition != null) {
this.pathPosition = null;
this.pathFinder.reset();
}
if (pathPosition != null) {
PATHFINDER_MANAGER.getPool().execute(() -> {
this.pathLock.lock();
this.path = pathFinder.updatePathFor(pathingEntity);
if (path != null) {
final float speed = getAttributeValue(Attribute.MOVEMENT_SPEED);
final Position targetPosition = pathingEntity.getTargetPosition();
moveTowards(targetPosition, speed);
} else {
if (pathPosition != null) {
this.pathPosition = null;
this.pathFinder.reset();
}
}
this.pathLock.unlock();
});
}
this.pathLock.unlock();
}
super.update(time);
@ -339,35 +347,33 @@ public abstract class EntityCreature extends LivingEntity {
}
this.pathLock.lock();
this.pathFinder.reset();
if (position == null) {
this.pathLock.unlock();
return false;
}
// Can't path outside of the world border
final WorldBorder worldBorder = instance.getWorldBorder();
if (!worldBorder.isInside(position)) {
this.pathLock.unlock();
return false;
}
// Can't path in an unloaded chunk
final Chunk chunk = instance.getChunkAt(position);
if (ChunkUtils.isChunkUnloaded(chunk)) {
this.pathLock.unlock();
return false;
}
position = position.clone();
final Position targetPosition = position.clone();
try {
this.path = pathFinder.initiatePathTo(position.getX(), position.getY(), position.getZ());
} catch (NullPointerException | IndexOutOfBoundsException e) {
this.path = null;
}
this.path = pathFinder.initiatePathTo(position.getX(), position.getY(), position.getZ());
this.pathLock.unlock();
final boolean success = path != null;
this.pathPosition = success ? position : null;
this.pathPosition = success ? targetPosition : null;
return success;
}

View File

@ -6,7 +6,6 @@ import com.extollit.gaming.ai.path.model.IInstanceSpace;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.validate.Check;
import java.util.HashMap;
import java.util.Map;
@ -30,9 +29,10 @@ public class PFInstanceSpace implements IInstanceSpace {
@Override
public IColumnarSpace columnarSpaceAt(int cx, int cz) {
final Chunk chunk = instance.getChunk(cx, cz);
Check.notNull(chunk,
"The pathfinder tried to get the unloaded chunk [" + cx + ":" + cz + "]," +
" try to lower the search range or to load the chunk manually");
if (chunk == null) {
return null;
}
final PFColumnarSpace columnarSpace =
chunkSpaceMap.computeIfAbsent(chunk, c -> {
final PFColumnarSpace cs = new PFColumnarSpace(this, c);

View File

@ -0,0 +1,16 @@
package net.minestom.server.entity.pathfinding;
import net.minestom.server.MinecraftServer;
import net.minestom.server.utils.thread.MinestomThread;
import java.util.concurrent.ExecutorService;
public final class PathfinderManager {
private ExecutorService pathfinderPool = new MinestomThread(MinecraftServer.THREAD_COUNT_PATHFINDER, MinecraftServer.THREAD_NAME_PATHFINDER);
public ExecutorService getPool() {
return pathfinderPool;
}
}