Compare commits

..

19 Commits

Author SHA1 Message Date
Sofiane H. Djerbi
7278888017 Avoid manipulating null paths 2023-08-01 01:58:54 +02:00
Sofiane H. Djerbi
d1a9c55403 Final changes 2023-08-01 00:03:12 +02:00
Sofiane H. Djerbi
29fabdd8f3 Set default queue to 1000 2023-07-31 20:05:22 +02:00
Sofiane H. Djerbi
ae1f11a394 Log async threads for pathfinding 2023-07-31 19:39:12 +02:00
Sofiane H. Djerbi
b45f3843c2 Add NodeEvaluatorType and use it in cache 2023-07-31 18:05:48 +02:00
Sofiane H. Djerbi
8e31fc9945 0 threads if not enabled 2023-07-31 05:12:28 +02:00
Sofiane H. Djerbi
ccd629843c Add thread options & improve thread control 2023-07-31 01:09:51 +02:00
Sofiane H. Djerbi
ada5265608 Fix TargetGoal autism 2023-07-30 23:05:19 +02:00
Sofiane H. Djerbi
f508c9cd84 Remove redundant isDone call (Raise exception) 2023-07-30 20:20:35 +02:00
Sofiane H. Djerbi
e6c765ef71 Add async pathfinding to warden 2023-07-30 18:19:31 +02:00
Sofiane H. Djerbi
cb1b2a78ac Add processing check back 2023-07-30 02:22:58 +02:00
Sofiane H. Djerbi
ad43ef6000 Add async pathfinding to WaterBound mobs & Strider 2023-07-29 22:57:38 +02:00
Sofiane H. Djerbi
eb571af123 Rework nodeEvaluatorGenerator cache 2023-07-29 22:24:44 +02:00
Sofiane H. Djerbi
9925aa59c7 Rebase nodeEvaluatorGenerator 2023-07-29 16:28:11 +02:00
Sofiane H. Djerbi
2dc38b4f88 [skip ci] credit peaches94 2023-07-25 02:51:21 +03:00
Sofiane H. Djerbi
4401555131 Fix mob in the water issue 2023-07-25 02:39:58 +03:00
Sofiane H. Djerbi
6da53043d4 Use the correct thread context to postprocess path 2023-07-25 02:28:47 +03:00
Sofiane H. Djerbi
ea1493dd8f Use local pool 2023-07-24 23:30:21 +03:00
Sofiane H. Djerbi
e18e9091fb Base asyncpathprocessing patch from petal 2023-07-24 21:08:06 +03:00
9 changed files with 89 additions and 612 deletions

View File

@@ -11,14 +11,13 @@
## Features ## Features
### Notable ### Primary
- **Xymb Linear Format**: A Region file format that reduces disk space usage by about 50%. - **Xymb Linear Format**: Saves about 50% of disk space in OW/Nether and 95% in The End.
- **Async Pathfinding**: Petal async pathfinding fixed & reworked. - **Auto update**: Automatic upstream updates.
- **Technical Minecraft**: Enable Vanilla exploits such as sand duping, RNG manipulation...
### Other ### Notable
- **Small optimizations**: Increase server efficiency by disabling unnecessary features. - **Entity throttling & removal**: Tweak entity tick frequency & max entity per region.
- **Commands**: Restore few commands that were previously removed by Folia. - **Technical Minecraft**: Enable Vanilla exploits such as sand duping, RNG manipulation...
### Configuration ### Configuration
@@ -26,31 +25,16 @@
network: network:
send-null-entity-packets: true send-null-entity-packets: true
alternate-keepalive: false alternate-keepalive: false
kick-player-on-bad-packet: true
gameplay:
server-mod-name: Kaiiju
shared-random-for-players: true
region-format:
debug: false
optimization: optimization:
disable-vanish-api: false disable-vanish-api: false
disable-player-stats: false disable-player-stats: false
disable-arm-swing-event: false disable-arm-swing-event: false
disable-ensure-tick-thread-checks: false disable-ensure-tick-thread-checks: false
async-path-processing: gameplay:
enable: false server-mod-name: Kaiiju
max-threads: 0 shared-random-for-players: true
keepalive: 60
queue-capacity: 4096
world-settings: world-settings:
default: default:
gameplay:
fix-void-trading: true
break-redstone-on-top-of-trap-doors-early: true
fix-tripwire-state-inconsistency: true
safe-teleportation: true
sand-duplication: false
teleport-async-on-high-velocity: false
region-format: region-format:
format: ANVIL format: ANVIL
linear: linear:
@@ -58,22 +42,25 @@ world-settings:
crash-on-broken-symlink: true crash-on-broken-symlink: true
optimization: optimization:
shulker-box-drop-contents-when-destroyed: true shulker-box-drop-contents-when-destroyed: true
optimize-hoppers: true
tick-when-empty: true
enable-entity-throttling: false enable-entity-throttling: false
disable-achievements: false disable-achievements: false
disable-creatures-spawn-events: false disable-creatures-spawn-events: false
disable-dolphin-swim-to-treasure: false disable-dolphin-swim-to-treasure: false
gameplay:
fix-void-trading: true
optimize-hoppers: true
tick-when-empty: true
break-redstone-on-top-of-trap-doors-early: true
fix-tripwire-state-inconsistency: true
safe-teleportation: true
sand-duplication: false
``` ```
Documentation: [Kaiiju Wiki](https://github.com/KaiijuMC/Kaiiju/wiki/Configuration) Documentation: [Kaiiju Wiki](https://github.com/KaiijuMC/Kaiiju/wiki/Configuration)
### Roadmap ### Roadmap
- **Stash deduplication**: Make giant dupe stashes possible and lagless. - **Static view distance**: Reduce RAM usage / Region size with a "static" view distance.
- **Multithreaded Tracker**: Rework Petal multithreaded tracker.
## Open to contributions
- **Native world conversion**: Convert region file format at startup. - **Native world conversion**: Convert region file format at startup.
- **Performance patch**: Any significative performance patch. - **Stash deduplication**: Make giant dupe stashes possible and lagless.
## Building ## Building

View File

@@ -2,7 +2,7 @@ group = dev.kaiijumc.kaiiju
version = 1.20.1-R0.1-SNAPSHOT version = 1.20.1-R0.1-SNAPSHOT
mcVersion = 1.20.1 mcVersion = 1.20.1
foliaRef = b2d7bdb0bb5c841b4ccd096c0181664664ce97b1 foliaRef = daacd4255022f3a1bf74dd3e84f751be838678ac
org.gradle.caching=true org.gradle.caching=true
org.gradle.parallel=true org.gradle.parallel=true

View File

@@ -42,7 +42,7 @@ index abf5e2a06af9853b58ac9107cd6e9787c4185c66..389c68c0becd2f69dc1004d0b383f1a8
long expectedChunks = (long)regionFiles.length * (32L * 32L); long expectedChunks = (long)regionFiles.length * (32L * 32L);
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index c4d28d887b4cc71dc713b1e3f46bc80f4484a95d..f50507ab85282d261985ce9b186581f5a7a50f79 100644 index 61c6bc2859235874aefac71e9e55162f0a89f29f..24bd63c596c9f61f1e89ec5b001b7cb7a29a09ff 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -269,7 +269,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -269,7 +269,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -64,7 +64,7 @@ index c4d28d887b4cc71dc713b1e3f46bc80f4484a95d..f50507ab85282d261985ce9b186581f5
// Paper start // Paper start
this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new); this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 7099a44a2322ab390c21e74668c8657dcc9e5e87..475554797ffc279243ac0d88f1e619c3dd07bc4b 100644 index 4774d3f357d62b0818b4713f8085d05be09eaa5c..1bbd8b475cdc57fb15ca05ffe122220a5539da10 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -426,8 +426,8 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -426,8 +426,8 @@ public class ServerLevel extends Level implements WorldGenLevel {

View File

@@ -22,7 +22,7 @@ index f3f824d0ab1a2a72825c40b67192386479a0b34c..95ed6cb7b94797187d1011cab344e187
} }
} }
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 475554797ffc279243ac0d88f1e619c3dd07bc4b..475d0f3dd38e0407fa120d57e7d89216836538dd 100644 index 1bbd8b475cdc57fb15ca05ffe122220a5539da10..7f39e36037d55278d15399196459e51b885c5d1e 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2838,7 +2838,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -2838,7 +2838,7 @@ public class ServerLevel extends Level implements WorldGenLevel {

View File

@@ -22,7 +22,7 @@ index 6d7356cc07da58b1cef8d8963e790251d765de2c..601b9867d839f4928ba993ee8f00df9c
public boolean fixVoidTrading = true; public boolean fixVoidTrading = true;
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 475d0f3dd38e0407fa120d57e7d89216836538dd..245c3e63588379f51780963ba91bc6bf0a3feda6 100644 index 7f39e36037d55278d15399196459e51b885c5d1e..66509fa23bfcde70abd3917eb774cf48d5d6da93 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -798,7 +798,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -798,7 +798,7 @@ public class ServerLevel extends Level implements WorldGenLevel {

View File

@@ -319,7 +319,7 @@ index 991e4c19763a34a6fead88363e007c2d11aad836..24a2d3f496727790f63cb66a2534d442
dev.kaiijumc.kaiiju.KaiijuConfig.registerCommands(); dev.kaiijumc.kaiiju.KaiijuConfig.registerCommands();
// Kaiiju end // Kaiiju end
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 245c3e63588379f51780963ba91bc6bf0a3feda6..6efc8b37d4ee929522f5646c972565b99aa45de3 100644 index 245c3e63588379f51780963ba91bc6bf0a3feda6..761019f86983daaea4fface519e052f8fb6de1cd 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -822,6 +822,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -822,6 +822,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -337,7 +337,7 @@ index 245c3e63588379f51780963ba91bc6bf0a3feda6..6efc8b37d4ee929522f5646c972565b9
+ // Kaiiju start + // Kaiiju start
+ if (kaiijuConfig.enableEntityThrottling) { + if (kaiijuConfig.enableEntityThrottling) {
+ dev.kaiijumc.kaiiju.KaiijuEntityThrottler.EntityThrottlerReturn throttle = regionizedWorldData.entityThrottler.tickLimiterShouldSkip(entity); + dev.kaiijumc.kaiiju.KaiijuEntityThrottler.EntityThrottlerReturn throttle = regionizedWorldData.entityThrottler.tickLimiterShouldSkip(entity);
+ if (throttle.remove && !entity.hasCustomName()) entity.remove(Entity.RemovalReason.DISCARDED); + if (throttle.remove) entity.remove(Entity.RemovalReason.DISCARDED);
+ if (throttle.skip) return; + if (throttle.skip) return;
+ } + }
+ // Kaiiju end + // Kaiiju end

View File

@@ -5,15 +5,12 @@ Subject: [PATCH] Vanilla end portal teleportation
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index b971f35b69a930dddcf603207f524dc95e09f0fd..03895d35c02ff9422aaa0177eb0aa40e03fdc925 100644 index b971f35b69a930dddcf603207f524dc95e09f0fd..135573308662845ecc73fde1c620345e1f372538 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java --- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4029,12 +4029,17 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { @@ -4031,10 +4031,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
targetPos, 16, // load 16 blocks to be safe from block physics
ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH,
(chunks) -> { (chunks) -> {
- ServerLevel.makeObsidianPlatform(destination, null, targetPos); ServerLevel.makeObsidianPlatform(destination, null, targetPos);
+ //ServerLevel.makeObsidianPlatform(destination, null, targetPos); // Kaiiju - Vanilla end teleportation - moved down
+ // Kaiiju start - Vanilla end teleportation + // Kaiiju start - Vanilla end teleportation
+ Vec3 finalPos; + Vec3 finalPos;
@@ -28,23 +25,3 @@ index b971f35b69a930dddcf603207f524dc95e09f0fd..03895d35c02ff9422aaa0177eb0aa40e
); );
} }
); );
@@ -4221,6 +4226,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (!this.canPortalAsync(takePassengers)) {
return false;
}
+ // Kaiiju start - sync end platform spawning & entity teleportation
+ final java.util.function.Consumer<Entity> tpComplete = type == PortalType.END && destination.getTypeKey() == LevelStem.END ?
+ e -> ServerLevel.makeObsidianPlatform(destination, null, ServerLevel.END_SPAWN_POINT) : teleportComplete;
+ // Kaiiju end
Vec3 initialPosition = this.position();
ChunkPos initialPositionChunk = new ChunkPos(
@@ -4279,7 +4288,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
// place
passengerTree.root.placeInAsync(
originWorld, destination, Entity.TELEPORT_FLAG_LOAD_CHUNK | (takePassengers ? Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS : 0L),
- passengerTree, teleportComplete
+ passengerTree, tpComplete // Kaiiju - vanilla end teleportation
);
});

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Async path processing
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index 6df1720159383c2f536b40ded1092a437c1a20af..fc88b9f1e7e8f5858a91deeca2a5d51266a79a93 100644 index ebfa9e1dcca5ea8272e796f0409902d92b59ee76..6be4abdd16f2d57a80dbe175a91ff304fd17a7db 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java --- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java +++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -12,6 +12,7 @@ import org.bukkit.configuration.file.YamlConfiguration; @@ -12,6 +12,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
@@ -16,13 +16,14 @@ index 6df1720159383c2f536b40ded1092a437c1a20af..fc88b9f1e7e8f5858a91deeca2a5d512
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@@ -218,12 +219,26 @@ public class KaiijuConfig { @@ -213,12 +214,28 @@ public class KaiijuConfig {
public static boolean disablePlayerStats = false; public static boolean disablePlayerStats = false;
public static boolean disableArmSwingEvent = false; public static boolean disableArmSwingEvent = false;
public static boolean disableEnsureTickThreadChecks = false; public static boolean disableEnsureTickThreadChecks = false;
+ public static boolean asyncPathProcessing = false; + public static boolean asyncPathProcessing = false;
+ public static int asyncPathProcessingMaxThreads = 0; + public static int asyncPathProcessingMaxThreads = 0;
+ public static int asyncPathProcessingKeepalive = 60; + public static int asyncPathProcessingKeepalive = 60;
+ public static int asyncPathProcessingQueueCapacity = 4096;
private static void optimizationSettings() { private static void optimizationSettings() {
disableVanishApi = getBoolean("optimization.disable-vanish-api", disableVanishApi); disableVanishApi = getBoolean("optimization.disable-vanish-api", disableVanishApi);
@@ -32,6 +33,7 @@ index 6df1720159383c2f536b40ded1092a437c1a20af..fc88b9f1e7e8f5858a91deeca2a5d512
+ asyncPathProcessing = getBoolean("optimization.async-path-processing.enable", asyncPathProcessing); + asyncPathProcessing = getBoolean("optimization.async-path-processing.enable", asyncPathProcessing);
+ asyncPathProcessingMaxThreads = getInt("optimization.async-path-processing.max-threads", asyncPathProcessingMaxThreads); + asyncPathProcessingMaxThreads = getInt("optimization.async-path-processing.max-threads", asyncPathProcessingMaxThreads);
+ asyncPathProcessingKeepalive = getInt("optimization.async-path-processing.keepalive", asyncPathProcessingKeepalive); + asyncPathProcessingKeepalive = getInt("optimization.async-path-processing.keepalive", asyncPathProcessingKeepalive);
+ asyncPathProcessingQueueCapacity = getInt("optimization.async-path-processing.queue-capacity", asyncPathProcessingQueueCapacity);
+ if (asyncPathProcessingMaxThreads < 0) + if (asyncPathProcessingMaxThreads < 0)
+ asyncPathProcessingMaxThreads = Math.max(Runtime.getRuntime().availableProcessors() + asyncPathProcessingMaxThreads, 1); + asyncPathProcessingMaxThreads = Math.max(Runtime.getRuntime().availableProcessors() + asyncPathProcessingMaxThreads, 1);
+ else if (asyncPathProcessingMaxThreads == 0) + else if (asyncPathProcessingMaxThreads == 0)
@@ -338,7 +340,7 @@ index 0000000000000000000000000000000000000000..6b91852238f80d236fc44f766b115267
+} +}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/path/AsyncPathProcessor.java b/src/main/java/dev/kaiijumc/kaiiju/path/AsyncPathProcessor.java diff --git a/src/main/java/dev/kaiijumc/kaiiju/path/AsyncPathProcessor.java b/src/main/java/dev/kaiijumc/kaiiju/path/AsyncPathProcessor.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..2a54fa6d733cb5d406fd218161448197515be7fb index 0000000000000000000000000000000000000000..a6de8906d1629c60523c02681379ccdcaa22b588
--- /dev/null --- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/path/AsyncPathProcessor.java +++ b/src/main/java/dev/kaiijumc/kaiiju/path/AsyncPathProcessor.java
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
@@ -346,7 +348,6 @@ index 0000000000000000000000000000000000000000..2a54fa6d733cb5d406fd218161448197
+ +
+import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.common.util.concurrent.ThreadFactoryBuilder;
+ +
+import dev.kaiijumc.kaiiju.KaiijuConfig;
+import net.minecraft.world.level.pathfinder.Path; +import net.minecraft.world.level.pathfinder.Path;
+import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity;
+ +
@@ -363,13 +364,14 @@ index 0000000000000000000000000000000000000000..2a54fa6d733cb5d406fd218161448197
+ +
+ private static final Executor pathProcessingExecutor = new ThreadPoolExecutor( + private static final Executor pathProcessingExecutor = new ThreadPoolExecutor(
+ 1, + 1,
+ KaiijuConfig.asyncPathProcessingMaxThreads, + dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessingMaxThreads,
+ KaiijuConfig.asyncPathProcessingKeepalive, TimeUnit.SECONDS, + dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessingKeepalive,
+ new LinkedBlockingQueue<>(), + TimeUnit.SECONDS,
+ new ThreadFactoryBuilder() + new ArrayBlockingQueue<>(dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessingQueueCapacity),
+ .setNameFormat("petal-path-processor-%d") + new ThreadFactoryBuilder()
+ .setPriority(Thread.NORM_PRIORITY - 2) + .setNameFormat("petal-path-processor-%d")
+ .build() + .setPriority(Thread.NORM_PRIORITY - 2)
+ .build()
+ ); + );
+ +
+ protected static CompletableFuture<Void> queue(@NotNull AsyncPath path) { + protected static CompletableFuture<Void> queue(@NotNull AsyncPath path) {
@@ -397,10 +399,10 @@ index 0000000000000000000000000000000000000000..2a54fa6d733cb5d406fd218161448197
+} +}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorCache.java b/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorCache.java diff --git a/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorCache.java b/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorCache.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..3213fed7cea3ebfc364f4d6603b95f4263222c76 index 0000000000000000000000000000000000000000..121eda164714650f76bb6c8495ef375d8a00d812
--- /dev/null --- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorCache.java +++ b/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorCache.java
@@ -0,0 +1,45 @@ @@ -0,0 +1,42 @@
+package dev.kaiijumc.kaiiju.path; +package dev.kaiijumc.kaiiju.path;
+ +
+import net.minecraft.world.level.pathfinder.NodeEvaluator; +import net.minecraft.world.level.pathfinder.NodeEvaluator;
@@ -417,13 +419,13 @@ index 0000000000000000000000000000000000000000..3213fed7cea3ebfc364f4d6603b95f42
+ private static final Map<NodeEvaluatorFeatures, ConcurrentLinkedQueue<NodeEvaluator>> threadLocalNodeEvaluators = new ConcurrentHashMap<>(); + private static final Map<NodeEvaluatorFeatures, ConcurrentLinkedQueue<NodeEvaluator>> threadLocalNodeEvaluators = new ConcurrentHashMap<>();
+ private static final Map<NodeEvaluator, NodeEvaluatorGenerator> nodeEvaluatorToGenerator = new ConcurrentHashMap<>(); + private static final Map<NodeEvaluator, NodeEvaluatorGenerator> nodeEvaluatorToGenerator = new ConcurrentHashMap<>();
+ +
+ private static @NotNull Queue<NodeEvaluator> getQueueForFeatures(@NotNull NodeEvaluatorFeatures nodeEvaluatorFeatures) { + private static @NotNull Queue<NodeEvaluator> getDequeForGenerator(@NotNull NodeEvaluatorFeatures nodeEvaluatorFeatures) {
+ return threadLocalNodeEvaluators.computeIfAbsent(nodeEvaluatorFeatures, (key) -> new ConcurrentLinkedQueue<>()); + return threadLocalNodeEvaluators.computeIfAbsent(nodeEvaluatorFeatures, (key) -> new ConcurrentLinkedQueue<>());
+ } + }
+ +
+ public static @NotNull NodeEvaluator takeNodeEvaluator(@NotNull NodeEvaluatorGenerator generator, @NotNull NodeEvaluator localNodeEvaluator) { + public static @NotNull NodeEvaluator takeNodeEvaluator(@NotNull NodeEvaluatorGenerator generator, @NotNull NodeEvaluator localNodeEvaluator) {
+ final NodeEvaluatorFeatures nodeEvaluatorFeatures = NodeEvaluatorFeatures.fromNodeEvaluator(localNodeEvaluator); + final NodeEvaluatorFeatures nodeEvaluatorFeatures = NodeEvaluatorFeatures.fromNodeEvaluator(localNodeEvaluator);
+ NodeEvaluator nodeEvaluator = getQueueForFeatures(nodeEvaluatorFeatures).poll(); + NodeEvaluator nodeEvaluator = getDequeForGenerator(nodeEvaluatorFeatures).poll();
+ +
+ if (nodeEvaluator == null) { + if (nodeEvaluator == null) {
+ nodeEvaluator = generator.generate(nodeEvaluatorFeatures); + nodeEvaluator = generator.generate(nodeEvaluatorFeatures);
@@ -435,16 +437,13 @@ index 0000000000000000000000000000000000000000..3213fed7cea3ebfc364f4d6603b95f42
+ } + }
+ +
+ public static void returnNodeEvaluator(@NotNull NodeEvaluator nodeEvaluator) { + public static void returnNodeEvaluator(@NotNull NodeEvaluator nodeEvaluator) {
+ final NodeEvaluatorGenerator generator = nodeEvaluatorToGenerator.remove(nodeEvaluator); + final NodeEvaluatorFeatures nodeEvaluatorFeatures = NodeEvaluatorFeatures.fromNodeEvaluator(nodeEvaluator);
+ final var generator = nodeEvaluatorToGenerator.remove(nodeEvaluator);
+ Validate.notNull(generator, "NodeEvaluator already returned"); + Validate.notNull(generator, "NodeEvaluator already returned");
+ +
+ final NodeEvaluatorFeatures nodeEvaluatorFeatures = NodeEvaluatorFeatures.fromNodeEvaluator(nodeEvaluator); + getDequeForGenerator(nodeEvaluatorFeatures).offer(nodeEvaluator);
+ getQueueForFeatures(nodeEvaluatorFeatures).offer(nodeEvaluator);
+ } + }
+ +
+ public static void removeNodeEvaluator(@NotNull NodeEvaluator nodeEvaluator) {
+ nodeEvaluatorToGenerator.remove(nodeEvaluator);
+ }
+} +}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorFeatures.java b/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorFeatures.java diff --git a/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorFeatures.java b/src/main/java/dev/kaiijumc/kaiiju/path/NodeEvaluatorFeatures.java
new file mode 100644 new file mode 100644
@@ -514,14 +513,14 @@ index 0000000000000000000000000000000000000000..130d61324679c8600faa52255f3ad99f
+ } + }
+} +}
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index a8b23b1594d2b39568c68c93a8a1b936457672bc..af4305813abdb5db5e35ba4466e3e0b717e78cda 100644 index a8b23b1594d2b39568c68c93a8a1b936457672bc..8bd27e1a60c1a92350f4954764ea17914959e6dc 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java --- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -294,6 +294,7 @@ public abstract class Mob extends LivingEntity implements Targeting { @@ -294,6 +294,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
@Nullable @Nullable
@Override @Override
public LivingEntity getTarget() { public LivingEntity getTarget() {
+ if (Thread.currentThread().getName().contains("petal-path-processor")) return this.target; // Kaiiju - Don't reset target when async pathfinding! + if (!io.papermc.paper.util.TickThread.isTickThreadFor(this)) return this.target; // Kaiiju - for the async path processor
// Folia start - region threading // Folia start - region threading
if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.target)) { if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.target)) {
this.target = null; this.target = null;
@@ -579,7 +578,7 @@ index d4c91e0a0c64fcb7f1145de3f30134cb1f1f8ee6..ef5ec638bcd88df6eb93746868e863db
return true; return true;
} }
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
index 98bf17441da3169d49de55fe89d79ebe250a2b7e..5f3b38830c786deed161bdd2efd2d3c4071d34ec 100644 index 98bf17441da3169d49de55fe89d79ebe250a2b7e..df85430912bb00cef1994ded357ca93680f0650d 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java --- a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
@@ -21,6 +21,7 @@ public class MoveToTargetSink extends Behavior<Mob> { @@ -21,6 +21,7 @@ public class MoveToTargetSink extends Behavior<Mob> {
@@ -590,19 +589,19 @@ index 98bf17441da3169d49de55fe89d79ebe250a2b7e..5f3b38830c786deed161bdd2efd2d3c4
@Nullable @Nullable
private BlockPos lastTargetPos; private BlockPos lastTargetPos;
private float speedModifier; private float speedModifier;
@@ -42,9 +43,10 @@ public class MoveToTargetSink extends Behavior<Mob> { @@ -42,7 +43,10 @@ public class MoveToTargetSink extends Behavior<Mob> {
Brain<?> brain = entity.getBrain(); Brain<?> brain = entity.getBrain();
WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get(); WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get();
boolean bl = this.reachedTarget(entity, walkTarget); boolean bl = this.reachedTarget(entity, walkTarget);
- if (!bl && this.tryComputePath(entity, walkTarget, world.getGameTime())) { - if (!bl && this.tryComputePath(entity, walkTarget, world.getGameTime())) {
+ if (!dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessing && !bl && this.tryComputePath(entity, walkTarget, world.getGameTime())) { // Kaiiju - petal - async path processing means we can't know if the path is reachable here + // Kaiiju start - petal - async path processing means we can't know if the path is reachable here
+ if (dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessing && !bl) return true;
+ else if (!dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessing && !bl && this.tryComputePath(entity, walkTarget, world.getGameTime())) {
+ // Kaiiju end
this.lastTargetPos = walkTarget.getTarget().currentBlockPosition(); this.lastTargetPos = walkTarget.getTarget().currentBlockPosition();
return true; return true;
+ } else if (dev.kaiijumc.kaiiju.KaiijuConfig.asyncPathProcessing && !bl) { return true; // Kaiiju - async pathfinding
} else { } else {
brain.eraseMemory(MemoryModuleType.WALK_TARGET); @@ -58,6 +62,7 @@ public class MoveToTargetSink extends Behavior<Mob> {
if (bl) {
@@ -58,6 +60,7 @@ public class MoveToTargetSink extends Behavior<Mob> {
@Override @Override
protected boolean canStillUse(ServerLevel world, Mob entity, long time) { protected boolean canStillUse(ServerLevel world, Mob entity, long time) {
@@ -610,7 +609,7 @@ index 98bf17441da3169d49de55fe89d79ebe250a2b7e..5f3b38830c786deed161bdd2efd2d3c4
if (this.path != null && this.lastTargetPos != null) { if (this.path != null && this.lastTargetPos != null) {
Optional<WalkTarget> optional = entity.getBrain().getMemory(MemoryModuleType.WALK_TARGET); Optional<WalkTarget> optional = entity.getBrain().getMemory(MemoryModuleType.WALK_TARGET);
boolean bl = optional.map(MoveToTargetSink::isWalkTargetSpectator).orElse(false); boolean bl = optional.map(MoveToTargetSink::isWalkTargetSpectator).orElse(false);
@@ -82,12 +85,68 @@ public class MoveToTargetSink extends Behavior<Mob> { @@ -82,12 +87,74 @@ public class MoveToTargetSink extends Behavior<Mob> {
@Override @Override
protected void start(ServerLevel serverLevel, Mob mob, long l) { protected void start(ServerLevel serverLevel, Mob mob, long l) {
@@ -649,16 +648,22 @@ index 98bf17441da3169d49de55fe89d79ebe250a2b7e..5f3b38830c786deed161bdd2efd2d3c4
+ if (!canReach) { + if (!canReach) {
+ Optional<WalkTarget> walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET); + Optional<WalkTarget> walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET);
+ +
+ if (!walkTarget.isPresent()) return; + if (walkTarget.isPresent()) {
+ + BlockPos blockPos = walkTarget.get().getTarget().currentBlockPosition();
+ BlockPos blockPos = walkTarget.get().getTarget().currentBlockPosition(); + Vec3 vec3 = DefaultRandomPos.getPosTowards((PathfinderMob)mob, 10, 7, Vec3.atBottomCenterOf(blockPos), (float)Math.PI / 2F);
+ Vec3 vec3 = DefaultRandomPos.getPosTowards((PathfinderMob)mob, 10, 7, Vec3.atBottomCenterOf(blockPos), (float)Math.PI / 2F); + if (vec3 != null) {
+ if (vec3 != null) { + // try recalculating the path using a random position
+ // try recalculating the path using a random position + this.path = mob.getNavigation().createPath(vec3.x, vec3.y, vec3.z, 0);
+ this.path = mob.getNavigation().createPath(vec3.x, vec3.y, vec3.z, 0); + this.finishedProcessing = false;
+ this.finishedProcessing = false; + return;
+ return; + }
+ } + }
+
+ // we failed, erase and move on
+ brain.eraseMemory(MemoryModuleType.WALK_TARGET);
+ this.path = null;
+
+ return;
+ } + }
+ +
+ mob.getBrain().setMemory(MemoryModuleType.PATH, this.path); + mob.getBrain().setMemory(MemoryModuleType.PATH, this.path);
@@ -669,7 +674,7 @@ index 98bf17441da3169d49de55fe89d79ebe250a2b7e..5f3b38830c786deed161bdd2efd2d3c4
+ Brain<?> brain = mob.getBrain(); + Brain<?> brain = mob.getBrain();
+ +
+ if (path != null && this.lastTargetPos != null && brain.hasMemoryValue(MemoryModuleType.WALK_TARGET)) { + if (path != null && this.lastTargetPos != null && brain.hasMemoryValue(MemoryModuleType.WALK_TARGET)) {
+ WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get(); // we know isPresent = true + WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get();
+ if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0D) { + if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0D) {
+ this.start(serverLevel, mob, l); + this.start(serverLevel, mob, l);
+ } + }
@@ -679,7 +684,7 @@ index 98bf17441da3169d49de55fe89d79ebe250a2b7e..5f3b38830c786deed161bdd2efd2d3c4
Path path = mob.getNavigation().getPath(); Path path = mob.getNavigation().getPath();
Brain<?> brain = mob.getBrain(); Brain<?> brain = mob.getBrain();
if (this.path != path) { if (this.path != path) {
@@ -103,7 +162,23 @@ public class MoveToTargetSink extends Behavior<Mob> { @@ -103,7 +170,23 @@ public class MoveToTargetSink extends Behavior<Mob> {
} }
} }
@@ -1135,30 +1140,6 @@ index 97b763431bc5015448ee7a26a340635a932c950b..48109aebe34cbdfac3eceffb1c20aa84
return new PathFinder(this.nodeEvaluator, range) { return new PathFinder(this.nodeEvaluator, range) {
@Override @Override
protected float distance(Node a, Node b) { protected float distance(Node a, Node b) {
diff --git a/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java b/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java
index b51155ad12515b2d0dd0f202580b9f455c114d9a..fd336bc5a209caf6fd7f85f781b2b0a303dbd5ec 100644
--- a/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -242,6 +242,7 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@Override
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
+ if (Thread.currentThread().getName().contains("petal-path-processor")) return Shapes.block(); // Kaiiju - async pathfinding - we cannot get block entities
BlockEntity blockEntity = world.getBlockEntity(pos);
return blockEntity instanceof ShulkerBoxBlockEntity ? Shapes.create(((ShulkerBoxBlockEntity)blockEntity).getBoundingBox(state)) : Shapes.block();
}
diff --git a/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index e941a4ce35c1bcc84836d04fb97cb1e7f292ae42..26f3c25f2dfda5f7c6213746efa8b883b655d2e1 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -102,6 +102,7 @@ public class MovingPistonBlock extends BaseEntityBlock {
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
+ if (Thread.currentThread().getName().contains("petal-path-processor")) return Shapes.empty(); // Kaiiju - async pathfinding - we cannot get block entities
PistonMovingBlockEntity pistonMovingBlockEntity = this.getBlockEntity(world, pos);
return pistonMovingBlockEntity != null ? pistonMovingBlockEntity.getCollisionShape(world, pos) : Shapes.empty();
}
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
index 2a335f277bd0e4b8ad0f60d8226eb8aaa80a871f..b2c3c459fae7d0cb5ef0fcbc2ff0e61c7b952087 100644 index 2a335f277bd0e4b8ad0f60d8226eb8aaa80a871f..b2c3c459fae7d0cb5ef0fcbc2ff0e61c7b952087 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java --- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java
@@ -1190,10 +1171,10 @@ index 2a335f277bd0e4b8ad0f60d8226eb8aaa80a871f..b2c3c459fae7d0cb5ef0fcbc2ff0e61c
return false; return false;
} else if (o.nodes.size() != this.nodes.size()) { } else if (o.nodes.size() != this.nodes.size()) {
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
index d23481453717f715124156b5d83f6448f720d049..7be397d884ec091e0f51ae48ee2c83b6f0e486ea 100644 index d23481453717f715124156b5d83f6448f720d049..d4cc2a5f99f8445be9a63c279e28032f11a91304 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java --- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
@@ -24,37 +24,80 @@ public class PathFinder { @@ -24,37 +24,77 @@ public class PathFinder {
public final NodeEvaluator nodeEvaluator; public final NodeEvaluator nodeEvaluator;
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private final BinaryHeap openSet = new BinaryHeap(); private final BinaryHeap openSet = new BinaryHeap();
@@ -1226,7 +1207,11 @@ index d23481453717f715124156b5d83f6448f720d049..7be397d884ec091e0f51ae48ee2c83b6
+ Node node = nodeEvaluator.getStart(); + Node node = nodeEvaluator.getStart();
+ // Kaiiju end + // Kaiiju end
if (node == null) { if (node == null) {
+ dev.kaiijumc.kaiiju.path.NodeEvaluatorCache.removeNodeEvaluator(nodeEvaluator); // Kaiiju - petal - handle nodeEvaluatorGenerator + // Kaiiju start - petal - handle nodeEvaluatorGenerator
+ if (this.nodeEvaluatorGenerator != null) {
+ dev.kaiijumc.kaiiju.path.NodeEvaluatorCache.returnNodeEvaluator(nodeEvaluator);
+ }
+ // Kaiiju end
return null; return null;
} else { } else {
// Paper start - remove streams - and optimize collection // Paper start - remove streams - and optimize collection
@@ -1242,16 +1227,12 @@ index d23481453717f715124156b5d83f6448f720d049..7be397d884ec091e0f51ae48ee2c83b6
+ // Kaiiju start - petal - async path processing + // Kaiiju start - petal - async path processing
+ if (this.nodeEvaluatorGenerator == null) { + if (this.nodeEvaluatorGenerator == null) {
+ // run sync :( + // run sync :(
+ dev.kaiijumc.kaiiju.path.NodeEvaluatorCache.removeNodeEvaluator(nodeEvaluator); + return this.findPath(nodeEvaluator, world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
+ return this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
+ } + }
+ +
+ return new dev.kaiijumc.kaiiju.path.AsyncPath(Lists.newArrayList(), positions, () -> { + return new dev.kaiijumc.kaiiju.path.AsyncPath(Lists.newArrayList(), positions, () -> {
+ try { + try {
+ return this.processPath(nodeEvaluator, node, map, followRange, distance, rangeMultiplier); + return this.processPath(nodeEvaluator, node, map, followRange, distance, rangeMultiplier);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ } finally { + } finally {
+ nodeEvaluator.done(); + nodeEvaluator.done();
+ dev.kaiijumc.kaiiju.path.NodeEvaluatorCache.returnNodeEvaluator(nodeEvaluator); + dev.kaiijumc.kaiiju.path.NodeEvaluatorCache.returnNodeEvaluator(nodeEvaluator);
@@ -1264,26 +1245,24 @@ index d23481453717f715124156b5d83f6448f720d049..7be397d884ec091e0f51ae48ee2c83b6
- @Nullable - @Nullable
+ //@Nullable // Kaiiju - Always not null + //@Nullable // Kaiiju - Always not null
// Paper start - optimize collection // Paper start - optimize collection
private Path findPath(ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) { - private Path findPath(ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) {
+ private Path findPath(NodeEvaluator nodeEvaluator, ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) {
profiler.push("find_path"); profiler.push("find_path");
profiler.markForCharting(MetricCategory.PATH_FINDING); profiler.markForCharting(MetricCategory.PATH_FINDING);
+ // Kaiiju start - petal - split pathfinding into the original sync method for compat and processing for delaying + // Kaiiju start - petal - split pathfinding into the original sync method for compat and processing for delaying
+ try { + try {
+ return this.processPath(this.nodeEvaluator, startNode, positions, followRange, distance, rangeMultiplier); + return this.processPath(this.nodeEvaluator, startNode, positions, followRange, distance, rangeMultiplier);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ } finally { + } finally {
+ this.nodeEvaluator.done(); + nodeEvaluator.done();
+ } + }
+ } + }
+ private synchronized @org.jetbrains.annotations.NotNull Path processPath(NodeEvaluator nodeEvaluator, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) { // sync to only use the caching functions in this class on a single thread + private synchronized Path processPath(NodeEvaluator nodeEvaluator, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) { // sync to only use the caching functions in this class on a single thread
+ org.apache.commons.lang3.Validate.isTrue(!positions.isEmpty()); // ensure that we have at least one position, which means we'll always return a path + org.apache.commons.lang3.Validate.isTrue(!positions.isEmpty()); // ensure that we have at least one position, which means we'll always return a path
+ // Kaiiju end + // Kaiiju end
// Set<Target> set = positions.keySet(); // Set<Target> set = positions.keySet();
startNode.g = 0.0F; startNode.g = 0.0F;
startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection
@@ -91,7 +134,7 @@ public class PathFinder { @@ -91,7 +131,7 @@ public class PathFinder {
} }
if (!(node.distanceTo(startNode) >= followRange)) { if (!(node.distanceTo(startNode) >= followRange)) {
@@ -1292,14 +1271,6 @@ index d23481453717f715124156b5d83f6448f720d049..7be397d884ec091e0f51ae48ee2c83b6
for(int l = 0; l < k; ++l) { for(int l = 0; l < k; ++l) {
Node node2 = this.neighbors[l]; Node node2 = this.neighbors[l];
@@ -123,6 +166,7 @@ public class PathFinder {
if (best == null || comparator.compare(path, best) < 0)
best = path;
}
+ //noinspection ConstantConditions // Kaiiju - petal - ignore this warning, we know that the above loop always runs at least once since positions is not empty
return best;
// Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java diff --git a/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java
index 0e2b14e7dfedf209d63279c81723fd7955122d78..079b278e2e262af433bb5bd0c12b3d8db4fa12fc 100644 index 0e2b14e7dfedf209d63279c81723fd7955122d78..079b278e2e262af433bb5bd0c12b3d8db4fa12fc 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java --- a/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java

View File

@@ -1,458 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Tue, 1 Aug 2023 03:38:09 +0200
Subject: [PATCH] Improve container checking with a bitset
diff --git a/src/main/java/dev/kaiijumc/kaiiju/structs/ItemListWithBitset.java b/src/main/java/dev/kaiijumc/kaiiju/structs/ItemListWithBitset.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee32b7c4a1ae1e23149694ecba5ab7bd347d6ca6
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/structs/ItemListWithBitset.java
@@ -0,0 +1,114 @@
+package dev.kaiijumc.kaiiju.structs;
+
+
+import net.minecraft.core.NonNullList;
+import net.minecraft.world.item.ItemStack;
+import org.apache.commons.lang.Validate;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ItemListWithBitset extends AbstractList<ItemStack> {
+ public static ItemListWithBitset fromList(List<ItemStack> list) {
+ if (list instanceof ItemListWithBitset ours) {
+ return ours;
+ }
+ return new ItemListWithBitset(list);
+ }
+
+ private static ItemStack[] createArray(int size) {
+ ItemStack[] array = new ItemStack[size];
+ Arrays.fill(array, ItemStack.EMPTY);
+ return array;
+ }
+
+ private final ItemStack[] items;
+
+ private long bitSet = 0;
+ private final long allBits;
+
+ private static class OurNonNullList extends NonNullList<ItemStack> {
+ protected OurNonNullList(List<ItemStack> delegate) {
+ super(delegate, ItemStack.EMPTY);
+ }
+ }
+
+ public final NonNullList<ItemStack> nonNullList = new OurNonNullList(this);
+
+ private ItemListWithBitset(List<ItemStack> list) {
+ this(list.size());
+
+ for (int i = 0; i < list.size(); i++) {
+ this.set(i, list.get(i));
+ }
+ }
+
+ public ItemListWithBitset(int size) {
+ Validate.isTrue(size < Long.BYTES * 8, "size is too large");
+
+ this.items = createArray(size);
+ this.allBits = ((1L << size) - 1);
+ }
+
+ public boolean isCompletelyEmpty() {
+ return this.bitSet == 0;
+ }
+
+ public boolean hasFullStacks() {
+ return (this.bitSet & this.allBits) == allBits;
+ }
+
+ @Override
+ public ItemStack set(int index, @NotNull ItemStack itemStack) {
+ ItemStack existing = this.items[index];
+
+ this.items[index] = itemStack;
+
+ if (itemStack == ItemStack.EMPTY) {
+ this.bitSet &= ~(1L << index);
+ } else {
+ this.bitSet |= 1L << index;
+ }
+
+ return existing;
+ }
+
+ @NotNull
+ @Override
+ public ItemStack get(int var0) {
+ return this.items[var0];
+ }
+
+ @Override
+ public int size() {
+ return this.items.length;
+ }
+
+ @Override
+ public void clear() {
+ Arrays.fill(this.items, ItemStack.EMPTY);
+ }
+
+ // these are unsupported for block inventories which have a static size
+ @Override
+ public void add(int var0, ItemStack var1) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ItemStack remove(int var0) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String toString() {
+ return "ItemListWithBitset{" +
+ "items=" + Arrays.toString(items) +
+ ", bitSet=" + Long.toString(bitSet, 2) +
+ ", allBits=" + Long.toString(allBits, 2) +
+ ", size=" + this.items.length +
+ '}';
+ }
+}
diff --git a/src/main/java/net/minecraft/world/CompoundContainer.java b/src/main/java/net/minecraft/world/CompoundContainer.java
index 241fec02e6869c638d3a160819b32173a081467b..62848ca68f532fa14241320df76d180c13072c34 100644
--- a/src/main/java/net/minecraft/world/CompoundContainer.java
+++ b/src/main/java/net/minecraft/world/CompoundContainer.java
@@ -64,6 +64,23 @@ public class CompoundContainer implements Container {
this.container2 = second;
}
+ // Kaiiju start - airplane - improve container checking with a bitset
+ @Override
+ public boolean hasEmptySlot(net.minecraft.core.Direction enumdirection) {
+ return this.container1.hasEmptySlot(null) || this.container2.hasEmptySlot(null);
+ }
+
+ @Override
+ public boolean isCompletelyFull(net.minecraft.core.Direction enumdirection) {
+ return this.container1.isCompletelyFull(null) && this.container2.isCompletelyFull(null);
+ }
+
+ @Override
+ public boolean isCompletelyEmpty(net.minecraft.core.Direction enumdirection) {
+ return this.container1.isCompletelyEmpty(null) && this.container2.isCompletelyEmpty(null);
+ }
+ // Kaiiju end
+
@Override
public int getContainerSize() {
return this.container1.getContainerSize() + this.container2.getContainerSize();
diff --git a/src/main/java/net/minecraft/world/Container.java b/src/main/java/net/minecraft/world/Container.java
index 04b1531572e8fff1e46fe1c94e7fc863841e0f66..ac1e21a4fc210424ea57c247d03914c54129de9c 100644
--- a/src/main/java/net/minecraft/world/Container.java
+++ b/src/main/java/net/minecraft/world/Container.java
@@ -13,6 +13,63 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity;
// CraftBukkit end
public interface Container extends Clearable {
+ // Kaiiju start - airplane - allow the inventory to override and optimize these frequent calls
+ default boolean hasEmptySlot(@org.jetbrains.annotations.Nullable net.minecraft.core.Direction enumdirection) { // there is a slot with 0 items in it
+ if (this instanceof WorldlyContainer worldlyContainer) {
+ for (int i : worldlyContainer.getSlotsForFace(enumdirection)) {
+ if (this.getItem(i).isEmpty()) {
+ return true;
+ }
+ }
+ } else {
+ int size = this.getContainerSize();
+ for (int i = 0; i < size; i++) {
+ if (this.getItem(i).isEmpty()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ default boolean isCompletelyFull(@org.jetbrains.annotations.Nullable net.minecraft.core.Direction enumdirection) { // every stack is maxed
+ if (this instanceof WorldlyContainer worldlyContainer) {
+ for (int i : worldlyContainer.getSlotsForFace(enumdirection)) {
+ ItemStack itemStack = this.getItem(i);
+ if (itemStack.getCount() < itemStack.getMaxStackSize()) {
+ return false;
+ }
+ }
+ } else {
+ int size = this.getContainerSize();
+ for (int i = 0; i < size; i++) {
+ ItemStack itemStack = this.getItem(i);
+ if (itemStack.getCount() < itemStack.getMaxStackSize()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ default boolean isCompletelyEmpty(@org.jetbrains.annotations.Nullable net.minecraft.core.Direction enumdirection) {
+ if (this instanceof WorldlyContainer worldlyContainer) {
+ for (int i : worldlyContainer.getSlotsForFace(enumdirection)) {
+ if (!this.getItem(i).isEmpty()) {
+ return false;
+ }
+ }
+ } else {
+ int size = this.getContainerSize();
+ for (int i = 0; i < size; i++) {
+ if (!this.getItem(i).isEmpty()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ // Kaiiju end
int LARGE_MAX_STACK_SIZE = 64;
int DEFAULT_DISTANCE_LIMIT = 8;
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
index 272095d7a09ab41227d741172735f66fd2798ce1..1f2e2d7726abd63bb46697697c91696387c819a2 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
@@ -28,6 +28,7 @@ import org.bukkit.inventory.InventoryHolder;
public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity {
private NonNullList<ItemStack> itemStacks;
+ private dev.kaiijumc.kaiiju.structs.ItemListWithBitset itemStacksOptimized; // Kaiiju - airplane - implement ItemListWithBitset
@Nullable
public ResourceLocation lootTable;
public long lootTableSeed;
@@ -89,12 +90,18 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
protected AbstractMinecartContainer(EntityType<?> type, Level world) {
super(type, world);
- this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.itemStacksOptimized = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); // CraftBukkit - SPIGOT-3513
+ this.itemStacks = this.itemStacksOptimized.nonNullList;
+ // Kaiiju end
}
protected AbstractMinecartContainer(EntityType<?> type, double x, double y, double z, Level world) {
super(type, world, x, y, z);
- this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.itemStacksOptimized = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); // CraftBukkit - SPIGOT-3513
+ this.itemStacks = this.itemStacksOptimized.nonNullList;
+ // Kaiiju end
}
@Override
@@ -156,6 +163,10 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
protected void readAdditionalSaveData(CompoundTag nbt) {
super.readAdditionalSaveData(nbt);
this.lootableData.loadNbt(nbt); // Paper
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.itemStacksOptimized = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); // CraftBukkit - SPIGOT-3513
+ this.itemStacks = this.itemStacksOptimized.nonNullList;
+ // Kaiiju end
this.readChestVehicleSaveData(nbt);
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
index a71414397bd45ee7bcacfeef0041d80dfa25f114..67f69540e6c217070f8d2af8908d4eb6f2b5c1c1 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
@@ -31,6 +31,7 @@ import org.bukkit.entity.HumanEntity;
public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity {
private static final int EVENT_SET_OPEN_COUNT = 1;
+ private dev.kaiijumc.kaiiju.structs.ItemListWithBitset optimizedItems; // Kaiiju - airplane - implement ItemListWithBitset
private NonNullList<ItemStack> items;
public final ContainerOpenersCounter openersCounter;
private final ChestLidController chestLidController;
@@ -65,9 +66,14 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
}
// CraftBukkit end
+ private final boolean isNative = getClass().equals(ChestBlockEntity.class); // Kaiiju - airplane
+
protected ChestBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
- this.items = NonNullList.withSize(27, ItemStack.EMPTY);
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(27);
+ this.items = this.optimizedItems.nonNullList;
+ // Kaiiju end
this.openersCounter = new ContainerOpenersCounter() {
@Override
protected void onOpen(Level world, BlockPos pos, BlockState state) {
@@ -98,6 +104,23 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
this.chestLidController = new ChestLidController();
}
+ // Kaiiju start - airplane - improve container checking with a bitset
+ @Override
+ public boolean hasEmptySlot(Direction enumdirection) {
+ return isNative ? !this.optimizedItems.hasFullStacks() : super.hasEmptySlot(enumdirection);
+ }
+
+ @Override
+ public boolean isCompletelyFull(Direction enumdirection) {
+ return isNative ? this.optimizedItems.hasFullStacks() && super.isCompletelyFull(enumdirection) : super.isCompletelyFull(enumdirection);
+ }
+
+ @Override
+ public boolean isCompletelyEmpty(Direction enumdirection) {
+ return isNative && this.optimizedItems.isCompletelyEmpty() || super.isCompletelyEmpty(enumdirection);
+ }
+ // Kaiiju end
+
public ChestBlockEntity(BlockPos pos, BlockState state) {
this(BlockEntityType.CHEST, pos, state);
}
@@ -115,7 +138,10 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
@Override
public void load(CompoundTag nbt) {
super.load(nbt);
- this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize());
+ this.items = this.optimizedItems.nonNullList;
+ // Kaiiju end
if (!this.tryLoadLootTable(nbt)) {
ContainerHelper.loadAllItems(nbt, this.items);
}
@@ -187,7 +213,10 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
@Override
protected void setItems(NonNullList<ItemStack> list) {
- this.items = list;
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.optimizedItems = dev.kaiijumc.kaiiju.structs.ItemListWithBitset.fromList(list);
+ this.items = this.optimizedItems.nonNullList;
+ // Kaiiju end
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 762b763f271c3208b4f8a7e346897207ec5beb6c..a212a62bc2b43b55e9040e2de8360d6e55a7dd86 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -48,6 +48,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
public static final int MOVE_ITEM_SPEED = 8;
public static final int HOPPER_CONTAINER_SIZE = 5;
private NonNullList<ItemStack> items;
+ private dev.kaiijumc.kaiiju.structs.ItemListWithBitset optimizedItems; // Kaiiju - airplane - implement ItemListWithBitset
private int cooldownTime;
private long tickedGameTime;
@@ -83,14 +84,37 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
public HopperBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.HOPPER, pos, state);
- this.items = NonNullList.withSize(5, ItemStack.EMPTY);
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(5);
+ this.items = this.optimizedItems.nonNullList;
+ // Kaiiju end
this.cooldownTime = -1;
}
+ // Kaiiju start - airplane - improve container checking with a bitset
+ @Override
+ public boolean hasEmptySlot(Direction enumdirection) {
+ return !this.optimizedItems.hasFullStacks();
+ }
+
+ @Override
+ public boolean isCompletelyFull(Direction enumdirection) {
+ return this.optimizedItems.hasFullStacks() && super.isCompletelyFull(enumdirection);
+ }
+
+ @Override
+ public boolean isCompletelyEmpty(Direction enumdirection) {
+ return this.optimizedItems.isCompletelyEmpty() || super.isCompletelyEmpty(enumdirection);
+ }
+ // Kaiiju end
+
@Override
public void load(CompoundTag nbt) {
super.load(nbt);
- this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize());
+ this.items = this.optimizedItems.nonNullList;
+ // Kaiiju end
if (!this.tryLoadLootTable(nbt)) {
ContainerHelper.loadAllItems(nbt, this.items);
}
@@ -162,7 +186,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
flag = HopperBlockEntity.ejectItems(world, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit
}
- if (!blockEntity.inventoryFull()) {
+ if (!blockEntity.optimizedItems.hasFullStacks() || !blockEntity.inventoryFull()) { // Kaiiju - airplane
flag |= booleansupplier.getAsBoolean();
}
@@ -455,11 +479,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
private static boolean isFullContainer(Container inventory, Direction direction) {
- return allMatch(inventory, direction, STACK_SIZE_TEST); // Paper - no streams
+ return inventory.isCompletelyFull(direction); // Kaiiju - airplane - use bitsets
}
private static boolean isEmptyContainer(Container inv, Direction facing) {
- return allMatch(inv, facing, IS_EMPTY_TEST);
+ return inv.isCompletelyEmpty(facing); // Kaiiju - airplane - use bitsets
}
public static boolean suckInItems(Level world, Hopper hopper) {
@@ -649,7 +673,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (HopperBlockEntity.canPlaceItemInContainer(to, stack, slot, side)) {
boolean flag = false;
- boolean flag1 = to.isEmpty();
+ boolean flag1 = to.isCompletelyEmpty(side); // Kaiiju - airplane - use bitsets
if (itemstack1.isEmpty()) {
// Spigot start - SPIGOT-6693, InventorySubcontainer#setItem
@@ -844,7 +868,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@Override
protected void setItems(NonNullList<ItemStack> list) {
- this.items = list;
+ // Kaiiju start - airplane - use ItemListWithBitset
+ this.optimizedItems = dev.kaiijumc.kaiiju.structs.ItemListWithBitset.fromList(list);
+ this.items = this.optimizedItems.nonNullList;
+ // Kaiiju end
}
public static void entityInside(Level world, BlockPos pos, BlockState state, Entity entity, HopperBlockEntity blockEntity) {
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
index 081691f9710ff1115e4308f79ed49fbc38941193..648e28c5fba5c62e65f83fbb5ebc8836ffb166a9 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
@@ -95,14 +95,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
@Override
public boolean isEmpty() {
this.unpackLootTable((Player)null);
- // Paper start
- for (final ItemStack itemStack : this.getItems()) {
- if (!itemStack.isEmpty()) {
- return false;
- }
- }
- return true;
- // Paper end
+ return this.isCompletelyEmpty(null); // Kaiiju - airplane - use super
}
@Override