From 478d55ec4d017eeb282e528b24c6e58049ac9727 Mon Sep 17 00:00:00 2001 From: BillyGalbreath Date: Mon, 26 Sep 2022 04:35:03 -0500 Subject: [PATCH] Updated Upstream (Paper) Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@6d63005 Fix setEggCount method from TurtleLayEggEvent (#8385) PaperMC/Paper@abe53a7 Fix typos in isTickingWorlds API javadocs (#8382) PaperMC/Paper@01a1387 Rewrite chunk system (#8177) --- gradle.properties | 2 +- .../0001-Pufferfish-Server-Changes.patch | 2377 +---------------- .../server/0002-Fix-pufferfish-issues.patch | 12 +- patches/server/0003-Rebrand.patch | 32 +- .../server/0005-Purpur-client-support.patch | 8 +- .../0007-Component-related-conveniences.patch | 10 +- patches/server/0008-Ridables.patch | 36 +- ...-Configurable-entity-base-attributes.patch | 22 +- patches/server/0012-AFK-API.patch | 8 +- .../0014-Configurable-server-mod-name.patch | 4 +- patches/server/0016-Lagging-threshold.patch | 6 +- .../0019-Player-invulnerabilities.patch | 24 +- .../0029-Zombie-horse-naturally-spawn.patch | 6 +- ...-Minecart-settings-and-WASD-controls.patch | 8 +- .../0052-Configurable-TPS-Catchup.patch | 4 +- ...urable-void-damage-height-and-damage.patch | 6 +- .../0061-Add-canSaveToDisk-to-Entity.patch | 24 +- ...0065-Add-5-second-tps-average-in-tps.patch | 8 +- ...-Add-allow-water-in-end-world-option.patch | 4 +- ...leport-to-spawn-if-outside-world-bor.patch | 8 +- ...Stop-squids-floating-on-top-of-water.patch | 4 +- ...tities-can-use-portals-configuration.patch | 6 +- ...stomizable-wither-health-and-healing.patch | 6 +- ...ggling-special-MobSpawners-per-world.patch | 6 +- ...e-config-options-per-projectile-type.patch | 6 +- .../0103-Configurable-daylight-cycle.patch | 18 +- .../0115-Add-boat-fall-damage-config.patch | 6 +- patches/server/0125-Implement-TPSBar.patch | 20 +- ...iefing-bypass-to-everything-affected.patch | 6 +- ...34-Movement-options-for-armor-stands.patch | 4 +- .../server/0135-Fix-stuck-in-portals.patch | 8 +- ...ither-Ender-Dragon-can-ride-vehicles.patch | 10 +- ...-to-ignore-nearby-mobs-when-sleeping.patch | 4 +- .../0152-Config-for-skipping-night.patch | 6 +- patches/server/0155-Drowning-Settings.patch | 6 +- ...0170-Configurable-broadcast-settings.patch | 4 +- ...183-API-for-any-mob-to-burn-daylight.patch | 6 +- ...ggle-for-end-portal-safe-teleporting.patch | 4 +- ...ake-lightning-rod-range-configurable.patch | 4 +- ...omizable-sleeping-actionbar-messages.patch | 4 +- patches/server/0210-Add-compass-command.patch | 12 +- ...0216-Toggle-for-Wither-s-spawn-sound.patch | 6 +- ...ain-and-thunder-should-stop-on-sleep.patch | 8 +- .../server/0233-UPnP-Port-Forwarding.patch | 6 +- .../server/0238-Signs-allow-color-codes.patch | 4 +- ...t-spiders-from-climbing-world-border.patch | 4 +- ...counts-in-beehives-to-Purpur-clients.patch | 6 +- patches/server/0254-Allow-void-trading.patch | 6 +- ...ont-eat-blocks-in-non-ticking-chunks.patch | 4 +- .../0282-Add-local-difficulty-api.patch | 4 +- ...0283-Add-toggle-for-RNG-manipulation.patch | 6 +- .../0286-Allow-custom-ChatDecorators.patch | 4 +- patches/server/0287-Cache-server-motd.patch | 4 +- patches/server/0288-Remove-Timings.patch | 323 +-- .../server/0289-Remove-Mojang-Profiler.patch | 220 +- patches/server/0292-Debug-Marker-API.patch | 8 +- ...5-Make-pufferfish-config-relocatable.patch | 8 +- 57 files changed, 467 insertions(+), 2913 deletions(-) diff --git a/gradle.properties b/gradle.properties index f280584fd..a51799092 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ group = org.purpurmc.purpur version = 1.19.2-R0.1-SNAPSHOT -paperCommit = b4c025b92c48fb2b55a7433f85627184aee5d90a +paperCommit = 01a13871deefa50e186a10b63f71c5e0459e7d30 org.gradle.caching = true org.gradle.parallel = true diff --git a/patches/server/0001-Pufferfish-Server-Changes.patch b/patches/server/0001-Pufferfish-Server-Changes.patch index 512f79f1d..b0237c5f1 100644 --- a/patches/server/0001-Pufferfish-Server-Changes.patch +++ b/patches/server/0001-Pufferfish-Server-Changes.patch @@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/build.gradle.kts b/build.gradle.kts -index 2374cc9bab5039d0a0dc11d4b2ec573ab75778a7..7074295d7399d03e259598bb4bfa0f21434d74be 100644 +index 2374cc9bab5039d0a0dc11d4b2ec573ab75778a7..0485d126f799789b5d5abcaf96da96df25a12dfd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,8 +9,12 @@ plugins { @@ -38,7 +38,7 @@ index 2374cc9bab5039d0a0dc11d4b2ec573ab75778a7..7074295d7399d03e259598bb4bfa0f21 // Paper start implementation("org.jline:jline-terminal-jansi:3.21.0") implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -44,6 +48,14 @@ dependencies { +@@ -44,6 +48,13 @@ dependencies { runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3") runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3") @@ -48,12 +48,11 @@ index 2374cc9bab5039d0a0dc11d4b2ec573ab75778a7..7074295d7399d03e259598bb4bfa0f21 + exclude(group="org.yaml", module="snakeyaml") + } + // Pufferfish end -+ implementation("com.github.technove:Flare:34637f3f87") // Pufferfish - flare + testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test testImplementation("junit:junit:4.13.2") testImplementation("org.hamcrest:hamcrest-library:1.3") -@@ -52,6 +64,14 @@ dependencies { +@@ -52,6 +63,14 @@ dependencies { } val craftbukkitPackageVersion = "1_19_R1" // Paper @@ -68,7 +67,7 @@ index 2374cc9bab5039d0a0dc11d4b2ec573ab75778a7..7074295d7399d03e259598bb4bfa0f21 tasks.jar { archiveClassifier.set("dev") -@@ -64,7 +84,7 @@ tasks.jar { +@@ -64,7 +83,7 @@ tasks.jar { attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "CraftBukkit", @@ -612,10 +611,10 @@ index 0000000000000000000000000000000000000000..020368da69b9a492155f6de6297f7473 +} diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..38cb29c646ff496ffaa6553f98a565b71155c464 +index 0000000000000000000000000000000000000000..ed9c8e882739c02d0d04129d251e4c726b422c07 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -0,0 +1,337 @@ +@@ -0,0 +1,283 @@ +package gg.pufferfish.pufferfish; + +import gg.pufferfish.pufferfish.simd.SIMDDetection; @@ -633,7 +632,6 @@ index 0000000000000000000000000000000000000000..38cb29c646ff496ffaa6553f98a565b7 +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.List; -+import gg.pufferfish.pufferfish.flare.FlareCommand; +import net.minecraft.server.MinecraftServer; +import org.apache.logging.log4j.Level; +import org.bukkit.configuration.ConfigurationSection; @@ -642,13 +640,6 @@ index 0000000000000000000000000000000000000000..38cb29c646ff496ffaa6553f98a565b7 +import org.simpleyaml.configuration.comments.CommentType; +import org.simpleyaml.configuration.file.YamlFile; +import org.simpleyaml.exceptions.InvalidConfigurationException; -+import org.bukkit.command.SimpleCommandMap; -+ -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.List; -+import java.net.URI; -+import java.util.Collections; + +public class PufferfishConfig { + @@ -831,28 +822,6 @@ index 0000000000000000000000000000000000000000..38cb29c646ff496ffaa6553f98a565b7 + } + } + -+ public static boolean enableAsyncEntityTracker; -+ public static boolean enableAsyncEntityTrackerInitialized; -+ private static void asyncEntityTracker() { -+ boolean temp = getBoolean("enable-async-entity-tracker", false, -+ "Whether or not async entity tracking should be enabled."); -+ if (!enableAsyncEntityTrackerInitialized) { -+ enableAsyncEntityTrackerInitialized = true; -+ enableAsyncEntityTracker = temp; -+ } -+ } -+ -+ public static boolean enableAsyncPathfinding; -+ public static boolean enableAsyncPathfindingInitialized; -+ private static void asyncPathfinding() { -+ boolean temp = getBoolean("enable-async-pathfinding", false, -+ "Whether or not async pathfinding should be enabled."); -+ if (!enableAsyncPathfindingInitialized) { -+ enableAsyncPathfindingInitialized = true; -+ enableAsyncPathfinding = temp; -+ } -+ } -+ + public static int maxProjectileLoadsPerTick; + public static int maxProjectileLoadsPerProjectile; + private static void projectileLoading() { @@ -919,30 +888,6 @@ index 0000000000000000000000000000000000000000..38cb29c646ff496ffaa6553f98a565b7 + "This can improve performance by a few percent, but has minor gameplay implications."); + } + -+ public static URI profileWebUrl; -+ private static void profilerOptions() { -+ profileWebUrl = URI.create(getString("flare.url", "https://flare.airplane.gg", "Sets the server to use for profiles.")); -+ -+ setComment("flare", "Configures Flare, the built-in profiler"); -+ } -+ -+ -+ public static String accessToken; -+ private static void airplaneWebServices() { -+ accessToken = getString("web-services.token", ""); -+ // todo lookup token (off-thread) and let users know if their token is valid -+ if (accessToken.length() > 0) { -+ gg.pufferfish.pufferfish.flare.FlareSetup.init(); // Pufferfish -+ SimpleCommandMap commandMap = MinecraftServer.getServer().server.getCommandMap(); -+ if (commandMap.getCommand("flare") == null) { -+ commandMap.register("flare", "Pufferfish", new FlareCommand()); -+ } -+ } -+ -+ setComment("web-services", "Options for connecting to Pufferfish/Airplane's online utilities"); -+ -+ } -+ + + public static boolean disableMethodProfiler; + public static boolean disableOutOfOrderChat; @@ -1118,1102 +1063,6 @@ index 0000000000000000000000000000000000000000..e877921370f6009a4bd204d9b17d2d58 + } +} \ No newline at end of file -diff --git a/src/main/java/gg/pufferfish/pufferfish/compat/ServerConfigurations.java b/src/main/java/gg/pufferfish/pufferfish/compat/ServerConfigurations.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4ad189d52b27560424ddb311d0817a334637dc95 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/compat/ServerConfigurations.java -@@ -0,0 +1,78 @@ -+package gg.pufferfish.pufferfish.compat; -+ -+import co.aikar.timings.TimingsManager; -+import com.google.common.io.Files; -+import org.bukkit.configuration.InvalidConfigurationException; -+import org.bukkit.configuration.file.YamlConfiguration; -+ -+import java.io.ByteArrayOutputStream; -+import java.io.File; -+import java.io.FileInputStream; -+import java.io.IOException; -+import java.nio.charset.StandardCharsets; -+import java.util.Arrays; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.Properties; -+import java.util.stream.Collectors; -+ -+public class ServerConfigurations { -+ -+ public static final String[] configurationFiles = new String[]{ -+ "server.properties", -+ "bukkit.yml", -+ "spigot.yml", -+ // "paper.yml", // TODO: Figure out what to do with this. -+ "pufferfish.yml" -+ }; -+ -+ public static Map getCleanCopies() throws IOException { -+ Map files = new HashMap<>(configurationFiles.length); -+ for (String file : configurationFiles) { -+ files.put(file, getCleanCopy(file)); -+ } -+ return files; -+ } -+ -+ public static String getCleanCopy(String configName) throws IOException { -+ File file = new File(configName); -+ List hiddenConfigs = TimingsManager.hiddenConfigs; -+ -+ switch (Files.getFileExtension(configName)) { -+ case "properties": { -+ Properties properties = new Properties(); -+ try (FileInputStream inputStream = new FileInputStream(file)) { -+ properties.load(inputStream); -+ } -+ for (String hiddenConfig : hiddenConfigs) { -+ properties.remove(hiddenConfig); -+ } -+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -+ properties.store(outputStream, ""); -+ return Arrays.stream(outputStream.toString() -+ .split("\n")) -+ .filter(line -> !line.startsWith("#")) -+ .collect(Collectors.joining("\n")); -+ } -+ case "yml": { -+ YamlConfiguration configuration = new YamlConfiguration(); -+ try { -+ configuration.load(file); -+ } catch (InvalidConfigurationException e) { -+ throw new IOException(e); -+ } -+ configuration.options().header(null); -+ for (String key : configuration.getKeys(true)) { -+ if (hiddenConfigs.contains(key)) { -+ configuration.set(key, null); -+ } -+ } -+ return configuration.saveToString(); -+ } -+ default: -+ throw new IllegalArgumentException("Bad file type " + configName); -+ } -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/CustomCategories.java b/src/main/java/gg/pufferfish/pufferfish/flare/CustomCategories.java -new file mode 100644 -index 0000000000000000000000000000000000000000..401b42e29bccb5251684062f10b2e0f8b091bc95 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/CustomCategories.java -@@ -0,0 +1,8 @@ -+package gg.pufferfish.pufferfish.flare; -+ -+import co.technove.flare.live.category.GraphCategory; -+ -+public class CustomCategories { -+ public static final GraphCategory MC_PERF = new GraphCategory("MC Performance"); -+ public static final GraphCategory ENTITIES_AND_CHUNKS = new GraphCategory("Entities & Chunks"); -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/FlareCommand.java b/src/main/java/gg/pufferfish/pufferfish/flare/FlareCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3785d1512eb650f91d58903672c059e7449598fc ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/FlareCommand.java -@@ -0,0 +1,136 @@ -+package gg.pufferfish.pufferfish.flare; -+ -+import co.technove.flare.exceptions.UserReportableException; -+import co.technove.flare.internal.profiling.ProfileType; -+import gg.pufferfish.pufferfish.PufferfishConfig; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextColor; -+import net.kyori.adventure.text.format.TextDecoration; -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Level; -+import org.bukkit.Bukkit; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.command.ConsoleCommandSender; -+import org.bukkit.craftbukkit.scheduler.MinecraftInternalPlugin; -+import org.bukkit.util.StringUtil; -+import org.jetbrains.annotations.NotNull; -+ -+import java.time.Duration; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+ -+public class FlareCommand extends Command { -+ -+ private static final String BASE_URL = "https://blog.airplane.gg/flare-tutorial/#setting-the-access-token"; -+ private static final TextColor HEX = TextColor.fromHexString("#e3eaea"); -+ private static final Component PREFIX = Component.text() -+ .append(Component.text("Flare ✈") -+ .color(TextColor.fromHexString("#6a7eda")) -+ .decoration(TextDecoration.BOLD, true) -+ .append(Component.text(" ", HEX) -+ .decoration(TextDecoration.BOLD, false))) -+ .asComponent(); -+ -+ public FlareCommand() { -+ super("flare", "Profile your server with Flare", "/flare", Collections.singletonList("profile")); -+ this.setPermission("airplane.flare"); -+ } -+ -+ @Override -+ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, String @NotNull [] args) { -+ if (!testPermission(sender)) return true; -+ if (PufferfishConfig.accessToken.length() == 0) { -+ Component clickable = Component.text(BASE_URL, HEX, TextDecoration.UNDERLINED).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, BASE_URL)); -+ -+ sender.sendMessage(PREFIX.append(Component.text("Flare currently requires an access token to use. To learn more, visit ").color(HEX).append(clickable))); -+ return true; -+ } -+ -+ if (!FlareSetup.isSupported()) { -+ sender.sendMessage(PREFIX.append( -+ Component.text("Profiling is not supported in this environment, check your startup logs for the error.", NamedTextColor.RED))); -+ return true; -+ } -+ if (ProfilingManager.isProfiling()) { -+ if (args.length == 1 && args[0].equalsIgnoreCase("status")) { -+ sender.sendMessage(PREFIX.append(Component.text("Current profile has been ran for " + ProfilingManager.getTimeRan().toString(), HEX))); -+ return true; -+ } -+ if (ProfilingManager.stop()) { -+ if (!(sender instanceof ConsoleCommandSender)) { -+ sender.sendMessage(PREFIX.append(Component.text("Profiling has been stopped.", HEX))); -+ } -+ } else { -+ sender.sendMessage(PREFIX.append(Component.text("Profiling has already been stopped.", HEX))); -+ } -+ } else { -+ ProfileType profileType = ProfileType.ITIMER; -+ if (args.length > 0) { -+ try { -+ profileType = ProfileType.valueOf(args[0].toUpperCase()); -+ } catch (Exception e) { -+ sender.sendMessage(PREFIX.append(Component -+ .text("Invalid profile type ", HEX) -+ .append(Component.text(args[0], HEX, TextDecoration.BOLD) -+ .append(Component.text("!", HEX))) -+ )); -+ } -+ } -+ ProfileType finalProfileType = profileType; -+ Bukkit.getScheduler().runTaskAsynchronously(new MinecraftInternalPlugin(), () -> { -+ try { -+ if (ProfilingManager.start(finalProfileType)) { -+ if (!(sender instanceof ConsoleCommandSender)) { -+ sender.sendMessage(PREFIX.append(Component -+ .text("Flare has been started: " + ProfilingManager.getProfilingUri(), HEX) -+ .clickEvent(ClickEvent.openUrl(ProfilingManager.getProfilingUri())) -+ )); -+ sender.sendMessage(PREFIX.append(Component.text(" Run /" + commandLabel + " to stop the Flare.", HEX))); -+ } -+ } else { -+ sender.sendMessage(PREFIX.append(Component -+ .text("Flare has already been started: " + ProfilingManager.getProfilingUri(), HEX) -+ .clickEvent(ClickEvent.openUrl(ProfilingManager.getProfilingUri())) -+ )); -+ } -+ } catch (UserReportableException e) { -+ sender.sendMessage(Component.text("Flare failed to start: " + e.getUserError(), NamedTextColor.RED)); -+ if (e.getCause() != null) { -+ MinecraftServer.LOGGER.warn("Flare failed to start", e); -+ } -+ } -+ }); -+ } -+ return true; -+ } -+ -+ @Override -+ public @NotNull List tabComplete(@NotNull CommandSender sender, @NotNull String alias, String @NotNull [] args) throws IllegalArgumentException { -+ List list = new ArrayList<>(); -+ if (ProfilingManager.isProfiling()) { -+ if (args.length == 1) { -+ String lastWord = args[0]; -+ if (StringUtil.startsWithIgnoreCase("status", lastWord)) { -+ list.add("status"); -+ } -+ if (StringUtil.startsWithIgnoreCase("stop", lastWord)) { -+ list.add("stop"); -+ } -+ } -+ } else { -+ if (args.length <= 1) { -+ String lastWord = args.length == 0 ? "" : args[0]; -+ for (ProfileType value : ProfileType.values()) { -+ if (StringUtil.startsWithIgnoreCase(value.getInternalName(), lastWord)) { -+ list.add(value.name().toLowerCase()); -+ } -+ } -+ } -+ } -+ return list; -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/FlareSetup.java b/src/main/java/gg/pufferfish/pufferfish/flare/FlareSetup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cd22e4dcc8b7b57b10a95ef084637249a98e524f ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/FlareSetup.java -@@ -0,0 +1,33 @@ -+package gg.pufferfish.pufferfish.flare; -+ -+import co.technove.flare.FlareInitializer; -+import co.technove.flare.internal.profiling.InitializationException; -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Level; -+ -+public class FlareSetup { -+ -+ private static boolean initialized = false; -+ private static boolean supported = false; -+ -+ public static void init() { -+ if (initialized) { -+ return; -+ } -+ -+ initialized = true; -+ try { -+ for (String warning : FlareInitializer.initialize()) { -+ MinecraftServer.LOGGER.warn("Flare warning: " + warning); -+ } -+ supported = true; -+ } catch (InitializationException e) { -+ MinecraftServer.LOGGER.warn("Failed to enable Flare:", e); -+ } -+ } -+ -+ public static boolean isSupported() { -+ return supported; -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/PluginLookup.java b/src/main/java/gg/pufferfish/pufferfish/flare/PluginLookup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..74aab5eb4b54ffbaf19b8976ffb8ca4a64584006 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/PluginLookup.java -@@ -0,0 +1,44 @@ -+package gg.pufferfish.pufferfish.flare; -+ -+import com.google.common.cache.Cache; -+import com.google.common.cache.CacheBuilder; -+import org.bukkit.Bukkit; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.plugin.java.PluginClassLoader; -+ -+import java.util.Optional; -+import java.util.concurrent.TimeUnit; -+ -+public class PluginLookup { -+ private static final Cache pluginNameCache = CacheBuilder.newBuilder() -+ .expireAfterAccess(1, TimeUnit.MINUTES) -+ .maximumSize(1024) -+ .build(); -+ -+ public static Optional getPluginForClass(String name) { -+ if (name.startsWith("net.minecraft") || name.startsWith("java.") || name.startsWith("com.mojang") || -+ name.startsWith("com.google") || name.startsWith("it.unimi") || name.startsWith("sun")) { -+ return Optional.empty(); -+ } -+ -+ String existing = pluginNameCache.getIfPresent(name); -+ if (existing != null) { -+ return Optional.ofNullable(existing.isEmpty() ? null : existing); -+ } -+ -+ String newValue = ""; -+ -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ ClassLoader classLoader = plugin.getClass().getClassLoader(); -+ if (classLoader instanceof PluginClassLoader) { -+ if (((PluginClassLoader) classLoader)._airplane_hasClass(name)) { -+ newValue = plugin.getName(); -+ break; -+ } -+ } -+ } -+ -+ pluginNameCache.put(name, newValue); -+ return Optional.ofNullable(newValue.isEmpty() ? null : newValue); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/ProfilingManager.java b/src/main/java/gg/pufferfish/pufferfish/flare/ProfilingManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e3f76eb11a261c3347f0cd89b5da309bc2dc82f9 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/ProfilingManager.java -@@ -0,0 +1,151 @@ -+package gg.pufferfish.pufferfish.flare; -+ -+import co.technove.flare.Flare; -+import co.technove.flare.FlareAuth; -+import co.technove.flare.FlareBuilder; -+import co.technove.flare.exceptions.UserReportableException; -+import co.technove.flare.internal.profiling.ProfileType; -+import gg.pufferfish.pufferfish.PufferfishConfig; -+import gg.pufferfish.pufferfish.PufferfishLogger; -+import gg.pufferfish.pufferfish.compat.ServerConfigurations; -+import gg.pufferfish.pufferfish.flare.collectors.GCEventCollector; -+import gg.pufferfish.pufferfish.flare.collectors.StatCollector; -+import gg.pufferfish.pufferfish.flare.collectors.TPSCollector; -+import gg.pufferfish.pufferfish.flare.collectors.WorldCountCollector; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.scheduler.MinecraftInternalPlugin; -+import org.bukkit.scheduler.BukkitTask; -+import oshi.SystemInfo; -+import oshi.hardware.CentralProcessor; -+import oshi.hardware.GlobalMemory; -+import oshi.hardware.HardwareAbstractionLayer; -+import oshi.hardware.VirtualMemory; -+import oshi.software.os.OperatingSystem; -+ -+import java.io.IOException; -+import java.net.URI; -+import java.time.Duration; -+import java.util.Objects; -+import java.util.logging.Level; -+ -+public class ProfilingManager { -+ -+ private static Flare currentFlare; -+ private static BukkitTask currentTask = null; -+ -+ public static synchronized boolean isProfiling() { -+ return currentFlare != null && currentFlare.isRunning(); -+ } -+ -+ public static synchronized String getProfilingUri() { -+ return Objects.requireNonNull(currentFlare).getURI().map(URI::toString).orElse("Flare is not running"); -+ } -+ -+ public static Duration getTimeRan() { -+ Flare flare = currentFlare; // copy reference so no need to sync -+ if (flare == null) { -+ return Duration.ofMillis(0); -+ } -+ return flare.getCurrentDuration(); -+ } -+ -+ public static synchronized boolean start(ProfileType profileType) throws UserReportableException { -+ if (currentFlare != null && !currentFlare.isRunning()) { -+ currentFlare = null; // errored out -+ } -+ if (isProfiling()) { -+ return false; -+ } -+ if (Bukkit.isPrimaryThread()) { -+ throw new UserReportableException("Profiles should be started off-thread"); -+ } -+ -+ try { -+ OperatingSystem os = new SystemInfo().getOperatingSystem(); -+ -+ SystemInfo systemInfo = new SystemInfo(); -+ HardwareAbstractionLayer hardware = systemInfo.getHardware(); -+ -+ CentralProcessor processor = hardware.getProcessor(); -+ CentralProcessor.ProcessorIdentifier processorIdentifier = processor.getProcessorIdentifier(); -+ -+ GlobalMemory memory = hardware.getMemory(); -+ VirtualMemory virtualMemory = memory.getVirtualMemory(); -+ -+ FlareBuilder builder = new FlareBuilder() -+ .withProfileType(profileType) -+ .withMemoryProfiling(true) -+ .withAuth(FlareAuth.fromTokenAndUrl(PufferfishConfig.accessToken, PufferfishConfig.profileWebUrl)) -+ -+ .withFiles(ServerConfigurations.getCleanCopies()) -+ .withVersion("Primary Version", Bukkit.getVersion()) -+ .withVersion("Bukkit Version", Bukkit.getBukkitVersion()) -+ .withVersion("Minecraft Version", Bukkit.getMinecraftVersion()) -+ -+ .withGraphCategories(CustomCategories.ENTITIES_AND_CHUNKS, CustomCategories.MC_PERF) -+ .withCollectors(new TPSCollector(), new WorldCountCollector(), new GCEventCollector(), new StatCollector()) -+ .withClassIdentifier(PluginLookup::getPluginForClass) -+ -+ .withHardware(new FlareBuilder.HardwareBuilder() -+ .setCoreCount(processor.getPhysicalProcessorCount()) -+ .setThreadCount(processor.getLogicalProcessorCount()) -+ .setCpuModel(processorIdentifier.getName()) -+ .setCpuFrequency(processor.getMaxFreq()) -+ -+ .setTotalMemory(memory.getTotal()) -+ .setTotalSwap(virtualMemory.getSwapTotal()) -+ .setTotalVirtual(virtualMemory.getVirtualMax()) -+ ) -+ -+ .withOperatingSystem(new FlareBuilder.OperatingSystemBuilder() -+ .setManufacturer(os.getManufacturer()) -+ .setFamily(os.getFamily()) -+ .setVersion(os.getVersionInfo().toString()) -+ .setBitness(os.getBitness()) -+ ); -+ -+ currentFlare = builder.build(); -+ } catch (IOException e) { -+ PufferfishLogger.LOGGER.log(Level.WARNING, "Failed to read configuration files:", e); -+ throw new UserReportableException("Failed to load configuration files, check logs for further details."); -+ } -+ -+ try { -+ currentFlare.start(); -+ } catch (IllegalStateException e) { -+ PufferfishLogger.LOGGER.log(Level.WARNING, "Error starting Flare:", e); -+ throw new UserReportableException("Failed to start Flare, check logs for further details."); -+ } -+ -+ currentTask = Bukkit.getScheduler().runTaskLater(new MinecraftInternalPlugin(), ProfilingManager::stop, 20 * 60 * 15); -+ PufferfishLogger.LOGGER.log(Level.INFO, "Flare has been started: " + getProfilingUri()); -+ return true; -+ } -+ -+ public static synchronized boolean stop() { -+ if (!isProfiling()) { -+ return false; -+ } -+ if (!currentFlare.isRunning()) { -+ currentFlare = null; -+ return true; -+ } -+ PufferfishLogger.LOGGER.log(Level.INFO, "Flare has been stopped: " + getProfilingUri()); -+ try { -+ currentFlare.stop(); -+ } catch (IllegalStateException e) { -+ PufferfishLogger.LOGGER.log(Level.WARNING, "Error occurred stopping Flare", e); -+ } -+ currentFlare = null; -+ -+ try { -+ currentTask.cancel(); -+ } catch (Throwable t) { -+ PufferfishLogger.LOGGER.log(Level.WARNING, "Error occurred stopping Flare", t); -+ } -+ -+ currentTask = null; -+ return true; -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/collectors/GCEventCollector.java b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/GCEventCollector.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d426575c669020f369960107da1e2de2f11f082f ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/GCEventCollector.java -@@ -0,0 +1,66 @@ -+package gg.pufferfish.pufferfish.flare.collectors; -+ -+import co.technove.flare.Flare; -+import co.technove.flare.internal.FlareInternal; -+import co.technove.flare.live.CollectorData; -+import co.technove.flare.live.EventCollector; -+import co.technove.flare.live.LiveEvent; -+import co.technove.flare.live.category.GraphCategory; -+import co.technove.flare.live.formatter.DataFormatter; -+import com.google.common.collect.ImmutableMap; -+import com.sun.management.GarbageCollectionNotificationInfo; -+ -+import javax.management.ListenerNotFoundException; -+import javax.management.Notification; -+import javax.management.NotificationEmitter; -+import javax.management.NotificationListener; -+import javax.management.openmbean.CompositeData; -+import java.lang.management.GarbageCollectorMXBean; -+import java.lang.management.ManagementFactory; -+ -+public class GCEventCollector extends EventCollector implements NotificationListener { -+ -+ private static final CollectorData MINOR_GC = new CollectorData("builtin:gc:minor", "Minor GC", "A small pause in the program to allow Garbage Collection to run.", DataFormatter.MILLISECONDS, GraphCategory.SYSTEM); -+ private static final CollectorData MAJOR_GC = new CollectorData("builtin:gc:major", "Major GC", "A large pause in the program to allow Garbage Collection to run.", DataFormatter.MILLISECONDS, GraphCategory.SYSTEM); -+ private static final CollectorData UNKNOWN_GC = new CollectorData("builtin:gc:generic", "Major GC", "A run of the Garbage Collection.", DataFormatter.MILLISECONDS, GraphCategory.SYSTEM); -+ -+ public GCEventCollector() { -+ super(MINOR_GC, MAJOR_GC, UNKNOWN_GC); -+ } -+ -+ private static CollectorData fromString(String string) { -+ if (string.endsWith("minor GC")) { -+ return MINOR_GC; -+ } else if (string.endsWith("major GC")) { -+ return MAJOR_GC; -+ } -+ return UNKNOWN_GC; -+ } -+ -+ @Override -+ public void start(Flare flare) { -+ for (GarbageCollectorMXBean garbageCollectorBean : ManagementFactory.getGarbageCollectorMXBeans()) { -+ NotificationEmitter notificationEmitter = (NotificationEmitter) garbageCollectorBean; -+ notificationEmitter.addNotificationListener(this, null, null); -+ } -+ } -+ -+ @Override -+ public void stop(Flare flare) { -+ for (GarbageCollectorMXBean garbageCollectorBean : ManagementFactory.getGarbageCollectorMXBeans()) { -+ NotificationEmitter notificationEmitter = (NotificationEmitter) garbageCollectorBean; -+ try { -+ notificationEmitter.removeNotificationListener(this); -+ } catch (ListenerNotFoundException e) { -+ } -+ } -+ } -+ -+ @Override -+ public void handleNotification(Notification notification, Object o) { -+ if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { -+ GarbageCollectionNotificationInfo gcInfo = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData()); -+ reportEvent(new LiveEvent(fromString(gcInfo.getGcAction()), System.currentTimeMillis(), (int) gcInfo.getGcInfo().getDuration(), ImmutableMap.of())); -+ } -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/collectors/StatCollector.java b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/StatCollector.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a22c6dbae53667e4c72464fa27153aee30c7946e ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/StatCollector.java -@@ -0,0 +1,41 @@ -+package gg.pufferfish.pufferfish.flare.collectors; -+ -+import co.technove.flare.live.CollectorData; -+import co.technove.flare.live.LiveCollector; -+import co.technove.flare.live.category.GraphCategory; -+import co.technove.flare.live.formatter.DataFormatter; -+import com.sun.management.OperatingSystemMXBean; -+import oshi.SystemInfo; -+import oshi.hardware.CentralProcessor; -+ -+import java.lang.management.ManagementFactory; -+import java.time.Duration; -+ -+public class StatCollector extends LiveCollector { -+ -+ private static final CollectorData CPU = new CollectorData("builtin:stat:cpu", "CPU Load", "The total amount of CPU usage across all cores.", DataFormatter.PERCENT, GraphCategory.SYSTEM); -+ private static final CollectorData CPU_PROCESS = new CollectorData("builtin:stat:cpu_process", "Process CPU", "The amount of CPU being used by this process.", DataFormatter.PERCENT, GraphCategory.SYSTEM); -+ private static final CollectorData MEMORY = new CollectorData("builtin:stat:memory_used", "Memory", "The amount of memory being used currently.", DataFormatter.BYTES, GraphCategory.SYSTEM); -+ private static final CollectorData MEMORY_TOTAL = new CollectorData("builtin:stat:memory_total", "Memory Total", "The total amount of memory allocated.", DataFormatter.BYTES, GraphCategory.SYSTEM); -+ -+ private final OperatingSystemMXBean bean; -+ private final CentralProcessor processor; -+ -+ public StatCollector() { -+ super(CPU, CPU_PROCESS, MEMORY, MEMORY_TOTAL); -+ this.interval = Duration.ofSeconds(5); -+ -+ this.bean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); -+ this.processor = new SystemInfo().getHardware().getProcessor(); -+ } -+ -+ @Override -+ public void run() { -+ Runtime runtime = Runtime.getRuntime(); -+ -+ this.report(CPU, this.processor.getSystemLoadAverage(1)[0] / 100); // percentage -+ this.report(CPU_PROCESS, this.bean.getProcessCpuLoad()); -+ this.report(MEMORY, runtime.totalMemory() - runtime.freeMemory()); -+ this.report(MEMORY_TOTAL, runtime.totalMemory()); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/collectors/TPSCollector.java b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/TPSCollector.java -new file mode 100644 -index 0000000000000000000000000000000000000000..40447d00aefb5ffedb8a2ee87155a04088f0649f ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/TPSCollector.java -@@ -0,0 +1,31 @@ -+package gg.pufferfish.pufferfish.flare.collectors; -+ -+import co.technove.flare.live.CollectorData; -+import co.technove.flare.live.LiveCollector; -+import co.technove.flare.live.formatter.SuffixFormatter; -+import gg.pufferfish.pufferfish.flare.CustomCategories; -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+ -+import java.time.Duration; -+import java.util.Arrays; -+ -+public class TPSCollector extends LiveCollector { -+ private static final CollectorData TPS = new CollectorData("airplane:tps", "TPS", "Ticks per second, or how fast the server updates. For a smooth server this should be a constant 20TPS.", SuffixFormatter.of("TPS"), CustomCategories.MC_PERF); -+ private static final CollectorData MSPT = new CollectorData("airplane:mspt", "MSPT", "Milliseconds per tick, which can show how well your server is performing. This value should always be under 50mspt.", SuffixFormatter.of("mspt"), CustomCategories.MC_PERF); -+ -+ public TPSCollector() { -+ super(TPS, MSPT); -+ -+ this.interval = Duration.ofSeconds(5); -+ } -+ -+ @Override -+ public void run() { -+ long[] times = MinecraftServer.getServer().tickTimes5s.getTimes(); -+ double mspt = ((double) Arrays.stream(times).sum() / (double) times.length) * 1.0E-6D; -+ -+ this.report(TPS, Math.min(20D, Math.round(Bukkit.getServer().getTPS()[0] * 100d) / 100d)); -+ this.report(MSPT, (double) Math.round(mspt * 100d) / 100d); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/flare/collectors/WorldCountCollector.java b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/WorldCountCollector.java -new file mode 100644 -index 0000000000000000000000000000000000000000..db15d3fbe2b65fc8035573f5fdbea382055db9b2 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/flare/collectors/WorldCountCollector.java -@@ -0,0 +1,45 @@ -+package gg.pufferfish.pufferfish.flare.collectors; -+ -+import co.technove.flare.live.CollectorData; -+import co.technove.flare.live.LiveCollector; -+import co.technove.flare.live.formatter.SuffixFormatter; -+import gg.pufferfish.pufferfish.flare.CustomCategories; -+import org.bukkit.Bukkit; -+import org.bukkit.World; -+import org.bukkit.craftbukkit.CraftWorld; -+ -+import java.time.Duration; -+ -+public class WorldCountCollector extends LiveCollector { -+ -+ private static final CollectorData PLAYER_COUNT = new CollectorData("airplane:world:playercount", "Player Count", "The number of players currently on the server.", new SuffixFormatter(" Player", " Players"), CustomCategories.ENTITIES_AND_CHUNKS); -+ private static final CollectorData ENTITY_COUNT = new CollectorData("airplane:world:entitycount", "Entity Count", "The number of entities in all worlds", new SuffixFormatter(" Entity", " Entities"), CustomCategories.ENTITIES_AND_CHUNKS); -+ private static final CollectorData CHUNK_COUNT = new CollectorData("airplane:world:chunkcount", "Chunk Count", "The number of chunks currently loaded.", new SuffixFormatter(" Chunk", " Chunks"), CustomCategories.ENTITIES_AND_CHUNKS); -+ private static final CollectorData TILE_ENTITY_COUNT = new CollectorData("airplane:world:blockentitycount", "Block Entity Count", "The number of block entities currently loaded.", new SuffixFormatter(" Block Entity", " Block Entities"), CustomCategories.ENTITIES_AND_CHUNKS); -+ -+ public WorldCountCollector() { -+ super(PLAYER_COUNT, ENTITY_COUNT, CHUNK_COUNT, TILE_ENTITY_COUNT); -+ -+ this.interval = Duration.ofSeconds(5); -+ } -+ -+ @Override -+ public void run() { -+ int entities = 0; -+ int chunkCount = 0; -+ int tileEntityCount = 0; -+ -+ if (!Bukkit.isStopping()) { -+ for (World world : Bukkit.getWorlds()) { -+ entities += ((CraftWorld) world).getHandle().entityManager.getEntityGetter().getCount(); -+ chunkCount += world.getChunkCount(); -+ tileEntityCount += world.getTileEntityCount(); -+ } -+ } -+ -+ this.report(PLAYER_COUNT, Bukkit.getOnlinePlayers().size()); -+ this.report(ENTITY_COUNT, entities); -+ this.report(CHUNK_COUNT, chunkCount); -+ this.report(TILE_ENTITY_COUNT, tileEntityCount); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/path/AsyncPath.java b/src/main/java/gg/pufferfish/pufferfish/path/AsyncPath.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dcfe6fa538c54417b90a138b26c451f63b408ff6 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/path/AsyncPath.java -@@ -0,0 +1,282 @@ -+package gg.pufferfish.pufferfish.path; -+ -+import net.minecraft.core.BlockPos; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.level.pathfinder.Node; -+import net.minecraft.world.level.pathfinder.Path; -+import net.minecraft.world.phys.Vec3; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Set; -+import java.util.function.Supplier; -+ -+/** -+ * i'll be using this to represent a path that not be processed yet! -+ */ -+public class AsyncPath extends Path { -+ -+ /** -+ * marks whether this async path has been processed -+ */ -+ private volatile boolean processed = false; -+ -+ /** -+ * runnables waiting for path to be processed -+ */ -+ private final @NotNull List postProcessing = new ArrayList<>(); -+ -+ /** -+ * a list of positions that this path could path towards -+ */ -+ private final Set positions; -+ -+ /** -+ * the supplier of the real processed path -+ */ -+ private final Supplier pathSupplier; -+ -+ /* -+ * Processed values -+ */ -+ -+ /** -+ * this is a reference to the nodes list in the parent `Path` object -+ */ -+ private final List nodes; -+ /** -+ * the block we're trying to path to -+ * -+ * while processing, we have no idea where this is so consumers of `Path` should check that the path is processed before checking the target block -+ */ -+ private @Nullable BlockPos target; -+ /** -+ * how far we are to the target -+ * -+ * while processing, the target could be anywhere but theoretically we're always "close" to a theoretical target so default is 0 -+ */ -+ private float distToTarget = 0; -+ /** -+ * whether we can reach the target -+ * -+ * while processing we can always theoretically reach the target so default is true -+ */ -+ private boolean canReach = true; -+ -+ public AsyncPath(@NotNull List emptyNodeList, @NotNull Set positions, @NotNull Supplier pathSupplier) { -+ //noinspection ConstantConditions -+ super(emptyNodeList, null, false); -+ -+ this.nodes = emptyNodeList; -+ this.positions = positions; -+ this.pathSupplier = pathSupplier; -+ -+ AsyncPathProcessor.queue(this); -+ } -+ -+ @Override -+ public boolean isProcessed() { -+ return this.processed; -+ } -+ -+ /** -+ * add a post-processing action -+ */ -+ public synchronized void postProcessing(@NotNull Runnable runnable) { -+ if (processed) runnable.run(); -+ else postProcessing.add(runnable); -+ } -+ -+ /** -+ * an easy way to check if this processing path is the same as an attempted new path -+ * -+ * @param positions - the positions to compare against -+ * @return true if we are processing the same positions -+ */ -+ public boolean hasSameProcessingPositions(final Set positions) { -+ if (this.positions.size() != positions.size()) { -+ return false; -+ } -+ -+ return this.positions.containsAll(positions); -+ } -+ -+ /** -+ * starts processing this path -+ */ -+ public synchronized void process() { -+ if (this.processed) { -+ return; -+ } -+ -+ final Path bestPath = this.pathSupplier.get(); -+ -+ this.nodes.addAll(bestPath.nodes); // we mutate this list to reuse the logic in Path -+ this.target = bestPath.getTarget(); -+ this.distToTarget = bestPath.getDistToTarget(); -+ this.canReach = bestPath.canReach(); -+ -+ this.processed = true; -+ -+ this.postProcessing.forEach(Runnable::run); -+ } -+ -+ /** -+ * if this path is accessed while it hasn't processed, just process it in-place -+ */ -+ private void checkProcessed() { -+ if (!this.processed) { -+ this.process(); -+ } -+ } -+ -+ /* -+ * overrides we need for final fields that we cannot modify after processing -+ */ -+ -+ @Override -+ public @NotNull BlockPos getTarget() { -+ this.checkProcessed(); -+ -+ return this.target; -+ } -+ -+ @Override -+ public float getDistToTarget() { -+ this.checkProcessed(); -+ -+ return this.distToTarget; -+ } -+ -+ @Override -+ public boolean canReach() { -+ this.checkProcessed(); -+ -+ return this.canReach; -+ } -+ -+ /* -+ * overrides to ensure we're processed first -+ */ -+ -+ @Override -+ public boolean isDone() { -+ return this.isProcessed() && super.isDone(); -+ } -+ -+ @Override -+ public void advance() { -+ this.checkProcessed(); -+ -+ super.advance(); -+ } -+ -+ @Override -+ public boolean notStarted() { -+ this.checkProcessed(); -+ -+ return super.notStarted(); -+ } -+ -+ @Nullable -+ @Override -+ public Node getEndNode() { -+ this.checkProcessed(); -+ -+ return super.getEndNode(); -+ } -+ -+ @Override -+ public Node getNode(int index) { -+ this.checkProcessed(); -+ -+ return super.getNode(index); -+ } -+ -+ @Override -+ public void truncateNodes(int length) { -+ this.checkProcessed(); -+ -+ super.truncateNodes(length); -+ } -+ -+ @Override -+ public void replaceNode(int index, Node node) { -+ this.checkProcessed(); -+ -+ super.replaceNode(index, node); -+ } -+ -+ @Override -+ public int getNodeCount() { -+ this.checkProcessed(); -+ -+ return super.getNodeCount(); -+ } -+ -+ @Override -+ public int getNextNodeIndex() { -+ this.checkProcessed(); -+ -+ return super.getNextNodeIndex(); -+ } -+ -+ @Override -+ public void setNextNodeIndex(int nodeIndex) { -+ this.checkProcessed(); -+ -+ super.setNextNodeIndex(nodeIndex); -+ } -+ -+ @Override -+ public Vec3 getEntityPosAtNode(Entity entity, int index) { -+ this.checkProcessed(); -+ -+ return super.getEntityPosAtNode(entity, index); -+ } -+ -+ @Override -+ public BlockPos getNodePos(int index) { -+ this.checkProcessed(); -+ -+ return super.getNodePos(index); -+ } -+ -+ @Override -+ public Vec3 getNextEntityPos(Entity entity) { -+ this.checkProcessed(); -+ -+ return super.getNextEntityPos(entity); -+ } -+ -+ @Override -+ public BlockPos getNextNodePos() { -+ this.checkProcessed(); -+ -+ return super.getNextNodePos(); -+ } -+ -+ @Override -+ public Node getNextNode() { -+ this.checkProcessed(); -+ -+ return super.getNextNode(); -+ } -+ -+ @Nullable -+ @Override -+ public Node getPreviousNode() { -+ this.checkProcessed(); -+ -+ return super.getPreviousNode(); -+ } -+ -+ @Override -+ public boolean hasNext() { -+ this.checkProcessed(); -+ -+ return super.hasNext(); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/path/AsyncPathProcessor.java b/src/main/java/gg/pufferfish/pufferfish/path/AsyncPathProcessor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6c8035ef7effd0ccdc887b3792ba09ef6b2a74fa ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/path/AsyncPathProcessor.java -@@ -0,0 +1,44 @@ -+package gg.pufferfish.pufferfish.path; -+ -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.level.pathfinder.Path; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.function.Consumer; -+ -+/** -+ * used to handle the scheduling of async path processing -+ */ -+public class AsyncPathProcessor { -+ -+ private static final Executor mainThreadExecutor = MinecraftServer.getServer(); -+ private static final Executor pathProcessingExecutor = Executors.newCachedThreadPool(new ThreadFactoryBuilder() -+ .setNameFormat("puff-path-processor-%d") -+ .setPriority(Thread.NORM_PRIORITY - 2) -+ .build()); -+ -+ protected static CompletableFuture queue(@NotNull AsyncPath path) { -+ return CompletableFuture.runAsync(path::process, pathProcessingExecutor); -+ } -+ -+ /** -+ * takes a possibly unprocessed path, and waits until it is completed -+ * the consumer will be immediately invoked if the path is already processed -+ * the consumer will always be called on the main thread -+ * -+ * @param path a path to wait on -+ * @param afterProcessing a consumer to be called -+ */ -+ public static void awaitProcessing(@Nullable Path path, Consumer<@Nullable Path> afterProcessing) { -+ if (path != null && !path.isProcessed() && path instanceof AsyncPath asyncPath) { -+ asyncPath.postProcessing(() -> mainThreadExecutor.execute(() -> afterProcessing.accept(path))); -+ } else { -+ afterProcessing.accept(path); -+ } -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/path/NodeEvaluatorCache.java b/src/main/java/gg/pufferfish/pufferfish/path/NodeEvaluatorCache.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a18b967d7a7325885c94a1093cc5800012998f1a ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/path/NodeEvaluatorCache.java -@@ -0,0 +1,43 @@ -+package gg.pufferfish.pufferfish.path; -+ -+import net.minecraft.world.level.pathfinder.NodeEvaluator; -+import org.apache.commons.lang.Validate; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Map; -+import java.util.Queue; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentLinkedQueue; -+ -+public class NodeEvaluatorCache { -+ private static final Map> threadLocalNodeEvaluators = new ConcurrentHashMap<>(); -+ private static final Map nodeEvaluatorToGenerator = new ConcurrentHashMap<>(); -+ -+ private static @NotNull Queue getDequeForGenerator(@NotNull NodeEvaluatorGenerator generator) { -+ return threadLocalNodeEvaluators.computeIfAbsent(generator, (key) -> new ConcurrentLinkedQueue<>()); -+ } -+ -+ public static @NotNull NodeEvaluator takeNodeEvaluator(@NotNull NodeEvaluatorGenerator generator) { -+ var nodeEvaluator = getDequeForGenerator(generator).poll(); -+ -+ if (nodeEvaluator == null) { -+ nodeEvaluator = generator.generate(); -+ } -+ -+ nodeEvaluatorToGenerator.put(nodeEvaluator, generator); -+ -+ return nodeEvaluator; -+ } -+ -+ public static void returnNodeEvaluator(@NotNull NodeEvaluator nodeEvaluator) { -+ final var generator = nodeEvaluatorToGenerator.remove(nodeEvaluator); -+ Validate.notNull(generator, "NodeEvaluator already returned"); -+ -+ getDequeForGenerator(generator).offer(nodeEvaluator); -+ } -+ -+ public static void removeNodeEvaluator(@NotNull NodeEvaluator nodeEvaluator) { -+ nodeEvaluatorToGenerator.remove(nodeEvaluator); -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/path/NodeEvaluatorGenerator.java b/src/main/java/gg/pufferfish/pufferfish/path/NodeEvaluatorGenerator.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7557f75d2eff3291d5881746ac920d16a241e244 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/path/NodeEvaluatorGenerator.java -@@ -0,0 +1,10 @@ -+package gg.pufferfish.pufferfish.path; -+ -+import net.minecraft.world.level.pathfinder.NodeEvaluator; -+import org.jetbrains.annotations.NotNull; -+ -+public interface NodeEvaluatorGenerator { -+ -+ @NotNull NodeEvaluator generate(); -+ -+} diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java new file mode 100644 index 0000000000000000000000000000000000000000..731ef11c7a025ae95ed8a757b530d834733d0621 @@ -2401,139 +1250,6 @@ index 0000000000000000000000000000000000000000..1b29210ad0bbb4ada150f23357f0c80d + } + +} -diff --git a/src/main/java/gg/pufferfish/pufferfish/tracker/MultithreadedTracker.java b/src/main/java/gg/pufferfish/pufferfish/tracker/MultithreadedTracker.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ac541ddf1594ae865de02fd40940e39285043b1f ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/tracker/MultithreadedTracker.java -@@ -0,0 +1,127 @@ -+package gg.pufferfish.pufferfish.tracker; -+ -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; -+import io.papermc.paper.world.ChunkEntitySlices; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkMap; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.level.chunk.LevelChunk; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.concurrent.atomic.AtomicInteger; -+ -+public class MultithreadedTracker { -+ -+ private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors()); -+ private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder() -+ .setNameFormat("puff-tracker-%d") -+ .setPriority(Thread.NORM_PRIORITY - 2) -+ .build()); -+ -+ private final IteratorSafeOrderedReferenceSet entityTickingChunks; -+ private final AtomicInteger taskIndex = new AtomicInteger(); -+ -+ private final ConcurrentLinkedQueue mainThreadTasks; -+ private final AtomicInteger finishedTasks = new AtomicInteger(); -+ -+ public MultithreadedTracker(IteratorSafeOrderedReferenceSet entityTickingChunks, ConcurrentLinkedQueue mainThreadTasks) { -+ this.entityTickingChunks = entityTickingChunks; -+ this.mainThreadTasks = mainThreadTasks; -+ } -+ -+ public void tick() { -+ int iterator = this.entityTickingChunks.createRawIterator(); -+ -+ if (iterator == -1) { -+ return; -+ } -+ -+ try { -+ this.taskIndex.set(iterator); -+ this.finishedTasks.set(0); -+ -+ for (int i = 0; i < parallelism; i++) { -+ trackerExecutor.execute(this::run); -+ } -+ -+ while (this.taskIndex.get() < this.entityTickingChunks.getListSize()) { -+ this.runMainThreadTasks(); -+ this.handleTasks(5); // assist -+ } -+ -+ while (this.finishedTasks.get() != parallelism) { -+ this.runMainThreadTasks(); -+ } -+ -+ this.runMainThreadTasks(); // finish any remaining tasks -+ } finally { -+ this.entityTickingChunks.finishRawIterator(); -+ } -+ } -+ -+ private void runMainThreadTasks() { -+ try { -+ Runnable task; -+ while ((task = this.mainThreadTasks.poll()) != null) { -+ task.run(); -+ } -+ } catch (Throwable throwable) { -+ MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable); -+ } -+ } -+ -+ private void run() { -+ try { -+ while (handleTasks(10)); -+ } finally { -+ this.finishedTasks.incrementAndGet(); -+ } -+ } -+ -+ private boolean handleTasks(int tasks) { -+ int index; -+ while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.getListSize()) { -+ for (int i = index; i < index + tasks && i < this.entityTickingChunks.getListSize(); i++) { -+ LevelChunk chunk = this.entityTickingChunks.rawGet(i); -+ if (chunk != null) { -+ try { -+ this.processChunk(chunk); -+ } catch (Throwable throwable) { -+ MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable); -+ } -+ -+ } -+ } -+ -+ return true; -+ } -+ -+ return false; -+ } -+ -+ private void processChunk(LevelChunk chunk) { -+ final ChunkEntitySlices entitySlices = chunk.level.entityManager.entitySliceManager.getChunk(chunk.locX, chunk.locZ); -+ if (entitySlices == null) { -+ return; -+ } -+ -+ final Entity[] rawEntities = entitySlices.entities.getRawData(); -+ final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap; -+ -+ for (int i = 0; i < rawEntities.length; i++) { -+ Entity entity = rawEntities[i]; -+ if (entity != null) { -+ ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId()); -+ if (entityTracker != null) { -+ entityTracker.updatePlayers(entityTracker.entity.getPlayersInTrackRange()); -+ -+ this.mainThreadTasks.offer(entityTracker.serverEntity::sendChanges); -+ } -+ } -+ } -+ } -+ -+} diff --git a/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java b/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..9d6dc2c80945bec9bea74714c657c7a2e0bdde9e @@ -2701,10 +1417,10 @@ index 0000000000000000000000000000000000000000..facd55463d44cb7e3d2ca6892982f549 + } +} diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index 96b68840ef5c7c726e4c8c2d9f907196561a94bf..2eb30c6c6f1354a559a7b8c14c36a9970bdf2a42 100644 +index 4a8286c78a9a5e305b19cc5d316bc73a78e49b4d..54bca103347e89f116fb7fbf37449a32ac094286 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -8,6 +8,7 @@ import net.kyori.adventure.text.Component; +@@ -7,6 +7,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket; @@ -2712,7 +1428,7 @@ index 96b68840ef5c7c726e4c8c2d9f907196561a94bf..2eb30c6c6f1354a559a7b8c14c36a997 import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; -@@ -17,6 +18,7 @@ import org.spongepowered.configurate.objectmapping.meta.Setting; +@@ -16,6 +17,7 @@ import org.spongepowered.configurate.objectmapping.meta.Setting; import java.util.List; import java.util.Map; import java.util.Objects; @@ -2720,7 +1436,7 @@ index 96b68840ef5c7c726e4c8c2d9f907196561a94bf..2eb30c6c6f1354a559a7b8c14c36a997 @SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"}) public class GlobalConfiguration extends ConfigurationPart { -@@ -52,6 +54,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -51,6 +53,7 @@ public class GlobalConfiguration extends ConfigurationPart { public class Timings extends ConfigurationPart.Post { public boolean enabled = true; @@ -2728,7 +1444,7 @@ index 96b68840ef5c7c726e4c8c2d9f907196561a94bf..2eb30c6c6f1354a559a7b8c14c36a997 public boolean verbose = true; public String url = "https://timings.aikar.co/"; public boolean serverNamePrivacy = false; -@@ -65,6 +68,14 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -64,6 +67,14 @@ public class GlobalConfiguration extends ConfigurationPart { @Override public void postProcess() { @@ -2743,37 +1459,11 @@ index 96b68840ef5c7c726e4c8c2d9f907196561a94bf..2eb30c6c6f1354a559a7b8c14c36a997 MinecraftTimings.processConfig(this); } } -diff --git a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java -index 0fd814f1d65c111266a2b20f86561839a4cef755..ffc217df0649e85d4a7b3d4b1c2c6a8287de1104 100644 ---- a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java -+++ b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java -@@ -15,7 +15,7 @@ public final class IteratorSafeOrderedReferenceSet { - - /* list impl */ - protected E[] listElements; -- protected int listSize; -+ protected int listSize; public int getListSize() { return this.listSize; } // Pufferfish - expose listSize - - protected final double maxFragFactor; - -diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java -index 47b5f75d9f27cf3ab947fd1f69cbd609fb9f2749..85882eeb86d7b74db0219aa65783946d8083885d 100644 ---- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java -+++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java -@@ -27,7 +27,7 @@ public final class ChunkEntitySlices { - protected final EntityCollectionBySection allEntities; - protected final EntityCollectionBySection hardCollidingEntities; - protected final Reference2ObjectOpenHashMap, EntityCollectionBySection> entitiesByClass; -- protected final EntityList entities = new EntityList(); -+ public final EntityList entities = new EntityList(); - - public ChunkHolder.FullChunkStatus status; - diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 6939ef9b1fe782980e77c351d8a385a573d6a8e6..e9f0ddf1a34bf3b0d868b53e4439d9d9851ad4d6 100644 +index 99f56658c70f99592fb40c9df0ce3e47053d1bd5..07b0b0993c01763b39d1c9a387447ec76b5de190 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -207,7 +207,7 @@ public final class MCUtil { +@@ -208,7 +208,7 @@ public final class MCUtil { } public static long getCoordinateKey(final Entity entity) { @@ -2783,7 +1473,7 @@ index 6939ef9b1fe782980e77c351d8a385a573d6a8e6..e9f0ddf1a34bf3b0d868b53e4439d9d9 public static long getCoordinateKey(final ChunkPos pair) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 055ba929341889f9ab57d649beffa6e92feb6e53..67e150e35d328eb13c8f86e61dab2f11c76b21df 100644 +index ce81ba5345c8d2fde8a2534b9673275c7e86af8b..af9da39dffda01325af2ab3dd8b5e1efb18e013a 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -298,6 +298,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); -@@ -1674,7 +1676,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop trackerMainThreadTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private boolean multithreadedTrackingInProgress; -+ -+ public void runOnTrackerMainThread(final Runnable runnable) { -+ if (multithreadedTrackingInProgress) { -+ this.trackerMainThreadTasks.add(runnable); -+ } else { -+ runnable.run(); -+ } -+ } -+ - // Paper start - optimised tracker - private final void processTrackQueue() { -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncEntityTracker) { -+ if (this.multithreadedTracker == null) { -+ this.multithreadedTracker = new gg.pufferfish.pufferfish.tracker.MultithreadedTracker(this.level.chunkSource.entityTickingChunks, this.trackerMainThreadTasks); -+ } -+ -+ try { -+ multithreadedTrackingInProgress = true; -+ this.multithreadedTracker.tick(); -+ } finally { -+ multithreadedTrackingInProgress = false; -+ } -+ return; -+ } -+ // Pufferfish end -+ - this.level.timings.tracker1.startTiming(); - try { - for (TrackedEntity tracker : this.entityMap.values()) { -@@ -2349,11 +2377,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - public class TrackedEntity { - -- final ServerEntity serverEntity; -- final Entity entity; -+ public final ServerEntity serverEntity; // Pufferfish - package->public -+ public final Entity entity; // Pufferfish -> public - private final int range; - SectionPos lastSectionPos; -- public final Set seenBy = new ReferenceOpenHashSet<>(); // Paper - optimise map impl -+ public final Set seenBy = it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Paper - optimise map impl // Pufferfish - sync - - public TrackedEntity(Entity entity, int i, int j, boolean flag) { - this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit -@@ -2365,7 +2393,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - use distance map to optimise tracker - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; - -- final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { -+ public final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { // Pufferfish -> public - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; - this.lastTrackerCandidates = newTrackerCandidates; - -@@ -2437,7 +2465,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - public void removePlayer(ServerPlayer player) { -- org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot -+ //org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot // Pufferfish - we can remove async too - if (this.seenBy.remove(player.connection)) { - this.serverEntity.removePairing(player); - } -@@ -2445,7 +2473,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - public void updatePlayer(ServerPlayer player) { -- org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot -+ //org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot // Pufferfish - we can update async - if (player != this.entity) { - // Paper start - remove allocation of Vec3D here - // Vec3 vec3d = player.position().subtract(this.entity.position()); -@@ -2477,8 +2505,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1592,8 +1592,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return ChunkMap.this.level.getServer().getScaledTrackingDistance(initialDistance); } @@ -2954,7 +1565,7 @@ index c2c01988bf3b6fbb0a7a4716373c2ff0cffce27d..5fdef81245cb3cc686225cfd7c5ce13b Iterator iterator = this.entity.getIndirectPassengers().iterator(); while (iterator.hasNext()) { -@@ -2490,6 +2538,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1605,6 +1625,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider i = j; } } @@ -2964,21 +1575,8 @@ index c2c01988bf3b6fbb0a7a4716373c2ff0cffce27d..5fdef81245cb3cc686225cfd7c5ce13b return this.scaledRange(i); } -diff --git a/src/main/java/net/minecraft/server/level/ServerBossEvent.java b/src/main/java/net/minecraft/server/level/ServerBossEvent.java -index ca42c2642a729b90d22b968af7258f3aee72e14b..7613510e5f4c22ee15651f162fe1bca1cfc81be0 100644 ---- a/src/main/java/net/minecraft/server/level/ServerBossEvent.java -+++ b/src/main/java/net/minecraft/server/level/ServerBossEvent.java -@@ -13,7 +13,7 @@ import net.minecraft.util.Mth; - import net.minecraft.world.BossEvent; - - public class ServerBossEvent extends BossEvent { -- private final Set players = Sets.newHashSet(); -+ private final Set players = Sets.newConcurrentHashSet(); // Pufferfish - players can be removed in async tracking - private final Set unmodifiablePlayers = Collections.unmodifiableSet(this.players); - public boolean visible = true; - diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index efcb80efc69a1e5ffc81b579bf535fd94e8144d7..795691bcb61a7c2b4f903d8db3b6714908c78ac2 100644 +index 6d1f929eb717f62f0d7ebb9e9b52c3788061e240..7266e6703d5cd0fea90ec88c74a7d4567f2420ae 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -75,6 +75,9 @@ public class ServerChunkCache extends ChunkSource { @@ -2991,7 +1589,7 @@ index efcb80efc69a1e5ffc81b579bf535fd94e8144d7..795691bcb61a7c2b4f903d8db3b67149 private static int getChunkCacheKey(int x, int z) { return x & 3 | ((z & 3) << 2); -@@ -785,6 +788,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -702,6 +705,7 @@ public class ServerChunkCache extends ChunkSource { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); gameprofilerfiller.push("pollingChunks"); @@ -2999,7 +1597,7 @@ index efcb80efc69a1e5ffc81b579bf535fd94e8144d7..795691bcb61a7c2b4f903d8db3b67149 int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit -@@ -794,18 +798,25 @@ public class ServerChunkCache extends ChunkSource { +@@ -711,18 +715,25 @@ public class ServerChunkCache extends ChunkSource { // Paper start - per player mob spawning NaturalSpawner.SpawnState spawnercreature_d; // moved down if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't count mobs when animals and monsters are disabled @@ -3031,9 +1629,9 @@ index efcb80efc69a1e5ffc81b579bf535fd94e8144d7..795691bcb61a7c2b4f903d8db3b67149 gameprofilerfiller.popPush("filteringLoadedChunks"); // Paper - moved down this.level.timings.chunkTicks.startTiming(); // Paper -@@ -843,8 +854,8 @@ public class ServerChunkCache extends ChunkSource { +@@ -760,8 +771,8 @@ public class ServerChunkCache extends ChunkSource { - if ((true || this.level.isNaturalSpawningAllowed(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning // Paper - replace player chunk loader system + if ((true || this.level.isNaturalSpawningAllowed(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning // Paper - the chunk is known ticking chunk1.incrementInhabitedTime(j); - if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration - NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); @@ -3041,8 +1639,8 @@ index efcb80efc69a1e5ffc81b579bf535fd94e8144d7..795691bcb61a7c2b4f903d8db3b67149 + NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish } - if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - replace player chunk loader system -@@ -906,6 +917,30 @@ public class ServerChunkCache extends ChunkSource { + if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - the chunk is known ticking +@@ -823,6 +834,30 @@ public class ServerChunkCache extends ChunkSource { } // Paper end - controlled flush for entity tracker packets } @@ -3074,7 +1672,7 @@ index efcb80efc69a1e5ffc81b579bf535fd94e8144d7..795691bcb61a7c2b4f903d8db3b67149 private void getFullChunk(long pos, Consumer chunkConsumer) { diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 3b144c820531122eb37d41be06c182b5f5dc0724..88152988425b7b02ec5ce229ba4c24b40e030329 100644 +index 3b144c820531122eb37d41be06c182b5f5dc0724..1eb912ad97f9663bf6bd336ad739f2552b0a5c9b 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java @@ -165,6 +165,7 @@ public class ServerEntity { @@ -3093,62 +1691,11 @@ index 3b144c820531122eb37d41be06c182b5f5dc0724..88152988425b7b02ec5ce229ba4c24b4 } else { this.wasOnGround = this.entity.isOnGround(); this.teleportDelay = 0; -@@ -247,14 +249,18 @@ public class ServerEntity { - - public void removePairing(ServerPlayer player) { - this.entity.stopSeenByPlayer(player); -- player.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()})); -+ // Pufferfish start - ensure main thread -+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() -> -+ player.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()})) -+ ); -+ // Pufferfish end - } - - public void addPairing(ServerPlayer player) { - ServerGamePacketListenerImpl playerconnection = player.connection; - - Objects.requireNonNull(player.connection); -- this.sendPairingData(playerconnection::send, player); // CraftBukkit - add player -+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() -> this.sendPairingData(playerconnection::send, player)); // CraftBukkit - add player // Pufferfish - main thread - this.entity.startSeenByPlayer(player); - } - -@@ -360,19 +366,26 @@ public class ServerEntity { - SynchedEntityData datawatcher = this.entity.getEntityData(); - - if (datawatcher.isDirty()) { -- this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), datawatcher, false)); -+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() -> // Pufferfish -+ this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), datawatcher, false)) -+ ); // Pufferfish - } - - if (this.entity instanceof LivingEntity) { - Set set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes(); - - if (!set.isEmpty()) { -+ // Pufferfish start -+ List attributesCopy = Lists.newArrayList(set); -+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() -> { - // CraftBukkit start - Send scaled max health - if (this.entity instanceof ServerPlayer) { -- ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false); -+ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(attributesCopy, false); // Pufferfish - } - // CraftBukkit end -- this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set)); -+ this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesCopy)); // Pufferfish -+ }); -+ // Pufferfish end - } - - set.clear(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 96bb0e56f12437037b598cd7baabf369e5994517..8ed9f14f1ca71111a8215b28821bd5e398c0d0a6 100644 +index b396e9b35f315db37ba070ad4baeec1f098d0cb8..f8750675044708e71dbf6293be6ce36bd6c510ca 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -695,7 +695,20 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -725,7 +725,20 @@ public class ServerLevel extends Level implements WorldGenLevel { } gameprofilerfiller.push("tick"); @@ -3170,7 +1717,7 @@ index 96bb0e56f12437037b598cd7baabf369e5994517..8ed9f14f1ca71111a8215b28821bd5e3 gameprofilerfiller.pop(); } } -@@ -762,9 +775,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -792,9 +805,11 @@ public class ServerLevel extends Level implements WorldGenLevel { } // Paper start - optimise random block ticking private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); @@ -3183,7 +1730,7 @@ index 96bb0e56f12437037b598cd7baabf369e5994517..8ed9f14f1ca71111a8215b28821bd5e3 public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); -@@ -775,7 +790,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -805,7 +820,7 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.push("thunder"); final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change @@ -3192,7 +1739,7 @@ index 96bb0e56f12437037b598cd7baabf369e5994517..8ed9f14f1ca71111a8215b28821bd5e3 blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); -@@ -799,7 +814,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -829,7 +844,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } gameprofilerfiller.popPush("iceandsnow"); @@ -3334,7 +1881,7 @@ index 540bc9500c35c0db719b00aa26f6fb3a1b08ed9f..806cb760822a99316b08ad95ff8922df int LARGE_MAX_STACK_SIZE = 64; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c4bfbea57 100644 +index 008bd65d838819431a0823c6ac5925774bd155a1..fc4bd8ad4836aa6bdd228885f0aeb22500782af5 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -292,7 +292,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { @@ -3345,7 +1892,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c + public BlockPos blockPosition; // Pufferfish - private->public private ChunkPos chunkPosition; private Vec3 deltaMovement; - public float yRot; // Paper - private->public + private float yRot; @@ -414,6 +414,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return this.originWorld; } @@ -3358,7 +1905,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c public float getBukkitYaw() { return this.yRot; } -@@ -437,17 +442,36 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -488,17 +493,36 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { this.isLegacyTrackingEntity = isLegacyTrackingEntity; } @@ -3396,7 +1943,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c for (Entity passenger : passengers) { org.spigotmc.TrackingRange.TrackingRangeType passengerType = passenger.trackingRangeType; int passengerRange = chunkMap.getEntityTrackerRange(passengerType.ordinal()); -@@ -456,6 +480,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -507,6 +531,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { range = passengerRange; } } @@ -3406,7 +1953,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c return chunkMap.playerEntityTrackerTrackMaps[type.ordinal()].getObjectsInRange(MCUtil.getCoordinateKey(this)); } -@@ -787,6 +814,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -788,6 +815,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { // CraftBukkit end public void baseTick() { @@ -3419,7 +1966,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c this.level.getProfiler().push("entityBaseTick"); if (firstTick && this instanceof net.minecraft.world.entity.NeutralMob neutralMob) neutralMob.tickInitialPersistentAnger(level); // Paper - Update last hurt when ticking this.feetBlockState = null; -@@ -4005,16 +4038,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -4016,16 +4049,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) { @@ -3445,7 +1992,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c double d1 = 0.0D; boolean flag = this.isPushedByFluid(); boolean flag1 = false; -@@ -4022,14 +4057,61 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -4033,14 +4068,61 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { int k1 = 0; BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); @@ -3513,7 +2060,7 @@ index a3f1aef9d8f254747bd6580e8e3087a5c6829128..4971ec79a114fd0d7540eaa0ef54b18c if (d2 >= axisalignedbb.minY) { flag1 = true; -@@ -4051,9 +4133,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -4062,9 +4144,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { // CraftBukkit end } } @@ -3685,7 +2232,7 @@ index c770ee21b7b699522941f6a1584d532001c04082..9bce290eb0c2cfef4896a3f2076c80bf public boolean hasAttribute(Attribute attribute) { diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java -index 43243537b765a2d270be6de3f053fea77ff67d18..b56bb0ac37a6d51d645b6189af0ae7da01a353fd 100644 +index 43243537b765a2d270be6de3f053fea77ff67d18..bf3b8ccb3e031e0ad24cd51e28ea8cbd4f8a8030 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java @@ -72,6 +72,7 @@ public class AcquirePoi extends Behavior { @@ -3696,271 +2243,6 @@ index 43243537b765a2d270be6de3f053fea77ff67d18..b56bb0ac37a6d51d645b6189af0ae7da PoiManager poiManager = world.getPoiManager(); this.batchCache.long2ObjectEntrySet().removeIf((entry) -> { return !entry.getValue().isStillValid(time); -@@ -92,27 +93,60 @@ public class AcquirePoi extends Behavior { - io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, this.poiType, predicate, entity.blockPosition(), 48, 48*48, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes); - Set, BlockPos>> set = new java.util.HashSet<>(poiposes); - // Paper end - optimise POI access -- Path path = findPathToPois(entity, set); -- if (path != null && path.canReach()) { -- BlockPos blockPos = path.getTarget(); -- poiManager.getType(blockPos).ifPresent((holder) -> { -- poiManager.take(this.poiType, (holderx, blockPos2) -> { -- return blockPos2.equals(blockPos); -- }, blockPos, 1); -- entity.getBrain().setMemory(this.memoryToAcquire, GlobalPos.of(world.dimension(), blockPos)); -- this.onPoiAcquisitionEvent.ifPresent((byte_) -> { -- world.broadcastEntityEvent(entity, byte_); -+ // Pufferfish start - await on path async -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ Path possiblePath = findPathToPois(entity, set); -+ -+ // Pufferfish - wait on the path to be processed -+ gg.pufferfish.pufferfish.path.AsyncPathProcessor.awaitProcessing(possiblePath, path -> { -+ // Pufferfish - readd canReach check -+ if (path == null || !path.canReach()) { -+ for(Pair, BlockPos> pair : set) { -+ this.batchCache.computeIfAbsent(pair.getSecond().asLong(), (m) -> { -+ return new AcquirePoi.JitteredLinearRetry(entity.level.random, time); -+ }); -+ } -+ return; -+ } -+ -+ BlockPos blockPos = path.getTarget(); -+ poiManager.getType(blockPos).ifPresent((holder) -> { -+ poiManager.take(this.poiType, (holderx, blockPos2) -> { -+ return blockPos2.equals(blockPos); -+ }, blockPos, 1); -+ entity.getBrain().setMemory(this.memoryToAcquire, GlobalPos.of(world.dimension(), blockPos)); -+ this.onPoiAcquisitionEvent.ifPresent((byte_) -> { -+ world.broadcastEntityEvent(entity, byte_); -+ }); -+ this.batchCache.clear(); -+ DebugPackets.sendPoiTicketCountPacket(world, blockPos); - }); -- this.batchCache.clear(); -- DebugPackets.sendPoiTicketCountPacket(world, blockPos); - }); - } else { -- for(Pair, BlockPos> pair : set) { -- this.batchCache.computeIfAbsent(pair.getSecond().asLong(), (m) -> { -- return new AcquirePoi.JitteredLinearRetry(entity.level.random, time); -+ Path path = findPathToPois(entity, set); -+ if (path != null && path.canReach()) { -+ BlockPos blockPos = path.getTarget(); -+ poiManager.getType(blockPos).ifPresent((holder) -> { -+ poiManager.take(this.poiType, (holderx, blockPos2) -> { -+ return blockPos2.equals(blockPos); -+ }, blockPos, 1); -+ entity.getBrain().setMemory(this.memoryToAcquire, GlobalPos.of(world.dimension(), blockPos)); -+ this.onPoiAcquisitionEvent.ifPresent((byte_) -> { -+ world.broadcastEntityEvent(entity, byte_); -+ }); -+ this.batchCache.clear(); -+ DebugPackets.sendPoiTicketCountPacket(world, blockPos); - }); -+ } else { -+ for(Pair, BlockPos> pair : set) { -+ this.batchCache.computeIfAbsent(pair.getSecond().asLong(), (m) -> { -+ return new AcquirePoi.JitteredLinearRetry(entity.level.random, time); -+ }); -+ } - } - } -+ -+ // Pufferfish end - - } - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java -index 18364ce4c60172529b10bc9e3a813dcedc4b766f..72dfb58a7f4586387c2d32cf54fff137b2d26666 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java -@@ -21,6 +21,7 @@ public class MoveToTargetSink extends Behavior { - private int remainingCooldown; - @Nullable - private Path path; -+ private boolean finishedProcessing; // Pufferfish - @Nullable - private BlockPos lastTargetPos; - private float speedModifier; -@@ -42,9 +43,10 @@ public class MoveToTargetSink extends Behavior { - Brain brain = entity.getBrain(); - WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get(); - boolean bl = this.reachedTarget(entity, walkTarget); -- if (!bl && this.tryComputePath(entity, walkTarget, world.getGameTime())) { -+ if (!bl && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && this.tryComputePath(entity, walkTarget, world.getGameTime()))) { // Pufferfish - this.lastTargetPos = walkTarget.getTarget().currentBlockPosition(); - return true; -+ } else if (!bl) { return true; // Pufferfish - } else { - brain.eraseMemory(MemoryModuleType.WALK_TARGET); - if (bl) { -@@ -58,6 +60,7 @@ public class MoveToTargetSink extends Behavior { - - @Override - protected boolean canStillUse(ServerLevel serverLevel, Mob mob, long l) { -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && !finishedProcessing) return true; // Pufferfish - wait for path to process - if (this.path != null && this.lastTargetPos != null) { - Optional optional = mob.getBrain().getMemory(MemoryModuleType.WALK_TARGET); - PathNavigation pathNavigation = mob.getNavigation(); -@@ -81,28 +84,96 @@ public class MoveToTargetSink extends Behavior { - - @Override - protected void start(ServerLevel serverLevel, Mob mob, long l) { -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { // Pufferfish - mob.getBrain().setMemory(MemoryModuleType.PATH, this.path); - mob.getNavigation().moveTo(this.path, (double)this.speedModifier); -+ // Pufferfish start -+ } else { -+ Brain brain = mob.getBrain(); -+ WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get(); -+ -+ this.finishedProcessing = false; -+ this.lastTargetPos = walkTarget.getTarget().currentBlockPosition(); -+ this.path = this.computePath(mob, walkTarget); -+ } -+ // Pufferfish end - } - - @Override - protected void tick(ServerLevel world, Mob entity, long time) { -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && this.path != null && !this.path.isProcessed()) return; // Pufferfish - wait for processing -+ -+ // Pufferfish start -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && !finishedProcessing) { -+ this.finishedProcessing = true; -+ Brain brain = entity.getBrain(); -+ boolean canReach = this.path != null && this.path.canReach(); -+ if (canReach) { -+ brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); -+ } else if (brain.hasMemoryValue(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) { -+ brain.setMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, time); -+ } -+ -+ if (!canReach) { -+ Optional walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET); -+ -+ if (walkTarget.isPresent()) { -+ BlockPos blockPos = walkTarget.get().getTarget().currentBlockPosition(); -+ Vec3 vec3 = DefaultRandomPos.getPosTowards((PathfinderMob)entity, 10, 7, Vec3.atBottomCenterOf(blockPos), (double)((float)Math.PI / 2F)); -+ if (vec3 != null) { -+ // try recalculating the path using a random position -+ this.path = entity.getNavigation().createPath(vec3.x, vec3.y, vec3.z, 0); -+ this.finishedProcessing = false; -+ return; -+ } -+ } -+ -+ brain.eraseMemory(MemoryModuleType.WALK_TARGET); -+ this.path = null; -+ -+ return; -+ } -+ -+ entity.getBrain().setMemory(MemoryModuleType.PATH, this.path); -+ entity.getNavigation().moveTo(this.path, (double)this.speedModifier); -+ } -+ // Pufferfish end -+ - Path path = entity.getNavigation().getPath(); - Brain brain = entity.getBrain(); -- if (this.path != path) { -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && this.path != path) { // Pufferfish - this.path = path; - brain.setMemory(MemoryModuleType.PATH, path); - } - -- if (path != null && this.lastTargetPos != null) { -+ if (path != null && this.lastTargetPos != null && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || brain.hasMemoryValue(MemoryModuleType.WALK_TARGET))) { // Pufferfish - WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get(); -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { // Pufferfish - if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0D && this.tryComputePath(entity, walkTarget, world.getGameTime())) { - this.lastTargetPos = walkTarget.getTarget().currentBlockPosition(); - this.start(world, entity, time); - } -+ // Pufferfish start -+ } else { -+ if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0D) this.start(world, entity, time); -+ } -+ // Pufferfish end -+ -+ } -+ } - -+ // Pufferfish start -+ private Path computePath(Mob entity, WalkTarget walkTarget) { -+ BlockPos blockPos = walkTarget.getTarget().currentBlockPosition(); -+ this.speedModifier = walkTarget.getSpeedModifier(); -+ Brain brain = entity.getBrain(); -+ if (this.reachedTarget(entity, walkTarget)) { -+ brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); - } -+ -+ return entity.getNavigation().createPath(blockPos, 0); - } -+ // Pufferfish end - - private boolean tryComputePath(Mob entity, WalkTarget walkTarget, long time) { - BlockPos blockPos = walkTarget.getTarget().currentBlockPosition(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java -index 9bd6d4f7b86daaaa9cfbad454dde06b797e3f667..2402a8c1067a74a21d9812561df5fb6284670571 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java -@@ -71,19 +71,41 @@ public class SetClosestHomeAsWalkTarget extends Behavior { - Set, BlockPos>> set = poiManager.findAllWithType((poiType) -> { - return poiType.is(PoiTypes.HOME); - }, predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY).collect(Collectors.toSet()); -- Path path = AcquirePoi.findPathToPois(pathfinderMob, set); -- if (path != null && path.canReach()) { -- BlockPos blockPos = path.getTarget(); -- Optional> optional = poiManager.getType(blockPos); -- if (optional.isPresent()) { -- entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(blockPos, this.speedModifier, 1)); -- DebugPackets.sendPoiTicketCountPacket(world, blockPos); -- } -- } else if (this.triedCount < 5) { -- this.batchCache.long2LongEntrySet().removeIf((entry) -> { -- return entry.getLongValue() < this.lastUpdate; -+ // Pufferfish start - await on path async -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ Path possiblePath = AcquirePoi.findPathToPois(pathfinderMob, set); -+ -+ // Pufferfish - wait on the path to be processed -+ gg.pufferfish.pufferfish.path.AsyncPathProcessor.awaitProcessing(possiblePath, path -> { -+ if (path == null || !path.canReach() || this.triedCount < 5) { // Pufferfish - readd canReach check -+ this.batchCache.long2LongEntrySet().removeIf((entry) -> { -+ return entry.getLongValue() < this.lastUpdate; -+ }); -+ return; -+ } -+ -+ BlockPos blockPos = path.getTarget(); -+ Optional> optional = poiManager.getType(blockPos); -+ if (optional.isPresent()) { -+ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(blockPos, this.speedModifier, 1)); -+ DebugPackets.sendPoiTicketCountPacket(world, blockPos); -+ } - }); -+ } else { -+ Path path = AcquirePoi.findPathToPois(pathfinderMob, set); -+ if (path != null && path.canReach()) { -+ BlockPos blockPos = path.getTarget(); -+ Optional> optional = poiManager.getType(blockPos); -+ if (optional.isPresent()) { -+ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(blockPos, this.speedModifier, 1)); -+ DebugPackets.sendPoiTicketCountPacket(world, blockPos); -+ } -+ } else if (this.triedCount < 5) { -+ this.batchCache.long2LongEntrySet().removeIf((entry) -> { -+ return entry.getLongValue() < this.lastUpdate; -+ }); -+ } - } -- -+ // Pufferfish end - } - } diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java index 42d466f7f162943886078eba3db18f2dfc2d7bee..6c0dda1ce018ec6bb2ebb97147045fffae0a89d5 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java @@ -4009,273 +2291,6 @@ index 26bf383caea68834c654b25653ced9017f1b1b22..615eb55e24d365d994fbfe9d45d2be38 if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level, mutableBlockPos)) { this.blockPos = mutableBlockPos; setTargetPosition(mutableBlockPos.immutable()); // Paper -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java -index 29a872393f2f995b13b4ed26b42c6464ab27ca73..6fda4eebe743dcc88aa253c4d0e539b20ed27a7e 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java -@@ -8,6 +8,14 @@ import net.minecraft.world.level.pathfinder.PathFinder; - import net.minecraft.world.phys.Vec3; - - public class AmphibiousPathNavigation extends PathNavigation { -+ // Pufferfish start -+ private static final gg.pufferfish.pufferfish.path.NodeEvaluatorGenerator nodeEvaluatorGenerator = () -> { -+ var nodeEvaluator = new AmphibiousNodeEvaluator(false); -+ nodeEvaluator.setCanPassDoors(true); -+ return nodeEvaluator; -+ }; -+ // Pufferfish end -+ - public AmphibiousPathNavigation(Mob mob, Level world) { - super(mob, world); - } -@@ -16,7 +24,13 @@ public class AmphibiousPathNavigation extends PathNavigation { - protected PathFinder createPathFinder(int range) { - this.nodeEvaluator = new AmphibiousNodeEvaluator(false); - this.nodeEvaluator.setCanPassDoors(true); -- return new PathFinder(this.nodeEvaluator, range); -+ // Pufferfish start -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ return new PathFinder(this.nodeEvaluator, range, nodeEvaluatorGenerator); -+ } else { -+ return new PathFinder(this.nodeEvaluator, range); -+ } -+ // Pufferfish end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -index 27cd393e81f6ef9b5690c051624d8d2af50acd34..33bee4233ba159d72a851d67b99836f8f2d66b64 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -@@ -12,6 +12,15 @@ import net.minecraft.world.level.pathfinder.PathFinder; - import net.minecraft.world.phys.Vec3; - - public class FlyingPathNavigation extends PathNavigation { -+ -+ // Pufferfish start -+ private static final gg.pufferfish.pufferfish.path.NodeEvaluatorGenerator nodeEvaluatorGenerator = () -> { -+ var nodeEvaluator = new FlyNodeEvaluator(); -+ nodeEvaluator.setCanPassDoors(true); -+ return nodeEvaluator; -+ }; -+ // Pufferfish end -+ - public FlyingPathNavigation(Mob entity, Level world) { - super(entity, world); - } -@@ -20,7 +29,13 @@ public class FlyingPathNavigation extends PathNavigation { - protected PathFinder createPathFinder(int range) { - this.nodeEvaluator = new FlyNodeEvaluator(); - this.nodeEvaluator.setCanPassDoors(true); -- return new PathFinder(this.nodeEvaluator, range); -+ // Pufferfish start -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ return new PathFinder(this.nodeEvaluator, range, nodeEvaluatorGenerator); -+ } else { -+ return new PathFinder(this.nodeEvaluator, range); -+ } -+ // Pufferfish end - } - - @Override -@@ -45,9 +60,11 @@ public class FlyingPathNavigation extends PathNavigation { - this.recomputePath(); - } - -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && this.path != null && !this.path.isProcessed()) return; // Pufferfish -+ - if (!this.isDone()) { - if (this.canUpdatePath()) { -- this.followThePath(); -+ this.followThePathSuper(); // Pufferfish - } else if (this.path != null && !this.path.isDone()) { - Vec3 vec3 = this.path.getNextEntityPos(this.mob); - if (this.mob.getBlockX() == Mth.floor(vec3.x) && this.mob.getBlockY() == Mth.floor(vec3.y) && this.mob.getBlockZ() == Mth.floor(vec3.z)) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -index f0248d839255763005ba333b0bfcf691407fb69b..fcc40d8ff949bc7bb8a581133837ca93f53e8949 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -@@ -15,6 +15,15 @@ import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; - import net.minecraft.world.phys.Vec3; - - public class GroundPathNavigation extends PathNavigation { -+ -+ // Pufferfish start -+ private static final gg.pufferfish.pufferfish.path.NodeEvaluatorGenerator nodeEvaluatorGenerator = () -> { -+ var nodeEvaluator = new WalkNodeEvaluator(); -+ nodeEvaluator.setCanPassDoors(true); -+ return nodeEvaluator; -+ }; -+ // Pufferfish end -+ - private boolean avoidSun; - - public GroundPathNavigation(Mob entity, Level world) { -@@ -25,7 +34,13 @@ public class GroundPathNavigation extends PathNavigation { - protected PathFinder createPathFinder(int range) { - this.nodeEvaluator = new WalkNodeEvaluator(); - this.nodeEvaluator.setCanPassDoors(true); -- return new PathFinder(this.nodeEvaluator, range); -+ // Pufferfish start -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ return new PathFinder(this.nodeEvaluator, range, nodeEvaluatorGenerator); -+ } else { -+ return new PathFinder(this.nodeEvaluator, range); -+ } -+ // Pufferfish end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 02653adc591d390ca8b4ee13289510d4652c8894..cb4a162903207754be90ff8da0156f97791cccef 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -150,6 +150,9 @@ public abstract class PathNavigation { - return null; - } else if (!this.canUpdatePath()) { - return null; -+ } else if (this.path instanceof gg.pufferfish.pufferfish.path.AsyncPath asyncPath && !asyncPath.isProcessed() && asyncPath.hasSameProcessingPositions(positions)) { // Pufferfish start - catch early if it's still processing these positions let it keep processing -+ return this.path; -+ // Pufferfish end - } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { - return this.path; - } else { -@@ -176,11 +179,28 @@ public abstract class PathNavigation { - PathNavigationRegion pathNavigationRegion = new PathNavigationRegion(this.level, blockPos.offset(-i, -i, -i), blockPos.offset(i, i, i)); - Path path = this.pathFinder.findPath(pathNavigationRegion, this.mob, positions, followRange, distance, this.maxVisitedNodesMultiplier); - this.level.getProfiler().pop(); -- if (path != null && path.getTarget() != null) { -+ -+ // Pufferfish start -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ if (path != null && path.getTarget() != null) { - this.targetPos = path.getTarget(); - this.reachRange = distance; - this.resetStuckTimeout(); -+ } -+ } else { -+ if (!positions.isEmpty()) this.targetPos = positions.iterator().next(); // Pufferfish - assign early a target position. most calls will only have 1 position -+ -+ gg.pufferfish.pufferfish.path.AsyncPathProcessor.awaitProcessing(path, processedPath -> { -+ if (processedPath != this.path) return; // Pufferfish - check that processing didn't take so long that we calculated a new path -+ -+ if (processedPath != null && processedPath.getTarget() != null) { -+ this.targetPos = processedPath.getTarget(); -+ this.reachRange = distance; -+ this.resetStuckTimeout(); -+ } -+ }); - } -+ // Pufferfish end - - return path; - } -@@ -227,8 +247,8 @@ public abstract class PathNavigation { - if (this.isDone()) { - return false; - } else { -- this.trimPath(); -- if (this.path.getNodeCount() <= 0) { -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || path.isProcessed()) this.trimPath(); // Pufferfish - only trim if processed -+ if ((!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || path.isProcessed()) && this.path.getNodeCount() <= 0) { // Pufferfish - only check node count if processed - return false; - } else { - this.speedModifier = speed; -@@ -252,9 +272,11 @@ public abstract class PathNavigation { - this.recomputePath(); - } - -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && this.path != null && !this.path.isProcessed()) return; // Pufferfish - skip pathfinding if we're still processing -+ - if (!this.isDone()) { - if (this.canUpdatePath()) { -- this.followThePath(); -+ this.followThePathSuper(); // Pufferfish - } else if (this.path != null && !this.path.isDone()) { - Vec3 vec3 = this.getTempMobPos(); - Vec3 vec32 = this.path.getNextEntityPos(this.mob); -@@ -275,6 +297,13 @@ public abstract class PathNavigation { - BlockPos blockPos = new BlockPos(pos); - return this.level.getBlockState(blockPos.below()).isAir() ? pos.y : WalkNodeEvaluator.getFloorLevel(this.level, blockPos); - } -+ -+ // Pufferfish start - this fixes plugin compat by ensuring the isProcessed check is completed properly. -+ protected final void followThePathSuper() { -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding && !this.path.isProcessed()) return; // Pufferfish -+ followThePath(); -+ } -+ // Pufferfish end - - protected void followThePath() { - Vec3 vec3 = this.getTempMobPos(); -@@ -439,7 +468,7 @@ public abstract class PathNavigation { - // Paper start - public boolean isViableForPathRecalculationChecking() { - return !this.needsPathRecalculation() && -- (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0); -+ (this.path != null && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || this.path.isProcessed()) && !this.path.isDone() && this.path.getNodeCount() != 0); // Pufferfish - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java -index 8db20db72cd51046213625fac46c35854c59ec5d..52768c8797bf8b03e92840d68b91239835e6c467 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java -@@ -57,20 +57,42 @@ public class NearestBedSensor extends Sensor { - java.util.List, BlockPos>> poiposes = new java.util.ArrayList<>(); - // don't ask me why it's unbounded. ask mojang. - io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); -- Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes)); -- // Paper end - optimise POI access -- if (path != null && path.canReach()) { -- BlockPos blockPos = path.getTarget(); -- Optional> optional = poiManager.getType(blockPos); -- if (optional.isPresent()) { -- entity.getBrain().setMemory(MemoryModuleType.NEAREST_BED, blockPos); -- } -- } else if (this.triedCount < 5) { -- this.batchCache.long2LongEntrySet().removeIf((entry) -> { -- return entry.getLongValue() < this.lastUpdate; -+ -+ // Pufferfish start - await on path async -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ Path possiblePath = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes)); -+ // Paper end - optimise POI access -+ // Pufferfish - wait on the path to be processed -+ gg.pufferfish.pufferfish.path.AsyncPathProcessor.awaitProcessing(possiblePath, path -> { -+ // Pufferfish - readd canReach check -+ if (path == null || !path.canReach()) { -+ this.batchCache.long2LongEntrySet().removeIf((entry) -> { -+ return entry.getLongValue() < this.lastUpdate; -+ }); -+ return; -+ } -+ -+ BlockPos blockPos = path.getTarget(); -+ Optional> optional = poiManager.getType(blockPos); -+ if (optional.isPresent()) { -+ entity.getBrain().setMemory(MemoryModuleType.NEAREST_BED, blockPos); -+ } - }); -+ } else { -+ Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes)); -+ if (path != null && path.canReach()) { -+ BlockPos blockPos = path.getTarget(); -+ Optional> optional = poiManager.getType(blockPos); -+ if (optional.isPresent()) { -+ entity.getBrain().setMemory(MemoryModuleType.NEAREST_BED, blockPos); -+ } -+ } else if (this.triedCount < 5) { -+ this.batchCache.long2LongEntrySet().removeIf((entry) -> { -+ return entry.getLongValue() < this.lastUpdate; -+ }); -+ } - } -- -+ // Pufferfish end - } - } - } diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java index a7575b5ef56af6f53448d391abb4956e130148ca..e752c83df50fb9b670ecea2abc95426c2a009b6f 100644 --- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java @@ -4329,28 +2344,6 @@ index 50d4595b81f24949011c7565c5e3fc8c26c86019..234ad92d666775dcf5a29a60551b17cb @Override protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index a9cdf9034ad269f7a71358443acc053288cfbe6d..dbeb70913d3933164e997ce5d662b4890ffe4f36 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -1071,7 +1071,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - } else { - Bee.this.pathfindRandomlyTowards(Bee.this.hivePos); - } -- } else { -+ } else if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || (navigation.getPath() != null && navigation.getPath().isProcessed())) { // Pufferfish - check processing - boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos); - - if (!flag) { -@@ -1133,7 +1133,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - } else { - Path pathentity = Bee.this.navigation.getPath(); - -- return pathentity != null && pathentity.getTarget().equals(pos) && pathentity.canReach() && pathentity.isDone(); -+ return pathentity != null && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || pathentity.isProcessed()) && pathentity.getTarget().equals(pos) && pathentity.canReach() && pathentity.isDone(); // Pufferfish - ensure path is processed - } - } - } diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java index 2d87b740e84435ef9bd3eee3d3e2af9f707a0826..d38d1e3692e093d6707b6bd80cd56ec4afcf093b 100644 --- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java @@ -4384,7 +2377,7 @@ index e7467fec2cab37c1a9933d1096724e3732913590..1c93872f9fcc6f6a19dee8565726501d this.level.getProfiler().pop(); this.level.getProfiler().push("axolotlActivityUpdate"); diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -index bb6063ae7f4438916306ce876057f7488537b444..4c3fd27bff777139e29905e8684f6e92a44decfe 100644 +index bb6063ae7f4438916306ce876057f7488537b444..74cb2741a5cd66bdac3a22de938ae82968705a56 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java @@ -174,9 +174,11 @@ public class Frog extends Animal { @@ -4399,36 +2392,6 @@ index bb6063ae7f4438916306ce876057f7488537b444..4c3fd27bff777139e29905e8684f6e92 this.getBrain().tick((ServerLevel)this.level, this); this.level.getProfiler().pop(); this.level.getProfiler().push("frogActivityUpdate"); -@@ -411,6 +413,14 @@ public class Frog extends Animal { - } - - static class FrogPathNavigation extends AmphibiousPathNavigation { -+ // Pufferfish start -+ private static final gg.pufferfish.pufferfish.path.NodeEvaluatorGenerator nodeEvaluatorGenerator = () -> { -+ var nodeEvaluator = new Frog.FrogNodeEvaluator(true); -+ nodeEvaluator.setCanPassDoors(true); -+ return nodeEvaluator; -+ }; -+ // Pufferfish end -+ - FrogPathNavigation(Frog frog, Level world) { - super(frog, world); - } -@@ -419,7 +429,13 @@ public class Frog extends Animal { - protected PathFinder createPathFinder(int range) { - this.nodeEvaluator = new Frog.FrogNodeEvaluator(true); - this.nodeEvaluator.setCanPassDoors(true); -- return new PathFinder(this.nodeEvaluator, range); -+ // Pufferfish start -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { -+ return new PathFinder(this.nodeEvaluator, range, nodeEvaluatorGenerator); -+ } else { -+ return new PathFinder(this.nodeEvaluator, range); -+ } -+ // Pufferfish end - } - } - } diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java index 3dd4e6d622a6daafa00ae971edd88a147e34beef..32cca29fd622d18030931e1f330791491e7f9fa0 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java @@ -4482,19 +2445,6 @@ index fcc5444a1268931a0fd2df1e6bbbc17cfd5a61e0..16a55f94bda9f959548772c8916b4dc3 } // Paper End this.tryToMerge(entityitem); -diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index 1b1305f5eaf5710b72c57ab4c3953e703a23f1e0..30a67a1eef9238e12e54c57a0608387cc0f763ef 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -@@ -222,7 +222,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - protected boolean closeToNextPos() { - Path pathentity = this.getNavigation().getPath(); - -- if (pathentity != null) { -+ if (pathentity != null && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding || pathentity.isProcessed())) { // Pufferfish - ensure path is processed - BlockPos blockposition = pathentity.getTarget(); - - if (blockposition != null) { diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java index f22e615dba31619c97bf58930da060476a52facf..f5bb64f9f683cf21e772035e9be100ed2ddf8bc6 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java @@ -4850,7 +2800,7 @@ index 468c635d31cfa8051666bbefce8df4b448e9ed93..17e869074b8cf29a8c3280499a27e951 final String id; private final GameRules.Category category; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ceb1f18ec16ddcda792ef0393b5f4649fbef3017..388a153113d87ba99515828c6d535110b4413c7c 100644 +index d89471935b2b5888cb5d1f6829ae479003451fda..0277633fd328ef9993fea4ac29df83b5b00c0f42 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -271,6 +271,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -4885,7 +2835,7 @@ index ceb1f18ec16ddcda792ef0393b5f4649fbef3017..388a153113d87ba99515828c6d535110 this.dimension = resourcekey; this.isClientSide = flag; if (dimensionmanager.coordinateScale() != 1.0D) { -@@ -409,6 +427,91 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -408,6 +426,91 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return null; } @@ -4977,7 +2927,7 @@ index ceb1f18ec16ddcda792ef0393b5f4649fbef3017..388a153113d87ba99515828c6d535110 public boolean isInWorldBounds(BlockPos pos) { return pos.isInsideBuildHeightAndWorldBoundsHorizontal(this); // Paper - use better/optimized check } -@@ -897,13 +1000,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -896,13 +999,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { tickConsumer.accept(entity); MinecraftServer.getServer().executeMidTickTasks(); // Paper - execute chunk tasks mid tick @@ -4993,7 +2943,7 @@ index ceb1f18ec16ddcda792ef0393b5f4649fbef3017..388a153113d87ba99515828c6d535110 // Paper end } } -@@ -1389,6 +1492,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1388,6 +1491,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } public ProfilerFiller getProfiler() { @@ -5284,12 +3234,12 @@ index d559f93a9a09bac414dd5d58afccad42c127f09b..13e749a3c40f0b2cc002f13675a9a56e @Override diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 2292cb0e0c1a3e0ed34b941f028136bfb0bff13e..0b08a91ae9dc73c011dbb5f517becac7d08fd1e9 100644 +index 05499ae9fc331471db6e763a2adb46b5da8522d3..34334c139176e0aa9f6d93a87821508d17567cfc 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -94,6 +94,18 @@ public class LevelChunk extends ChunkAccess { - } - // Paper end +@@ -88,6 +88,18 @@ public class LevelChunk extends ChunkAccess { + private final LevelChunkTicks blockTicks; + private final LevelChunkTicks fluidTicks; + // Pufferfish start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively + private int lightningTick; @@ -5306,7 +3256,7 @@ index 2292cb0e0c1a3e0ed34b941f028136bfb0bff13e..0b08a91ae9dc73c011dbb5f517becac7 public LevelChunk(Level world, ChunkPos pos) { this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); } -@@ -124,6 +136,7 @@ public class LevelChunk extends ChunkAccess { +@@ -118,6 +130,7 @@ public class LevelChunk extends ChunkAccess { this.fluidTicks = fluidTickScheduler; // CraftBukkit start this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); @@ -5363,32 +3313,6 @@ index 4cdfc433df67afcd455422e9baf56f167dd712ae..57fcf3910f45ce371ac2e237b277b103 private void ensureActiveIsNotIterated() { // Paper - replace with better logic, do not delay removals -diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java -index da1ad0b2679e392ed81b50c15f012c63cb5c939e..9c6ab057dccd6331e9c577e0c6192c0d84718906 100644 ---- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java -@@ -6,6 +6,8 @@ import javax.annotation.Nullable; - import net.minecraft.world.phys.AABB; - - public interface LevelEntityGetter { -+ int getCount(); // Pufferfish -+ - @Nullable - T get(int id); - -diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java -index 3b13f6ea36a3bfecabe09221eb5c48dddab119db..563b6c47df0c5ae9efcb91fd53a065b1da1cdb94 100644 ---- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java -+++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java -@@ -14,6 +14,8 @@ public class LevelEntityGetterAdapter implements LevelEn - this.sectionStorage = cache; - } - -+ @Override public int getCount() { return this.visibleEntities.count(); } // Pufferfish -+ - @Nullable - @Override - public T get(int id) { diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java index ff40fe323964f173561a6838fb443e79abf9df38..c2c3ed6ba79f9f41497e042571f699a0fc6e9335 100644 --- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java @@ -5478,150 +3402,6 @@ index ff40fe323964f173561a6838fb443e79abf9df38..c2c3ed6ba79f9f41497e042571f699a0 return flag; } -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java -index 2a335f277bd0e4b8ad0f60d8226eb8aaa80a871f..228b11a21735885055d2fb5e0568e21aed32a6cb 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java -@@ -30,6 +30,17 @@ public class Path { - this.reached = reachesTarget; - } - -+ // Pufferfish start -+ /** -+ * checks if the path is completely processed in the case of it being computed async -+ * -+ * @return true if the path is processed -+ */ -+ public boolean isProcessed() { -+ return true; -+ } -+ // Pufferfish end -+ - public void advance() { - ++this.nextNodeIndex; - } -@@ -104,6 +115,8 @@ public class Path { - } - - public boolean sameAs(@Nullable Path o) { -+ if (o == this) return true; // Pufferfish - short circuit -+ - if (o == null) { - return false; - } else if (o.nodes.size() != this.nodes.size()) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index d23481453717f715124156b5d83f6448f720d049..0455c8a7da880da4f0b7ae9d57e83e281a55f0ae 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -25,36 +25,75 @@ public class PathFinder { - private static final boolean DEBUG = false; - private final BinaryHeap openSet = new BinaryHeap(); - -- public PathFinder(NodeEvaluator pathNodeMaker, int range) { -+ private final @Nullable gg.pufferfish.pufferfish.path.NodeEvaluatorGenerator nodeEvaluatorGenerator; // Pufferfish - we use this later to generate an evaluator -+ -+ // Pufferfish start - add nodeEvaluatorGenerator as optional param -+ public PathFinder(NodeEvaluator pathNodeMaker, int range, @Nullable gg.pufferfish.pufferfish.path.NodeEvaluatorGenerator nodeEvaluatorGenerator) { - this.nodeEvaluator = pathNodeMaker; - this.maxVisitedNodes = range; -+ this.nodeEvaluatorGenerator = nodeEvaluatorGenerator; -+ } -+ -+ public PathFinder(NodeEvaluator pathNodeMaker, int range) { -+ this(pathNodeMaker, range, null); - } -+ // Pufferfish end - - @Nullable - public Path findPath(PathNavigationRegion world, Mob mob, Set positions, float followRange, int distance, float rangeMultiplier) { -- this.openSet.clear(); -- this.nodeEvaluator.prepare(world, mob); -- Node node = this.nodeEvaluator.getStart(); -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) this.openSet.clear(); // Pufferfish - it's always cleared in processPath -+ // Pufferfish start - use a generated evaluator if we have one otherwise run sync -+ var nodeEvaluator = this.nodeEvaluatorGenerator == null ? this.nodeEvaluator : gg.pufferfish.pufferfish.path.NodeEvaluatorCache.takeNodeEvaluator(this.nodeEvaluatorGenerator); -+ nodeEvaluator.prepare(world, mob); -+ Node node = nodeEvaluator.getStart(); - if (node == null) { -+ gg.pufferfish.pufferfish.path.NodeEvaluatorCache.removeNodeEvaluator(nodeEvaluator); - return null; - } else { - // Paper start - remove streams - and optimize collection - List> map = Lists.newArrayList(); - for (BlockPos pos : positions) { -- map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos)); -+ map.add(new java.util.AbstractMap.SimpleEntry<>(nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos)); - } - // Paper end -- Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier); -- this.nodeEvaluator.done(); -- return path; -+ -+ // Pufferfish start -+ if (this.nodeEvaluatorGenerator == null) { -+ // run sync :( -+ gg.pufferfish.pufferfish.path.NodeEvaluatorCache.removeNodeEvaluator(nodeEvaluator); -+ return this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier); -+ } -+ -+ return new gg.pufferfish.pufferfish.path.AsyncPath(Lists.newArrayList(), positions, () -> { -+ try { -+ return this.processPath(nodeEvaluator, node, map, followRange, distance, rangeMultiplier); -+ } finally { -+ nodeEvaluator.done(); -+ gg.pufferfish.pufferfish.path.NodeEvaluatorCache.returnNodeEvaluator(nodeEvaluator); -+ } -+ }); -+ // Pufferfish end - } - } - -- @Nullable -+ // Pufferfish start - split pathfinding into the original sync method for compat and processing for delaying - // Paper start - optimize collection - private Path findPath(ProfilerFiller profiler, Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { -+ // readd the profiler code for sync - profiler.push("find_path"); - profiler.markForCharting(MetricCategory.PATH_FINDING); -+ -+ try { -+ return this.processPath(this.nodeEvaluator, startNode, positions, followRange, distance, rangeMultiplier); -+ } finally { -+ this.nodeEvaluator.done(); -+ } -+ } -+ // Pufferfish end -+ -+ private synchronized @org.jetbrains.annotations.NotNull Path processPath(NodeEvaluator nodeEvaluator, Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { // Pufferfish - sync to only use the caching functions in this class on a single thread -+ org.apache.commons.lang3.Validate.isTrue(!positions.isEmpty()); // ensure that we have at least one position, which means we'll always return a path -+ - // Set set = positions.keySet(); - startNode.g = 0.0F; - startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection -@@ -91,7 +130,7 @@ public class PathFinder { - } - - if (!(node.distanceTo(startNode) >= followRange)) { -- int k = this.nodeEvaluator.getNeighbors(this.neighbors, node); -+ int k = nodeEvaluator.getNeighbors(this.neighbors, node); - - for(int l = 0; l < k; ++l) { - Node node2 = this.neighbors[l]; -@@ -123,9 +162,14 @@ public class PathFinder { - if (best == null || comparator.compare(path, best) < 0) - best = path; - } -+ -+ // Pufferfish start - ignore this warning, we know that the above loop always runs at least once since positions is not empty -+ //noinspection ConstantConditions - return best; - // Paper end -+ // Pufferfish end - } -+ // Pufferfish end - - protected float distance(Node a, Node b) { - return a.distanceTo(b); diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootContext.java b/src/main/java/net/minecraft/world/level/storage/loot/LootContext.java index 35f9b11a3a61976c952a2c1c64bb2a932538f54f..9e9ac64764cf0a84e25e75d8d6f516cde6047284 100644 --- a/src/main/java/net/minecraft/world/level/storage/loot/LootContext.java @@ -5726,7 +3506,7 @@ index b1992ed5136cc7dcf04219868b94b3c37ae36b4b..5b5339cba819368f4d6b7eaf404fa59b @Nullable diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 29a69edc642820b30a842cc580f48c49dfe96eec..ff520a7fa8235a46d861df60569077be258d7cb1 100644 +index 111f8276f26350a5c62a7b8577b4598978b5355d..b8efe50c860a7537f345f46f3b3d68906ad54006 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -248,7 +248,7 @@ import javax.annotation.Nullable; // Paper @@ -5762,43 +3542,6 @@ index 0b3b46348ac9195bff1492ffc11fcbff7d3f5c6f..4010052c53f3a2831b4d5aa1c041d858 + MinecraftServer.getServer().getRecipeManager().addRecipe(new net.minecraft.world.item.crafting.ShapelessRecipe(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftItemStack.asNMSCopy(this.getResult()), data, true)); } } -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -index 909b2c98e7a9117d2f737245e4661792ffafb744..0d9e2b3728f9ab500bd5e44702718535d338e9a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -@@ -22,7 +22,8 @@ public class MinecraftInternalPlugin extends PluginBase { - private boolean enabled = true; - - private final String pluginName; -- private PluginDescriptionFile pdf; -+ private org.bukkit.plugin.PluginLogger logger; -+ private PluginDescriptionFile pdf; // Pufferfish - - public MinecraftInternalPlugin() { - this.pluginName = "Minecraft"; -@@ -75,7 +76,12 @@ public class MinecraftInternalPlugin extends PluginBase { - - @Override - public PluginLogger getLogger() { -- throw new UnsupportedOperationException("Not supported."); -+ // Pufferfish start -+ if (this.logger == null) { -+ this.logger = new org.bukkit.plugin.PluginLogger(this); // Pufferfish -+ } -+ return this.logger; -+ // Pufferfish end - } - - @Override -@@ -85,7 +91,7 @@ public class MinecraftInternalPlugin extends PluginBase { - - @Override - public Server getServer() { -- throw new UnsupportedOperationException("Not supported."); -+ return org.bukkit.Bukkit.getServer(); // Pufferfish - impl - } - - @Override diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index 1628913b1e9b91e68dcd942a38da4aed95b12d4a..05cc8f9cdcd7e920bf9503f68efb16cd74a359a2 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -5812,18 +3555,6 @@ index 1628913b1e9b91e68dcd942a38da4aed95b12d4a..05cc8f9cdcd7e920bf9503f68efb16cd } @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index e948ec5a573b22645664eb53bc3e9932246544e4..e3845dc3357bbb74885ae3a1a08525adde581235 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -11,6 +11,7 @@ public class ServerShutdownThread extends Thread { - - @Override - public void run() { -+ try { gg.pufferfish.pufferfish.flare.ProfilingManager.stop(); } catch (Throwable t) {} // Pufferfish - shut down Flare if it's running - try { - // Paper start - try to shutdown on main - server.safeShutdown(false, false); diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java index 774556a62eb240da42e84db4502e2ed43495be17..80553face9c70c2a3d897681e7761df85b22d464 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java diff --git a/patches/server/0002-Fix-pufferfish-issues.patch b/patches/server/0002-Fix-pufferfish-issues.patch index 7b4f20a6a..3a9c61924 100644 --- a/patches/server/0002-Fix-pufferfish-issues.patch +++ b/patches/server/0002-Fix-pufferfish-issues.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix pufferfish issues diff --git a/build.gradle.kts b/build.gradle.kts -index 7074295d7399d03e259598bb4bfa0f21434d74be..26f8979c1a150159823be1693cf2aa5366401015 100644 +index 0485d126f799789b5d5abcaf96da96df25a12dfd..692789a473665c1fc7be56b8913cd208ae27d2e5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,8 +49,8 @@ dependencies { @@ -20,10 +20,10 @@ index 7074295d7399d03e259598bb4bfa0f21434d74be..26f8979c1a150159823be1693cf2aa53 } // Pufferfish end diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8ed9f14f1ca71111a8215b28821bd5e398c0d0a6..42c88ef31474690c95f7cfe7c3075e1f854c4005 100644 +index f8750675044708e71dbf6293be6ce36bd6c510ca..b69799d0ae0ce8b176b910da886e71c4d25c94aa 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -775,7 +775,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -805,7 +805,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } // Paper start - optimise random block ticking private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); @@ -33,7 +33,7 @@ index 8ed9f14f1ca71111a8215b28821bd5e398c0d0a6..42c88ef31474690c95f7cfe7c3075e1f private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Pufferfish diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 388a153113d87ba99515828c6d535110b4413c7c..29a2ba6b84c01280f8c7f32e6a78e3dd6c53cb07 100644 +index 0277633fd328ef9993fea4ac29df83b5b00c0f42..35d6a8fe168caa5b68b471bd78cc95b99758d1b0 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -271,7 +271,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -46,10 +46,10 @@ index 388a153113d87ba99515828c6d535110b4413c7c..29a2ba6b84c01280f8c7f32e6a78e3dd // Pufferfish start - ensure these get inlined private final int minBuildHeight, minSection, height, maxBuildHeight, maxSection; diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 0b08a91ae9dc73c011dbb5f517becac7d08fd1e9..6fbf26eb7da8df2f0a4158ff9f12022518ada8e3 100644 +index 34334c139176e0aa9f6d93a87821508d17567cfc..df2786516fe641edff7bbe9fe0665bf07502d830 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -136,7 +136,7 @@ public class LevelChunk extends ChunkAccess { +@@ -130,7 +130,7 @@ public class LevelChunk extends ChunkAccess { this.fluidTicks = fluidTickScheduler; // CraftBukkit start this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); diff --git a/patches/server/0003-Rebrand.patch b/patches/server/0003-Rebrand.patch index afa39770c..068b1f37e 100644 --- a/patches/server/0003-Rebrand.patch +++ b/patches/server/0003-Rebrand.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Rebrand diff --git a/build.gradle.kts b/build.gradle.kts -index 26f8979c1a150159823be1693cf2aa5366401015..441a18132eb60e1af8b624ab7cf3de61669ced1f 100644 +index 692789a473665c1fc7be56b8913cd208ae27d2e5..4e4bc7e55a81dc44d7f6cfc6a8761141d0d3bb6c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ plugins { @@ -27,7 +27,7 @@ index 26f8979c1a150159823be1693cf2aa5366401015..441a18132eb60e1af8b624ab7cf3de61 runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.5") runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3") runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3") -@@ -84,7 +87,7 @@ tasks.jar { +@@ -83,7 +86,7 @@ tasks.jar { attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "CraftBukkit", @@ -36,7 +36,7 @@ index 26f8979c1a150159823be1693cf2aa5366401015..441a18132eb60e1af8b624ab7cf3de61 "Implementation-Vendor" to date, // Paper "Specification-Title" to "Bukkit", "Specification-Version" to project.version, -@@ -183,7 +186,7 @@ fun TaskContainer.registerRunTask( +@@ -182,7 +185,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { @@ -168,7 +168,7 @@ index abe37c7c3c6f5ab73afd738ec78f06d7e4d2ed96..b5b6657e52e4f7a630229bd3ba433438 stringbuilder.append(CrashReport.getErrorComment()); stringbuilder.append("\n\n"); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 67e150e35d328eb13c8f86e61dab2f11c76b21df..cb907fe3988705e5dd961a9b9b2cbc9321e59d69 100644 +index af9da39dffda01325af2ab3dd8b5e1efb18e013a..957587f5c3f9c26794c80146b4deb282af3469e8 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -298,7 +298,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop true); // Pufferfish - optimize mob spawning public static S spin(Function serverFactory) { -@@ -913,7 +913,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index cc55cb14f2d0f656213be25a1e428132871ac5dd..184c5540e519edd0430ae586bfae93d3ff798de2 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -43,7 +43,7 @@ index cc55cb14f2d0f656213be25a1e428132871ac5dd..184c5540e519edd0430ae586bfae93d3 try { byte[] data = new byte[packet.data.readableBytes()]; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 099987645142a5a065b5bd377a16d9d6c59dabd9..3a4f2453831eda258ab5f7907204ee5d2bdac4c7 100644 +index a508619e6855ee0b96a9bf61526b1b88abf0e732..ea2c76116d8328d2ba6e5e7cc2ed1464f43a8c82 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -2937,4 +2937,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0007-Component-related-conveniences.patch b/patches/server/0007-Component-related-conveniences.patch index e3fbf71df..219ab7925 100644 --- a/patches/server/0007-Component-related-conveniences.patch +++ b/patches/server/0007-Component-related-conveniences.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Component related conveniences diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 3300a10b2558651c68fac18939815eb45889152b..a16f72e34af8cfef50622dba18750926ace1008e 100644 +index 63aef471ceba18c2b296f4e287837c6df44809d7..5f854b9d25d5965268a089a992ee9bacf7b3aa0f 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1705,6 +1705,26 @@ public class ServerPlayer extends Player { +@@ -1690,6 +1690,26 @@ public class ServerPlayer extends Player { this.lastSentExp = -1; // CraftBukkit - Added to reset } @@ -36,7 +36,7 @@ index 3300a10b2558651c68fac18939815eb45889152b..a16f72e34af8cfef50622dba18750926 public void displayClientMessage(Component message, boolean overlay) { this.sendSystemMessage(message, overlay); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5999d85e38951503fc83b40cfe39671921ae5088..263e61b655d0ec58b63da859df46f0962de45ec7 100644 +index 06eda955f96b5fe2d08ed0d39229c7a6ebb88931..16154d89a1c67ebc9dc6ecaeb214799e75d16b6f 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -1074,6 +1074,20 @@ public abstract class PlayerList { @@ -81,10 +81,10 @@ index 67bce77093dcc126098731047447da2031e3388d..c4088446d30c3b25cf196f51fd394cd0 return this.isFireSource; } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4971ec79a114fd0d7540eaa0ef54b18c4bfbea57..4a069182f6cc3b40f6b5eabb85f70365bd9bfdcc 100644 +index fc4bd8ad4836aa6bdd228885f0aeb22500782af5..d9348a2f58eea3bd1d70851bedf29fd96430e1ff 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3797,6 +3797,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -3798,6 +3798,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return SlotAccess.NULL; } diff --git a/patches/server/0008-Ridables.patch b/patches/server/0008-Ridables.patch index ce1cd07f3..d3c9293cb 100644 --- a/patches/server/0008-Ridables.patch +++ b/patches/server/0008-Ridables.patch @@ -22,10 +22,10 @@ index 153451ecd5b3c8e8ecb2d5ec91ccd582d4300899..56536c39bccfe097f8227c74a0d16799 super(x, y, z); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index cb907fe3988705e5dd961a9b9b2cbc9321e59d69..6845b05225cd679d7b40695455f4ea651507787e 100644 +index 957587f5c3f9c26794c80146b4deb282af3469e8..7f0551e70c545f8e77d18b11e836233faeba9161 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1537,6 +1537,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper @@ -34,7 +34,7 @@ index cb907fe3988705e5dd961a9b9b2cbc9321e59d69..6845b05225cd679d7b40695455f4ea65 this.profiler.push(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 42c88ef31474690c95f7cfe7c3075e1f854c4005..738ffcc9f8ec1b34e7e1357ae48283e3245d906f 100644 +index b69799d0ae0ce8b176b910da886e71c4d25c94aa..eab96c9b53cd608ff99cdad06721cd19e490ad14 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -220,6 +220,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -46,10 +46,10 @@ index 42c88ef31474690c95f7cfe7c3075e1f854c4005..738ffcc9f8ec1b34e7e1357ae48283e3 return new Throwable(entity + " Added to world at " + new java.util.Date()); } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a16f72e34af8cfef50622dba18750926ace1008e..f9c77e5280950af9b6d650041b14c501657b8669 100644 +index 5f854b9d25d5965268a089a992ee9bacf7b3aa0f..e0a7a932ebfdec18b28ce5b697400951ea54c0a9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -670,6 +670,15 @@ public class ServerPlayer extends Player { +@@ -655,6 +655,15 @@ public class ServerPlayer extends Player { this.trackStartFallingPosition(); this.trackEnteredOrExitedLavaOnVehicle(); this.advancements.flushDirty(this); @@ -79,7 +79,7 @@ index 184c5540e519edd0430ae586bfae93d3ff798de2..b5e3f57a1a8875c33c3a01a525efc692 if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) { ServerGamePacketListenerImpl.this.send(new ClientboundAddEntityPacket(entity)); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4a069182f6cc3b40f6b5eabb85f70365bd9bfdcc..8dd2710b7db50d74c53ded1fbf23dccf32e41357 100644 +index d9348a2f58eea3bd1d70851bedf29fd96430e1ff..726c4a9dac41a887537b91ade7cb7b2a722a1e63 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -362,7 +362,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { @@ -91,7 +91,7 @@ index 4a069182f6cc3b40f6b5eabb85f70365bd9bfdcc..8dd2710b7db50d74c53ded1fbf23dccf private float eyeHeight; public boolean isInPowderSnow; public boolean wasInPowderSnow; -@@ -2781,6 +2781,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -2782,6 +2782,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { this.passengers = ImmutableList.copyOf(list); } @@ -104,7 +104,7 @@ index 4a069182f6cc3b40f6b5eabb85f70365bd9bfdcc..8dd2710b7db50d74c53ded1fbf23dccf } return true; // CraftBukkit } -@@ -2821,6 +2827,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -2822,6 +2828,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return false; } // Spigot end @@ -119,7 +119,7 @@ index 4a069182f6cc3b40f6b5eabb85f70365bd9bfdcc..8dd2710b7db50d74c53ded1fbf23dccf if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { this.passengers = ImmutableList.of(); } else { -@@ -4544,4 +4558,45 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -4568,4 +4582,45 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return ((ServerChunkCache) level.getChunkSource()).isPositionTicking(this); } // Paper end @@ -702,7 +702,7 @@ index 1f85f34c1e50f34fb270d2fac7d307c82a550bfa..324f52edd95b5f9a498e46def8c14435 double d = this.wantedX - this.fish.getX(); double e = this.wantedY - this.fish.getY(); diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index dbeb70913d3933164e997ce5d662b4890ffe4f36..cf7036e014097183c697b06ea5865a361221bd6a 100644 +index a9cdf9034ad269f7a71358443acc053288cfbe6d..69a214c3a9f49d5b30b56f880263e736548a064f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -43,6 +43,7 @@ import net.minecraft.world.entity.EntityType; @@ -2320,7 +2320,7 @@ index 1c93872f9fcc6f6a19dee8565726501d0e580d44..3b576e8944bcef78f5769ccd90591f2d } diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -index 4c3fd27bff777139e29905e8684f6e92a44decfe..5c670b368407010524dcee1064fac2748d84cec2 100644 +index 74cb2741a5cd66bdac3a22de938ae82968705a56..6a6613f70f9c4cc950882191b00048d4c47bd84f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java @@ -83,16 +83,65 @@ public class Frog extends Animal { @@ -2770,7 +2770,7 @@ index 305a891e4b51d1031d9e9238ff00e2ea7de8d954..84625d09df800fcfd477fc493fb5f824 protected void defineSynchedData() { } diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 47d6236daca806878399890a8d08e55233f19fd9..0876034f2735af2b143112162b38a5bfd71139bb 100644 +index ac3d4d90407288526a8c787e365ff41234a58543..f892b25c45c7b84fa37f4ddfe2c1068cfa1be483 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java @@ -103,6 +103,7 @@ public class EnderDragon extends Mob implements Enemy { @@ -2801,7 +2801,7 @@ index 47d6236daca806878399890a8d08e55233f19fd9..0876034f2735af2b143112162b38a5bf + + @Override + public void purpurTick(Player rider) { -+ setYawPitch(rider.yRot - 180F, rider.xRotO * 0.5F); ++ setYawPitch(rider.getYRot() - 180F, rider.xRotO * 0.5F); + } + }; + // Purpur end @@ -2919,7 +2919,7 @@ index 47d6236daca806878399890a8d08e55233f19fd9..0876034f2735af2b143112162b38a5bf this.dragonFight.updateDragon(this); } diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 4fb40aa91e0961f1974c74c88fa68359e4ad6b16..7a0653ae3bf1f9c99e3363fb27a9af30cbc2f27a 100644 +index a6d30f3213d30ba925926437ed4535319061213d..11f6465cbf26f4a632f597f2158c6c91d5056c41 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java @@ -84,16 +84,30 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @@ -3091,7 +3091,7 @@ index 4fb40aa91e0961f1974c74c88fa68359e4ad6b16..7a0653ae3bf1f9c99e3363fb27a9af30 int i; if (this.getInvulnerableTicks() > 0) { -@@ -583,11 +713,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -582,11 +712,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob } public int getAlternativeTarget(int headIndex) { @@ -3348,7 +3348,7 @@ index e0f71dc12cfc28710cacfbc372026f556dcab165..17cc847fd6e5a128c9ae7427dc0aef51 } // Paper end diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index 30a67a1eef9238e12e54c57a0608387cc0f763ef..af1a6cd77e70141be8b6507e1494babaeab3828c 100644 +index 1b1305f5eaf5710b72c57ab4c3953e703a23f1e0..869a2ee5e0775cc477fb56063dfa4ce4a0c6e3f2 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java @@ -68,6 +68,23 @@ public class Drowned extends Zombie implements RangedAttackMob { @@ -3904,7 +3904,7 @@ index ea4fa9eba301e462c159cdb970079f6d87d25f4d..3a2261687ec8b3b1f69b89ceeb2cc8cc @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index cb81c5d37c72845133c4e59acaf8de56dcc9e62a..a8565816836e5ab55086a6024dc47df277cd7277 100644 +index cb81c5d37c72845133c4e59acaf8de56dcc9e62a..308debc811b8eb61c8d9d5aeba3e118b9802e401 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java @@ -60,6 +60,64 @@ public class Phantom extends FlyingMob implements Enemy { @@ -4035,7 +4035,7 @@ index cb81c5d37c72845133c4e59acaf8de56dcc9e62a..a8565816836e5ab55086a6024dc47df2 + // Purpur start + public void purpurTick(Player rider) { -+ setYawPitch(rider.yRot, -rider.xRotO * 0.75F); ++ setYawPitch(rider.getYRot(), -rider.xRotO * 0.75F); + } + // Purpur end + diff --git a/patches/server/0009-Configurable-entity-base-attributes.patch b/patches/server/0009-Configurable-entity-base-attributes.patch index 85448604a..e973d368a 100644 --- a/patches/server/0009-Configurable-entity-base-attributes.patch +++ b/patches/server/0009-Configurable-entity-base-attributes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Configurable entity base attributes diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 3545d6ede83ebf000e05f873c62deed27403845e..55c5ec3a4ad21e2a10bd99a1560ee29f9ad9bd39 100644 +index 726c4a9dac41a887537b91ade7cb7b2a722a1e63..4227272cc2bac2b603e4d477031d4c71641c5748 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -156,7 +156,7 @@ import org.bukkit.plugin.PluginManager; @@ -34,7 +34,7 @@ index 882ab40c8cdea8c214cb8344b3ccecddb2967c1c..cb79d2c958fbd34f8c8818e7e1c0db88 @Override diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 69de163971a9877d8b020184c296f7f98ee877ed..6f6386230dcd061760a8386691063601f9a7f1d5 100644 +index 4eb4c99a0284b3bc324f37cf55c09ef0006b1136..dbf1ef9297efd628f8479c63217919d179418295 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -288,6 +288,7 @@ public abstract class LivingEntity extends Entity { @@ -78,7 +78,7 @@ index 2edc11b093dbfc96d287dc9d3e208cc2a39c537e..007c945725721ddb8a3dc4b8085e8c68 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index cf7036e014097183c697b06ea5865a361221bd6a..feab2c5553e62016f2e82977257ecf2a22fd713d 100644 +index 69a214c3a9f49d5b30b56f880263e736548a064f..33f2100a9cb7616339c18d9b41293eab8c0e4a65 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -214,6 +214,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @@ -94,7 +94,7 @@ index cf7036e014097183c697b06ea5865a361221bd6a..feab2c5553e62016f2e82977257ecf2a @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index cc73dffbeb8a118de2b913c6f9d40c61f94dabbd..90ef6c8d5371b62d043320d493d624ae18737f07 100644 +index e163851c02e38c294d95dbabafd4903b8846b551..413205e8214b87f022dda5eeb1eeca3794dcd6ce 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java @@ -118,6 +118,11 @@ public class Cat extends TamableAnimal { @@ -459,7 +459,7 @@ index 248531727dcafb71d7d2d2767205e09a8c0f1876..01c8508571a88c22359cbf36341338c5 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java -index 32b31e5efb5fc68430b9bcd4cd972494f53accc8..a80a7d460051a39fe805ae669b4586fb42e46943 100644 +index 3b576e8944bcef78f5769ccd90591f2db4dfd697..ad6a87ba97138253db2b300dec8a89faff38f075 100644 --- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java +++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java @@ -117,6 +117,11 @@ public class Axolotl extends Animal implements LerpingModel, Bucketable { @@ -589,7 +589,7 @@ index f711ea32db68fb7aece5081e741c4e161123467f..390f630462c907cd6e961c6ca432804e @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index b6a5ac35bed88e9d55b4de0551a13ea58901315e..fd5802bf7554590a19b3d5fc50c9ced02232f294 100644 +index 84faefeb6504a079ca907afcba7ff90873c68f8c..7c1120b51d196179f92ce0d3fc5d2bf48e2a1514 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java @@ -115,6 +115,21 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { @@ -719,7 +719,7 @@ index 0f8ce0c6ddbb37a61c6b15bb769b627bcd8105fa..6ed9e4e98c46b51cf398641ffb66abf3 public static AttributeSupplier.Builder createAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 0876034f2735af2b143112162b38a5bfd71139bb..7dcc1fd63294afa95b2f7115a72961ce175f01f2 100644 +index f892b25c45c7b84fa37f4ddfe2c1068cfa1be483..1e3afa3d98e755b7a06dc6b90f90e2d41843a482 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java @@ -160,6 +160,11 @@ public class EnderDragon extends Mob implements Enemy { @@ -735,7 +735,7 @@ index 0876034f2735af2b143112162b38a5bfd71139bb..7dcc1fd63294afa95b2f7115a72961ce public static AttributeSupplier.Builder createAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 7a0653ae3bf1f9c99e3363fb27a9af30cbc2f27a..606fa521d577f832cd7a82c1c6c67414e1a01589 100644 +index 11f6465cbf26f4a632f597f2158c6c91d5056c41..cdaefabf24c59338a0406072ce01029c194700fd 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java @@ -224,6 +224,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @@ -750,7 +750,7 @@ index 7a0653ae3bf1f9c99e3363fb27a9af30cbc2f27a..606fa521d577f832cd7a82c1c6c67414 // Purpur end @Override -@@ -428,7 +433,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -427,7 +432,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob this.setInvulnerableTicks(i); if (this.tickCount % 10 == 0) { @@ -808,7 +808,7 @@ index 17cc847fd6e5a128c9ae7427dc0aef51918bc30a..bb9fc7f78514b434aba2de25f79fb340 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index af1a6cd77e70141be8b6507e1494babaeab3828c..9e7ea6be928fb536c9898a85bb0a9ad40af25bd5 100644 +index 869a2ee5e0775cc477fb56063dfa4ce4a0c6e3f2..4b58ca48deda0410edf9ad3c9079858d5a31a762 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java @@ -83,6 +83,16 @@ public class Drowned extends Zombie implements RangedAttackMob { @@ -1013,7 +1013,7 @@ index 3a2261687ec8b3b1f69b89ceeb2cc8cc524ab57a..69375fdb63b9edde3d161bac7a1946a3 public static AttributeSupplier.Builder createAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index a8565816836e5ab55086a6024dc47df277cd7277..a3b871797c3e006f66978a73da01fede52fc8c49 100644 +index 308debc811b8eb61c8d9d5aeba3e118b9802e401..022f40b66864940652099e91fad18e02aee8c5b2 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java @@ -116,6 +116,21 @@ public class Phantom extends FlyingMob implements Enemy { diff --git a/patches/server/0012-AFK-API.patch b/patches/server/0012-AFK-API.patch index 6b4abe4ad..dc8779d09 100644 --- a/patches/server/0012-AFK-API.patch +++ b/patches/server/0012-AFK-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] AFK API diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f9c77e5280950af9b6d650041b14c501657b8669..4c1c5b43b5080ff860ee511d00dc9fdd6cab8b7b 100644 +index e0a7a932ebfdec18b28ce5b697400951ea54c0a9..492a7f7d2d0a06c10f11c7cd61edba26e40d9f42 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2002,8 +2002,58 @@ public class ServerPlayer extends Player { +@@ -1987,8 +1987,58 @@ public class ServerPlayer extends Player { public void resetLastActionTime() { this.lastActionTime = Util.getMillis(); @@ -213,10 +213,10 @@ index 3f458ddd4dc04ed28510a212be76bb19e7f6a61e..a36469186f72eccf8c4428d920d0583b if (range < 0.0D || d < range * range) { return true; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3a4f2453831eda258ab5f7907204ee5d2bdac4c7..4225dd4e7a03fbddec6589eb8e8d4cec9deac305 100644 +index ea2c76116d8328d2ba6e5e7cc2ed1464f43a8c82..c272fc856113ca2399832b4af7f1e94af9ebb3e2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -447,10 +447,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -522,10 +522,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setPlayerListName(String name) { diff --git a/patches/server/0014-Configurable-server-mod-name.patch b/patches/server/0014-Configurable-server-mod-name.patch index 9f7d29a2e..c75d70b22 100644 --- a/patches/server/0014-Configurable-server-mod-name.patch +++ b/patches/server/0014-Configurable-server-mod-name.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable server mod name diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6845b05225cd679d7b40695455f4ea651507787e..081c35af457bd7a0a2bca8bf6428e26b0e4c2207 100644 +index 7f0551e70c545f8e77d18b11e836233faeba9161..ffa6466c21ddc6a312a0a3aa400717a481400237 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1677,7 +1677,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper @@ -339,6 +340,7 @@ public class ServerPlayer extends Player { this.bukkitPickUpLoot = true; this.maxHealthCache = this.getMaxHealth(); this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + this.spawnInvulnerableTime = world.purpurConfig.playerSpawnInvulnerableTicks; // Purpur } - // Paper start - Chunk priority - public BlockPos getPointInFront(double inFront) { -@@ -1018,6 +1020,12 @@ public class ServerPlayer extends Player { + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. +@@ -1003,6 +1005,12 @@ public class ServerPlayer extends Player { } @@ -37,7 +37,7 @@ index 4c1c5b43b5080ff860ee511d00dc9fdd6cab8b7b..d504c6efe13681f4d62862074d49d7c2 @Override public boolean hurt(DamageSource source, float amount) { if (this.isInvulnerableTo(source)) { -@@ -1025,7 +1033,7 @@ public class ServerPlayer extends Player { +@@ -1010,7 +1018,7 @@ public class ServerPlayer extends Player { } else { boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && "fall".equals(source.msgId); @@ -46,7 +46,7 @@ index 4c1c5b43b5080ff860ee511d00dc9fdd6cab8b7b..d504c6efe13681f4d62862074d49d7c2 return false; } else { if (source instanceof EntityDamageSource) { -@@ -1199,6 +1207,7 @@ public class ServerPlayer extends Player { +@@ -1184,6 +1192,7 @@ public class ServerPlayer extends Player { } // Paper end @@ -54,7 +54,7 @@ index 4c1c5b43b5080ff860ee511d00dc9fdd6cab8b7b..d504c6efe13681f4d62862074d49d7c2 return this; } } -@@ -1988,6 +1997,7 @@ public class ServerPlayer extends Player { +@@ -1973,6 +1982,7 @@ public class ServerPlayer extends Player { } public void sendTexturePack(String url, String hash, boolean required, @Nullable Component resourcePackPrompt) { @@ -62,7 +62,7 @@ index 4c1c5b43b5080ff860ee511d00dc9fdd6cab8b7b..d504c6efe13681f4d62862074d49d7c2 this.connection.send(new ClientboundResourcePackPacket(url, hash, required, resourcePackPrompt)); } -@@ -2513,9 +2523,17 @@ public class ServerPlayer extends Player { +@@ -2498,9 +2508,17 @@ public class ServerPlayer extends Player { @Override public boolean isImmobile() { @@ -108,7 +108,7 @@ index 0f0a862e3f0702a9e61bcb6b80b0375c01f46da8..3a2b67b459692a30feaec8362e44be55 this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), packStatus)); // CraftBukkit // Paper end diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0c05466b1265a22009781d469f8d324e3d42e0d3..dae6334ad480bc6323fa47421a22598e58e56684 100644 +index 2da8186b5f34b5cce97512f50323bee091d380ab..e09cfac18f2b952bb54ec75b0450502433370819 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -1014,6 +1014,8 @@ public abstract class PlayerList { @@ -121,7 +121,7 @@ index 0c05466b1265a22009781d469f8d324e3d42e0d3..dae6334ad480bc6323fa47421a22598e return entityplayer1; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 4225dd4e7a03fbddec6589eb8e8d4cec9deac305..7f123c203bc53582d71862c4630d63ba06779a8d 100644 +index c272fc856113ca2399832b4af7f1e94af9ebb3e2..dee07e6f1d85f37f4dbb9cd0956d48f91bd39ca2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -2963,5 +2963,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0029-Zombie-horse-naturally-spawn.patch b/patches/server/0029-Zombie-horse-naturally-spawn.patch index 4cdf49760..77852f542 100644 --- a/patches/server/0029-Zombie-horse-naturally-spawn.patch +++ b/patches/server/0029-Zombie-horse-naturally-spawn.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Zombie horse naturally spawn diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 738ffcc9f8ec1b34e7e1357ae48283e3245d906f..7cc90afe9fe9d2ce95905c19f3bcf026a04c614c 100644 +index eab96c9b53cd608ff99cdad06721cd19e490ad14..6e6559b7edbabc000ac47617ab064e438a95720d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -798,9 +798,15 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -828,9 +828,15 @@ public class ServerLevel extends Level implements WorldGenLevel { boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01D) && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper if (flag1) { @@ -28,7 +28,7 @@ index 738ffcc9f8ec1b34e7e1357ae48283e3245d906f..7cc90afe9fe9d2ce95905c19f3bcf026 entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 2cf4bab37d7789f9d22ae1d9edbdabbe8fa79ab5..408f80e6046a45ff3f7526f603e5c68d222057d4 100644 +index 3e86f0fa382a80250c9b9a0e97eb6544b597760d..3657c311c2be4c8f9f6c8816c885bce7ed621f0f 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -1457,6 +1457,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0046-Minecart-settings-and-WASD-controls.patch b/patches/server/0046-Minecart-settings-and-WASD-controls.patch index 2b1a94c30..c499338bb 100644 --- a/patches/server/0046-Minecart-settings-and-WASD-controls.patch +++ b/patches/server/0046-Minecart-settings-and-WASD-controls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Minecart settings and WASD controls diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 481e474f48d9409f4d8a337b334a17627c9b8ccb..de96a37827fd31f3189e18298e2f9e1370761a30 100644 +index 2044a297f1820b41c41df9a8b3b0bbff9ae08432..ff3561fa225420bfa92fd081a2f54216845be860 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1031,6 +1031,7 @@ public class ServerPlayer extends Player { +@@ -1016,6 +1016,7 @@ public class ServerPlayer extends Player { if (this.isInvulnerableTo(source)) { return false; } else { @@ -136,7 +136,7 @@ index 127a799f7848b32664b77bf67847ca6b8ac9a90d..178cd88a7de291136e0486617e8347b7 } } diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index fd74cc9c0dab84b176f7da3fbbbdbc8fd3a7e26d..fdda70f216b3805cc6d8105c3d85814a2ae6b6ad 100644 +index b86c17b5572f8f74bfefd0f3c6f9d25187574392..304f0f372d669e3da2e8131c50f2f1246185a56b 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java @@ -73,7 +73,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @@ -149,7 +149,7 @@ index fd74cc9c0dab84b176f7da3fbbbdbc8fd3a7e26d..fdda70f216b3805cc6d8105c3d85814a protected final float explosionResistance; protected final boolean isRandomlyTicking; diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 805434c62063cfa9b26d92431fa62b10504ad0f8..8e6bc5815e9624c6eb24e66cdba6d95989de4aae 100644 +index b069f9a5da47d5117a220335035952eea142d6c4..0b7a5fa45591ae79f95af3390373250b6e6b83db 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -97,6 +97,68 @@ public class PurpurWorldConfig { diff --git a/patches/server/0052-Configurable-TPS-Catchup.patch b/patches/server/0052-Configurable-TPS-Catchup.patch index 357fe1b47..f4783f47e 100644 --- a/patches/server/0052-Configurable-TPS-Catchup.patch +++ b/patches/server/0052-Configurable-TPS-Catchup.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable TPS Catchup diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 610f3ba3a983144b8b7f56e39d1c60bde6f35491..9ff46c460f09bf3e62f958a4a87632d59a310e24 100644 +index c1719af753e4efa8fcbd49a801ee86b307d27779..963a1998f808061c7e7fcd0d15725e38fe606ce7 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1197,7 +1197,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= this.level.paperConfig().environment.netherCeilingVoidDamageHeight)) { // Paper end diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index fe6483d505f9148f82f80abc1438945ed0741ba3..cf67b497d1a0e56fa949802804d6d2cf855d52ff 100644 +index 0f2260e3c5bad76f691bdfa144f9a340a3e34a5e..f6e6ef12f76d8c0e3c62daa4b831fb214ed3b09e 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -2488,7 +2488,7 @@ public abstract class LivingEntity extends Entity { diff --git a/patches/server/0061-Add-canSaveToDisk-to-Entity.patch b/patches/server/0061-Add-canSaveToDisk-to-Entity.patch index 47e428800..37c292bbc 100644 --- a/patches/server/0061-Add-canSaveToDisk-to-Entity.patch +++ b/patches/server/0061-Add-canSaveToDisk-to-Entity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add canSaveToDisk to Entity diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 5af14bd15b134b87f2b8afc35b00f8798d1e8486..381fe41045e2550d5b4ce45973d06e50ec15d8ce 100644 +index 28df085e8de4ef3433ad65d1a48c81a22070f66e..63cd078dcb4eb4951395ca788ba5c04ffb289902 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -4598,5 +4598,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -4622,5 +4622,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { public boolean processClick(InteractionHand hand) { return false; } @@ -19,7 +19,7 @@ index 5af14bd15b134b87f2b8afc35b00f8798d1e8486..381fe41045e2550d5b4ce45973d06e50 // Purpur end } diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 606fa521d577f832cd7a82c1c6c67414e1a01589..7c2c5b5205c7b422903fb6984f2b411d20189b22 100644 +index cdaefabf24c59338a0406072ce01029c194700fd..80674ee4882d2d1c67f78c6bc627e34a78d0c4b0 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java @@ -220,6 +220,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @@ -35,17 +35,17 @@ index 606fa521d577f832cd7a82c1c6c67414e1a01589..7c2c5b5205c7b422903fb6984f2b411d skull.setPosRaw(headX, headY, headZ); level.addFreshEntity(skull); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java -index 2bc0384728f89b7c64a8beec78a1b77dc063d37b..e4af49d85c8f6265b550c0a7cbea7d495f47150a 100644 +index 1782d6957fa0290368e443e2e8d7b3c77ac6b8ef..2c9e9d35cd6500aa0ce3b53122067c6a2a15cbf7 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java -@@ -92,6 +92,7 @@ public class EntityStorage implements EntityPersistentStorage { - ListTag listTag = new ListTag(); - final java.util.Map, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - dataList.getEntities().forEach((entity) -> { -+ if (!entity.canSaveToDisk()) return; // Purpur - // Paper start - final EntityType entityType = entity.getType(); - final int saveLimit = this.level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); +@@ -112,6 +112,7 @@ public class EntityStorage implements EntityPersistentStorage { + ListTag listTag = new ListTag(); + final java.util.Map, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper + entities.forEach((entity) -> { // diff here: use entities parameter ++ if (!entity.canSaveToDisk()) return; // Purpur + // Paper start + final EntityType entityType = entity.getType(); + final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); diff --git a/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java b/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java index d55f7611599b2a339293688861100cb8dae9f6c6..5e99789e5156e8ffbf125e77114c547e1f8e7925 100644 --- a/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java diff --git a/patches/server/0065-Add-5-second-tps-average-in-tps.patch b/patches/server/0065-Add-5-second-tps-average-in-tps.patch index 94c03fe0c..7ec8915e7 100644 --- a/patches/server/0065-Add-5-second-tps-average-in-tps.patch +++ b/patches/server/0065-Add-5-second-tps-average-in-tps.patch @@ -27,7 +27,7 @@ index fa56cd09102a89692b42f1d14257990508c5c720..f9251183df72ddc56662fd3f02acf216 setListData(vector); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 79fa0e88f24857b9ff1e02e550d219f5ed6e4cda..db7646f82ccbda375ddb57dbfd4e5c1baec95184 100644 +index 963a1998f808061c7e7fcd0d15725e38fe606ce7..bc8152edd32238025321512cb72bbb62dd2175bc 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -290,7 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper -@@ -485,6 +486,7 @@ public class ServerPlayer extends Player { +@@ -470,6 +471,7 @@ public class ServerPlayer extends Player { } } @@ -60,7 +60,7 @@ index 6036db50f05e8658f645848e03b276a1352a9424..e8663f8f23f71cfabde12585c6d9bc82 } @Override -@@ -545,6 +547,7 @@ public class ServerPlayer extends Player { +@@ -530,6 +532,7 @@ public class ServerPlayer extends Player { } this.getBukkitEntity().setExtraData(nbt); // CraftBukkit @@ -68,7 +68,7 @@ index 6036db50f05e8658f645848e03b276a1352a9424..e8663f8f23f71cfabde12585c6d9bc82 } // CraftBukkit start - World fallback code, either respawn location or global spawn -@@ -2614,5 +2617,13 @@ public class ServerPlayer extends Player { +@@ -2597,5 +2600,13 @@ public class ServerPlayer extends Player { this.server.getPlayerList().respawn(this, toLevel, true, to, !toLevel.paperConfig().environment.disableTeleportationSuffocationCheck); } } @@ -83,7 +83,7 @@ index 6036db50f05e8658f645848e03b276a1352a9424..e8663f8f23f71cfabde12585c6d9bc82 // Purpur end } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 08aa692b8f80ace6ce552e78476a76220d6d00eb..3d777aae5a91190e1c3bde234bc53a56fdf3c414 100644 +index d0db1623c8132eb4c9a51b6e452280c56f544bf5..8182e9d69083ade08ae0b9c0512b8b7b48de3655 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -503,6 +503,7 @@ public abstract class PlayerList { diff --git a/patches/server/0130-Add-mobGriefing-bypass-to-everything-affected.patch b/patches/server/0130-Add-mobGriefing-bypass-to-everything-affected.patch index feb36560e..976d4c0bf 100644 --- a/patches/server/0130-Add-mobGriefing-bypass-to-everything-affected.patch +++ b/patches/server/0130-Add-mobGriefing-bypass-to-everything-affected.patch @@ -131,7 +131,7 @@ index b9025929fcc89e72aa820953b91a65423878ba0f..edf4537f08a54e1a5b043927678bbddf } diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 6ccacd37f7602a759e47433a97ff54ff761c50fc..a639ebe2ea3f7fdc5367e0d2cec7a257c7cb4933 100644 +index a2d7d2e1ea6596d0a3188169cf8d7295e888c20f..7cc0d8c9dbfe24de4fa2937db9fe6ef8e78bbef7 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java @@ -578,7 +578,7 @@ public class EnderDragon extends Mob implements Enemy { @@ -144,7 +144,7 @@ index 6ccacd37f7602a759e47433a97ff54ff761c50fc..a639ebe2ea3f7fdc5367e0d2cec7a257 // flag1 = this.level.removeBlock(blockposition, false) || flag1; flag1 = true; diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index c39e6ab8ffb850eb6ba783d237daad7e011a03bc..2207c5a71b8a3c7c0c68388ec744c5272d10ab36 100644 +index 9cf7cd70492c8769cd3dad1ed57eeff1150bc4e8..ab3c741aa0894a9383833b3aa4a8d45ad46dd013 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java @@ -402,7 +402,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @@ -156,7 +156,7 @@ index c39e6ab8ffb850eb6ba783d237daad7e011a03bc..2207c5a71b8a3c7c0c68388ec744c527 // CraftBukkit start // this.level.explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, explosion_effect); ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); -@@ -498,7 +498,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -497,7 +497,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob if (this.destroyBlocksTick > 0) { --this.destroyBlocksTick; diff --git a/patches/server/0134-Movement-options-for-armor-stands.patch b/patches/server/0134-Movement-options-for-armor-stands.patch index 326463c20..2b62324df 100644 --- a/patches/server/0134-Movement-options-for-armor-stands.patch +++ b/patches/server/0134-Movement-options-for-armor-stands.patch @@ -17,10 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2ea49b50189e4bc2abfe791bc17e7ea5d9c9e56f..628ea838c16a964bc233f166edc8105c1543e2f9 100644 +index edf291ea8a2bd1a94d4f8e8b6fa0a3f5f68480fa..08a5be138c0c0f2d1239e13c5dd1a82a13145938 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1732,7 +1732,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -1733,7 +1733,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return this.isInWater() || flag; } diff --git a/patches/server/0135-Fix-stuck-in-portals.patch b/patches/server/0135-Fix-stuck-in-portals.patch index 6e15122c5..297af713c 100644 --- a/patches/server/0135-Fix-stuck-in-portals.patch +++ b/patches/server/0135-Fix-stuck-in-portals.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix stuck in portals diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b858ce2ad443f6690dd71e56fb9eea14793df19d..f8b7b12b0030fea6132b426b41adb2180f1b1157 100644 +index ca7199452cbfc7d18203eae17c417c829c3b39bf..743a5cf750cc56856477cf2b4d75ceb241ef1eb6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1184,6 +1184,7 @@ public class ServerPlayer extends Player { +@@ -1169,6 +1169,7 @@ public class ServerPlayer extends Player { playerlist.sendPlayerPermissionLevel(this); worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); this.unsetRemoved(); @@ -17,10 +17,10 @@ index b858ce2ad443f6690dd71e56fb9eea14793df19d..f8b7b12b0030fea6132b426b41adb218 // CraftBukkit end this.setLevel(worldserver); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 628ea838c16a964bc233f166edc8105c1543e2f9..51fd2d02236da23a57773086313fee8183817346 100644 +index 08a5be138c0c0f2d1239e13c5dd1a82a13145938..33050a4ad2448a2d96b9633302a057f15360ea38 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2889,12 +2889,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -2890,12 +2890,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return Vec3.directionFromRotation(this.getRotationVector()); } diff --git a/patches/server/0139-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch b/patches/server/0139-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch index 8f0ee4b2b..874d5f765 100644 --- a/patches/server/0139-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch +++ b/patches/server/0139-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configs for if Wither/Ender Dragon can ride vehicles diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 23e5ab0e3b99659d30d8139dc005a714741a97c7..6c0bcbf1a2a0ccd3efa4827cd04289eb3e1f41e8 100644 +index 0363ba7cd8aa6c2f585355d2c8a86263277d6cfd..c77a9ce015cb219d9ecd68223858dbb775a4ea9b 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -1156,6 +1156,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -1155,6 +1155,7 @@ public class EnderDragon extends Mob implements Enemy { @Override protected boolean canRide(Entity entity) { @@ -17,10 +17,10 @@ index 23e5ab0e3b99659d30d8139dc005a714741a97c7..6c0bcbf1a2a0ccd3efa4827cd04289eb } diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 1329de5d3e6294d2eb7b6852b8cad19f0f4dba77..6818618cd2f702e894ac4098b4eb5afc7664408e 100644 +index d5fc11b01fcd064562173fb35856686f6977144e..0c3fe609a9d4c4c485b1a11e6ec39c06464cda05 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -749,6 +749,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -748,6 +748,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @Override protected boolean canRide(Entity entity) { @@ -29,7 +29,7 @@ index 1329de5d3e6294d2eb7b6852b8cad19f0f4dba77..6818618cd2f702e894ac4098b4eb5afc } diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 570e90dd3cd3bbd3078893fb972f7018b516f3e0..3624304329d0a6728c0e4981bd9dcfb350edaab5 100644 +index 3b80759754a200d2dbbca63e0cfd25aa126b4641..41a4abb7c676285435f9a744ae3f50b9c80c8cbd 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -914,6 +914,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0143-Config-to-ignore-nearby-mobs-when-sleeping.patch b/patches/server/0143-Config-to-ignore-nearby-mobs-when-sleeping.patch index 2e14d2da2..008b84155 100644 --- a/patches/server/0143-Config-to-ignore-nearby-mobs-when-sleeping.patch +++ b/patches/server/0143-Config-to-ignore-nearby-mobs-when-sleeping.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Config to ignore nearby mobs when sleeping diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 6f36354c424f91e7bfbb4619ff03a32d69b9f595..ad2ac7b21296c6995b548fd3c4bf128cd0eb809c 100644 +index 743a5cf750cc56856477cf2b4d75ceb241ef1eb6..5d989ef08080bc6622b64b1eea8ae63ac59dfa4d 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1341,7 +1341,7 @@ public class ServerPlayer extends Player { +@@ -1326,7 +1326,7 @@ public class ServerPlayer extends Player { return entitymonster.isPreventingPlayerRest(this); }); diff --git a/patches/server/0152-Config-for-skipping-night.patch b/patches/server/0152-Config-for-skipping-night.patch index d914b8a65..8f3029d38 100644 --- a/patches/server/0152-Config-for-skipping-night.patch +++ b/patches/server/0152-Config-for-skipping-night.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Config for skipping night diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 827bc3d177d1d8e37d936720e939f3fe03b1ff83..a37365e3cd58e4a39060cf1145a5ae7eb735955a 100644 +index 284fb0308ccd458804f9dfe9eb10529e32ba0207..9dc317d471ce6eab24e0ebec729cea1dbed8b2ec 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -631,7 +631,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -661,7 +661,7 @@ public class ServerLevel extends Level implements WorldGenLevel { int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); long j; @@ -18,7 +18,7 @@ index 827bc3d177d1d8e37d936720e939f3fe03b1ff83..a37365e3cd58e4a39060cf1145a5ae7e j = this.levelData.getDayTime() + 24000L; TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index c659ff37eeae38ab21ad808f35c3452d27a377b3..6a82355509fdb04acc920b21c0c76328999e48e8 100644 +index 9c925dbee68ae33ae98436a5bb70d7fc5b55fe23..23a95b87cf7b92bbb2b34975e49d1d0d65e5e9b5 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -356,6 +356,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0155-Drowning-Settings.patch b/patches/server/0155-Drowning-Settings.patch index 51401ecc6..57b5aee37 100644 --- a/patches/server/0155-Drowning-Settings.patch +++ b/patches/server/0155-Drowning-Settings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Drowning Settings diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 51fd2d02236da23a57773086313fee8183817346..8d97593403198941ff6775dd8576a0e4ea8eb83e 100644 +index 33050a4ad2448a2d96b9633302a057f15360ea38..7f3fc8149b1cf42ce9f92717dcf9aea7b25d60dc 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3128,7 +3128,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -3129,7 +3129,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } public int getMaxAirSupply() { @@ -18,7 +18,7 @@ index 51fd2d02236da23a57773086313fee8183817346..8d97593403198941ff6775dd8576a0e4 public int getAirSupply() { diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c318a83363048e052333e98705f94217039662c4..8820cc6ed4ab7de2d0574575d8168ff4f85a1ea1 100644 +index ebed5983846bb4cfde5ecb06f99b3df8f514b6f3..e11b9c477dabe9c5e00bf41739b0fe52f5ef2093 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -423,7 +423,7 @@ public abstract class LivingEntity extends Entity { diff --git a/patches/server/0170-Configurable-broadcast-settings.patch b/patches/server/0170-Configurable-broadcast-settings.patch index 5e76301dc..000c635dd 100644 --- a/patches/server/0170-Configurable-broadcast-settings.patch +++ b/patches/server/0170-Configurable-broadcast-settings.patch @@ -17,10 +17,10 @@ index 897e761be8c1f79562f54101173fbba7656a37ec..ce42e91a95ccd42deff65e1942b918e9 // Paper end } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5d27110793a95118fae2e671e6f9cdede0763216..9eb1c15d831cd5ccdbd1e28bbf2d994bfae4f039 100644 +index 5d989ef08080bc6622b64b1eea8ae63ac59dfa4d..93afb1cb8c0980a2a66590a27de28fd79595635b 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -922,6 +922,7 @@ public class ServerPlayer extends Player { +@@ -907,6 +907,7 @@ public class ServerPlayer extends Player { })); Team scoreboardteambase = this.getTeam(); diff --git a/patches/server/0183-API-for-any-mob-to-burn-daylight.patch b/patches/server/0183-API-for-any-mob-to-burn-daylight.patch index af8836ee3..c69fdc2b7 100644 --- a/patches/server/0183-API-for-any-mob-to-burn-daylight.patch +++ b/patches/server/0183-API-for-any-mob-to-burn-daylight.patch @@ -6,10 +6,10 @@ Subject: [PATCH] API for any mob to burn daylight Co-authored by: Encode42 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e9a931ce31257ad1a29c15d1619e5f80865f151b..9af78fde6b4d75cf7656c575b98e1e174f599e22 100644 +index 7f3fc8149b1cf42ce9f92717dcf9aea7b25d60dc..3b173754e35f4ec9deaa84c7d3e3467ca06521d3 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -4611,5 +4611,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -4635,5 +4635,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { public boolean canSaveToDisk() { return true; } @@ -211,7 +211,7 @@ index 47e4f62d177c14ceffeb13a3fee5bfa342da7184..bcbce83f9e304809fb946f80c9dd32c4 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index f7689ba01ec6d7f3483be831026e0c5f995459e9..836ca1a47524088c78c6c72a9479c7ffabfbee10 100644 +index 93ce4f81ca03c003596f86810d4a869502c76242..67b940682dc84a8843119e1e990a69aa9dc9c0c4 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java @@ -60,6 +60,7 @@ public class Phantom extends FlyingMob implements Enemy { diff --git a/patches/server/0187-Add-toggle-for-end-portal-safe-teleporting.patch b/patches/server/0187-Add-toggle-for-end-portal-safe-teleporting.patch index dfb1b20d2..e7c5071bc 100644 --- a/patches/server/0187-Add-toggle-for-end-portal-safe-teleporting.patch +++ b/patches/server/0187-Add-toggle-for-end-portal-safe-teleporting.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add toggle for end portal safe teleporting diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4e5b2704f22ac8e94c8ec3b7bfe1e755207eb8cb..a49cc52d5181c56159cbab14c5bec2d7e55c5396 100644 +index 3b173754e35f4ec9deaa84c7d3e3467ca06521d3..01b5629ff8a39f761402d8a8d0e71f9cfc7ab7dd 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2948,7 +2948,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -2949,7 +2949,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } this.processPortalCooldown(); diff --git a/patches/server/0189-Make-lightning-rod-range-configurable.patch b/patches/server/0189-Make-lightning-rod-range-configurable.patch index c4186e27d..fd22948a3 100644 --- a/patches/server/0189-Make-lightning-rod-range-configurable.patch +++ b/patches/server/0189-Make-lightning-rod-range-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make lightning rod range configurable diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a37365e3cd58e4a39060cf1145a5ae7eb735955a..cf89dde659141a2a78e9b2d2b007b4c54db4b1ed 100644 +index 9dc317d471ce6eab24e0ebec729cea1dbed8b2ec..a7820becea1e46154975f4cd7b8e8d24f9f0e4ad 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -941,7 +941,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -971,7 +971,7 @@ public class ServerLevel extends Level implements WorldGenLevel { return holder.is(PoiTypes.LIGHTNING_ROD); }, (blockposition1) -> { return blockposition1.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition1.getX(), blockposition1.getZ()) - 1; diff --git a/patches/server/0204-Customizable-sleeping-actionbar-messages.patch b/patches/server/0204-Customizable-sleeping-actionbar-messages.patch index cd9e57cc3..cd61ddf5e 100644 --- a/patches/server/0204-Customizable-sleeping-actionbar-messages.patch +++ b/patches/server/0204-Customizable-sleeping-actionbar-messages.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Customizable sleeping actionbar messages diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index cf89dde659141a2a78e9b2d2b007b4c54db4b1ed..4b55a46033089e27462b7a8d87cc5631cbcee6a6 100644 +index a7820becea1e46154975f4cd7b8e8d24f9f0e4ad..66ab18b0654b1408fae1a5948290d44dd888b4b4 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -990,11 +990,27 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1020,11 +1020,27 @@ public class ServerLevel extends Level implements WorldGenLevel { if (this.canSleepThroughNights()) { if (!this.getServer().isSingleplayer() || this.getServer().isPublished()) { int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); diff --git a/patches/server/0210-Add-compass-command.patch b/patches/server/0210-Add-compass-command.patch index fcf7879c5..d1f9e3121 100644 --- a/patches/server/0210-Add-compass-command.patch +++ b/patches/server/0210-Add-compass-command.patch @@ -17,18 +17,18 @@ index 6a044a9c97db9bba75f8dbbaa8515e3167841855..edd378813873ed367784379b0f1666d1 if (environment.includeIntegrated) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 2e886f8f56cda44d74bac7028236273e811d4473..ff4c7dcb2734b120026b19bd63d8fdcd5cad12f1 100644 +index 93afb1cb8c0980a2a66590a27de28fd79595635b..40dc37c7acabc8eb601035d5a61cf09ef0c96ccd 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -265,6 +265,7 @@ public class ServerPlayer extends Player { +@@ -264,6 +264,7 @@ public class ServerPlayer extends Player { public boolean purpurClient = false; // Purpur public boolean acceptingResourcePack = false; // Purpur private boolean tpsBar = false; // Purpur + private boolean compassBar = false; // Purpur + public boolean isRealPlayer; // Paper public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper -@@ -487,6 +488,7 @@ public class ServerPlayer extends Player { +@@ -472,6 +473,7 @@ public class ServerPlayer extends Player { } if (nbt.contains("Purpur.TPSBar")) { this.tpsBar = nbt.getBoolean("Purpur.TPSBar"); } // Purpur @@ -36,7 +36,7 @@ index 2e886f8f56cda44d74bac7028236273e811d4473..ff4c7dcb2734b120026b19bd63d8fdcd } @Override -@@ -548,6 +550,7 @@ public class ServerPlayer extends Player { +@@ -533,6 +535,7 @@ public class ServerPlayer extends Player { this.getBukkitEntity().setExtraData(nbt); // CraftBukkit nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur @@ -44,7 +44,7 @@ index 2e886f8f56cda44d74bac7028236273e811d4473..ff4c7dcb2734b120026b19bd63d8fdcd } // CraftBukkit start - World fallback code, either respawn location or global spawn -@@ -2627,5 +2630,13 @@ public class ServerPlayer extends Player { +@@ -2610,5 +2613,13 @@ public class ServerPlayer extends Player { public void tpsBar(boolean tpsBar) { this.tpsBar = tpsBar; } diff --git a/patches/server/0216-Toggle-for-Wither-s-spawn-sound.patch b/patches/server/0216-Toggle-for-Wither-s-spawn-sound.patch index aec2a8419..2f6d4f74b 100644 --- a/patches/server/0216-Toggle-for-Wither-s-spawn-sound.patch +++ b/patches/server/0216-Toggle-for-Wither-s-spawn-sound.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Toggle for Wither's spawn sound diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 01397e9daf03a308707cc7e2bb85db68137d3021..0dd31e45252d54b8bfa3645b25c984de30934a0e 100644 +index bf608c0bad8f1cd99f27b610c0d6dfa4d638374d..3f0b62c733c62b8d1a9fc6494d787c9865fefadb 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java @@ -430,7 +430,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @@ -16,9 +16,9 @@ index 01397e9daf03a308707cc7e2bb85db68137d3021..0dd31e45252d54b8bfa3645b25c984de + if (!this.isSilent() && level.purpurConfig.witherPlaySpawnSound) { // CraftBukkit start - Use relative location for far away sounds // this.world.globalLevelEvent(1023, new BlockPosition(this), 0); - //int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index c2d73249ec7cb74a318d2c33159ad6aeb713bfed..504487696324b53cebdb10e635c9f7aae733c028 100644 +index d7c5764ac50f313c691667bd8beb6f7067da67d0..0c21e0ca6da3819d41f55fe4b2f1539efb5eaec1 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -2554,6 +2554,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0225-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch b/patches/server/0225-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch index 1a523cbf7..49423b57c 100644 --- a/patches/server/0225-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch +++ b/patches/server/0225-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option for if rain and thunder should stop on sleep diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 4b55a46033089e27462b7a8d87cc5631cbcee6a6..9d22e2acfcec99f7cf9e763c3a185479c970f552 100644 +index 66ab18b0654b1408fae1a5948290d44dd888b4b4..0c23de7ed20ac3be4a2462a246b5f746706226c6 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1149,6 +1149,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1179,6 +1179,7 @@ public class ServerLevel extends Level implements WorldGenLevel { private void resetWeatherCycle() { // CraftBukkit start @@ -16,7 +16,7 @@ index 4b55a46033089e27462b7a8d87cc5631cbcee6a6..9d22e2acfcec99f7cf9e763c3a185479 this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... -@@ -1156,6 +1157,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1186,6 +1187,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.serverLevelData.setRainTime(0); } // CraftBukkit end @@ -25,7 +25,7 @@ index 4b55a46033089e27462b7a8d87cc5631cbcee6a6..9d22e2acfcec99f7cf9e763c3a185479 // CraftBukkit start // If we stop due to everyone sleeping we should reset the weather duration to some other random value. diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 55733b718b077d90802e2bdace3dbcab76a166f2..0ec0db28bf3fa246a5f57c8b36fd8a43e8a72cba 100644 +index c30d9c42b9d973976c40be5ddf1c529c6e565eb3..115f026e425a71eaebaf20c491b61503a590f6f6 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -141,6 +141,8 @@ public class PurpurWorldConfig { diff --git a/patches/server/0233-UPnP-Port-Forwarding.patch b/patches/server/0233-UPnP-Port-Forwarding.patch index 197104589..0c9a44707 100644 --- a/patches/server/0233-UPnP-Port-Forwarding.patch +++ b/patches/server/0233-UPnP-Port-Forwarding.patch @@ -5,7 +5,7 @@ Subject: [PATCH] UPnP Port Forwarding diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d8e0bac3de2f7810d7af82fe6c5c00870fef3155..d950b72b7287b857cb849c1a2fc931fa7d30f25f 100644 +index fa2812d94045e5d49fdd9990eac918975c9fcee5..2030779f7c430a6d30679935c108d2deb21a1cef 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -296,6 +296,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { -+ //try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { // Purpur - CompoundTag data = PaperFileIOThread.FAILURE_VALUE; + private static final ThreadLocal> CURRENT_TICKET_UPDATE_SCHEDULING = new ThreadLocal<>(); +diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java +index 9a4ec0f1fb3bac0e84e6bd3aaeb77f44e248aadb..4d285d7c0cbc0a84a11e0c403dc91a9626757f06 100644 +--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java ++++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java +@@ -1747,7 +1747,7 @@ public final class NewChunkHolder { + boolean canSavePOI = !(chunk instanceof LevelChunk levelChunk && levelChunk.mustNotSave) && (poi != null && poi.isDirty()); + boolean canSaveEntities = entities != null; - try { -@@ -54,7 +54,7 @@ public final class ChunkSaveTask extends ChunkTask { - } +- try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper ++ //try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper // Purpur + if (canSaveChunk) { + canSaveChunk = this.saveChunk(chunk, unloading); + } +@@ -1761,7 +1761,7 @@ public final class NewChunkHolder { + this.lastEntityUnload = null; + } + } +- } ++ //} // Purpur - ChunkSaveTask.this.complete(data); -- } -+ // } // Purpur - }); - - return; // the main thread will now complete the data + return executedUnloadTask | canSaveChunk | canSaveEntities | canSavePOI; + } diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index 2eb30c6c6f1354a559a7b8c14c36a9970bdf2a42..d9f5f48fbb67d7f8dbfc0b7fa8fe0c294a7e8f0d 100644 +index 54bca103347e89f116fb7fbf37449a32ac094286..a7f4b791894c5d8b7af4b0c067cf167b29272a27 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -68,14 +68,14 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -67,14 +67,14 @@ public class GlobalConfiguration extends ConfigurationPart { @Override public void postProcess() { @@ -103,10 +88,10 @@ index 8bc0cb9ad5bb4e76d962ff54305e2c08e279a17b..e8efbbeece7e866c6c4d7489677d2d9e PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f018d4bec5e09118b99933b58efe24da995fde75..d1987cfa0b1bd60cb6d3145d9522216d72f253cc 100644 +index bc80783d36d46fb138bfa6f2e5e84679db0a68c1..7063ef7d547714d6647290e36da3a07b3b946871 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1428,15 +1428,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> scheduleChunkLoad(ChunkPos pos) { - // Paper start - Async chunk io - final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { -- try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper -+ try /*(Timing ignored = this.level.timings.chunkLoad.startTimingIfSync())*/ { // Paper // Purpur - this.level.getProfiler().incrementCounter("chunkLoad"); - if (ioThrowable != null) { - return this.handleChunkLoadFailure(ioThrowable, pos); -@@ -1352,7 +1352,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkStatus chunkstatus = ChunkHolder.getStatus(chunkHolder.getTicketLevel()); - - return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { -- try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper -+ //try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper // Purpur - ChunkPos chunkcoordintpair = chunkHolder.getPos(); - ProtoChunk protochunk = (ProtoChunk) ichunkaccess; - LevelChunk chunk; -@@ -1377,7 +1377,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - return chunk; -- } // Paper -+ //} // Paper // Purpur - }); - }, (runnable) -> { - ProcessorHandle mailbox = this.mainThreadMailbox; -@@ -1509,9 +1509,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private void asyncSave(ChunkAccess chunk) { - ChunkPos chunkPos = chunk.getPos(); - CompoundTag poiData; -- try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { -+ //try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { // Purpur - poiData = this.poiManager.getData(chunk.getPos()); -- } -+ //} // Purpur - - com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z, - poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); -@@ -1531,9 +1531,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - ChunkSerializer.AsyncSaveData asyncSaveData; -- try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) { -+ //try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) { // Purpur - asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk); -- } -+ //} // Purpur - - this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, - asyncSaveData, chunk); -@@ -1544,7 +1544,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end - - public boolean save(ChunkAccess chunk) { -- try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper -+ //try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper // Purpur - this.poiManager.flush(chunk.getPos()); - if (!chunk.isUnsaved()) { - return false; -@@ -1568,9 +1568,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - this.level.getProfiler().incrementCounter("chunkSave"); - CompoundTag nbttagcompound; -- try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper -+ //try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper // Purpur - nbttagcompound = ChunkSerializer.write(this.level, chunk); -- } // Paper -+ //} // Paper // Purpur - - // Paper start - async chunk io - com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, -@@ -1584,7 +1584,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return false; - } - } -- } // Paper -+ //} // Paper // Purpur - } - - private boolean isExistingChunkFull(ChunkPos pos) { -@@ -2107,24 +2107,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Pufferfish end +@@ -1241,24 +1241,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - optimised tracker + private final void processTrackQueue() { - this.level.timings.tracker1.startTiming(); + //this.level.timings.tracker1.startTiming(); // Purpur try { @@ -419,7 +323,7 @@ index cec58f0d7ac6bf73a0f7b418a595704b8b807425..56ec684bac1c29c99bac117e38d82db2 } } // Paper end - optimised tracker -@@ -2139,7 +2139,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1273,7 +1273,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider List list = Lists.newArrayList(); List list1 = this.level.players(); ObjectIterator objectiterator = this.entityMap.values().iterator(); @@ -428,7 +332,7 @@ index cec58f0d7ac6bf73a0f7b418a595704b8b807425..56ec684bac1c29c99bac117e38d82db2 ChunkMap.TrackedEntity playerchunkmap_entitytracker; -@@ -2164,17 +2164,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1298,17 +1298,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider playerchunkmap_entitytracker.serverEntity.sendChanges(); } } @@ -450,41 +354,23 @@ index cec58f0d7ac6bf73a0f7b418a595704b8b807425..56ec684bac1c29c99bac117e38d82db2 } diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c2689ae00ab 100644 +index 7266e6703d5cd0fea90ec88c74a7d4567f2420ae..157efbbc57f1b5d92f296a70823c75b6d01ac065 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -483,10 +483,10 @@ public class ServerChunkCache extends ChunkSource { - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); +@@ -449,10 +449,10 @@ public class ServerChunkCache extends ChunkSource { + io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.pushChunkWait(this.level, x1, z1); // Paper - rewrite chunk system // Paper end com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info - this.level.timings.syncChunkLoad.startTiming(); // Paper + //this.level.timings.syncChunkLoad.startTiming(); // Paper // Purpur chunkproviderserver_b.managedBlock(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.popChunkWait(); // Paper - async chunk debug // Paper - rewrite chunk system - this.level.timings.syncChunkLoad.stopTiming(); // Paper + //this.level.timings.syncChunkLoad.stopTiming(); // Paper // Purpur - this.distanceManager.clearPriorityTickets(pair); // Paper - Chunk priority - this.distanceManager.clearUrgent(pair); // Paper - Chunk priority } // Paper -@@ -650,7 +650,7 @@ public class ServerChunkCache extends ChunkSource { - public boolean runDistanceManagerUpdates() { - if (distanceManager.delayDistanceManagerTick) return false; // Paper - Chunk priority - if (this.chunkMap.unloadingPlayerChunk) { LOGGER.error("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper -- co.aikar.timings.MinecraftTimings.distanceManagerTick.startTiming(); try { // Paper - add timings for distance manager -+ //co.aikar.timings.MinecraftTimings.distanceManagerTick.startTiming(); try { // Paper - add timings for distance manager // Purpur - boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); - boolean flag1 = this.chunkMap.promoteChunkMap(); - -@@ -660,7 +660,7 @@ public class ServerChunkCache extends ChunkSource { - this.clearCache(); - return true; - } -- } finally { co.aikar.timings.MinecraftTimings.distanceManagerTick.stopTiming(); } // Paper - add timings for distance manager -+ //} finally { co.aikar.timings.MinecraftTimings.distanceManagerTick.stopTiming(); } // Paper - add timings for distance manager // Purpur - } - - // Paper start -@@ -678,17 +678,17 @@ public class ServerChunkCache extends ChunkSource { + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; +@@ -600,17 +600,17 @@ public class ServerChunkCache extends ChunkSource { public void save(boolean flush) { this.runDistanceManagerUpdates(); @@ -506,7 +392,7 @@ index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c26 } // Paper end -@@ -723,22 +723,22 @@ public class ServerChunkCache extends ChunkSource { +@@ -640,22 +640,22 @@ public class ServerChunkCache extends ChunkSource { @Override public void tick(BooleanSupplier shouldKeepTicking, boolean tickChunks) { this.level.getProfiler().push("purge"); @@ -535,7 +421,7 @@ index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c26 this.level.getProfiler().pop(); this.clearCache(); } -@@ -793,7 +793,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -710,7 +710,7 @@ public class ServerChunkCache extends ChunkSource { boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit gameprofilerfiller.push("naturalSpawnCount"); @@ -544,7 +430,7 @@ index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c26 int l = this.distanceManager.getNaturalSpawnChunkCount(); // Paper start - per player mob spawning NaturalSpawner.SpawnState spawnercreature_d; // moved down -@@ -814,12 +814,12 @@ public class ServerChunkCache extends ChunkSource { +@@ -731,12 +731,12 @@ public class ServerChunkCache extends ChunkSource { // Pufferfish end } // Paper end @@ -559,7 +445,7 @@ index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c26 // Paper - moved down -@@ -873,17 +873,17 @@ public class ServerChunkCache extends ChunkSource { +@@ -790,17 +790,17 @@ public class ServerChunkCache extends ChunkSource { } } // Paper end - optimise chunk tick iteration @@ -581,7 +467,7 @@ index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c26 if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) { ReferenceOpenHashSet copy = this.chunkMap.needsChangeBroadcasting.clone(); this.chunkMap.needsChangeBroadcasting.clear(); -@@ -895,7 +895,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -812,7 +812,7 @@ public class ServerChunkCache extends ChunkSource { } } } @@ -591,10 +477,10 @@ index 795691bcb61a7c2b4f903d8db3b6714908c78ac2..9e796ab10152d630fe78ec247d6b0c26 // Paper end - use set of chunks requiring updates, rather than iterating every single one loaded // Paper start - controlled flush for entity tracker packets diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069ca184123 100644 +index 682a29b24b986c832ce5c6f708fc78c0515aa824..d3b93712cd999d61f66a8ffefd9122ffc1596ba1 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -654,7 +654,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -684,7 +684,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.updateSkyBrightness(); this.tickTime(); gameprofilerfiller.popPush("tickPending"); @@ -603,7 +489,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 if (!this.isDebug()) { j = this.getGameTime(); gameprofilerfiller.push("blockTicks"); -@@ -663,20 +663,20 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -693,20 +693,20 @@ public class ServerLevel extends Level implements WorldGenLevel { this.fluidTicks.tick(j, 65536, this::tickFluid); gameprofilerfiller.pop(); } @@ -631,7 +517,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 this.handlingTick = false; gameprofilerfiller.pop(); boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -687,7 +687,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -717,7 +717,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (flag || this.emptyTime++ < 300) { gameprofilerfiller.push("entities"); @@ -640,7 +526,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 if (this.dragonFight != null) { gameprofilerfiller.push("dragonFight"); this.dragonFight.tick(); -@@ -695,7 +695,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -725,7 +725,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } org.spigotmc.ActivationRange.activateEntities(this); // Spigot @@ -649,7 +535,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 this.entityTickList.forEach((entity) -> { if (!entity.isRemoved()) { if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed -@@ -735,8 +735,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -765,8 +765,8 @@ public class ServerLevel extends Level implements WorldGenLevel { } } }); @@ -660,7 +546,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 gameprofilerfiller.pop(); this.tickBlockEntities(); } -@@ -898,7 +898,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -928,7 +928,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper start - optimise random block ticking gameprofilerfiller.popPush("randomTick"); @@ -669,7 +555,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 if (randomTickSpeed > 0) { LevelChunkSection[] sections = chunk.getSections(); int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this); -@@ -932,7 +932,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -962,7 +962,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } } // Paper end - optimise random block ticking @@ -678,7 +564,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 gameprofilerfiller.pop(); } -@@ -1226,8 +1226,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1255,8 +1255,8 @@ public class ServerLevel extends Level implements WorldGenLevel { // Spigot end // Paper start- timings final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); @@ -689,7 +575,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 // Paper end - timings entity.setOldPosAndRot(); ProfilerFiller gameprofilerfiller = this.getProfiler(); -@@ -1243,7 +1243,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1272,7 +1272,7 @@ public class ServerLevel extends Level implements WorldGenLevel { entity.postTick(); // CraftBukkit } else { entity.inactiveTick(); } // Paper - EAR 2 this.getProfiler().pop(); @@ -698,7 +584,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -1266,8 +1266,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1295,8 +1295,8 @@ public class ServerLevel extends Level implements WorldGenLevel { if (passenger instanceof Player || this.entityTickList.contains(passenger)) { // Paper - EAR 2 final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); @@ -709,7 +595,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 // Paper end passenger.setOldPosAndRot(); ++passenger.tickCount; -@@ -1297,7 +1297,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1326,7 +1326,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.tickPassenger(passenger, entity2); } @@ -718,7 +604,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 } } else { passenger.stopRiding(); -@@ -1317,14 +1317,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1346,14 +1346,14 @@ public class ServerLevel extends Level implements WorldGenLevel { org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); } @@ -736,7 +622,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 // Copied from save() // CraftBukkit start - moved from MinecraftServer.saveChunks -@@ -1336,7 +1336,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1365,7 +1365,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.convertable.saveDataTag(this.server.registryHolder, this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); } // CraftBukkit end @@ -745,7 +631,7 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 } // Paper end -@@ -1345,7 +1345,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1379,7 +1379,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (!savingDisabled) { org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit @@ -754,20 +640,21 @@ index 0df97cf932f8bd315e3ae645368ae8df6c51fc25..207f07dfd0d2fd0ff5fdb3952966d069 if (progressListener != null) { progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel")); } -@@ -1355,10 +1355,10 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1389,11 +1389,11 @@ public class ServerLevel extends Level implements WorldGenLevel { progressListener.progressStage(Component.translatable("menu.savingChunks")); } - timings.worldSaveChunks.startTiming(); // Paper + //timings.worldSaveChunks.startTiming(); // Paper // Purpur - chunkproviderserver.save(flush); + if (!close) chunkproviderserver.save(flush); // Paper - rewrite chunk system + if (close) chunkproviderserver.close(true); // Paper - rewrite chunk system - timings.worldSaveChunks.stopTiming(); // Paper - }// Paper + //timings.worldSaveChunks.stopTiming(); // Paper // Purpur + //}// Paper // Purpur - if (flush) { - this.entityManager.saveAll(); - } else { + // Paper - rewrite chunk system - entity saving moved into ChunkHolder + + } else if (close) { chunkproviderserver.close(false); } // Paper - rewrite chunk system diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index 9519e11fef244eb1b286b43b857d3f41865784c4..7a0adbdcadd20269e92cb698b569f04b169dade4 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -800,7 +687,7 @@ index 9519e11fef244eb1b286b43b857d3f41865784c4..7a0adbdcadd20269e92cb698b569f04b } // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9ed964da70a17afbe26c513f67b2d911f2c9e7c5..138b2c1a21b9ceb60030d10e24c78e09533937a0 100644 +index ae888c565e39fab22224cba96a0d8836a747738a..3fb2323c89d04f1a545897a1e67f6f637f5ab9c1 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -1287,7 +1287,7 @@ public abstract class PlayerList { @@ -870,27 +757,11 @@ index fcdb9bde8e1605e30dde3e580491522d4b62cdc0..7094701d213c73ba47ace806962244c1 } } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index 210b0cdd4831421c8f43c3d823ac8e962b56bbbc..de99946f5215ff2c78d6df5b8b7d5b6abaece907 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -351,9 +351,9 @@ public class PoiManager extends SectionStorage { - ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); - - net.minecraft.nbt.CompoundTag data; -- try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { -+ //try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { // Purpur - data = this.getData(chunkcoordintpair); -- } -+ //} // Purpur - com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, - chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); - } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index c5dac52a23d9df26cacb869fd841da9bf518c313..bd89e00f707b6ba297081c9aacb3c5463e80063e 100644 +index 0c9f7f9ed3e24ddc6b963063723feb56422843c5..93711ef7df591ab0f50b8f0f7798f938eeb0f3b3 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -995,15 +995,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -994,15 +994,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("blockEntities"); @@ -909,7 +780,7 @@ index c5dac52a23d9df26cacb869fd841da9bf518c313..bd89e00f707b6ba297081c9aacb3c546 // Spigot start // Iterator iterator = this.blockEntityTickers.iterator(); int tilesThisCycle = 0; -@@ -1036,7 +1036,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1035,7 +1035,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } this.blockEntityTickers.removeAll(toRemove); @@ -941,11 +812,11 @@ index 1f4acc1a2605f1e9051126fc811a5479351fc61a..5c6fde4baf27e7d8f027c138d843da39 } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 6fbf26eb7da8df2f0a4158ff9f12022518ada8e3..ab024c5315c0a7cb2f80d5d7b251f6a3531879b3 100644 +index df2786516fe641edff7bbe9fe0665bf07502d830..b4460ed16ba30173ad4a5fe8e405e1c34251912f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -875,7 +875,7 @@ public class LevelChunk extends ChunkAccess { - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); +@@ -927,7 +927,7 @@ public class LevelChunk extends ChunkAccess { + this.chunkHolder.getEntityChunk().callEntitiesLoadEvent(); // Paper - rewrite chunk system if (this.needsDecoration) { - try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper @@ -953,7 +824,7 @@ index 6fbf26eb7da8df2f0a4158ff9f12022518ada8e3..ab024c5315c0a7cb2f80d5d7b251f6a3 this.needsDecoration = false; java.util.Random random = new java.util.Random(); random.setSeed(this.level.getSeed()); -@@ -895,7 +895,7 @@ public class LevelChunk extends ChunkAccess { +@@ -947,7 +947,7 @@ public class LevelChunk extends ChunkAccess { } } server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(this.bukkitChunk)); @@ -962,7 +833,7 @@ index 6fbf26eb7da8df2f0a4158ff9f12022518ada8e3..ab024c5315c0a7cb2f80d5d7b251f6a3 } } } -@@ -1239,7 +1239,7 @@ public class LevelChunk extends ChunkAccess { +@@ -1292,7 +1292,7 @@ public class LevelChunk extends ChunkAccess { ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler(); gameprofilerfiller.push(this::getType); @@ -971,7 +842,7 @@ index 6fbf26eb7da8df2f0a4158ff9f12022518ada8e3..ab024c5315c0a7cb2f80d5d7b251f6a3 BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); if (this.blockEntity.getType().isValid(iblockdata)) { -@@ -1261,7 +1261,7 @@ public class LevelChunk extends ChunkAccess { +@@ -1314,7 +1314,7 @@ public class LevelChunk extends ChunkAccess { // Paper end // Spigot start } finally { diff --git a/patches/server/0289-Remove-Mojang-Profiler.patch b/patches/server/0289-Remove-Mojang-Profiler.patch index 021abca58..0a10ecb20 100644 --- a/patches/server/0289-Remove-Mojang-Profiler.patch +++ b/patches/server/0289-Remove-Mojang-Profiler.patch @@ -39,7 +39,7 @@ index edd378813873ed367784379b0f1666d1ccf2194d..eb4dac2239592d680ef31edf47f1ab66 return b0; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d1987cfa0b1bd60cb6d3145d9522216d72f253cc..d7c77908ba7f0a0c00c06744d1ee0c1ad3ee0d7c 100644 +index 7063ef7d547714d6647290e36da3a07b3b946871..60bed3f87016b29508ea1a94db65a1f60d960de1 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -328,13 +328,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0; try { this.isSaving = true; -@@ -1484,7 +1484,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Purpur net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper @@ -192,7 +192,7 @@ index d1987cfa0b1bd60cb6d3145d9522216d72f253cc..d7c77908ba7f0a0c00c06744d1ee0c1a try { //worldserver.timings.doTick.startTiming(); // Spigot // Purpur -@@ -1602,17 +1602,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { this.executeBlocking(() -> { this.saveDebugReport(path.resolve("server")); -@@ -2526,40 +2526,40 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> syncLoadComplete = (chunkHolder, ioThrowable) -> { - try /*(Timing ignored = this.level.timings.chunkLoad.startTimingIfSync())*/ { // Paper // Purpur -- this.level.getProfiler().incrementCounter("chunkLoad"); -+ //this.level.getProfiler().incrementCounter("chunkLoad"); // Purpur - if (ioThrowable != null) { - return this.handleChunkLoadFailure(ioThrowable, pos); - } -@@ -1258,9 +1258,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return this.getDependencyStatus(requiredStatus, i); - }); - -- this.level.getProfiler().incrementCounter(() -> { -+ /*this.level.getProfiler().incrementCounter(() -> { // Purpur - return "chunkGenerate " + requiredStatus.getName(); -- }); -+ });*/ // Purpur - Executor executor = (runnable) -> { - // Paper start - optimize chunk status progression without jumping through thread pool - if (holder.canAdvanceStatus()) { -@@ -1566,7 +1566,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - } - -- this.level.getProfiler().incrementCounter("chunkSave"); -+ //this.level.getProfiler().incrementCounter("chunkSave"); // Purpur - CompoundTag nbttagcompound; - //try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper // Purpur - nbttagcompound = ChunkSerializer.write(this.level, chunk); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd83e07bbc1 100644 +index 157efbbc57f1b5d92f296a70823c75b6d01ac065..cd5533c3c53215c9cc4be0b9097d76efbf5bd0c1 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -454,9 +454,9 @@ public class ServerChunkCache extends ChunkSource { +@@ -430,16 +430,16 @@ public class ServerChunkCache extends ChunkSource { return ifLoaded; } // Paper end @@ -445,33 +415,15 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 long k = ChunkPos.asLong(x, z); ChunkAccess ichunkaccess; -@@ -470,7 +470,7 @@ public class ServerChunkCache extends ChunkSource { - } - } + + // Paper - rewrite chunk system - there are no correct callbacks to remove items from cache in the new chunk system - gameprofilerfiller.incrementCounter("getChunkCacheMiss"); + //gameprofilerfiller.incrementCounter("getChunkCacheMiss"); // Purpur CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; -@@ -569,13 +569,13 @@ public class ServerChunkCache extends ChunkSource { - this.distanceManager.addTicket(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper - prevent plugin unloads from removing our ticket - if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper - Chunk priority - if (this.chunkAbsent(playerchunk, l)) { -- ProfilerFiller gameprofilerfiller = this.level.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.level.getProfiler(); // Purpur - -- gameprofilerfiller.push("chunkLoad"); -+ //gameprofilerfiller.push("chunkLoad"); // Purpur - distanceManager.delayDistanceManagerTick = false; // Paper - Chunk priority - ensure this is never false - this.runDistanceManagerUpdates(); - playerchunk = this.getVisibleChunkIfPresent(k); -- gameprofilerfiller.pop(); -+ //gameprofilerfiller.pop(); // Purpur - if (this.chunkAbsent(playerchunk, l)) { - this.distanceManager.removeTicket(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper - throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added")); -@@ -710,24 +710,24 @@ public class ServerChunkCache extends ChunkSource { +@@ -627,24 +627,24 @@ public class ServerChunkCache extends ChunkSource { // CraftBukkit start - modelled on below public void purgeUnload() { if (true) return; // Paper - tickets will be removed later, this behavior isn't really well accounted for by the chunk system @@ -501,7 +453,7 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 if (tickChunks) { //this.level.timings.chunks.startTiming(); // Paper - timings // Purpur this.chunkMap.playerChunkManager.tick(); // Paper - this is mostly is to account for view distance changes -@@ -736,10 +736,10 @@ public class ServerChunkCache extends ChunkSource { +@@ -653,10 +653,10 @@ public class ServerChunkCache extends ChunkSource { } //this.level.timings.doChunkUnload.startTiming(); // Spigot // Purpur @@ -514,7 +466,7 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 this.clearCache(); } -@@ -785,14 +785,14 @@ public class ServerChunkCache extends ChunkSource { +@@ -702,14 +702,14 @@ public class ServerChunkCache extends ChunkSource { } // Paper end - optimize isOutisdeRange LevelData worlddata = this.level.getLevelData(); @@ -532,7 +484,7 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 //this.level.timings.countNaturalMobs.startTiming(); // Paper - timings // Purpur int l = this.distanceManager.getNaturalSpawnChunkCount(); // Paper start - per player mob spawning -@@ -817,13 +817,13 @@ public class ServerChunkCache extends ChunkSource { +@@ -734,13 +734,13 @@ public class ServerChunkCache extends ChunkSource { //this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings // Purpur //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously @@ -548,7 +500,7 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit // Paper - only shuffle if per-player mob spawning is disabled -@@ -874,15 +874,15 @@ public class ServerChunkCache extends ChunkSource { +@@ -791,15 +791,15 @@ public class ServerChunkCache extends ChunkSource { } // Paper end - optimise chunk tick iteration //this.level.timings.chunkTicks.stopTiming(); // Paper // Purpur @@ -567,7 +519,7 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 //this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing // Purpur if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) { ReferenceOpenHashSet copy = this.chunkMap.needsChangeBroadcasting.clone(); -@@ -896,7 +896,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -813,7 +813,7 @@ public class ServerChunkCache extends ChunkSource { } } //this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing // Purpur @@ -576,7 +528,7 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 // Paper end - use set of chunks requiring updates, rather than iterating every single one loaded // Paper start - controlled flush for entity tracker packets List disabledFlushes = new java.util.ArrayList<>(this.level.players.size()); -@@ -1102,7 +1102,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -1024,7 +1024,7 @@ public class ServerChunkCache extends ChunkSource { @Override protected void doRunTask(Runnable task) { @@ -586,10 +538,10 @@ index 9e796ab10152d630fe78ec247d6b0c2689ae00ab..7d8f7ecad22cdcd39270af79af8e0cd8 } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30defa47a6 100644 +index d3b93712cd999d61f66a8ffefd9122ffc1596ba1..9f8d89e45c9d15f07e9b5c27451816ae06819f68 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -621,12 +621,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -651,12 +651,12 @@ public class ServerLevel extends Level implements WorldGenLevel { } } // Paper end - optimise checkDespawn @@ -605,7 +557,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 this.advanceWeatherCycle(); int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); long j; -@@ -653,32 +653,32 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -683,32 +683,32 @@ public class ServerLevel extends Level implements WorldGenLevel { this.updateSkyBrightness(); this.tickTime(); @@ -646,7 +598,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players if (flag) { -@@ -686,12 +686,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -716,12 +716,12 @@ public class ServerLevel extends Level implements WorldGenLevel { } if (flag || this.emptyTime++ < 300) { @@ -662,7 +614,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 } org.spigotmc.ActivationRange.activateEntities(this); // Spigot -@@ -701,9 +701,9 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -731,9 +731,9 @@ public class ServerLevel extends Level implements WorldGenLevel { if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed entity.discard(); } else { @@ -674,7 +626,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - now always true if in the ticking list Entity entity1 = entity.getVehicle(); -@@ -715,7 +715,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -745,7 +745,7 @@ public class ServerLevel extends Level implements WorldGenLevel { entity.stopRiding(); } @@ -683,7 +635,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 // Pufferfish start - copied from this.guardEntityTick try { this.tickNonPassenger(entity); // Pufferfish - changed -@@ -730,22 +730,22 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -760,22 +760,22 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end } // Pufferfish end @@ -702,7 +654,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 - gameprofilerfiller.push("entityManagement"); + //gameprofilerfiller.push("entityManagement"); // Purpur - this.entityManager.tick(); + //this.entityManager.tick(); // Paper - rewrite chunk system - gameprofilerfiller.popPush("gameEvents"); + //gameprofilerfiller.popPush("gameEvents"); // Purpur this.sendGameEvents(); @@ -711,7 +663,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 } @Override -@@ -827,9 +827,9 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -857,9 +857,9 @@ public class ServerLevel extends Level implements WorldGenLevel { boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); int k = chunkcoordintpair.getMinBlockZ(); @@ -723,7 +675,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - disable thunder // Pufferfish - replace random with shouldDoLightning -@@ -861,7 +861,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -891,7 +891,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } } @@ -732,7 +684,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 if (!this.paperConfig().environment.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Pufferfish - optimize further random ticking // Paper start - optimise chunk ticking this.getRandomBlockPosition(j, 0, k, 15, blockposition); -@@ -897,7 +897,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -927,7 +927,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } // Paper start - optimise random block ticking @@ -741,7 +693,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 //timings.chunkTicksBlocks.startTiming(); // Paper // Purpur if (randomTickSpeed > 0) { LevelChunkSection[] sections = chunk.getSections(); -@@ -933,7 +933,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -963,7 +963,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } // Paper end - optimise random block ticking //timings.chunkTicksBlocks.stopTiming(); // Paper // Purpur @@ -750,7 +702,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 } public Optional findLightningRod(BlockPos pos) { -@@ -1230,19 +1230,19 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1259,19 +1259,19 @@ public class ServerLevel extends Level implements WorldGenLevel { //try { // Purpur // Paper end - timings entity.setOldPosAndRot(); @@ -775,7 +727,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 //} finally { timer.stopTiming(); } // Paper - timings // Purpur Iterator iterator = entity.getPassengers().iterator(); -@@ -1271,12 +1271,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1300,12 +1300,12 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end passenger.setOldPosAndRot(); ++passenger.tickCount; @@ -792,7 +744,7 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 // Paper start - EAR 2 if (isActive) { passenger.rideTick(); -@@ -1288,7 +1288,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1317,7 +1317,7 @@ public class ServerLevel extends Level implements WorldGenLevel { vehicle.positionRider(passenger); } // Paper end - EAR 2 @@ -802,10 +754,10 @@ index 207f07dfd0d2fd0ff5fdb3952966d069ca184123..6859e2054e8eb4fc8ac005e0bf646a30 while (iterator.hasNext()) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 3b5b040cf3cdbb3798972f73b75e8ab4753987db..18068e33014936fd5471aad6b673c16982bd38fc 100644 +index 4abac5e3ba5dcf27248bda31d95c85bb5e23c19d..6979305279996be59756d0424e5bc16a19fde6b0 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1153,7 +1153,7 @@ public class ServerPlayer extends Player { +@@ -1138,7 +1138,7 @@ public class ServerPlayer extends Player { PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver); if (shapedetectorshape != null) { @@ -814,7 +766,7 @@ index 3b5b040cf3cdbb3798972f73b75e8ab4753987db..18068e33014936fd5471aad6b673c169 worldserver = shapedetectorshape.world; // CraftBukkit if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event if (resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit -@@ -1176,8 +1176,8 @@ public class ServerPlayer extends Player { +@@ -1161,8 +1161,8 @@ public class ServerPlayer extends Player { worldserver = ((CraftWorld) exit.getWorld()).getHandle(); // CraftBukkit end @@ -825,7 +777,7 @@ index 3b5b040cf3cdbb3798972f73b75e8ab4753987db..18068e33014936fd5471aad6b673c169 if (true) { // CraftBukkit this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds -@@ -1196,7 +1196,7 @@ public class ServerPlayer extends Player { +@@ -1181,7 +1181,7 @@ public class ServerPlayer extends Player { worldserver.addDuringPortalTeleport(this); this.connection.teleport(exit); // CraftBukkit - use internal teleport without event this.connection.resetPosition(); // CraftBukkit - sync position after changing it (from PortalTravelAgent#findAndteleport) @@ -1061,10 +1013,10 @@ index 5725c6593480fada65facc29664a00a8cc073512..ccb1f998ae3122d1856d77149ff7e7df }; } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f126630a968f5e 100644 +index 4f5c3c4285dd3b7ac901fb55e1ebbfec37ca601f..efd84a22bc063fe6266be876a38186c08296caa2 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -821,7 +821,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -822,7 +822,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return; } // Pufferfish end - entity TTL @@ -1073,7 +1025,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 if (firstTick && this instanceof net.minecraft.world.entity.NeutralMob neutralMob) neutralMob.tickInitialPersistentAnger(level); // Paper - Update last hurt when ticking this.feetBlockState = null; if (this.isPassenger() && this.getVehicle().isRemoved()) { -@@ -882,7 +882,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -883,7 +883,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } this.firstTick = false; @@ -1082,7 +1034,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 } public void setSharedFlagOnFire(boolean onFire) { -@@ -1056,7 +1056,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -1057,7 +1057,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } } @@ -1091,7 +1043,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7D) { movement = movement.multiply(this.stuckSpeedMultiplier); this.stuckSpeedMultiplier = Vec3.ZERO; -@@ -1065,7 +1065,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -1066,7 +1066,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { // Paper start - ignore movement changes while inactive. if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) { setDeltaMovement(Vec3.ZERO); @@ -1100,7 +1052,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 return; } // Paper end -@@ -1086,8 +1086,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -1087,8 +1087,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { this.setPos(this.getX() + vec3d1.x, this.getY() + vec3d1.y, this.getZ() + vec3d1.z); } @@ -1111,7 +1063,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 boolean flag = !Mth.equal(movement.x, vec3d1.x); boolean flag1 = !Mth.equal(movement.z, vec3d1.z); -@@ -1106,7 +1106,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -1107,7 +1107,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { this.checkFallDamage(vec3d1.y, this.onGround, iblockdata, blockposition); if (this.isRemoved()) { @@ -1120,7 +1072,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 } else { if (this.horizontalCollision) { Vec3 vec3d2 = this.getDeltaMovement(); -@@ -1247,7 +1247,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -1248,7 +1248,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { this.setRemainingFireTicks(-this.getFireImmuneTicks()); } @@ -1129,7 +1081,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 } } // Paper start - detailed watchdog information -@@ -2916,7 +2916,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -2917,7 +2917,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { ServerLevel worldserver1 = minecraftserver.getLevel(resourcekey); if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit @@ -1138,7 +1090,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 this.portalTime = i; // Paper start io.papermc.paper.event.entity.EntityPortalReadyEvent event = new io.papermc.paper.event.entity.EntityPortalReadyEvent(this.getBukkitEntity(), worldserver1 == null ? null : worldserver1.getWorld(), org.bukkit.PortalType.NETHER); -@@ -2934,7 +2934,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -2935,7 +2935,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } } // Paper // CraftBukkit end @@ -1147,7 +1099,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 } this.isInsidePortal = false; -@@ -3388,14 +3388,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -3389,14 +3389,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } // Paper end if (this.level instanceof ServerLevel && !this.isRemoved()) { @@ -1164,7 +1116,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 PortalInfo shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit if (shapedetectorshape == null) { -@@ -3429,7 +3429,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -3430,7 +3430,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { this.unRide(); // CraftBukkit end @@ -1173,7 +1125,7 @@ index cc355ddb74568717f28c74ab31566cd09c1209d7..2c7554a1dd092aca9dd1988b99f12663 // Paper start - Change lead drop timing to prevent dupe if (this instanceof Mob) { ((Mob) this).dropLeash(true, true); // Paper drop lead -@@ -3452,10 +3452,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -3453,10 +3453,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } this.removeAfterChangingDimensions(); @@ -1456,10 +1408,10 @@ index 0cc0d719e95e108263683b7a40f4ce3a8ca9465b..872ec431ae6beb0ef603d833f38aedb9 public Set getAvailableGoals() { diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index cb4a162903207754be90ff8da0156f97791cccef..9e6c4c2935e0a2cadfbf3da73eb4fe1881078c5a 100644 +index c1781c92ff59f0c9eb47cbbef01e3252c5e1a1bf..c06057cf9609e001f4512c247f355ded0ff2e8ce 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -173,12 +173,12 @@ public abstract class PathNavigation { +@@ -170,12 +170,12 @@ public abstract class PathNavigation { } } // Paper end @@ -1471,9 +1423,9 @@ index cb4a162903207754be90ff8da0156f97791cccef..9e6c4c2935e0a2cadfbf3da73eb4fe18 Path path = this.pathFinder.findPath(pathNavigationRegion, this.mob, positions, followRange, distance, this.maxVisitedNodesMultiplier); - this.level.getProfiler().pop(); + //this.level.getProfiler().pop(); // Purpur - - // Pufferfish start - if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncPathfinding) { + if (path != null && path.getTarget() != null) { + this.targetPos = path.getTarget(); + this.reachRange = distance; diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java index 288c6627906d07c0d223eacd84ae4eb31a349998..9babe636176da3c40598eb5bdac0919a1704eaa0 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java @@ -1535,7 +1487,7 @@ index b543387da275a0b3675a968b6cebf05cc227af14..2e0f340f9b339b1d772c0676e97c12f3 Optional optional = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS); diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -index b84effd5e18fee155e731d1a80ba516b86431d3b..989af6f3e0604a342032b308f97c7b863b3b1e40 100644 +index e739416fa58b182d7bd311be094d6aab2a7f7133..22f8db91f31be6a6d981c70e2ab94d031723ac9c 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java @@ -230,13 +230,13 @@ public class Frog extends Animal { @@ -1730,10 +1682,10 @@ index 01477e7240f9e33d08d416a7d40ee10f3e5d4abf..c9def2202d7c2a523858ec124df2beaf } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index bd89e00f707b6ba297081c9aacb3c5463e80063e..5e0fb02ccd1204a72b2d730a25e35844a07c5759 100644 +index 93711ef7df591ab0f50b8f0f7798f938eeb0f3b3..cf8693d02de53f1e02d55936f889c5724889e3f5 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -713,9 +713,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -712,9 +712,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { BlockState iblockdata2 = this.getBlockState(pos); if ((flags & 128) == 0 && iblockdata2 != iblockdata1 && (iblockdata2.getLightBlock(this, pos) != iblockdata1.getLightBlock(this, pos) || iblockdata2.getLightEmission() != iblockdata1.getLightEmission() || iblockdata2.useShapeForLightOcclusion() || iblockdata1.useShapeForLightOcclusion())) { @@ -1745,7 +1697,7 @@ index bd89e00f707b6ba297081c9aacb3c5463e80063e..5e0fb02ccd1204a72b2d730a25e35844 } /* -@@ -992,9 +992,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -991,9 +991,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } protected void tickBlockEntities() { @@ -1757,7 +1709,7 @@ index bd89e00f707b6ba297081c9aacb3c5463e80063e..5e0fb02ccd1204a72b2d730a25e35844 //timings.tileEntityPending.startTiming(); // Spigot // Purpur this.tickingBlockEntities = true; if (!this.pendingBlockEntityTickers.isEmpty()) { -@@ -1039,7 +1039,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1038,7 +1038,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { //timings.tileEntityTick.stopTiming(); // Spigot // Purpur this.tickingBlockEntities = false; co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper @@ -1766,16 +1718,16 @@ index bd89e00f707b6ba297081c9aacb3c5463e80063e..5e0fb02ccd1204a72b2d730a25e35844 spigotConfig.currentPrimedTnt = 0; // Spigot } -@@ -1200,7 +1200,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1199,7 +1199,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { - this.getProfiler().incrementCounter("getEntities"); + //this.getProfiler().incrementCounter("getEntities"); // Purpur List list = Lists.newArrayList(); - this.entitySliceManager.getEntities(except, box, list, predicate); // Paper - optimise this call + ((ServerLevel)this).getEntityLookup().getEntities(except, box, list, predicate); // Paper - optimise this call return list; -@@ -1208,7 +1208,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1207,7 +1207,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public List getEntities(EntityTypeTest filter, AABB box, Predicate predicate) { @@ -1784,7 +1736,7 @@ index bd89e00f707b6ba297081c9aacb3c5463e80063e..5e0fb02ccd1204a72b2d730a25e35844 List list = Lists.newArrayList(); // Paper start - optimise this call -@@ -1539,7 +1539,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1538,7 +1538,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } public ProfilerFiller getProfiler() { @@ -1816,10 +1768,10 @@ index 5c6fde4baf27e7d8f027c138d843da39a4a2ed36..4a8998a98987985e259b0a2a29ee7c94 // Paper start diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index ab024c5315c0a7cb2f80d5d7b251f6a3531879b3..12293740461b6cd965297543a1ae3bead83bd3a6 100644 +index b4460ed16ba30173ad4a5fe8e405e1c34251912f..6638a4fd77230ec9d5b5db097e9ee1a3cc92a726 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1236,9 +1236,9 @@ public class LevelChunk extends ChunkAccess { +@@ -1289,9 +1289,9 @@ public class LevelChunk extends ChunkAccess { if (LevelChunk.this.isTicking(blockposition)) { try { @@ -1831,7 +1783,7 @@ index ab024c5315c0a7cb2f80d5d7b251f6a3531879b3..12293740461b6cd965297543a1ae3bea //this.blockEntity.tickTimer.startTiming(); // Spigot // Purpur BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); -@@ -1250,7 +1250,7 @@ public class LevelChunk extends ChunkAccess { +@@ -1303,7 +1303,7 @@ public class LevelChunk extends ChunkAccess { LevelChunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new Object[]{LogUtils.defer(this::getType), LogUtils.defer(this::getPos), iblockdata}); } @@ -1841,20 +1793,20 @@ index ab024c5315c0a7cb2f80d5d7b251f6a3531879b3..12293740461b6cd965297543a1ae3bea if (throwable instanceof ThreadDeath) throw throwable; // Paper // Paper start - Prevent tile entity and entity crashes diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index 0455c8a7da880da4f0b7ae9d57e83e281a55f0ae..23cb03d28c43729d5b5d450cd975456512477353 100644 +index d23481453717f715124156b5d83f6448f720d049..a8af51a25b0f99c3a64d9150fdfcd6b818aa7581 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -80,8 +80,8 @@ public class PathFinder { +@@ -53,8 +53,8 @@ public class PathFinder { + @Nullable // Paper start - optimize collection private Path findPath(ProfilerFiller profiler, Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { - // readd the profiler code for sync - profiler.push("find_path"); - profiler.markForCharting(MetricCategory.PATH_FINDING); + //profiler.push("find_path"); // Purpur + //profiler.markForCharting(MetricCategory.PATH_FINDING); // Purpur - - try { - return this.processPath(this.nodeEvaluator, startNode, positions, followRange, distance, rangeMultiplier); + // Set set = positions.keySet(); + startNode.g = 0.0F; + startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection diff --git a/src/main/java/net/minecraft/world/ticks/LevelTicks.java b/src/main/java/net/minecraft/world/ticks/LevelTicks.java index 7f1ac2cb29eb84833c0895442d611dfa0504527e..5dea8414964e0d2d1fb15a6baa27227e9722bfc7 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelTicks.java diff --git a/patches/server/0292-Debug-Marker-API.patch b/patches/server/0292-Debug-Marker-API.patch index 16881d98e..8aa25f287 100644 --- a/patches/server/0292-Debug-Marker-API.patch +++ b/patches/server/0292-Debug-Marker-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Debug Marker API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0b1f803fb6e23e4bcd015aacc63be864c87dca6b..3fffeff2f7e12c021ac4d1e6754583f58a03f12f 100644 +index 14a9e509b4da2b4ad1f67d8c5533c36ad437704b..e9c20441e37db68d500c230a4371610f98c69428 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1468,6 +1468,42 @@ public final class CraftServer implements Server { @@ -52,10 +52,10 @@ index 0b1f803fb6e23e4bcd015aacc63be864c87dca6b..3fffeff2f7e12c021ac4d1e6754583f5 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4b9d57a63a0eb922f77d34e4d2d7f3b0aa364337..42058ebca02f1ae7fdf970b9fdf36afc4d486e87 100644 +index 68eb990c7d461c611310419c1eefaed79a7c8538..dabf1649f5bf14ec17dad6d43dcd7e2b7df255d3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2251,6 +2251,42 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2238,6 +2238,42 @@ public class CraftWorld extends CraftRegionAccessor implements World { public float getLocalDifficultyAt(Location location) { return getHandle().getCurrentDifficultyAt(net.minecraft.server.MCUtil.toBlockPosition(location)).getEffectiveDifficulty(); } @@ -99,7 +99,7 @@ index 4b9d57a63a0eb922f77d34e4d2d7f3b0aa364337..42058ebca02f1ae7fdf970b9fdf36afc @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3ba2cb10615069b78ad2f86f7bc0d2080b2f5472..0389107aba8f9f71f3d9defec167592e63f529b8 100644 +index 4260f540717afe6ed16f4f87f394c483537079e1..ab5ce7e867a3668d21071da73b84d197a34d3571 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -3019,5 +3019,48 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0295-Make-pufferfish-config-relocatable.patch b/patches/server/0295-Make-pufferfish-config-relocatable.patch index 88884410a..07d44f875 100644 --- a/patches/server/0295-Make-pufferfish-config-relocatable.patch +++ b/patches/server/0295-Make-pufferfish-config-relocatable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make pufferfish config relocatable diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -index e077a43cf3f06207234cb445b58dff79eabcb9c6..852ed093488ae624960a7dd35f68d8cee39067e7 100644 +index 0d32a0bb4bbd34dbeffea95cf8403ae54ef8f227..88d1c75c51ffc2e5f334b0c9d12ca63ff463ff0a 100644 --- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java +++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -36,6 +36,7 @@ public class PufferfishConfig { +@@ -28,6 +28,7 @@ public class PufferfishConfig { private static final YamlFile config = new YamlFile(); private static int updates = 0; @@ -16,7 +16,7 @@ index e077a43cf3f06207234cb445b58dff79eabcb9c6..852ed093488ae624960a7dd35f68d8ce private static ConfigurationSection convertToBukkit(org.simpleyaml.configuration.ConfigurationSection section) { ConfigurationSection newSection = new MemoryConfiguration(); -@@ -58,7 +59,7 @@ public class PufferfishConfig { +@@ -50,7 +51,7 @@ public class PufferfishConfig { } public static void load() throws IOException { @@ -26,7 +26,7 @@ index e077a43cf3f06207234cb445b58dff79eabcb9c6..852ed093488ae624960a7dd35f68d8ce if (configFile.exists()) { try { diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 0bfdc4247a651f6c1caf7a95114be68bc7d77d7b..33ec9cb7efd5623866c03506b8dcb28831b54b21 100644 +index c8b068ab73c8997fbd07e27ccd2dff77fef6bfe1..a029f51983bcfe49beab1359f282f0f957723ef2 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -235,6 +235,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface