Update paper

This commit is contained in:
Spottedleaf 2023-07-06 22:02:11 -07:00
parent 6b978f2aaf
commit bd96e299d4
16 changed files with 274 additions and 2263 deletions

View File

@ -2,7 +2,7 @@ group=dev.folia
version=1.20.1-R0.1-SNAPSHOT
mcVersion=1.20.1
paperRef=a226f44b452c8c75ca077b492ba4a957629ba489
paperRef=d7d3f6371e15f68bbbfc70d567552d426563acfb
org.gradle.caching=true
org.gradle.parallel=true

View File

@ -6,592 +6,6 @@ Subject: [PATCH] Region scheduler API
Add both a location based scheduler, an entity based scheduler,
and a global region scheduler.
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..66232a9f5cea31dc8046817c3c2a91695930e53f
--- /dev/null
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java
@@ -0,0 +1,50 @@
+package io.papermc.paper.threadedregions.scheduler;
+
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * Scheduler that may be used by plugins to schedule tasks to execute asynchronously from the server tick process.
+ */
+public interface AsyncScheduler {
+
+ /**
+ * Schedules the specified task to be executed asynchronously immediately.
+ * @param plugin Plugin which owns the specified task.
+ * @param task Specified task.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runNow(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task);
+
+ /**
+ * Schedules the specified task to be executed asynchronously after the time delay has passed.
+ * @param plugin Plugin which owns the specified task.
+ * @param task Specified task.
+ * @param delay The time delay to pass before the task should be executed.
+ * @param unit The time unit for the time delay.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task, long delay,
+ @NotNull TimeUnit unit);
+
+ /**
+ * Schedules the specified task to be executed asynchronously after the initial delay has passed,
+ * and then periodically executed with the specified period.
+ * @param plugin Plugin which owns the specified task.
+ * @param task Specified task.
+ * @param initialDelay The time delay to pass before the first execution of the task.
+ * @param period The time between task executions after the first execution of the task.
+ * @param unit The time unit for the initial delay and period.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
+ long initialDelay, long period, @NotNull TimeUnit unit);
+
+ /**
+ * Attempts to cancel all tasks scheduled by the specified plugin.
+ * @param plugin Specified plugin.
+ */
+ void cancelTasks(@NotNull Plugin plugin);
+}
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..01fc5d440ee96a2b00fadaf304cedf418a946b21
--- /dev/null
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java
@@ -0,0 +1,103 @@
+package io.papermc.paper.threadedregions.scheduler;
+
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.function.Consumer;
+
+/**
+ * An entity can move between worlds with an arbitrary tick delay, be temporarily removed
+ * for players (i.e end credits), be partially removed from world state (i.e inactive but not removed),
+ * teleport between ticking regions, teleport between worlds, and even be removed entirely from the server.
+ * The uncertainty of an entity's state can make it difficult to schedule tasks without worrying about undefined
+ * behaviors resulting from any of the states listed previously.
+ *
+ * <p>
+ * This class is designed to eliminate those states by providing an interface to run tasks only when an entity
+ * is contained in a world, on the owning thread for the region, and by providing the current Entity object.
+ * The scheduler also allows a task to provide a callback, the "retired" callback, that will be invoked
+ * if the entity is removed before a task that was scheduled could be executed. The scheduler is also
+ * completely thread-safe, allowing tasks to be scheduled from any thread context. The scheduler also indicates
+ * properly whether a task was scheduled successfully (i.e scheduler not retired), thus the code scheduling any task
+ * knows whether the given callbacks will be invoked eventually or not - which may be critical for off-thread
+ * contexts.
+ * </p>
+ */
+public interface EntityScheduler {
+
+ /**
+ * Schedules a task with the given delay. If the task failed to schedule because the scheduler is retired (entity
+ * removed), then returns {@code false}. Otherwise, either the run callback will be invoked after the specified delay,
+ * or the retired callback will be invoked if the scheduler is retired.
+ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove
+ * other entities, load chunks, load worlds, modify ticket levels, etc.
+ *
+ * <p>
+ * It is guaranteed that the run and retired callback are invoked on the region which owns the entity.
+ * </p>
+ * @param run The callback to run after the specified delay, may not be null.
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
+ * @param delay The delay in ticks before the run callback is invoked. Any value less-than 1 is treated as 1.
+ * @return {@code true} if the task was scheduled, which means that either the run function or the retired function
+ * will be invoked (but never both), or {@code false} indicating neither the run nor retired function will be invoked
+ * since the scheduler has been retired.
+ */
+ boolean execute(@NotNull Plugin plugin, @NotNull Runnable run, @Nullable Runnable retired, long delay);
+
+ /**
+ * Schedules a task to execute on the next tick. If the task failed to schedule because the scheduler is retired (entity
+ * removed), then returns {@code null}. Otherwise, either the task callback will be invoked after the specified delay,
+ * or the retired callback will be invoked if the scheduler is retired.
+ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove
+ * other entities, load chunks, load worlds, modify ticket levels, etc.
+ *
+ * <p>
+ * It is guaranteed that the task and retired callback are invoked on the region which owns the entity.
+ * </p>
+ * @param plugin The plugin that owns the task
+ * @param task The task to execute
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
+ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed.
+ */
+ @Nullable ScheduledTask run(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
+ @Nullable Runnable retired);
+
+ /**
+ * Schedules a task with the given delay. If the task failed to schedule because the scheduler is retired (entity
+ * removed), then returns {@code null}. Otherwise, either the task callback will be invoked after the specified delay,
+ * or the retired callback will be invoked if the scheduler is retired.
+ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove
+ * other entities, load chunks, load worlds, modify ticket levels, etc.
+ *
+ * <p>
+ * It is guaranteed that the task and retired callback are invoked on the region which owns the entity.
+ * </p>
+ * @param plugin The plugin that owns the task
+ * @param task The task to execute
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
+ * @param delayTicks The delay, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed.
+ */
+ @Nullable ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
+ @Nullable Runnable retired, long delayTicks);
+
+ /**
+ * Schedules a repeating task with the given delay and period. If the task failed to schedule because the scheduler
+ * is retired (entity removed), then returns {@code null}. Otherwise, either the task callback will be invoked after
+ * the specified delay, or the retired callback will be invoked if the scheduler is retired.
+ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove
+ * other entities, load chunks, load worlds, modify ticket levels, etc.
+ *
+ * <p>
+ * It is guaranteed that the task and retired callback are invoked on the region which owns the entity.
+ * </p>
+ * @param plugin The plugin that owns the task
+ * @param task The task to execute
+ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null.
+ * @param initialDelayTicks The initial delay, in ticks.
+ * @param periodTicks The period, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed.
+ */
+ @Nullable ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
+ @Nullable Runnable retired, long initialDelayTicks, long periodTicks);
+}
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..712af8218d5a81f731a227bcaccd7a1dc54628be
--- /dev/null
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
@@ -0,0 +1,57 @@
+package io.papermc.paper.threadedregions.scheduler;
+
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import java.util.function.Consumer;
+
+/**
+ * The global region task scheduler may be used to schedule tasks that will execute on the global region.
+ * <p>
+ * The global region is responsible for maintaining world day time, world game time, weather cycle,
+ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region.
+ * </p>
+ */
+public interface GlobalRegionScheduler {
+
+ /**
+ * Schedules a task to be executed on the global region.
+ * @param plugin The plugin that owns the task
+ * @param run The task to execute
+ */
+ void execute(@NotNull Plugin plugin, @NotNull Runnable run);
+
+ /**
+ * Schedules a task to be executed on the global region on the next tick.
+ * @param plugin The plugin that owns the task
+ * @param task The task to execute
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task);
+
+ /**
+ * Schedules a task to be executed on the global region after the specified delay in ticks.
+ * @param plugin The plugin that owns the task
+ * @param task The task to execute
+ * @param delayTicks The delay, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task, long delayTicks);
+
+ /**
+ * Schedules a repeating task to be executed on the global region after the initial delay with the
+ * specified period.
+ * @param plugin The plugin that owns the task
+ * @param task The task to execute
+ * @param initialDelayTicks The initial delay, in ticks.
+ * @param periodTicks The period, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer<ScheduledTask> task,
+ long initialDelayTicks, long periodTicks);
+
+ /**
+ * Attempts to cancel all tasks scheduled by the specified plugin.
+ * @param plugin Specified plugin.
+ */
+ void cancelTasks(@NotNull Plugin plugin);
+}
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a7afd4ffb323dd55db13ef1a49c6594aeb5ffea
--- /dev/null
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java
@@ -0,0 +1,126 @@
+package io.papermc.paper.threadedregions.scheduler;
+
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Entity;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import java.util.function.Consumer;
+
+/**
+ * The region task scheduler can be used to schedule tasks by location to be executed on the region which owns the location.
+ * <p>
+ * <b>Note</b>: It is entirely inappropriate to use the region scheduler to schedule tasks for entities.
+ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()}
+ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler
+ * will not.
+ * </p>
+ */
+public interface RegionScheduler {
+
+ /**
+ * Schedules a task to be executed on the region which owns the location.
+ *
+ * @param plugin The plugin that owns the task
+ * @param world The world of the region that owns the task
+ * @param chunkX The chunk X coordinate of the region that owns the task
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
+ * @param run The task to execute
+ */
+ void execute(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Runnable run);
+
+ /**
+ * Schedules a task to be executed on the region which owns the location.
+ *
+ * @param plugin The plugin that owns the task
+ * @param location The location at which the region executing should own
+ * @param run The task to execute
+ */
+ default void execute(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable run) {
+ this.execute(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, run);
+ }
+
+ /**
+ * Schedules a task to be executed on the region which owns the location on the next tick.
+ *
+ * @param plugin The plugin that owns the task
+ * @param world The world of the region that owns the task
+ * @param chunkX The chunk X coordinate of the region that owns the task
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
+ * @param task The task to execute
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<ScheduledTask> task);
+
+ /**
+ * Schedules a task to be executed on the region which owns the location on the next tick.
+ *
+ * @param plugin The plugin that owns the task
+ * @param location The location at which the region executing should own
+ * @param task The task to execute
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ default @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer<ScheduledTask> task) {
+ return this.run(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
+ }
+
+ /**
+ * Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
+ *
+ * @param plugin The plugin that owns the task
+ * @param world The world of the region that owns the task
+ * @param chunkX The chunk X coordinate of the region that owns the task
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
+ * @param task The task to execute
+ * @param delayTicks The delay, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<ScheduledTask> task,
+ long delayTicks);
+
+ /**
+ * Schedules a task to be executed on the region which owns the location after the specified delay in ticks.
+ *
+ * @param plugin The plugin that owns the task
+ * @param location The location at which the region executing should own
+ * @param task The task to execute
+ * @param delayTicks The delay, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ default @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer<ScheduledTask> task,
+ long delayTicks) {
+ return this.runDelayed(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks);
+ }
+
+ /**
+ * Schedules a repeating task to be executed on the region which owns the location after the initial delay with the
+ * specified period.
+ *
+ * @param plugin The plugin that owns the task
+ * @param world The world of the region that owns the task
+ * @param chunkX The chunk X coordinate of the region that owns the task
+ * @param chunkZ The chunk Z coordinate of the region that owns the task
+ * @param task The task to execute
+ * @param initialDelayTicks The initial delay, in ticks.
+ * @param periodTicks The period, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer<ScheduledTask> task,
+ long initialDelayTicks, long periodTicks);
+
+ /**
+ * Schedules a repeating task to be executed on the region which owns the location after the initial delay with the
+ * specified period.
+ *
+ * @param plugin The plugin that owns the task
+ * @param location The location at which the region executing should own
+ * @param task The task to execute
+ * @param initialDelayTicks The initial delay, in ticks.
+ * @param periodTicks The period, in ticks.
+ * @return The {@link ScheduledTask} that represents the scheduled task.
+ */
+ default @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer<ScheduledTask> task,
+ long initialDelayTicks, long periodTicks) {
+ return this.runAtFixedRate(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, initialDelayTicks, periodTicks);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6b50c9d8af589cc4747e14d343d2045216c249c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java
@@ -0,0 +1,112 @@
+package io.papermc.paper.threadedregions.scheduler;
+
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents a task scheduled to a scheduler.
+ */
+public interface ScheduledTask {
+
+ /**
+ * Returns the plugin that scheduled this task.
+ * @return the plugin that scheduled this task.
+ */
+ @NotNull Plugin getOwningPlugin();
+
+ /**
+ * Returns whether this task executes on a fixed period, as opposed to executing only once.
+ * @return whether this task executes on a fixed period, as opposed to executing only once.
+ */
+ boolean isRepeatingTask();
+
+ /**
+ * Attempts to cancel this task, returning the result of the attempt. In all cases, if the task is currently
+ * being executed no attempt is made to halt the task, however any executions in the future are halted.
+ * @return the result of the cancellation attempt.
+ */
+ @NotNull CancelledState cancel();
+
+ /**
+ * Returns the current execution state of this task.
+ * @return the current execution state of this task.
+ */
+ @NotNull ExecutionState getExecutionState();
+
+ /**
+ * Returns whether the current execution state is {@link ExecutionState#CANCELLED} or {@link ExecutionState#CANCELLED_RUNNING}.
+ * @return whether the current execution state is {@link ExecutionState#CANCELLED} or {@link ExecutionState#CANCELLED_RUNNING}.
+ */
+ default boolean isCancelled() {
+ final ExecutionState state = this.getExecutionState();
+ return state == ExecutionState.CANCELLED || state == ExecutionState.CANCELLED_RUNNING;
+ }
+
+ /**
+ * Represents the result of attempting to cancel a task.
+ */
+ enum CancelledState {
+ /**
+ * The task (repeating or not) has been successfully cancelled by the caller thread. The task is not executing
+ * currently, and it will not begin execution in the future.
+ */
+ CANCELLED_BY_CALLER,
+ /**
+ * The task (repeating or not) is already cancelled. The task is not executing currently, and it will not
+ * begin execution in the future.
+ */
+ CANCELLED_ALREADY,
+
+ /**
+ * The task is not a repeating task, and could not be cancelled because the task is being executed.
+ */
+ RUNNING,
+ /**
+ * The task is not a repeating task, and could not be cancelled because the task has already finished execution.
+ */
+ ALREADY_EXECUTED,
+
+ /**
+ * The caller thread successfully stopped future executions of a repeating task, but the task is currently
+ * being executed.
+ */
+ NEXT_RUNS_CANCELLED,
+
+ /**
+ * The repeating task's future executions are cancelled already, but the task is currently
+ * being executed.
+ */
+ NEXT_RUNS_CANCELLED_ALREADY,
+ }
+
+ /**
+ * Represents the current execution state of the task.
+ */
+ enum ExecutionState {
+ /**
+ * The task is currently not executing, but may begin execution in the future.
+ */
+ IDLE,
+
+ /**
+ * The task is currently executing.
+ */
+ RUNNING,
+
+ /**
+ * The task is not repeating, and the task finished executing.
+ */
+ FINISHED,
+
+ /**
+ * The task is not executing and will not begin execution in the future. If this task is not repeating, then
+ * this task was never executed.
+ */
+ CANCELLED,
+
+ /**
+ * The task is repeating and currently executing, but future executions are cancelled and will not occur.
+ */
+ CANCELLED_RUNNING;
+ }
+}
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index ef36d793ab77c7b7208f8f5994815599cff470d1..fdf5597804640839c3d92b5e7ee55a3388a63592 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2495,6 +2495,44 @@ public final class Bukkit {
return server.getPotionBrewer();
}
// Paper end
+ // Folia start - region threading API
+ /**
+ * Returns the region task scheduler. The region task scheduler can be used to schedule
+ * tasks by location to be executed on the region which owns the location.
+ * <p>
+ * <b>Note</b>: It is entirely inappropriate to use the region scheduler to schedule tasks for entities.
+ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()}
+ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler
+ * will not.
+ * </p>
+ * @return the region task scheduler
+ */
+ public static @NotNull io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler() {
+ return server.getRegionScheduler();
+ }
+
+ /**
+ * Returns the async task scheduler. The async task scheduler can be used to schedule tasks
+ * that execute asynchronously from the server tick process.
+ * @return the async task scheduler
+ */
+ public static @NotNull io.papermc.paper.threadedregions.scheduler.AsyncScheduler getAsyncScheduler() {
+ return server.getAsyncScheduler();
+ }
+
+ /**
+ * Returns the global region task scheduler. The global task scheduler can be used to schedule
+ * tasks to execute on the global region.
+ * <p>
+ * The global region is responsible for maintaining world day time, world game time, weather cycle,
+ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region.
+ * </p>
+ * @return the global region scheduler
+ */
+ public static @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler() {
+ return server.getGlobalRegionScheduler();
+ }
+ // Folia end - region threading API
@NotNull
public static Server.Spigot spigot() {
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 5b225bbb128893d67251a96ab318035802a0cf76..52e900cdd06b6927646f82f779c19aa7dc1e5c1e 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2175,4 +2175,36 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
@NotNull org.bukkit.potion.PotionBrewer getPotionBrewer();
// Paper end
+ // Folia start - region threading API
+ /**
+ * Returns the region task scheduler. The region task scheduler can be used to schedule
+ * tasks by location to be executed on the region which owns the location.
+ * <p>
+ * <b>Note</b>: It is entirely inappropriate to use the region scheduler to schedule tasks for entities.
+ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()}
+ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler
+ * will not.
+ * </p>
+ * @return the region task scheduler
+ */
+ public @NotNull io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler();
+
+ /**
+ * Returns the async task scheduler. The async task scheduler can be used to schedule tasks
+ * that execute asynchronously from the server tick process.
+ * @return the async task scheduler
+ */
+ public @NotNull io.papermc.paper.threadedregions.scheduler.AsyncScheduler getAsyncScheduler();
+
+ /**
+ * Returns the global region task scheduler. The global task scheduler can be used to schedule
+ * tasks to execute on the global region.
+ * <p>
+ * The global region is responsible for maintaining world day time, world game time, weather cycle,
+ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region.
+ * </p>
+ * @return the global region scheduler
+ */
+ public @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler();
+ // Folia end - region threading API
}
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index a2a423d4e4c2702ba5967223cab0432dd7d04732..de51553f7a03b367388aa37532f849c688447acb 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -954,4 +954,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
boolean wouldCollideUsing(@NotNull BoundingBox boundingBox);
// Paper End - Collision API
+ // Folia start - region threading API
+ /**
+ * Returns the task scheduler for this entity. The entity scheduler can be used to schedule tasks
+ * that are guaranteed to always execute on the tick thread that owns the entity.
+ * @return the task scheduler for this entity.
+ * @see io.papermc.paper.threadedregions.scheduler.EntityScheduler
+ */
+ @NotNull io.papermc.paper.threadedregions.scheduler.EntityScheduler getScheduler();
+ // Folia end - region threading API
}
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
index fc2dae69165776d08274e34a69962cc70445f411..06149045a44148bf0af5f52952ff0092fe2c70cb 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java

