From adc78043f5f19537fcd0c271576e097065467911 Mon Sep 17 00:00:00 2001 From: Encode42 Date: Thu, 6 Apr 2023 16:09:01 -0400 Subject: [PATCH] Add environment variable to ignore kick-if-idle value --- .../0001-Pufferfish-Server-Changes.patch | 830 +----------------- .../server/0002-Fix-pufferfish-issues.patch | 6 +- patches/server/0003-Rebrand.patch | 6 +- patches/server/0012-AFK-API.patch | 4 +- patches/server/0276-Remove-Timings.patch | 27 +- ...5-Make-pufferfish-config-relocatable.patch | 6 +- 6 files changed, 20 insertions(+), 859 deletions(-) diff --git a/patches/server/0001-Pufferfish-Server-Changes.patch b/patches/server/0001-Pufferfish-Server-Changes.patch index 65ad068b6..0a9df1178 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 9cf389defdaeb887e9cad4f0fed3f3b95667b238..3c8293f002f11b430083502362fdc801f44aa138 100644 +index 9cf389defdaeb887e9cad4f0fed3f3b95667b238..b41b186397d013c19436c345be98b785d4bd0295 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,12 @@ plugins { @@ -38,7 +38,7 @@ index 9cf389defdaeb887e9cad4f0fed3f3b95667b238..3c8293f002f11b430083502362fdc801 // Paper start implementation("org.jline:jline-terminal-jansi:3.21.0") implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -42,6 +46,14 @@ dependencies { +@@ -42,6 +46,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 9cf389defdaeb887e9cad4f0fed3f3b95667b238..3c8293f002f11b430083502362fdc801 + 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") -@@ -50,6 +62,14 @@ dependencies { +@@ -50,6 +61,14 @@ dependencies { } val craftbukkitPackageVersion = "1_19_R3" // Paper @@ -68,7 +67,7 @@ index 9cf389defdaeb887e9cad4f0fed3f3b95667b238..3c8293f002f11b430083502362fdc801 tasks.jar { archiveClassifier.set("dev") -@@ -62,7 +82,7 @@ tasks.jar { +@@ -62,7 +81,7 @@ tasks.jar { attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "CraftBukkit", @@ -617,10 +616,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..e0076044d0a29e33ee297fe6180a041436075297 +index 0000000000000000000000000000000000000000..6e441a1a28ba72a8b1cc09fe5fca71b3c70627d4 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -0,0 +1,317 @@ +@@ -0,0 +1,285 @@ +package gg.pufferfish.pufferfish; + +import gg.pufferfish.pufferfish.simd.SIMDDetection; @@ -638,7 +637,6 @@ index 0000000000000000000000000000000000000000..e0076044d0a29e33ee297fe6180a0414 +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; @@ -647,13 +645,6 @@ index 0000000000000000000000000000000000000000..e0076044d0a29e33ee297fe6180a0414 +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 { + @@ -904,30 +895,6 @@ index 0000000000000000000000000000000000000000..e0076044d0a29e33ee297fe6180a0414 + "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; @@ -1103,699 +1070,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..029d840e28d67d26d3c0dd6785e25dbf15f9226c ---- /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 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() { -+ if (true) return; // This doesn't work, and it's not worth fixing at the moment. -+ int entities = 0; -+ int chunkCount = 0; -+ int tileEntityCount = 0; -+ -+ if (!Bukkit.isStopping()) { -+ for (World world : Bukkit.getWorlds()) { -+ world.getEntityCount(); -+ 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/sentry/PufferfishSentryAppender.java b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java new file mode 100644 index 0000000000000000000000000000000000000000..731ef11c7a025ae95ed8a757b530d834733d0621 @@ -2171,49 +1445,6 @@ index 0000000000000000000000000000000000000000..facd55463d44cb7e3d2ca6892982f549 + return backingMap.size(); + } +} -diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index 8d442c5a498ecf288a0cc0c54889c6e2fda849ce..01bdf134fc21220ab7ecca51f2dcd51c0b466bba 100644 ---- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -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; -+import org.bukkit.Bukkit; // Pufferfish - import org.checkerframework.checker.nullness.qual.Nullable; - import org.spongepowered.configurate.objectmapping.ConfigSerializable; - import org.spongepowered.configurate.objectmapping.meta.Comment; -@@ -16,6 +17,7 @@ import org.spongepowered.configurate.objectmapping.meta.Setting; - import java.util.List; - import java.util.Map; - import java.util.Objects; -+import java.util.logging.Level; // Pufferfish - - @SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"}) - public class GlobalConfiguration extends ConfigurationPart { -@@ -51,6 +53,7 @@ public class GlobalConfiguration extends ConfigurationPart { - - public class Timings extends ConfigurationPart.Post { - public boolean enabled = true; -+ public boolean reallyEnabled = false; - public boolean verbose = true; - public String url = "https://timings.aikar.co/"; - public boolean serverNamePrivacy = false; -@@ -64,6 +67,14 @@ public class GlobalConfiguration extends ConfigurationPart { - - @Override - public void postProcess() { -+ // Pufferfish start -+ if (enabled && !reallyEnabled) { -+ Bukkit.getLogger().log(Level.WARNING, "[Pufferfish] To improve performance, timings have been disabled by default"); -+ Bukkit.getLogger().log(Level.WARNING, "[Pufferfish] You can still use timings by using /timings on, but they will not start on server startup unless you set timings.really-enabled to true in paper.yml"); -+ Bukkit.getLogger().log(Level.WARNING, "[Pufferfish] If you would like to disable this message, either set timings.really-enabled to true or timings.enabled to false."); -+ } -+ enabled = reallyEnabled; -+ // Pufferfish end - MinecraftTimings.processConfig(this); - } - } diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java index 6efb8b10f17c70b05128039376d254e6beda3841..57e8c6673c7cfe447a75f15506e8000062d813fe 100644 --- a/src/main/java/io/papermc/paper/util/MCUtil.java @@ -4235,43 +3466,6 @@ index f7ea77dd82d978ad307f99c743efacfb34478b3d..009ab06182359862b8f543030ec4fe4e + MinecraftServer.getServer().getRecipeManager().addRecipe(new net.minecraft.world.item.crafting.ShapelessRecipe(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftRecipe.getCategory(this.getCategory()), 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 d96399e9bf1a58db5a4a22e58abb99e7660e0694..eb19f679ee498e51d02fe9a961cf02699cf75848 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"; -@@ -81,7 +82,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 -@@ -91,7 +97,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 64c50c52c11214740de7903e5592b8b6b2c170b3..d4f62940504e3ef7a70e13b1f4a7726f23b4c637 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -4285,18 +3479,6 @@ index 64c50c52c11214740de7903e5592b8b6b2c170b3..d4f62940504e3ef7a70e13b1f4a7726f } @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 b263b448a..f78d16ff3 100644 --- a/patches/server/0002-Fix-pufferfish-issues.patch +++ b/patches/server/0002-Fix-pufferfish-issues.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix pufferfish issues diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -index e0076044d0a29e33ee297fe6180a041436075297..e6b26f883c4cc0473cfddb091b8b1b2e58cb1b72 100644 +index 6e441a1a28ba72a8b1cc09fe5fca71b3c70627d4..5c691db595ee412b77f729e90172bc4f8ae57226 100644 --- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java +++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -232,7 +232,7 @@ public class PufferfishConfig { +@@ -224,7 +224,7 @@ public class PufferfishConfig { public static int activationDistanceMod; private static void dynamicActivationOfBrains() throws IOException { @@ -17,7 +17,7 @@ index e0076044d0a29e33ee297fe6180a041436075297..e6b26f883c4cc0473cfddb091b8b1b2e startDistance = getInt("dab.start-distance", "activation-range.start-distance", 12, "This value determines how far away an entity has to be", "from the player to start being effected by DEAR."); -@@ -276,7 +276,7 @@ public class PufferfishConfig { +@@ -268,7 +268,7 @@ public class PufferfishConfig { public static boolean throttleInactiveGoalSelectorTick; private static void inactiveGoalSelectorThrottle() { diff --git a/patches/server/0003-Rebrand.patch b/patches/server/0003-Rebrand.patch index a915cdda7..81d1eb339 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 3c8293f002f11b430083502362fdc801f44aa138..6c5b3f6a2c4f7b20e3388b63c36b7c4bc4cf179f 100644 +index b41b186397d013c19436c345be98b785d4bd0295..22470f0ab8354a9f31a0f195f3fe80f2f5ee2f0e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,12 +7,8 @@ plugins { @@ -34,7 +34,7 @@ index 3c8293f002f11b430083502362fdc801f44aa138..6c5b3f6a2c4f7b20e3388b63c36b7c4b 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") -@@ -82,7 +82,7 @@ tasks.jar { +@@ -81,7 +81,7 @@ tasks.jar { attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "CraftBukkit", @@ -43,7 +43,7 @@ index 3c8293f002f11b430083502362fdc801f44aa138..6c5b3f6a2c4f7b20e3388b63c36b7c4b "Implementation-Vendor" to date, // Paper "Specification-Title" to "Bukkit", "Specification-Version" to project.version, -@@ -154,7 +154,7 @@ fun TaskContainer.registerRunTask( +@@ -153,7 +153,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { diff --git a/patches/server/0012-AFK-API.patch b/patches/server/0012-AFK-API.patch index 515228535..d767e7371 100644 --- a/patches/server/0012-AFK-API.patch +++ b/patches/server/0012-AFK-API.patch @@ -281,7 +281,7 @@ index 2f684a8f976f1f1a18c31f4c1a7eba9080099e55..c517873abdcb1e5334ba9e7a1c2f06bb public static int barrelRows = 3; diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 46b6994812086405f20a4dd410c1d79621958cd5..21a33a7952ea9d70df45a99e82286713fd939696 100644 +index 46b6994812086405f20a4dd410c1d79621958cd5..cbb750eabb892348b3b6632782e9eef9b125d16d 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -92,6 +92,24 @@ public class PurpurWorldConfig { @@ -299,7 +299,7 @@ index 46b6994812086405f20a4dd410c1d79621958cd5..21a33a7952ea9d70df45a99e82286713 + set("gameplay-mechanics.player.idle-timeout.mods-target", null); + set("gameplay-mechanics.player.idle-timeout.mobs-target", oldVal); + } -+ idleTimeoutKick = getBoolean("gameplay-mechanics.player.idle-timeout.kick-if-idle", idleTimeoutKick); ++ idleTimeoutKick = System.getenv("PURPUR_FORCE_IDLE_KICK") == null ? getBoolean("gameplay-mechanics.player.idle-timeout.kick-if-idle", idleTimeoutKick) : Boolean.parseBoolean(System.getenv("PURPUR_FORCE_IDLE_KICK")); + idleTimeoutTickNearbyEntities = getBoolean("gameplay-mechanics.player.idle-timeout.tick-nearby-entities", idleTimeoutTickNearbyEntities); + idleTimeoutCountAsSleeping = getBoolean("gameplay-mechanics.player.idle-timeout.count-as-sleeping", idleTimeoutCountAsSleeping); + idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList); diff --git a/patches/server/0276-Remove-Timings.patch b/patches/server/0276-Remove-Timings.patch index 7a60702db..9923054ae 100644 --- a/patches/server/0276-Remove-Timings.patch +++ b/patches/server/0276-Remove-Timings.patch @@ -42,27 +42,6 @@ index 8013dd333e27aa5fd0beb431fa32491eec9f5246..e42eb93fd9f6f51ff5bb4b14a2304d4f return executedUnloadTask | canSaveChunk | canSaveEntities | canSavePOI ? new SaveStat(executedUnloadTask || canSaveChunk, canSaveEntities, canSavePOI): null; } -diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index 01bdf134fc21220ab7ecca51f2dcd51c0b466bba..6bf14183a3fcd2b3d166752ce33240d2ff1ffa7c 100644 ---- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -67,14 +67,14 @@ public class GlobalConfiguration extends ConfigurationPart { - - @Override - public void postProcess() { -- // Pufferfish start -+ /*// Pufferfish start // Purpur - if (enabled && !reallyEnabled) { - Bukkit.getLogger().log(Level.WARNING, "[Pufferfish] To improve performance, timings have been disabled by default"); - Bukkit.getLogger().log(Level.WARNING, "[Pufferfish] You can still use timings by using /timings on, but they will not start on server startup unless you set timings.really-enabled to true in paper.yml"); - Bukkit.getLogger().log(Level.WARNING, "[Pufferfish] If you would like to disable this message, either set timings.really-enabled to true or timings.enabled to false."); - } - enabled = reallyEnabled; -- // Pufferfish end -+ */// Pufferfish end // Purpur - MinecraftTimings.processConfig(this); - } - } diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java index d2f0a0755317f5fa9a1ccf7db346aa77fd287d80..03852e7d21d9470a4469676367463fefb38acdc6 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java @@ -77,7 +56,7 @@ index d2f0a0755317f5fa9a1ccf7db346aa77fd287d80..03852e7d21d9470a4469676367463fef } catch (Exception exception) { if (listener.shouldPropagateHandlingExceptions()) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 64b4397a3d91d9c5a29498e738c317f362106fec..123c7f9730a999ea5ea11de817fa61cc455e6962 100644 +index 0decdb4687734ed901929115d176e5128db4d390..68552716b7ed7f93cb84b1951af85344dc2e83b0 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1408,15 +1408,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop