mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 15:49:00 +01:00
Optimise nearby player retrieval
Instead of searching/testing every player online on the server, we can instead use the nearby player tracking system to reduce the number of tests per search.
This commit is contained in:
parent
9abaff8a66
commit
0ef267f0e7
1 changed files with 162 additions and 0 deletions
162
patches/server/Optimise-nearby-player-retrieval.patch
Normal file
162
patches/server/Optimise-nearby-player-retrieval.patch
Normal file
|
@ -0,0 +1,162 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 23 Sep 2023 23:15:52 -0700
|
||||
Subject: [PATCH] Optimise nearby player retrieval
|
||||
|
||||
Instead of searching/testing every player online on the server,
|
||||
we can instead use the nearby player tracking system to reduce
|
||||
the number of tests per search.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
this.lagCompensationTick = (System.nanoTime() - net.minecraft.server.MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
|
||||
}
|
||||
// Paper end - lag compensation
|
||||
+ // Paper start - optimise nearby player retrieval
|
||||
+ @Override
|
||||
+ public java.util.List<net.minecraft.world.entity.player.Player> getNearbyPlayers(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate,
|
||||
+ net.minecraft.world.entity.LivingEntity entity,
|
||||
+ net.minecraft.world.phys.AABB box) {
|
||||
+ return this.getNearbyEntities(Player.class, targetPredicate, entity, box);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate<Entity> targetPredicate) {
|
||||
+ if (maxDistance > 0.0D) {
|
||||
+ io.papermc.paper.util.player.NearbyPlayers players = this.chunkSource.chunkMap.getNearbyPlayers();
|
||||
+
|
||||
+ com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> nearby = players.getPlayersByBlock(
|
||||
+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(x),
|
||||
+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(z),
|
||||
+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL
|
||||
+ );
|
||||
+
|
||||
+ if (nearby == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ ServerPlayer nearest = null;
|
||||
+ double nearestDist = maxDistance * maxDistance;
|
||||
+ Object[] rawData = nearby.getRawData();
|
||||
+ for (int i = 0, len = nearby.size(); i < len; ++i) {
|
||||
+ ServerPlayer player = (ServerPlayer)rawData[i];
|
||||
+ double dist = player.distanceToSqr(x, y, z);
|
||||
+ if (dist >= nearestDist) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (targetPredicate == null || targetPredicate.test(player)) {
|
||||
+ nearest = player;
|
||||
+ nearestDist = dist;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return nearest;
|
||||
+ } else {
|
||||
+ ServerPlayer nearest = null;
|
||||
+ double nearestDist = Double.MAX_VALUE;
|
||||
+
|
||||
+ for (ServerPlayer player : this.players()) {
|
||||
+ double dist = player.distanceToSqr(x, y, z);
|
||||
+ if (dist >= nearestDist) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (targetPredicate == null || targetPredicate.test(player)) {
|
||||
+ nearest = player;
|
||||
+ nearestDist = dist;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return nearest;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, LivingEntity entity) {
|
||||
+ return this.getNearestPlayer(targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, LivingEntity entity,
|
||||
+ double x, double y, double z) {
|
||||
+ double range = targetPredicate.range;
|
||||
+ if (range > 0.0D) {
|
||||
+ io.papermc.paper.util.player.NearbyPlayers players = this.chunkSource.chunkMap.getNearbyPlayers();
|
||||
+
|
||||
+ com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> nearby = players.getPlayersByBlock(
|
||||
+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(x),
|
||||
+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(z),
|
||||
+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL
|
||||
+ );
|
||||
+
|
||||
+ if (nearby == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ ServerPlayer nearest = null;
|
||||
+ double nearestDist = Double.MAX_VALUE;
|
||||
+ Object[] rawData = nearby.getRawData();
|
||||
+ for (int i = 0, len = nearby.size(); i < len; ++i) {
|
||||
+ ServerPlayer player = (ServerPlayer)rawData[i];
|
||||
+ double dist = player.distanceToSqr(x, y, z);
|
||||
+ if (dist >= nearestDist) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (targetPredicate.test(entity, player)) {
|
||||
+ nearest = player;
|
||||
+ nearestDist = dist;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return nearest;
|
||||
+ } else {
|
||||
+ return this.getNearestEntity(this.players(), targetPredicate, entity, x, y, z);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, double x, double y, double z) {
|
||||
+ return this.getNearestPlayer(targetPredicate, null, x, y, z);
|
||||
+ }
|
||||
+ // Paper end - optimise nearby player retrieval
|
||||
|
||||
// Add env and gen to constructor, IWorldDataServer -> WorldDataServer
|
||||
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
@@ -0,0 +0,0 @@ public class TargetingConditions {
|
||||
public static final TargetingConditions DEFAULT = forCombat();
|
||||
private static final double MIN_VISIBILITY_DISTANCE_FOR_INVISIBLE_TARGET = 2.0D;
|
||||
private final boolean isCombat;
|
||||
- private double range = -1.0D;
|
||||
+ public double range = -1.0D; // Paper - public
|
||||
private boolean checkLineOfSight = true;
|
||||
private boolean testInvisible = true;
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
@@ -0,0 +0,0 @@ public interface EntityGetter {
|
||||
T livingEntity = null;
|
||||
|
||||
for(T livingEntity2 : entityList) {
|
||||
+ // Paper start - move up
|
||||
+ // don't check entities outside closest range
|
||||
+ double e = livingEntity2.distanceToSqr(x, y, z);
|
||||
+ if (d == -1.0D || e < d) {
|
||||
+ // Paper end - move up
|
||||
if (targetPredicate.test(entity, livingEntity2)) {
|
||||
- double e = livingEntity2.distanceToSqr(x, y, z);
|
||||
- if (d == -1.0D || e < d) {
|
||||
+ // Paper - move up
|
||||
d = e;
|
||||
livingEntity = livingEntity2;
|
||||
}
|
Loading…
Reference in a new issue