View File

@ -31,10 +31,10 @@ index ef393f1f93ca48264fc1b6e3a27787f6a9152e1b..1325f9fed80731b74b80145dadc843b1
+
}
diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java
index 028805bcdb1d2bb0d11387db165b7376579e5f60..7bc31036a612df6088a7bb190ed16d0cdbfeaccc 100644
index 07e8908d25fcd4e5eabadc9f019b54acff3b5e3c..02ab82f6d0eb2a5afbb6b0ac4d738097c4986ad1 100644
--- a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java
+++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java
@@ -255,6 +255,21 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
@@ -258,6 +258,21 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
private Set<PluginAwareness> awareness = ImmutableSet.of();
private String apiVersion = null;
private List<String> libraries = ImmutableList.of();
@ -56,7 +56,7 @@ index 028805bcdb1d2bb0d11387db165b7376579e5f60..7bc31036a612df6088a7bb190ed16d0c
// Paper start - oh my goddddd
/**
* Don't use this.
@@ -1238,6 +1253,11 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
@@ -1241,6 +1256,11 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
if (map.get("prefix") != null) {
prefix = map.get("prefix").toString();
}
@ -68,7 +68,7 @@ index 028805bcdb1d2bb0d11387db165b7376579e5f60..7bc31036a612df6088a7bb190ed16d0c
}
@NotNull
@@ -1314,6 +1334,11 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
@@ -1317,6 +1337,11 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
if (prefix != null) {
map.put("prefix", prefix);
}

View File

@ -11,209 +11,36 @@ the schedulers depending on the result of the ownership
check.
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index fdf5597804640839c3d92b5e7ee55a3388a63592..db1944bc41ab0bae9b825c7839e8d1ee86eddff0 100644
index b243db56756c67cd2c41d7768898d01539f9260a..fd5ed5d6725537c26e6139dd6242c4154b306a97 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2532,6 +2532,107 @@ public final class Bukkit {
public static @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler() {
return server.getGlobalRegionScheduler();
@@ -2657,6 +2657,14 @@ public final class Bukkit {
return server.isOwnedByCurrentRegion(entity);
}
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified world and block position.
+ * @param world Specified world.
+ * @param position Specified block position.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position) {
+ return server.isOwnedByCurrentRegion(world, position);
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunks centered at the specified block position within the specified square radius.
+ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and
+ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region.
+ * @param world Specified world.
+ * @param position Specified block position.
+ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is <i>not</i> a <i>squared</i>
+ * radius, but rather a <i>Chebyshev Distance</i>.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position, int squareRadiusChunks) {
+ return server.isOwnedByCurrentRegion(world, position, squareRadiusChunks);
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified world and block position as included in the specified location.
+ * @param location Specified location, must have a non-null world.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull Location location) {
+ return server.isOwnedByCurrentRegion(location);
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunks centered at the specified world and block position as included in the specified location
+ * within the specified square radius.
+ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and
+ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region.
+ * @param location Specified location, must have a non-null world.
+ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is <i>not</i> a <i>squared</i>
+ * radius, but rather a <i>Chebyshev Distance</i>.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks) {
+ return server.isOwnedByCurrentRegion(location, squareRadiusChunks);
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified block position.
+ * @param block Specified block position.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull org.bukkit.block.Block block) {
+ return server.isOwnedByCurrentRegion(block.getLocation());
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified world and chunk position.
+ * @param world Specified world.
+ * @param chunkX Specified x-coordinate of the chunk position.
+ * @param chunkZ Specified z-coordinate of the chunk position.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ) {
+ return server.isOwnedByCurrentRegion(world, chunkX, chunkZ);
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunks centered at the specified world and chunk position within the specified
+ * square radius.
+ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and
+ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region.
+ * @param world Specified world.
+ * @param chunkX Specified x-coordinate of the chunk position.
+ * @param chunkZ Specified z-coordinate of the chunk position.
+ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is <i>not</i> a <i>squared</i>
+ * radius, but rather a <i>Chebyshev Distance</i>.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks) {
+ return server.isOwnedByCurrentRegion(world, chunkX, chunkZ, squareRadiusChunks);
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the specified entity. Note that this function is the only appropriate method of checking
+ * for ownership of an entity, as retrieving the entity's location is undefined unless the entity is owned
+ * by the current region.
+ * @param entity Specified entity.
+ */
+ public static boolean isOwnedByCurrentRegion(@NotNull Entity entity) {
+ return server.isOwnedByCurrentRegion(entity);
+ }
+
// Paper end - Folia region threading API
+ // Folia start - region threading API
+ /**
+ * Returns whether the current thread is ticking the global region.
+ */
+ public static boolean isGlobalTickThread() {
+ return server.isGlobalTickThread();
+ }
// Folia end - region threading API
+ // Folia end - region threading API
@NotNull
public static Server.Spigot spigot() {
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 52e900cdd06b6927646f82f779c19aa7dc1e5c1e..1ef4cf3b19d58565e052829358eb5902f070ae02 100644
index 6b72eccdcb6f75534a4267a1dd0a4cc2f39e917b..57d4789c1eb00cb376adce31ece2b6672c4a12a9 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2206,5 +2206,90 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @return the global region scheduler
@@ -2313,4 +2313,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
public @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler();
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified world and block position.
+ * @param world Specified world.
+ * @param position Specified block position.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position);
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunks centered at the specified block position within the specified square radius.
+ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and
+ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region.
+ * @param world Specified world.
+ * @param position Specified block position.
+ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is <i>not</i> a <i>squared</i>
+ * radius, but rather a <i>Chebyshev Distance</i>.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position, int squareRadiusChunks);
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified world and block position as included in the specified location.
+ * @param location Specified location, must have a non-null world.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull Location location);
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunks centered at the specified world and block position as included in the specified location
+ * within the specified square radius.
+ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and
+ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region.
+ * @param location Specified location, must have a non-null world.
+ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is <i>not</i> a <i>squared</i>
+ * radius, but rather a <i>Chebyshev Distance</i>.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks);
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified block position.
+ * @param block Specified block position.
+ */
+ default boolean isOwnedByCurrentRegion(@NotNull org.bukkit.block.Block block) {
+ return isOwnedByCurrentRegion(block.getLocation());
+ }
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunk at the specified world and chunk position.
+ * @param world Specified world.
+ * @param chunkX Specified x-coordinate of the chunk position.
+ * @param chunkZ Specified z-coordinate of the chunk position.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ);
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the chunks centered at the specified world and chunk position within the specified
+ * square radius.
+ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and
+ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region.
+ * @param world Specified world.
+ * @param chunkX Specified x-coordinate of the chunk position.
+ * @param chunkZ Specified z-coordinate of the chunk position.
+ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is <i>not</i> a <i>squared</i>
+ * radius, but rather a <i>Chebyshev Distance</i>.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks);
+
+ /**
+ * Returns whether the current thread is ticking a region and that the region being ticked
+ * owns the specified entity. Note that this function is the only appropriate method of checking
+ * for ownership of an entity, as retrieving the entity's location is undefined unless the entity is owned
+ * by the current region.
+ * @param entity Specified entity.
+ */
+ public boolean isOwnedByCurrentRegion(@NotNull Entity entity);
+
boolean isOwnedByCurrentRegion(@NotNull Entity entity);
// Paper end - Folia region threading API
+ // Folia start - region threading API
+ /**
+ * Returns whether the current thread is ticking the global region.
+ */
+ public boolean isGlobalTickThread();
// Folia end - region threading API
+ // Folia end - region threading API
}

