mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 15:00:13 +01:00
Port CB changes from Moonrise patch
This commit is contained in:
parent
3af380ba08
commit
48f34f8c90
9 changed files with 337 additions and 112 deletions
|
@ -22768,7 +22768,7 @@ index 0000000000000000000000000000000000000000..689ce367164e79e0426eeecb81dbbc52
|
||||||
+ private SaveUtil() {}
|
+ private SaveUtil() {}
|
||||||
+}
|
+}
|
||||||
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
||||||
index d3aebc7f833764351c8e5fe1fad1aa2f8718ca37..046a6304ea7e9dd66cb9d4cb004a582f13018295 100644
|
index e40b83502c74d7dcae05d9d0c865affeee186893..c4ddf4b6fee8086481581fab88a807f63e211b5c 100644
|
||||||
--- a/io/papermc/paper/FeatureHooks.java
|
--- a/io/papermc/paper/FeatureHooks.java
|
||||||
+++ b/io/papermc/paper/FeatureHooks.java
|
+++ b/io/papermc/paper/FeatureHooks.java
|
||||||
@@ -1,6 +1,8 @@
|
@@ -1,6 +1,8 @@
|
||||||
|
@ -22793,6 +22793,159 @@ index d3aebc7f833764351c8e5fe1fad1aa2f8718ca37..046a6304ea7e9dd66cb9d4cb004a582f
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
||||||
|
@@ -79,89 +84,30 @@ public final class FeatureHooks {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSpiderCollidingWithWorldBorder(final Spider spider) {
|
||||||
|
- return true; // ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(spider.level().getWorldBorder(), spider.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON))
|
||||||
|
+ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(spider.level().getWorldBorder(), spider.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)); // Paper - rewrite collision system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpAllChunkLoadInfo(net.minecraft.server.MinecraftServer server, boolean isLongTimeout) {
|
||||||
|
+ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(server, isLongTimeout); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dumpEntity(final Entity entity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.bukkit.entity.Entity[] getChunkEntities(net.minecraft.server.level.ServerLevel world, int chunkX, int chunkZ) {
|
||||||
|
- world.getChunk(chunkX, chunkZ); // ensure full loaded
|
||||||
|
-
|
||||||
|
- net.minecraft.world.level.entity.PersistentEntitySectionManager<net.minecraft.world.entity.Entity> entityManager = world.entityManager;
|
||||||
|
- long pair = ChunkPos.asLong(chunkX, chunkZ);
|
||||||
|
-
|
||||||
|
- if (entityManager.areEntitiesLoaded(pair)) {
|
||||||
|
- return entityManager.getEntities(new ChunkPos(chunkX, chunkZ)).stream()
|
||||||
|
- .map(net.minecraft.world.entity.Entity::getBukkitEntity)
|
||||||
|
- .filter(java.util.Objects::nonNull).toArray(org.bukkit.entity.Entity[]::new);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- entityManager.ensureChunkQueuedForLoad(pair); // Start entity loading
|
||||||
|
-
|
||||||
|
- // SPIGOT-6772: Use entity mailbox and re-schedule entities if they get unloaded
|
||||||
|
- net.minecraft.util.thread.ConsecutiveExecutor mailbox = ((net.minecraft.world.level.chunk.storage.EntityStorage) entityManager.permanentStorage).entityDeserializerQueue;
|
||||||
|
- java.util.function.BooleanSupplier supplier = () -> {
|
||||||
|
- // only execute inbox if our entities are not present
|
||||||
|
- if (entityManager.areEntitiesLoaded(pair)) {
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (!entityManager.isPending(pair)) {
|
||||||
|
- // Our entities got unloaded, this should normally not happen.
|
||||||
|
- entityManager.ensureChunkQueuedForLoad(pair); // Re-start entity loading
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- // tick loading inbox, which loads the created entities to the world
|
||||||
|
- // (if present)
|
||||||
|
- entityManager.tick();
|
||||||
|
- // check if our entities are loaded
|
||||||
|
- return entityManager.areEntitiesLoaded(pair);
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
- // now we wait until the entities are loaded,
|
||||||
|
- // the converting from NBT to entity object is done on the main Thread which is why we wait
|
||||||
|
- while (!supplier.getAsBoolean()) {
|
||||||
|
- if (mailbox.size() != 0) {
|
||||||
|
- mailbox.run();
|
||||||
|
- } else {
|
||||||
|
- Thread.yield();
|
||||||
|
- java.util.concurrent.locks.LockSupport.parkNanos("waiting for entity loading", 100000L);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return entityManager.getEntities(new ChunkPos(chunkX, chunkZ)).stream()
|
||||||
|
- .map(net.minecraft.world.entity.Entity::getBukkitEntity)
|
||||||
|
- .filter(java.util.Objects::nonNull).toArray(org.bukkit.entity.Entity[]::new);
|
||||||
|
+ return world.getChunkEntities(chunkX, chunkZ); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static java.util.Collection<org.bukkit.plugin.Plugin> getPluginChunkTickets(net.minecraft.server.level.ServerLevel world,
|
||||||
|
int x, int z) {
|
||||||
|
- net.minecraft.server.level.DistanceManager chunkDistanceManager = world.getChunkSource().chunkMap.distanceManager;
|
||||||
|
- net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>> tickets = chunkDistanceManager.tickets.get(ChunkPos.asLong(x, z));
|
||||||
|
-
|
||||||
|
- if (tickets == null) {
|
||||||
|
- return java.util.Collections.emptyList();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- com.google.common.collect.ImmutableList.Builder<org.bukkit.plugin.Plugin> ret = com.google.common.collect.ImmutableList.builder();
|
||||||
|
- for (net.minecraft.server.level.Ticket<?> ticket : tickets) {
|
||||||
|
- if (ticket.getType() == net.minecraft.server.level.TicketType.PLUGIN_TICKET) {
|
||||||
|
- ret.add((org.bukkit.plugin.Plugin) ticket.key);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return ret.build();
|
||||||
|
+ return world.moonrise$getChunkTaskScheduler().chunkHolderManager.getPluginChunkTickets(x, z); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<org.bukkit.plugin.Plugin, java.util.Collection<org.bukkit.Chunk>> getPluginChunkTickets(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
Map<org.bukkit.plugin.Plugin, com.google.common.collect.ImmutableList.Builder<Chunk>> ret = new HashMap<>();
|
||||||
|
net.minecraft.server.level.DistanceManager chunkDistanceManager = world.getChunkSource().chunkMap.distanceManager;
|
||||||
|
|
||||||
|
- for (it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry<net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>>> chunkTickets : chunkDistanceManager.tickets.long2ObjectEntrySet()) {
|
||||||
|
+ for (it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry<net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>>> chunkTickets : chunkDistanceManager.moonrise$getChunkHolderManager().getTicketsCopy().long2ObjectEntrySet()) { // Paper - rewrite chunk system
|
||||||
|
long chunkKey = chunkTickets.getLongKey();
|
||||||
|
net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>> tickets = chunkTickets.getValue();
|
||||||
|
|
||||||
|
@@ -183,15 +129,15 @@ public final class FeatureHooks {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getViewDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
- return world.getChunkSource().chunkMap.serverViewDistance;
|
||||||
|
+ return world.moonrise$getPlayerChunkLoader().getAPIViewDistance(); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSimulationDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
- return world.getChunkSource().chunkMap.getDistanceManager().simulationDistance;
|
||||||
|
+ return world.moonrise$getPlayerChunkLoader().getAPITickDistance(); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSendViewDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
- return getViewDistance(world);
|
||||||
|
+ return world.moonrise$getPlayerChunkLoader().getAPISendViewDistance(); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
|
@@ -209,31 +155,31 @@ public final class FeatureHooks {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
|
- throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ world.chunkSource.setSendViewDistance(distance); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void tickEntityManager(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
- world.entityManager.tick();
|
||||||
|
+ // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeEntityManager(net.minecraft.server.level.ServerLevel world, boolean save) {
|
||||||
|
- world.entityManager.close(save);
|
||||||
|
+ // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static java.util.concurrent.Executor getWorldgenExecutor() {
|
||||||
|
- return net.minecraft.Util.backgroundExecutor();
|
||||||
|
+ return Runnable::run; // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setViewDistance(ServerPlayer player, int distance) {
|
||||||
|
- throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ ((ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer)player).moonrise$getViewDistanceHolder().setLoadViewDistance(distance == -1 ? distance : distance + 1); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSimulationDistance(ServerPlayer player, int distance) {
|
||||||
|
- throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ ((ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer)player).moonrise$getViewDistanceHolder().setTickViewDistance(distance); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendViewDistance(ServerPlayer player, int distance) {
|
||||||
|
- throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ ((ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer)player).moonrise$getViewDistanceHolder().setSendViewDistance(distance); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
diff --git a/io/papermc/paper/command/subcommands/ChunkDebugCommand.java b/io/papermc/paper/command/subcommands/ChunkDebugCommand.java
|
diff --git a/io/papermc/paper/command/subcommands/ChunkDebugCommand.java b/io/papermc/paper/command/subcommands/ChunkDebugCommand.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..2dca7afbd93cfbb8686f336fcd3b45dd01fba0fc
|
index 0000000000000000000000000000000000000000..2dca7afbd93cfbb8686f336fcd3b45dd01fba0fc
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/io/papermc/paper/FeatureHooks.java
|
+++ b/io/papermc/paper/FeatureHooks.java
|
||||||
@@ -1,0 +_,84 @@
|
@@ -1,0 +_,233 @@
|
||||||
+package io.papermc.paper;
|
+package io.papermc.paper;
|
||||||
+
|
+
|
||||||
+import io.papermc.paper.command.PaperSubcommand;
|
+import io.papermc.paper.command.PaperSubcommand;
|
||||||
|
@ -79,9 +79,158 @@
|
||||||
+ return true; // ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(spider.level().getWorldBorder(), spider.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON))
|
+ return true; // ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(spider.level().getWorldBorder(), spider.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON))
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ public static void dumpTickingInfo() {
|
+ public static void dumpAllChunkLoadInfo(net.minecraft.server.MinecraftServer server, boolean isLongTimeout) {
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private static void dumpEntity(final Entity entity) {
|
+ private static void dumpEntity(final Entity entity) {
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
|
+ public static org.bukkit.entity.Entity[] getChunkEntities(net.minecraft.server.level.ServerLevel world, int chunkX, int chunkZ) {
|
||||||
|
+ world.getChunk(chunkX, chunkZ); // ensure full loaded
|
||||||
|
+
|
||||||
|
+ net.minecraft.world.level.entity.PersistentEntitySectionManager<net.minecraft.world.entity.Entity> entityManager = world.entityManager;
|
||||||
|
+ long pair = ChunkPos.asLong(chunkX, chunkZ);
|
||||||
|
+
|
||||||
|
+ if (entityManager.areEntitiesLoaded(pair)) {
|
||||||
|
+ return entityManager.getEntities(new ChunkPos(chunkX, chunkZ)).stream()
|
||||||
|
+ .map(net.minecraft.world.entity.Entity::getBukkitEntity)
|
||||||
|
+ .filter(java.util.Objects::nonNull).toArray(org.bukkit.entity.Entity[]::new);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ entityManager.ensureChunkQueuedForLoad(pair); // Start entity loading
|
||||||
|
+
|
||||||
|
+ // SPIGOT-6772: Use entity mailbox and re-schedule entities if they get unloaded
|
||||||
|
+ net.minecraft.util.thread.ConsecutiveExecutor mailbox = ((net.minecraft.world.level.chunk.storage.EntityStorage) entityManager.permanentStorage).entityDeserializerQueue;
|
||||||
|
+ java.util.function.BooleanSupplier supplier = () -> {
|
||||||
|
+ // only execute inbox if our entities are not present
|
||||||
|
+ if (entityManager.areEntitiesLoaded(pair)) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!entityManager.isPending(pair)) {
|
||||||
|
+ // Our entities got unloaded, this should normally not happen.
|
||||||
|
+ entityManager.ensureChunkQueuedForLoad(pair); // Re-start entity loading
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // tick loading inbox, which loads the created entities to the world
|
||||||
|
+ // (if present)
|
||||||
|
+ entityManager.tick();
|
||||||
|
+ // check if our entities are loaded
|
||||||
|
+ return entityManager.areEntitiesLoaded(pair);
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ // now we wait until the entities are loaded,
|
||||||
|
+ // the converting from NBT to entity object is done on the main Thread which is why we wait
|
||||||
|
+ while (!supplier.getAsBoolean()) {
|
||||||
|
+ if (mailbox.size() != 0) {
|
||||||
|
+ mailbox.run();
|
||||||
|
+ } else {
|
||||||
|
+ Thread.yield();
|
||||||
|
+ java.util.concurrent.locks.LockSupport.parkNanos("waiting for entity loading", 100000L);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return entityManager.getEntities(new ChunkPos(chunkX, chunkZ)).stream()
|
||||||
|
+ .map(net.minecraft.world.entity.Entity::getBukkitEntity)
|
||||||
|
+ .filter(java.util.Objects::nonNull).toArray(org.bukkit.entity.Entity[]::new);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static java.util.Collection<org.bukkit.plugin.Plugin> getPluginChunkTickets(net.minecraft.server.level.ServerLevel world,
|
||||||
|
+ int x, int z) {
|
||||||
|
+ net.minecraft.server.level.DistanceManager chunkDistanceManager = world.getChunkSource().chunkMap.distanceManager;
|
||||||
|
+ net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>> tickets = chunkDistanceManager.tickets.get(ChunkPos.asLong(x, z));
|
||||||
|
+
|
||||||
|
+ if (tickets == null) {
|
||||||
|
+ return java.util.Collections.emptyList();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ com.google.common.collect.ImmutableList.Builder<org.bukkit.plugin.Plugin> ret = com.google.common.collect.ImmutableList.builder();
|
||||||
|
+ for (net.minecraft.server.level.Ticket<?> ticket : tickets) {
|
||||||
|
+ if (ticket.getType() == net.minecraft.server.level.TicketType.PLUGIN_TICKET) {
|
||||||
|
+ ret.add((org.bukkit.plugin.Plugin) ticket.key);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret.build();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static Map<org.bukkit.plugin.Plugin, java.util.Collection<org.bukkit.Chunk>> getPluginChunkTickets(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
+ Map<org.bukkit.plugin.Plugin, com.google.common.collect.ImmutableList.Builder<Chunk>> ret = new HashMap<>();
|
||||||
|
+ net.minecraft.server.level.DistanceManager chunkDistanceManager = world.getChunkSource().chunkMap.distanceManager;
|
||||||
|
+
|
||||||
|
+ for (it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry<net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>>> chunkTickets : chunkDistanceManager.tickets.long2ObjectEntrySet()) {
|
||||||
|
+ long chunkKey = chunkTickets.getLongKey();
|
||||||
|
+ net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>> tickets = chunkTickets.getValue();
|
||||||
|
+
|
||||||
|
+ org.bukkit.Chunk chunk = null;
|
||||||
|
+ for (net.minecraft.server.level.Ticket<?> ticket : tickets) {
|
||||||
|
+ if (ticket.getType() != net.minecraft.server.level.TicketType.PLUGIN_TICKET) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (chunk == null) {
|
||||||
|
+ chunk = world.getWorld().getChunkAt(ChunkPos.getX(chunkKey), ChunkPos.getZ(chunkKey));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret.computeIfAbsent((org.bukkit.plugin.Plugin) ticket.key, (key) -> com.google.common.collect.ImmutableList.builder()).add(chunk);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret.entrySet().stream().collect(com.google.common.collect.ImmutableMap.toImmutableMap(Map.Entry::getKey, (entry) -> entry.getValue().build()));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static int getViewDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
+ return world.getChunkSource().chunkMap.serverViewDistance;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static int getSimulationDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
+ return world.getChunkSource().chunkMap.getDistanceManager().simulationDistance;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static int getSendViewDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
+ return getViewDistance(world);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void setViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
|
+ if (distance < 2 || distance > 32) {
|
||||||
|
+ throw new IllegalArgumentException("View distance " + distance + " is out of range of [2, 32]");
|
||||||
|
+ }
|
||||||
|
+ world.chunkSource.chunkMap.setServerViewDistance(distance);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void setSimulationDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
|
+ if (distance < 2 || distance > 32) {
|
||||||
|
+ throw new IllegalArgumentException("Simulation distance " + distance + " is out of range of [2, 32]");
|
||||||
|
+ }
|
||||||
|
+ world.chunkSource.chunkMap.distanceManager.updateSimulationDistance(distance);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void setSendViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
|
+ throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void tickEntityManager(net.minecraft.server.level.ServerLevel world) {
|
||||||
|
+ world.entityManager.tick();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void closeEntityManager(net.minecraft.server.level.ServerLevel world, boolean save) {
|
||||||
|
+ world.entityManager.close(save);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static java.util.concurrent.Executor getWorldgenExecutor() {
|
||||||
|
+ return net.minecraft.Util.backgroundExecutor();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void setViewDistance(ServerPlayer player, int distance) {
|
||||||
|
+ throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void setSimulationDistance(ServerPlayer player, int distance) {
|
||||||
|
+ throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void setSendViewDistance(ServerPlayer player, int distance) {
|
||||||
|
+ throw new UnsupportedOperationException("Not implemented yet");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+}
|
+}
|
||||||
|
|
|
@ -83,6 +83,12 @@ public class CraftChunk implements Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkAccess getHandle(ChunkStatus chunkStatus) {
|
public ChunkAccess getHandle(ChunkStatus chunkStatus) {
|
||||||
|
// Paper start - chunk system
|
||||||
|
net.minecraft.world.level.chunk.LevelChunk full = this.worldServer.getChunkIfLoaded(this.x, this.z);
|
||||||
|
if (full != null) {
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
// Paper end - chunk system
|
||||||
ChunkAccess chunkAccess = this.worldServer.getChunk(this.x, this.z, chunkStatus);
|
ChunkAccess chunkAccess = this.worldServer.getChunk(this.x, this.z, chunkStatus);
|
||||||
|
|
||||||
// SPIGOT-7332: Get unwrapped extension
|
// SPIGOT-7332: Get unwrapped extension
|
||||||
|
@ -117,60 +123,12 @@ public class CraftChunk implements Chunk {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEntitiesLoaded() {
|
public boolean isEntitiesLoaded() {
|
||||||
return this.getCraftWorld().getHandle().entityManager.areEntitiesLoaded(ChunkPos.asLong(this.x, this.z));
|
return this.getCraftWorld().getHandle().areEntitiesLoaded(ChunkPos.asLong(this.x, this.z)); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Entity[] getEntities() {
|
public Entity[] getEntities() {
|
||||||
if (!this.isLoaded()) {
|
return FeatureHooks.getChunkEntities(this.worldServer, this.x, this.z); // Paper - chunk system
|
||||||
this.getWorld().getChunkAt(this.x, this.z); // Transient load for this tick
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentEntitySectionManager<net.minecraft.world.entity.Entity> entityManager = this.getCraftWorld().getHandle().entityManager;
|
|
||||||
long pair = ChunkPos.asLong(this.x, this.z);
|
|
||||||
|
|
||||||
if (entityManager.areEntitiesLoaded(pair)) {
|
|
||||||
return entityManager.getEntities(new ChunkPos(this.x, this.z)).stream()
|
|
||||||
.map(net.minecraft.world.entity.Entity::getBukkitEntity)
|
|
||||||
.filter(Objects::nonNull).toArray(Entity[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
entityManager.ensureChunkQueuedForLoad(pair); // Start entity loading
|
|
||||||
|
|
||||||
// SPIGOT-6772: Use entity mailbox and re-schedule entities if they get unloaded
|
|
||||||
ConsecutiveExecutor mailbox = ((EntityStorage) entityManager.permanentStorage).entityDeserializerQueue;
|
|
||||||
BooleanSupplier supplier = () -> {
|
|
||||||
// only execute inbox if our entities are not present
|
|
||||||
if (entityManager.areEntitiesLoaded(pair)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entityManager.isPending(pair)) {
|
|
||||||
// Our entities got unloaded, this should normally not happen.
|
|
||||||
entityManager.ensureChunkQueuedForLoad(pair); // Re-start entity loading
|
|
||||||
}
|
|
||||||
|
|
||||||
// tick loading inbox, which loads the created entities to the world
|
|
||||||
// (if present)
|
|
||||||
entityManager.tick();
|
|
||||||
// check if our entities are loaded
|
|
||||||
return entityManager.areEntitiesLoaded(pair);
|
|
||||||
};
|
|
||||||
|
|
||||||
// now we wait until the entities are loaded,
|
|
||||||
// the converting from NBT to entity object is done on the main Thread which is why we wait
|
|
||||||
while (!supplier.getAsBoolean()) {
|
|
||||||
if (mailbox.size() != 0) {
|
|
||||||
mailbox.run();
|
|
||||||
} else {
|
|
||||||
Thread.yield();
|
|
||||||
LockSupport.parkNanos("waiting for entity loading", 100000L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entityManager.getEntities(new ChunkPos(this.x, this.z)).stream()
|
|
||||||
.map(net.minecraft.world.entity.Entity::getBukkitEntity)
|
|
||||||
.filter(Objects::nonNull).toArray(Entity[]::new);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1448,7 +1448,7 @@ public final class CraftServer implements Server {
|
||||||
// Paper - Put world into worldlist before initing the world; move up
|
// Paper - Put world into worldlist before initing the world; move up
|
||||||
|
|
||||||
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
|
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
|
||||||
internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API
|
io.papermc.paper.FeatureHooks.tickEntityManager(internal); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - chunk system
|
||||||
|
|
||||||
this.pluginManager.callEvent(new WorldLoadEvent(internal.getWorld()));
|
this.pluginManager.callEvent(new WorldLoadEvent(internal.getWorld()));
|
||||||
return internal.getWorld();
|
return internal.getWorld();
|
||||||
|
@ -1493,7 +1493,7 @@ public final class CraftServer implements Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
handle.getChunkSource().close(save);
|
handle.getChunkSource().close(save);
|
||||||
handle.entityManager.close(save); // SPIGOT-6722: close entityManager
|
io.papermc.paper.FeatureHooks.closeEntityManager(handle, save); // SPIGOT-6722: close entityManager // Paper - chunk system
|
||||||
handle.levelStorageAccess.close();
|
handle.levelStorageAccess.close();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.getLogger().log(Level.SEVERE, null, ex);
|
this.getLogger().log(Level.SEVERE, null, ex);
|
||||||
|
|
|
@ -502,14 +502,17 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||||
ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
|
ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
|
||||||
if (playerChunk == null) return false;
|
if (playerChunk == null) return false;
|
||||||
|
|
||||||
playerChunk.getTickingChunkFuture().thenAccept(either -> {
|
// Paper start - chunk system
|
||||||
either.ifSuccess(chunk -> {
|
net.minecraft.world.level.chunk.LevelChunk chunk = playerChunk.getChunkToSend();
|
||||||
|
if (chunk == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Paper end - chunk system
|
||||||
List<ServerPlayer> playersInRange = playerChunk.playerProvider.getPlayers(playerChunk.getPos(), false);
|
List<ServerPlayer> playersInRange = playerChunk.playerProvider.getPlayers(playerChunk.getPos(), false);
|
||||||
if (playersInRange.isEmpty()) return;
|
if (playersInRange.isEmpty()) return true; // Paper - chunk system
|
||||||
|
|
||||||
FeatureHooks.sendChunkRefreshPackets(playersInRange, chunk);
|
FeatureHooks.sendChunkRefreshPackets(playersInRange, chunk);
|
||||||
});
|
// Paper - chunk system
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -611,47 +614,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Plugin> getPluginChunkTickets(int x, int z) {
|
public Collection<Plugin> getPluginChunkTickets(int x, int z) {
|
||||||
DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager;
|
return FeatureHooks.getPluginChunkTickets(this.world, x, z); // Paper - chunk system
|
||||||
SortedArraySet<Ticket<?>> tickets = chunkDistanceManager.tickets.get(ChunkPos.asLong(x, z));
|
|
||||||
|
|
||||||
if (tickets == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableList.Builder<Plugin> ret = ImmutableList.builder();
|
|
||||||
for (Ticket<?> ticket : tickets) {
|
|
||||||
if (ticket.getType() == TicketType.PLUGIN_TICKET) {
|
|
||||||
ret.add((Plugin) ticket.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Plugin, Collection<Chunk>> getPluginChunkTickets() {
|
public Map<Plugin, Collection<Chunk>> getPluginChunkTickets() {
|
||||||
Map<Plugin, ImmutableList.Builder<Chunk>> ret = new HashMap<>();
|
return FeatureHooks.getPluginChunkTickets(this.world); // Paper - chunk system
|
||||||
DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager;
|
|
||||||
|
|
||||||
for (Long2ObjectMap.Entry<SortedArraySet<Ticket<?>>> chunkTickets : chunkDistanceManager.tickets.long2ObjectEntrySet()) {
|
|
||||||
long chunkKey = chunkTickets.getLongKey();
|
|
||||||
SortedArraySet<Ticket<?>> tickets = chunkTickets.getValue();
|
|
||||||
|
|
||||||
Chunk chunk = null;
|
|
||||||
for (Ticket<?> ticket : tickets) {
|
|
||||||
if (ticket.getType() != TicketType.PLUGIN_TICKET) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk == null) {
|
|
||||||
chunk = this.getChunkAt(ChunkPos.getX(chunkKey), ChunkPos.getZ(chunkKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.computeIfAbsent((Plugin) ticket.key, (key) -> ImmutableList.builder()).add(chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.entrySet().stream().collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, (entry) -> entry.getValue().build()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -1336,12 +1304,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewDistance() {
|
public int getViewDistance() {
|
||||||
return this.world.getChunkSource().chunkMap.serverViewDistance;
|
return FeatureHooks.getViewDistance(this.world); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSimulationDistance() {
|
public int getSimulationDistance() {
|
||||||
return this.world.getChunkSource().chunkMap.getDistanceManager().simulationDistance;
|
return FeatureHooks.getSimulationDistance(this.world); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockMetadataStore getBlockMetadata() {
|
public BlockMetadataStore getBlockMetadata() {
|
||||||
|
@ -2472,25 +2440,22 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setViewDistance(final int viewDistance) {
|
public void setViewDistance(final int viewDistance) {
|
||||||
if (viewDistance < 2 || viewDistance > 32) {
|
FeatureHooks.setViewDistance(this.world, viewDistance); // Paper - chunk system
|
||||||
throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]");
|
|
||||||
}
|
|
||||||
this.getHandle().chunkSource.chunkMap.setServerViewDistance(viewDistance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSimulationDistance(final int simulationDistance) {
|
public void setSimulationDistance(final int simulationDistance) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
FeatureHooks.setSimulationDistance(this.world, simulationDistance); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSendViewDistance() {
|
public int getSendViewDistance() {
|
||||||
return this.getViewDistance();
|
return FeatureHooks.getSendViewDistance(this.world); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSendViewDistance(final int viewDistance) {
|
public void setSendViewDistance(final int viewDistance) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
FeatureHooks.setSendViewDistance(this.world, viewDistance); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paper start - implement pointers
|
// Paper start - implement pointers
|
||||||
|
|
|
@ -3527,7 +3527,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setViewDistance(final int viewDistance) {
|
public void setViewDistance(final int viewDistance) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
FeatureHooks.setViewDistance(this.getHandle(), viewDistance); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3537,7 +3537,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSimulationDistance(final int simulationDistance) {
|
public void setSimulationDistance(final int simulationDistance) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
FeatureHooks.setSimulationDistance(this.getHandle(), simulationDistance); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3547,7 +3547,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSendViewDistance(final int viewDistance) {
|
public void setSendViewDistance(final int viewDistance) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
FeatureHooks.setSendViewDistance(this.getHandle(), viewDistance); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paper start - entity effect API
|
// Paper start - entity effect API
|
||||||
|
|
|
@ -264,7 +264,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
||||||
return ichunkaccess1;
|
return ichunkaccess1;
|
||||||
};
|
};
|
||||||
|
|
||||||
return future == null ? CompletableFuture.supplyAsync(() -> function.apply(chunk), net.minecraft.Util.backgroundExecutor()) : future.thenApply(function);
|
return future == null ? CompletableFuture.supplyAsync(() -> function.apply(chunk), io.papermc.paper.FeatureHooks.getWorldgenExecutor()) : future.thenApply(function); // Paper - chunk system
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,7 +7,7 @@ public class AsyncCatcher {
|
||||||
public static boolean enabled = true;
|
public static boolean enabled = true;
|
||||||
|
|
||||||
public static void catchOp(String reason) {
|
public static void catchOp(String reason) {
|
||||||
if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) {
|
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { // Paper - chunk system
|
||||||
MinecraftServer.LOGGER.error("Thread {} failed main thread check: {}", Thread.currentThread().getName(), reason, new Throwable()); // Paper
|
MinecraftServer.LOGGER.error("Thread {} failed main thread check: {}", Thread.currentThread().getName(), reason, new Throwable()); // Paper
|
||||||
throw new IllegalStateException("Asynchronous " + reason + "!");
|
throw new IllegalStateException("Asynchronous " + reason + "!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class WatchdogThread extends Thread {
|
||||||
// Paper end - Different message for short timeout
|
// Paper end - Different message for short timeout
|
||||||
logger.log(Level.SEVERE, "------------------------------");
|
logger.log(Level.SEVERE, "------------------------------");
|
||||||
logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper
|
logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper
|
||||||
FeatureHooks.dumpTickingInfo(); // Paper - log detailed tick information
|
FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information
|
||||||
WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger);
|
WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger);
|
||||||
logger.log(Level.SEVERE, "------------------------------");
|
logger.log(Level.SEVERE, "------------------------------");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue