mirror of
https://github.com/PaperMC/Paper.git
synced 2024-10-30 23:39:58 +01:00
789bc79280
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: c9a46ebf #653: Add World#spawn with randomizeData parameter e49c2e3a Damageable should extend ItemMeta 01ff04f4 SPIGOT-5880, SPIGOT-5567: New ChunkGenerator API ca5b4b1a SPIGOT-6697: Deprecate generateTree with BlockChangeDelegate as it does not handle tiles CraftBukkit Changes: 7c8bbcbe SPIGOT-6716: Preserve the order of stored enchantments of enchanted books. 18027d02 #914: Add World#spawn with randomizeData parameter 3cad0316 SPIGOT-6714: Don't fire PlayerBucketEvent when empty 8c6d60cf Fix server crash with BlockPopulator when entities are at a negative chunk border 4f6bcc84 SPIGOT-5880, SPIGOT-5567: New ChunkGenerator API 78d5b35b SPIGOT-6697: Restore generateTree with BlockChangeDelegate behaviour 15792f0d Rebuild patch c949675e SPIGOT-6713: Cancelling EntityTransformEvent Causes Deceased Slimes To Not Despawn a955f15c Fix issues with new ChunkGenerator API a0a37f41 SPIGOT-6630: Replacing an enchantment on an item creates a conflict error Spigot Changes: b166a49b Rebuild patches 3c1fc60a SPIGOT-6693: Composters only take in one item at custom hopper speeds
127 lines
6.3 KiB
Diff
127 lines
6.3 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: underscore11code <minecrafter11mrt@gmail.com>
|
|
Date: Fri, 23 Jul 2021 23:01:42 -0700
|
|
Subject: [PATCH] Add System.out/err catcher
|
|
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/logging/SysoutCatcher.java b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..88608afed45f25f822121214f87e9f9b53143104
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
|
@@ -0,0 +1,94 @@
|
|
+package io.papermc.paper.logging;
|
|
+
|
|
+import org.bukkit.Bukkit;
|
|
+import org.bukkit.plugin.java.JavaPlugin;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+
|
|
+import java.io.OutputStream;
|
|
+import java.io.PrintStream;
|
|
+import java.util.Objects;
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
+import java.util.concurrent.ConcurrentMap;
|
|
+import java.util.concurrent.TimeUnit;
|
|
+import java.util.logging.Level;
|
|
+
|
|
+public final class SysoutCatcher {
|
|
+ private static final boolean SUPPRESS_NAGS = Boolean.getBoolean("io.papermc.paper.suppress.sout.nags");
|
|
+ // Nanoseconds between nag at most; if interval is caught first, this is reset.
|
|
+ // <= 0 for disabling.
|
|
+ private static final long NAG_TIMEOUT = TimeUnit.MILLISECONDS.toNanos(
|
|
+ Long.getLong("io.papermc.paper.sout.nags.timeout", TimeUnit.MINUTES.toMillis(5L)));
|
|
+ // Count since last nag; if timeout is first, this is reset.
|
|
+ // <= 0 for disabling.
|
|
+ private static final long NAG_INTERVAL = Long.getLong("io.papermc.paper.sout.nags.interval", 200L);
|
|
+
|
|
+ // We don't particularly care about how correct this is at any given moment; let's do it on a best attempt basis.
|
|
+ // The records are also pretty small, so let's just go for a size of 64 to start...
|
|
+ //
|
|
+ // Content: Plugin name => nag object
|
|
+ // Why plugin name?: This doesn't store a reference to the plugin; keeps the reload ability.
|
|
+ // Why not clean on reload?: Effort.
|
|
+ private final ConcurrentMap<String, PluginNag> nagRecords = new ConcurrentHashMap<>(64);
|
|
+
|
|
+ public SysoutCatcher() {
|
|
+ System.setOut(new WrappedOutStream(System.out, Level.INFO, "[STDOUT] "));
|
|
+ System.setErr(new WrappedOutStream(System.err, Level.SEVERE, "[STDERR] "));
|
|
+ }
|
|
+
|
|
+ private final class WrappedOutStream extends PrintStream {
|
|
+ private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
|
|
+ private final Level level;
|
|
+ private final String prefix;
|
|
+
|
|
+ public WrappedOutStream(@NotNull final OutputStream out, final Level level, final String prefix) {
|
|
+ super(out);
|
|
+ this.level = level;
|
|
+ this.prefix = prefix;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void println(@Nullable final String line) {
|
|
+ final Class<?> clazz = STACK_WALKER.getCallerClass();
|
|
+ try {
|
|
+ final JavaPlugin plugin = JavaPlugin.getProvidingPlugin(clazz);
|
|
+
|
|
+ // Instead of just printing the message, send it to the plugin's logger
|
|
+ plugin.getLogger().log(this.level, this.prefix + line);
|
|
+
|
|
+ if (SysoutCatcher.SUPPRESS_NAGS) {
|
|
+ return;
|
|
+ }
|
|
+ if (SysoutCatcher.NAG_INTERVAL > 0 || SysoutCatcher.NAG_TIMEOUT > 0) {
|
|
+ final PluginNag nagRecord = SysoutCatcher.this.nagRecords.computeIfAbsent(plugin.getName(), k -> new PluginNag());
|
|
+ final boolean hasTimePassed = SysoutCatcher.NAG_TIMEOUT > 0
|
|
+ && (nagRecord.lastNagTimestamp == Long.MIN_VALUE
|
|
+ || nagRecord.lastNagTimestamp + SysoutCatcher.NAG_TIMEOUT <= System.nanoTime());
|
|
+ final boolean hasMessagesPassed = SysoutCatcher.NAG_INTERVAL > 0
|
|
+ && (nagRecord.messagesSinceNag == Long.MIN_VALUE
|
|
+ || ++nagRecord.messagesSinceNag >= SysoutCatcher.NAG_INTERVAL);
|
|
+ if (!hasMessagesPassed && !hasTimePassed) {
|
|
+ return;
|
|
+ }
|
|
+ nagRecord.lastNagTimestamp = System.nanoTime();
|
|
+ nagRecord.messagesSinceNag = 0;
|
|
+ }
|
|
+ Bukkit.getLogger().warning(
|
|
+ String.format("Nag author(s): '%s' of '%s' about their usage of System.out/err.print. "
|
|
+ + "Please use your plugin's logger instead (JavaPlugin#getLogger).",
|
|
+ plugin.getDescription().getAuthors(),
|
|
+ plugin.getName())
|
|
+ );
|
|
+ } catch (final IllegalArgumentException | IllegalStateException e) {
|
|
+ // If anything happens, the calling class doesn't exist, there is no JavaPlugin that "owns" the calling class, etc
|
|
+ // Just print out normally, with some added information
|
|
+ Bukkit.getLogger().log(this.level, String.format("[%s] %s %s", this.prefix, clazz.getName(), line));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static class PluginNag {
|
|
+ private long lastNagTimestamp = Long.MIN_VALUE;
|
|
+ private long messagesSinceNag = Long.MIN_VALUE;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index ea9f97bc5196a26ae5caaf48fa846bf92e8f6188..41255bc4c03a02e76fbfc3b0b34c907fb3ad05b1 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle;
|
|
import io.netty.buffer.ByteBuf;
|
|
import io.netty.buffer.ByteBufOutputStream;
|
|
import io.netty.buffer.Unpooled;
|
|
+import io.papermc.paper.logging.SysoutCatcher;
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
@@ -283,6 +284,7 @@ public final class CraftServer implements Server {
|
|
public int reloadCount;
|
|
private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper
|
|
public static Exception excessiveVelEx; // Paper - Velocity warnings
|
|
+ private final SysoutCatcher sysoutCatcher = new SysoutCatcher(); // Paper
|
|
|
|
static {
|
|
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
|