View File

@ -5,11 +5,11 @@ Subject: [PATCH] Build changes
diff --git a/build.gradle.kts b/build.gradle.kts
index 19186e436cd6a5f00f0b42ac11f8050ad2ef6713..215366d7cc3720805d2dfde0662372ecede8383c 100644
index 57f2c414dbfe127c193002fbc8eeb22e94e9cb55..93f9abd2169a48a4fd32f712c68be7b49b034e83 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,8 +7,12 @@ plugins {
}
@@ -13,8 +13,12 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) {
val alsoShade: Configuration by configurations.creating
dependencies {
- implementation(project(":paper-api"))
@ -23,7 +23,7 @@ index 19186e436cd6a5f00f0b42ac11f8050ad2ef6713..215366d7cc3720805d2dfde0662372ec
// Paper start
implementation("org.jline:jline-terminal-jansi:3.21.0")
implementation("net.minecrell:terminalconsoleappender:1.3.0")
@@ -64,7 +68,7 @@ tasks.jar {
@@ -72,7 +76,7 @@ tasks.jar {
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
"Implementation-Title" to "CraftBukkit",
@ -32,7 +32,7 @@ index 19186e436cd6a5f00f0b42ac11f8050ad2ef6713..215366d7cc3720805d2dfde0662372ec
"Implementation-Vendor" to date, // Paper
"Specification-Title" to "Bukkit",
"Specification-Version" to project.version,
@@ -136,7 +140,7 @@ fun TaskContainer.registerRunTask(
@@ -149,7 +153,7 @@ fun TaskContainer.registerRunTask(
name: String,
block: JavaExec.() -> Unit
): TaskProvider<JavaExec> = register<JavaExec>(name) {
@ -88,10 +88,10 @@ index 9d687da5bdf398bb3f6c84cdf1249a7213d09f2e..e2f704c115fd6e00960bb56bb0779f11
).openBufferedStream()) {
JsonObject json = new Gson().fromJson(reader, JsonObject.class);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 80cf4852e4010eeeadaf920ab927a40df0179b40..c7a762abdfdc88fd26ec751c34e7b42bb3514515 100644
index 3238cbcba567b1242c77e41f6b6f19a8d157fb4e..f2bda376d64296cf41e44b03e83bc6fe000edb88 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1679,7 +1679,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1693,7 +1693,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@DontObfuscate
public String getServerModName() {
@ -101,10 +101,10 @@ index 80cf4852e4010eeeadaf920ab927a40df0179b40..c7a762abdfdc88fd26ec751c34e7b42b
public SystemReport fillSystemReport(SystemReport details) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 59984cb8ba9ffb66b59a2c907e4f04b5a51ea8ed..edb26528b943f13aa45aba6bcaf63f5403f2f897 100644
index a05c1bc8874ef5e380544a6a344c848e37da49c4..50f75400e59a5d917416f284ecc5a1f77896113f 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -261,7 +261,7 @@ import javax.annotation.Nullable; // Paper
@@ -264,7 +264,7 @@ import javax.annotation.Nullable; // Paper
import javax.annotation.Nonnull; // Paper
public final class CraftServer implements Server {

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@ index 2e96377d628b3a07fb565020074d665f594f32e8..75b1877f8c3e4da3183437f327ef3376
} // Folia - region threading - remove delayed accept
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 5b4e7e22b0e989b7d19b0b28cf74e08acacd1fa1..d4620ddfcd06a037f647ab0a8938797405e001b2 100644
index 9aa12c2ae7d86604583e98ba9872ad613882c867..39d404c278bdc1227cb806bb257492493d05a439 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -180,6 +180,17 @@ public abstract class PlayerList {

View File

@ -28,49 +28,27 @@ index 41bf71d116ffc5431586ce54abba7f8def6c1dcf..519da6886613b8460e989767b1a21e31
return (AbstractSchoolingFish) super.getHandle();
}
diff --git a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
index d9687722e02dfd4088c7030abbf5008eb0a092c8..62484ebf4550b05182f693a3180bbac5d5fd906d 100644
--- a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
+++ b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
@@ -68,7 +68,7 @@ public final class EntityScheduler {
this.tickCount = RETIRED_TICK_COUNT;
}
- final Entity thisEntity = this.entity.getHandle();
+ final Entity thisEntity = this.entity.getHandleRaw();
// correctly handle and order retiring while running executeTick
for (int i = 0, len = this.currentlyExecuting.size(); i < len; ++i) {
@@ -138,7 +138,7 @@ public final class EntityScheduler {
* @throws IllegalStateException If the scheduler is retired.
*/
public void executeTick() {
- final Entity thisEntity = this.entity.getHandle();
+ final Entity thisEntity = this.entity.getHandleRaw();
TickThread.ensureTickThread(thisEntity, "May not tick entity scheduler asynchronously");
final List<ScheduledTask> toRun;
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 5a71b5a37a55baea204821aba734d53dc49cb336..27b57db24587337ccdce29e492052ca419863323 100644
index bce3c60667ca11a062f1e83cbf125b1d5182e392..52aa759db930c04a051686766c1b822a5131a20a 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2889,6 +2889,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
// CraftBukkit start
com.google.common.base.Preconditions.checkState(!entity.passengers.contains(this), "Circular entity riding! %s %s", this, entity);
+ if (this.valid) { // Folia - region threading - suppress entire event logic during worldgen
CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle();
Entity orig = craft == null ? null : craft.getHandle();
if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) {
@@ -2916,6 +2917,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (event.isCancelled()) {
@@ -2820,6 +2820,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (!force && (!this.canRide(entity) || !entity.canAddPassenger(this))) {
return false;
}
+ } // Folia - region threading - suppress entire event logic during worldgen
// Spigot end
if (this.passengers.isEmpty()) {
this.passengers = ImmutableList.of(entity);
@@ -2944,6 +2946,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
} else {
+ if (this.valid) { // Folia - region threading - suppress entire event logic during worldgen
// CraftBukkit start
if (entity.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) {
VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) entity.getBukkitEntity(), this.getBukkitEntity());
@@ -2841,6 +2842,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (event.isCancelled()) {
return false;
}
+ } // Folia - region threading - suppress entire event logic during worldgen
// Spigot end
if (this.isPassenger()) {
this.stopRiding();
@@ -2923,6 +2925,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)");
} else {
// CraftBukkit start
@ -78,7 +56,7 @@ index 5a71b5a37a55baea204821aba734d53dc49cb336..27b57db24587337ccdce29e492052ca4
CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle();
Entity orig = craft == null ? null : craft.getHandle();
if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) {
@@ -2971,6 +2974,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -2950,6 +2953,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (event.isCancelled()) {
return false;
}
@ -86,19 +64,6 @@ index 5a71b5a37a55baea204821aba734d53dc49cb336..27b57db24587337ccdce29e492052ca4
// Spigot end
if (this.passengers.size() == 1 && this.passengers.get(0) == entity) {
this.passengers = ImmutableList.of();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 29b5427316b23ea36e035330b303a41a2ba46f47..5fc4bf032986599232fddff8b27cd3a85ecd1cd4 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -375,7 +375,7 @@ public final class CraftServer implements Server {
@Override
public final boolean isOwnedByCurrentRegion(Entity entity) {
- return io.papermc.paper.util.TickThread.isTickThreadFor(((org.bukkit.craftbukkit.entity.CraftEntity)entity).getHandle());
+ return io.papermc.paper.util.TickThread.isTickThreadFor(((org.bukkit.craftbukkit.entity.CraftEntity)entity).getHandleRaw()); // Folia - add thread checks to getHandle
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
index 5e82b2d57833fea1adb342f5c8d25f55491945cb..2c46527dfe832919b055579a0876a043c06d8b67 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
@ -281,10 +246,10 @@ index 56bc26f227b97e8e935a20c6393d3f2eb806b285..5cf8ea3a7dd4e8ea96ca6061aa1aaefc
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
index 0f9e1d7aaee8ae870acd41934d52964c4d1aaff3..2e5cc1c7cbe4fc7cbcc2b2aeb37d497e4909053d 100644
index 3034a3902a946162f48840682d434e554de4eae9..f67a9f77039c29daac80359e2793bee4baf3b3c4 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
@@ -24,8 +24,16 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@@ -26,8 +26,16 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
super(server, entity);
}
@ -932,10 +897,10 @@ index 75c7645fb5732c43d1da15181cf5c7ee4c3ecd6c..6d3325436a77153438bc40aa86819562
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 2fe15f615522b60bba8e7551eef182458d163cd5..bcb85a4253b5e44b78cbadfb16c3bf0d47d7369e 100644
index dafac02b73326aa04093f16ac2f142004abe26be..19b47478d318edce1242c2a5ddd73da963a24595 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -822,7 +822,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@@ -821,7 +821,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@Override
public UUID getUniqueId() {
@ -944,16 +909,9 @@ index 2fe15f615522b60bba8e7551eef182458d163cd5..bcb85a4253b5e44b78cbadfb16c3bf0d
}
@Override
@@ -836,7 +836,14 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
this.getHandle().tickCount = value;
@@ -836,6 +836,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
+ // Folia start - region threading
+ public Entity getHandleRaw() {
+ return this.entity;
+ }
+ // Folia end - region threading
+
public Entity getHandle() {
+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading
return this.entity;
@ -1023,7 +981,7 @@ index 84899284703baeb04bfc79251941265d52ac07e8..5b8333e342c639f33acf62e5f8eb72d0
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java
index e99314b905a7ed54ceeb156ed92ff1a5793df99a..61bed78df554dc6a9689ea19e159fde990082a1e 100644
index d17808d132b332d51189067fed245eb6bb904968..fc7d7c0645ff9a8b4d6a0bc78cf6bd64d1a0d858 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java
@@ -15,8 +15,16 @@ public class CraftFallingBlock extends CraftEntity implements FallingBlock {
@ -1611,10 +1569,10 @@ index e515e819774bfb31ec03f05a5502921e66f2b0e2..80cac5d7362577e53ef5ca215ab32618
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 7880631fe8a4b06f29ef69ab850129737a99521b..564c72d6351721505dbffaf5af732db2dd3210ac 100644
index 6095d43e08bc1ffc4e9a4796fc7adbd07d69d716..fae85d064bcea3589a69483ec6ac6c4cca73ad9a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -415,8 +415,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@@ -417,6 +417,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
this.getHandle().invulnerableTime = ticks;
}
@ -1625,6 +1583,11 @@ index 7880631fe8a4b06f29ef69ab850129737a99521b..564c72d6351721505dbffaf5af732db2
+ }
+ // Folia end - region threading
+
@Override
public int getNoActionTicks() {
return this.getHandle().getNoActionTime();
@@ -430,6 +437,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public net.minecraft.world.entity.LivingEntity getHandle() {
+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading
@ -2146,10 +2109,10 @@ index beea227855f0b978e655efc298024120df8f4945..e1b7922ed298b6b3068c3f5fbe3b4030
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 5e362b1b7b95c908b0ea13a355c85386582b3f98..43c899d466bfffec4ea5ce1a4ed988f9ce4ecf42 100644
index b291941717b6f9e1bed2c8e89bdd15200f8b8699..66f4e0578e7682d732ba4b36f5c3344d1d0e3d68 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -594,7 +594,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -600,7 +600,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) {
@ -2158,7 +2121,7 @@ index 5e362b1b7b95c908b0ea13a355c85386582b3f98..43c899d466bfffec4ea5ce1a4ed988f9
final ServerGamePacketListenerImpl connection = this.getHandle().connection;
if (connection != null) {
connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause);
@@ -2024,9 +2024,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2054,9 +2054,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return this;
}
@ -2176,7 +2139,7 @@ index 5e362b1b7b95c908b0ea13a355c85386582b3f98..43c899d466bfffec4ea5ce1a4ed988f9
}
public void setHandle(final ServerPlayer entity) {
@@ -3032,7 +3039,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -3061,7 +3068,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
{
if ( CraftPlayer.this.getHealth() <= 0 && CraftPlayer.this.isOnline() )
{
@ -2250,10 +2213,10 @@ index bb9722a2cf5f05d1488f7fec2851644ea3e8b975..ed0e5d32a187dd41952b923e4a1734af
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java
index 3cb4860fea30bfaf2147b4f29a34336b6e417d6c..5d852e0a34004b877555157dd45020e5a5d30fd1 100644
index 3cd6052ae1e2db15d26157679506ba63a9a59a2f..34a1b2853023006d3ef255651ffa58452ce4cc79 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java
@@ -14,8 +14,16 @@ public class CraftRabbit extends CraftAnimals implements Rabbit {
@@ -12,8 +12,16 @@ public class CraftRabbit extends CraftAnimals implements Rabbit {
super(server, entity);
}
@ -2271,10 +2234,10 @@ index 3cb4860fea30bfaf2147b4f29a34336b6e417d6c..5d852e0a34004b877555157dd45020e5
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java
index f0b061979f9acdce6d06f70b651692c841418d96..6fb31c15d65885614b3878b5bcce08567d5b2089 100644
index c3185e189ed06e27e518d29b8577b8f694220b12..cfb231848766414297a13fea16308597546c86ce 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java
@@ -14,8 +14,16 @@ public abstract class CraftRaider extends CraftMonster implements Raider {
@@ -16,8 +16,16 @@ public abstract class CraftRaider extends CraftMonster implements Raider {
super(server, entity);
}
@ -2839,10 +2802,10 @@ index 5c3bc680c4e4e6dc4b2d9edc666d6a8d95c2e7b7..6c15ba92215634a06a1d95fbd7d64bff
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
index 0b39bb689717c13f03753f49d66b85cb2b964d83..8c4c07db82ed8aa1a1f746cfc43eef5ff81d085b 100644
index 6dde7fdff3943e5d58d1dd5debadbf7de569f8e2..64058e89a029a75c112569c40d7216a4d349f3e8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
@@ -20,8 +20,16 @@ public class CraftTippedArrow extends CraftArrow implements Arrow {
@@ -22,8 +22,16 @@ public class CraftTippedArrow extends CraftArrow implements Arrow {
super(server, entity);
}

View File

@ -10,7 +10,7 @@ the impact from scaling the region threads, but is not a fix
to the underlying issue.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index c772f5f48b1f0be2c55846154684a5d98f1267b9..d307826380c4bd47ee4602813737a11339cb8357 100644
index 056dc0df81c056672ee59664def01ed726b8f710..355acd1dd3b2e9f2a086a8d95928cdebbf63d06f 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2875,6 +2875,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Throw UnsupportedOperationException() for broken APIs
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 5fc4bf032986599232fddff8b27cd3a85ecd1cd4..20af7484bf570d28cd9723fdbb1ec07657117367 100644
index c9ee1662ab2bff205b509554f0883658682e87c8..23556931a812ed9b2dac5b4b4712961c2d9aa025 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1268,6 +1268,7 @@ public final class CraftServer implements Server {
@@ -1271,6 +1271,7 @@ public final class CraftServer implements Server {
@Override
public World createWorld(WorldCreator creator) {
@ -16,7 +16,7 @@ index 5fc4bf032986599232fddff8b27cd3a85ecd1cd4..20af7484bf570d28cd9723fdbb1ec076
Preconditions.checkState(this.console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP");
//Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot create a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes.
Preconditions.checkArgument(creator != null, "WorldCreator cannot be null");
@@ -1409,6 +1410,7 @@ public final class CraftServer implements Server {
@@ -1412,6 +1413,7 @@ public final class CraftServer implements Server {
@Override
public boolean unloadWorld(World world, boolean save) {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Fix tests by removing them
We don't care about this one, some commands just need to be removed.
diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
index 8665e2740aedcc2895b0e2c44ebaba53d2a40568..76522ba797f5db099b474f2d4459513ae5f5fff9 100644
index 4f43882d930ab8816e75b216d9a61a06b79df265..79f39ef98920b87ac196eefbaa46fe7ad6a41a2d 100644
--- a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
@@ -36,6 +36,7 @@ public class MinecraftCommandPermissionsTest extends AbstractTestingBase {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Work around https://github.com/PaperMC/paperweight/issues/194
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index f405b376c313ef297b47191e25c43ad90813f673..ace5e9900eb4e08ace4fb24ffa66c6d6d03ab82a 100644
index b0de5f603f01010a496c6760610dab9ea9b5581b..3c5b412ac6b09c667b05d9c44f341d4e8506c4cc 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -504,7 +504,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic

View File

@ -41,7 +41,7 @@ index 41db6c61de36ebb1c214423dca0ba6a0c5a95cc1..65c4e158d81ac5c5788cf4dcb379061a
// connections
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 7e303f86b6d8d41f96e5b3b3b0327da2082a8211..edfa7fbf209128b2254aa238e679f7be45162327 100644
index 8b685377b8cc2d36f1fb7ec05c72f2240e3f2d80..d6aba41ee2919942fe895db15fb9b19721bce618 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -124,7 +124,7 @@ public class ServerPlayerGameMode {

View File

@ -22,10 +22,10 @@ index aa42c1a05f12a614c0a7553d52efa1137b9363f9..817f79bfca1aec161cb4635b9c7a8e21
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 2d5f18322ed9d82eecef69c0a04c5d4358004df0..414c72d630b1464ed4f3bc294ae0a3b265ecd3e8 100644
index 40dd667bacd296a3a329391dc87a5713c464f4a2..f636bdf1075fa784ce7ee25478d4d94bacb05677 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -4284,6 +4284,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -4280,6 +4280,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
});

View File

@ -5,7 +5,7 @@ Subject: [PATCH] fixup! Rewrite chunk system
diff --git a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
index b9095f559472dd92375ea719886913f606f0374c..fdbd2e442d983ab17ba0d805a12c59acbe8dd2ec 100644
index a295f7a7c59f0a291aec4f9f1a08f6b2798689f6..3208d68c0e8220307028acd4bcd859465611f992 100644
--- a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
+++ b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
@@ -17,6 +17,7 @@ import net.minecraft.util.AbortableIterationConsumer;
@ -24,7 +24,7 @@ index b9095f559472dd92375ea719886913f606f0374c..fdbd2e442d983ab17ba0d805a12c59ac
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -314,22 +316,55 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
@@ -319,22 +321,55 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
this.getChunk(x, z).updateStatus(newStatus, this);
}

View File

@ -7,7 +7,7 @@ This allows the player to be re-positioned before logging into
the world without causing thread checks to trip on Folia.
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index d4620ddfcd06a037f647ab0a8938797405e001b2..654ab7fc8caa9af7dc665391a197b41599c2bc8f 100644
index 39d404c278bdc1227cb806bb257492493d05a439..ffb5332310e9b2d10292fe01c37fd48552fedffc 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -498,7 +498,13 @@ public abstract class PlayerList {