mirror of
https://github.com/PaperMC/Paper.git
synced 2025-07-31 12:12:08 -07:00
More patches
This commit is contained in:
105
patches/server/Add-TickThread.patch
Normal file
105
patches/server/Add-TickThread.patch
Normal file
@@ -0,0 +1,105 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 3 Mar 2019 20:53:18 -0800
|
||||
Subject: [PATCH] Add TickThread
|
||||
|
||||
Placeholder patch, to be used by chunksystem rewrite
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/TickThread.java b/src/main/java/io/papermc/paper/util/TickThread.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/TickThread.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.world.entity.Entity;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import java.util.concurrent.atomic.AtomicInteger;
|
||||
+
|
||||
+public final class TickThread extends Thread {
|
||||
+
|
||||
+ public static final boolean STRICT_THREAD_CHECKS = Boolean.getBoolean("paper.strict-thread-checks");
|
||||
+
|
||||
+ static {
|
||||
+ if (STRICT_THREAD_CHECKS) {
|
||||
+ MinecraftServer.LOGGER.warn("Strict thread checks enabled - performance may suffer");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void softEnsureTickThread(final String reason) {
|
||||
+ if (!STRICT_THREAD_CHECKS) {
|
||||
+ return;
|
||||
+ }
|
||||
+ ensureTickThread(reason);
|
||||
+ }
|
||||
+
|
||||
+ public static void ensureTickThread(final String reason) {
|
||||
+ if (!isTickThread()) {
|
||||
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
+ throw new IllegalStateException(reason);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void ensureTickThread(final ServerLevel world, final int chunkX, final int chunkZ, final String reason) {
|
||||
+ if (!isTickThreadFor(world, chunkX, chunkZ)) {
|
||||
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
+ throw new IllegalStateException(reason);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void ensureTickThread(final Entity entity, final String reason) {
|
||||
+ if (!isTickThreadFor(entity)) {
|
||||
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
+ throw new IllegalStateException(reason);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public final int id; /* We don't override getId as the spec requires that it be unique (with respect to all other threads) */
|
||||
+
|
||||
+ private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
|
||||
+
|
||||
+ public TickThread(final String name) {
|
||||
+ this(null, name);
|
||||
+ }
|
||||
+
|
||||
+ public TickThread(final Runnable run, final String name) {
|
||||
+ this(run, name, ID_GENERATOR.incrementAndGet());
|
||||
+ }
|
||||
+
|
||||
+ private TickThread(final Runnable run, final String name, final int id) {
|
||||
+ super(run, name);
|
||||
+ this.id = id;
|
||||
+ }
|
||||
+
|
||||
+ public static TickThread getCurrentTickThread() {
|
||||
+ return (TickThread)Thread.currentThread();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean isTickThread() {
|
||||
+ return Bukkit.isPrimaryThread();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ) {
|
||||
+ return Bukkit.isPrimaryThread();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean isTickThreadFor(final Entity entity) {
|
||||
+ return Bukkit.isPrimaryThread();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
|
||||
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
|
||||
@@ -0,0 +0,0 @@ public class AsyncCatcher
|
||||
|
||||
public static void catchOp(String reason)
|
||||
{
|
||||
- if ( AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread )
|
||||
+ if ( (AsyncCatcher.enabled || io.papermc.paper.util.TickThread.STRICT_THREAD_CHECKS) && Thread.currentThread() != MinecraftServer.getServer().serverThread ) // Paper
|
||||
{
|
||||
throw new IllegalStateException( "Asynchronous " + reason + "!" );
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Tue, 18 May 2021 14:39:44 -0700
|
||||
Subject: [PATCH] Add command line option to load extra plugin jars not in the
|
||||
plugins folder
|
||||
|
||||
ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
|
||||
io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.INSTANCE.enter(io.papermc.paper.plugin.entrypoint.Entrypoint.PLUGIN); // Paper - replace implementation
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public File getPluginsFolder() {
|
||||
+ return (File) this.console.options.valueOf("plugins");
|
||||
+ }
|
||||
+
|
||||
+ private List<File> extraPluginJars() {
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ final List<File> jars = (List<File>) this.console.options.valuesOf("add-plugin");
|
||||
+ final List<File> list = new ArrayList<>();
|
||||
+ for (final File file : jars) {
|
||||
+ if (!file.exists()) {
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument does not exist, cannot load a plugin from it!", file.getAbsolutePath());
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!file.isFile()) {
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument is not a file, cannot load a plugin from it!", file.getAbsolutePath());
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!file.getName().endsWith(".jar")) {
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument is not a jar file, cannot load a plugin from it!", file.getAbsolutePath());
|
||||
+ continue;
|
||||
+ }
|
||||
+ list.add(file);
|
||||
+ }
|
||||
+ return list;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public void enablePlugins(PluginLoadOrder type) {
|
||||
if (type == PluginLoadOrder.STARTUP) {
|
||||
this.helpMap.clear();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -0,0 +0,0 @@ public class Main {
|
||||
.ofType(File.class)
|
||||
.defaultsTo(new File("paper.yml"))
|
||||
.describedAs("Yml file");
|
||||
+
|
||||
+ acceptsAll(asList("add-plugin", "add-extra-plugin-jar"), "Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path.")
|
||||
+ .withRequiredArg()
|
||||
+ .ofType(File.class)
|
||||
+ .defaultsTo(new File[] {})
|
||||
+ .describedAs("Jar file");
|
||||
// Paper end
|
||||
}
|
||||
};
|
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Suddenly <suddenly@suddenly.coffee>
|
||||
Date: Tue, 1 Mar 2016 13:51:54 -0600
|
||||
Subject: [PATCH] Add configurable despawn distances for living entities
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements Targeting {
|
||||
|
||||
if (entityhuman != null) {
|
||||
double d0 = entityhuman.distanceToSqr((Entity) this);
|
||||
- int i = this.getType().getCategory().getDespawnDistance();
|
||||
+ int i = this.level.paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).hard(); // Paper - custom despawn distances
|
||||
int j = i * i;
|
||||
|
||||
if (d0 > (double) j && this.removeWhenFarAway(d0)) {
|
||||
this.discard();
|
||||
}
|
||||
|
||||
- int k = this.getType().getCategory().getNoDespawnDistance();
|
||||
+ int k = this.level.paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).soft(); // Paper - custom despawn distances
|
||||
int l = k * k;
|
||||
|
||||
if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) {
|
214
patches/server/Add-version-history-to-version-command.patch
Normal file
214
patches/server/Add-version-history-to-version-command.patch
Normal file
@@ -0,0 +1,214 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Wood <kyle@denwav.dev>
|
||||
Date: Thu, 1 Mar 2018 19:37:52 -0600
|
||||
Subject: [PATCH] Add version history to version command
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
@@ -0,0 +0,0 @@ import com.google.gson.*;
|
||||
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.TextDecoration;
|
||||
+import net.kyori.adventure.text.TextComponent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -0,0 +0,0 @@ public class PaperVersionFetcher implements VersionFetcher {
|
||||
@Override
|
||||
public Component getVersionMessage(@Nonnull String serverVersion) {
|
||||
String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]");
|
||||
- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]);
|
||||
+ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]);
|
||||
+ final Component history = getHistory();
|
||||
+
|
||||
+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage;
|
||||
}
|
||||
|
||||
private static @Nullable String getMinecraftVersion() {
|
||||
@@ -0,0 +0,0 @@ public class PaperVersionFetcher implements VersionFetcher {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ @Nullable
|
||||
+ private Component getHistory() {
|
||||
+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData();
|
||||
+ if (data == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final String oldVersion = data.getOldVersion();
|
||||
+ if (oldVersion == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import com.google.common.base.MoreObjects;
|
||||
+import com.google.gson.Gson;
|
||||
+import com.google.gson.JsonSyntaxException;
|
||||
+import java.io.BufferedReader;
|
||||
+import java.io.BufferedWriter;
|
||||
+import java.io.IOException;
|
||||
+import java.nio.charset.StandardCharsets;
|
||||
+import java.nio.file.Files;
|
||||
+import java.nio.file.Path;
|
||||
+import java.nio.file.Paths;
|
||||
+import java.nio.file.StandardOpenOption;
|
||||
+import java.util.Objects;
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.logging.Logger;
|
||||
+import org.bukkit.Bukkit;
|
||||
+
|
||||
+import javax.annotation.Nonnull;
|
||||
+import javax.annotation.Nullable;
|
||||
+
|
||||
+public enum VersionHistoryManager {
|
||||
+ INSTANCE;
|
||||
+
|
||||
+ private final Gson gson = new Gson();
|
||||
+
|
||||
+ private final Logger logger = Bukkit.getLogger();
|
||||
+
|
||||
+ private VersionData currentData = null;
|
||||
+
|
||||
+ VersionHistoryManager() {
|
||||
+ final Path path = Paths.get("version_history.json");
|
||||
+
|
||||
+ if (Files.exists(path)) {
|
||||
+ // Basic file santiy checks
|
||||
+ if (!Files.isRegularFile(path)) {
|
||||
+ if (Files.isDirectory(path)) {
|
||||
+ logger.severe(path + " is a directory, cannot be used for version history");
|
||||
+ } else {
|
||||
+ logger.severe(path + " is not a regular file, cannot be used for version history");
|
||||
+ }
|
||||
+ // We can't continue
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
|
||||
+ currentData = gson.fromJson(reader, VersionData.class);
|
||||
+ } catch (final IOException e) {
|
||||
+ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e);
|
||||
+ return;
|
||||
+ } catch (final JsonSyntaxException e) {
|
||||
+ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final String version = Bukkit.getVersion();
|
||||
+ if (version == null) {
|
||||
+ logger.severe("Failed to retrieve current version");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!version.equals(currentData.getCurrentVersion())) {
|
||||
+ // The version appears to have changed
|
||||
+ currentData.setOldVersion(currentData.getCurrentVersion());
|
||||
+ currentData.setCurrentVersion(version);
|
||||
+ writeFile(path);
|
||||
+ }
|
||||
+ } else {
|
||||
+ // File doesn't exist, start fresh
|
||||
+ currentData = new VersionData();
|
||||
+ // oldVersion is null
|
||||
+ currentData.setCurrentVersion(Bukkit.getVersion());
|
||||
+ writeFile(path);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void writeFile(@Nonnull final Path path) {
|
||||
+ try (final BufferedWriter writer = Files.newBufferedWriter(
|
||||
+ path,
|
||||
+ StandardCharsets.UTF_8,
|
||||
+ StandardOpenOption.WRITE,
|
||||
+ StandardOpenOption.CREATE,
|
||||
+ StandardOpenOption.TRUNCATE_EXISTING
|
||||
+ )) {
|
||||
+ gson.toJson(currentData, writer);
|
||||
+ } catch (final IOException e) {
|
||||
+ logger.log(Level.SEVERE, "Failed to write to version history file", e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public VersionData getVersionData() {
|
||||
+ return currentData;
|
||||
+ }
|
||||
+
|
||||
+ public static class VersionData {
|
||||
+ private String oldVersion;
|
||||
+
|
||||
+ private String currentVersion;
|
||||
+
|
||||
+ @Nullable
|
||||
+ public String getOldVersion() {
|
||||
+ return oldVersion;
|
||||
+ }
|
||||
+
|
||||
+ public void setOldVersion(@Nullable String oldVersion) {
|
||||
+ this.oldVersion = oldVersion;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public String getCurrentVersion() {
|
||||
+ return currentVersion;
|
||||
+ }
|
||||
+
|
||||
+ public void setCurrentVersion(@Nullable String currentVersion) {
|
||||
+ this.currentVersion = currentVersion;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return MoreObjects.toStringHelper(this)
|
||||
+ .add("oldVersion", oldVersion)
|
||||
+ .add("currentVersion", currentVersion)
|
||||
+ .toString();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(@Nullable Object o) {
|
||||
+ if (this == o) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (o == null || getClass() != o.getClass()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ final VersionData versionData = (VersionData) o;
|
||||
+ return Objects.equals(oldVersion, versionData.oldVersion) &&
|
||||
+ Objects.equals(currentVersion, versionData.currentVersion);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return Objects.hash(oldVersion, currentVersion);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
paperConfigurations.initializeWorldDefaultsConfiguration();
|
||||
io.papermc.paper.command.PaperCommands.registerCommands(this);
|
||||
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics();
|
||||
+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
|
||||
// Paper end
|
||||
|
||||
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
4722
patches/server/Adventure.patch
Normal file
4722
patches/server/Adventure.patch
Normal file
File diff suppressed because it is too large
Load Diff
18
patches/server/Allow-for-toggling-of-spawn-chunks.patch
Normal file
18
patches/server/Allow-for-toggling-of-spawn-chunks.patch
Normal file
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Thu, 3 Mar 2016 03:53:43 -0600
|
||||
Subject: [PATCH] Allow for toggling of spawn chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
});
|
||||
// CraftBukkit end
|
||||
timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings
|
||||
+ this.keepSpawnInMemory = this.paperConfig().spawn.keepSpawnLoaded; // Paper
|
||||
this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
|
||||
this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Tue, 1 Mar 2016 13:24:16 -0600
|
||||
Subject: [PATCH] Allow nerfed mobs to jump and take water damage
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements Targeting {
|
||||
private final BodyRotationControl bodyRotationControl;
|
||||
protected PathNavigation navigation;
|
||||
public GoalSelector goalSelector;
|
||||
+ @Nullable public net.minecraft.world.entity.ai.goal.FloatGoal goalFloat; // Paper
|
||||
public GoalSelector targetSelector;
|
||||
@Nullable
|
||||
private LivingEntity target;
|
||||
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements Targeting {
|
||||
@Override
|
||||
protected final void serverAiStep() {
|
||||
++this.noActionTime;
|
||||
- if (!this.aware) return; // CraftBukkit
|
||||
+ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage
|
||||
+ if (goalFloat != null) {
|
||||
+ if (goalFloat.canUse()) goalFloat.tick();
|
||||
+ this.getJumpControl().tick();
|
||||
+ }
|
||||
+ if (this.isSensitiveToWater() && isInWaterRainOrBubble()) {
|
||||
+ hurt(DamageSource.DROWN, 1.0F);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.level.getProfiler().push("sensing");
|
||||
this.sensing.tick();
|
||||
this.level.getProfiler().pop();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java
|
||||
@@ -0,0 +0,0 @@ public class FloatGoal extends Goal {
|
||||
|
||||
public FloatGoal(Mob mob) {
|
||||
this.mob = mob;
|
||||
+ if (mob.getCommandSenderWorld().paperConfig().entities.behavior.spawnerNerfedMobsShouldJump) mob.goalFloat = this; // Paper
|
||||
this.setFlags(EnumSet.of(Goal.Flag.JUMP));
|
||||
mob.getNavigation().setCanFloat(true);
|
||||
}
|
94
patches/server/Build-system-changes.patch
Normal file
94
patches/server/Build-system-changes.patch
Normal file
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Mon, 29 Feb 2016 20:40:33 -0600
|
||||
Subject: [PATCH] Build system changes
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -0,0 +0,0 @@ plugins {
|
||||
dependencies {
|
||||
implementation(project(":paper-api"))
|
||||
implementation("jline:jline:2.12.1")
|
||||
- implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") {
|
||||
- exclude(group = "org.apache.logging.log4j", module = "log4j-api")
|
||||
- }
|
||||
+ implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion
|
||||
implementation("org.ow2.asm:asm:9.4")
|
||||
+ implementation("org.ow2.asm:asm-commons:9.4") // Paper - ASM event executor generation
|
||||
implementation("commons-lang:commons-lang:2.6")
|
||||
runtimeOnly("org.xerial:sqlite-jdbc:3.36.0.3")
|
||||
runtimeOnly("com.mysql:mysql-connector-j:8.0.32")
|
||||
@@ -0,0 +0,0 @@ dependencies {
|
||||
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
testImplementation("org.hamcrest:hamcrest-library:1.3")
|
||||
+
|
||||
+ implementation("io.netty:netty-all:4.1.87.Final"); // Paper - Bump netty
|
||||
}
|
||||
|
||||
val craftbukkitPackageVersion = "1_19_R3" // Paper
|
||||
@@ -0,0 +0,0 @@ tasks.jar {
|
||||
val gitHash = git("rev-parse", "--short=7", "HEAD").getText().trim()
|
||||
val implementationVersion = System.getenv("BUILD_NUMBER") ?: "\"$gitHash\""
|
||||
val date = git("show", "-s", "--format=%ci", gitHash).getText().trim() // Paper
|
||||
+ val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper
|
||||
attributes(
|
||||
"Main-Class" to "org.bukkit.craftbukkit.Main",
|
||||
"Implementation-Title" to "CraftBukkit",
|
||||
@@ -0,0 +0,0 @@ tasks.jar {
|
||||
"Specification-Title" to "Bukkit",
|
||||
"Specification-Version" to project.version,
|
||||
"Specification-Vendor" to "Bukkit Team",
|
||||
+ "Git-Branch" to gitBranch, // Paper
|
||||
+ "Git-Commit" to gitHash, // Paper
|
||||
+ "CraftBukkit-Package-Version" to craftbukkitPackageVersion, // Paper
|
||||
)
|
||||
for (tld in setOf("net", "com", "org")) {
|
||||
attributes("$tld/bukkit", "Sealed" to true)
|
||||
@@ -0,0 +0,0 @@ tasks.shadowJar {
|
||||
}
|
||||
}
|
||||
|
||||
+// Paper start
|
||||
+val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
|
||||
+ badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
|
||||
+ jarToScan.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
+ classpath.from(configurations.compileClasspath)
|
||||
+}
|
||||
+tasks.check {
|
||||
+ dependsOn(scanJar)
|
||||
+}
|
||||
+// Paper end
|
||||
+
|
||||
tasks.test {
|
||||
exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class")
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -0,0 +0,0 @@ public class Main {
|
||||
}
|
||||
|
||||
if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) {
|
||||
- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L);
|
||||
+ Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(Main.class.getPackage().getImplementationVendor()); // Paper
|
||||
|
||||
Calendar deadline = Calendar.getInstance();
|
||||
deadline.add(Calendar.DAY_OF_YEAR, -3);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
@@ -0,0 +0,0 @@ public final class Versioning {
|
||||
public static String getBukkitVersion() {
|
||||
String result = "Unknown-Version";
|
||||
|
||||
- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties");
|
||||
+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties");
|
||||
Properties properties = new Properties();
|
||||
|
||||
if (stream != null) {
|
116
patches/server/CB-fixes.patch
Normal file
116
patches/server/CB-fixes.patch
Normal file
@@ -0,0 +1,116 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 25 Feb 2022 07:14:48 -0800
|
||||
Subject: [PATCH] CB fixes
|
||||
|
||||
* Missing Level -> LevelStem generic in StructureCheck
|
||||
Need to use the right for injectDatafixingContext (Spottedleaf)
|
||||
|
||||
* Removed incorrect parent perm for `minecraft.debugstick.always` (Machine_Maker)
|
||||
|
||||
* Fixed method signature of Marker#addPassenger (Machine_Maker)
|
||||
|
||||
* Removed unneeded UOE in CustomWorldChunkManager (extends BiomeSource) (Machine_Maker)
|
||||
|
||||
* Honor Server#getLootTable method contract (Machine_Maker)
|
||||
|
||||
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
||||
long l = minecraftserver.getWorldData().worldGenOptions().seed();
|
||||
|
||||
- this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer);
|
||||
+ this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), this.getTypeKey(), chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer); // Paper - Fix missing CB diff
|
||||
this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), this.structureCheck); // CraftBukkit
|
||||
if ((this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END
|
||||
this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Marker.java b/src/main/java/net/minecraft/world/entity/Marker.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Marker.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Marker.java
|
||||
@@ -0,0 +0,0 @@ public class Marker extends Entity {
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void addPassenger(Entity passenger) {
|
||||
- throw new IllegalStateException("Should never addPassenger without checking couldAcceptPassenger()");
|
||||
+ protected boolean addPassenger(Entity passenger) { // Paper - fix return type
|
||||
+ return false; // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
@@ -0,0 +0,0 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Rider
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void actuallyHurt(DamageSource source, float amount) {
|
||||
+ protected boolean damageEntity0(DamageSource source, float amount) { // Paper - fix CB method rename issue
|
||||
this.standUpPanic();
|
||||
- super.actuallyHurt(source, amount);
|
||||
+ return super.damageEntity0(source, amount); // Paper - fix CB method rename issue
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
|
||||
@@ -0,0 +0,0 @@ public class StructureCheck {
|
||||
private final Registry<Biome> biomes;
|
||||
private final Registry<Structure> structureConfigs;
|
||||
private final StructureTemplateManager structureTemplateManager;
|
||||
- private final ResourceKey<Level> dimension;
|
||||
+ private final ResourceKey<net.minecraft.world.level.dimension.LevelStem> dimension; // Paper - fix missing CB diff
|
||||
private final ChunkGenerator chunkGenerator;
|
||||
private final RandomState randomState;
|
||||
private final LevelHeightAccessor heightAccessor;
|
||||
@@ -0,0 +0,0 @@ public class StructureCheck {
|
||||
private final Long2ObjectMap<Object2IntMap<Structure>> loadedChunks = new Long2ObjectOpenHashMap<>();
|
||||
private final Map<Structure, Long2BooleanMap> featureChecks = new HashMap<>();
|
||||
|
||||
- public StructureCheck(ChunkScanAccess chunkIoWorker, RegistryAccess registryManager, StructureTemplateManager structureTemplateManager, ResourceKey<Level> worldKey, ChunkGenerator chunkGenerator, RandomState noiseConfig, LevelHeightAccessor world, BiomeSource biomeSource, long seed, DataFixer dataFixer) {
|
||||
+ public StructureCheck(ChunkScanAccess chunkIoWorker, RegistryAccess registryManager, StructureTemplateManager structureTemplateManager, ResourceKey<net.minecraft.world.level.dimension.LevelStem> worldKey, ChunkGenerator chunkGenerator, RandomState noiseConfig, LevelHeightAccessor world, BiomeSource biomeSource, long seed, DataFixer dataFixer) { // Paper - fix missing CB diff
|
||||
this.storageAccess = chunkIoWorker;
|
||||
this.registryAccess = registryManager;
|
||||
this.structureTemplateManager = structureTemplateManager;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
|
||||
Validate.notNull(key, "NamespacedKey cannot be null");
|
||||
|
||||
LootTables registry = this.getServer().getLootTables();
|
||||
- return new CraftLootTable(key, registry.get(CraftNamespacedKey.toMinecraft(key)));
|
||||
+ // Paper start - honor method contract
|
||||
+ final ResourceLocation lootTableKey = CraftNamespacedKey.toMinecraft(key);
|
||||
+ if (!registry.getIds().contains(lootTableKey)) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return new CraftLootTable(key, registry.get(lootTableKey));
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftDefaultPermissions {
|
||||
DefaultPermissions.registerPermission(CraftDefaultPermissions.ROOT + ".nbt.place", "Gives the user the ability to place restricted blocks with NBT in creative", org.bukkit.permissions.PermissionDefault.OP, parent);
|
||||
DefaultPermissions.registerPermission(CraftDefaultPermissions.ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent);
|
||||
DefaultPermissions.registerPermission(CraftDefaultPermissions.ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent);
|
||||
- DefaultPermissions.registerPermission(CraftDefaultPermissions.ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent);
|
||||
+ DefaultPermissions.registerPermission(CraftDefaultPermissions.ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE/* , parent */); // Paper - should not have this parent, as it's not a "vanilla" utility
|
||||
// Spigot end
|
||||
parent.recalculatePermissibles();
|
||||
}
|
7018
patches/server/ConcurrentUtil.patch
Normal file
7018
patches/server/ConcurrentUtil.patch
Normal file
File diff suppressed because it is too large
Load Diff
30
patches/server/Configurable-baby-zombie-movement-speed.patch
Normal file
30
patches/server/Configurable-baby-zombie-movement-speed.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Tue, 1 Mar 2016 13:09:16 -0600
|
||||
Subject: [PATCH] Configurable baby zombie movement speed
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
|
||||
private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836");
|
||||
private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE);
|
||||
+ private final AttributeModifier babyModifier = new net.minecraft.world.entity.ai.attributes.AttributeModifier(SPEED_MODIFIER_BABY.getId(), SPEED_MODIFIER_BABY.getName(), this.level.paperConfig().entities.behavior.babyZombieMovementModifier, SPEED_MODIFIER_BABY.getOperation()); // Paper - Make baby speed configurable
|
||||
private static final EntityDataAccessor<Boolean> DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final EntityDataAccessor<Integer> DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT);
|
||||
public static final EntityDataAccessor<Boolean> DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN);
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
if (this.level != null && !this.level.isClientSide) {
|
||||
AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
|
||||
- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY);
|
||||
+ attributemodifiable.removeModifier(this.babyModifier); // Paper
|
||||
if (baby) {
|
||||
- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY);
|
||||
+ attributemodifiable.addTransientModifier(this.babyModifier); // Paper
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,92 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Tue, 1 Mar 2016 13:02:51 -0600
|
||||
Subject: [PATCH] Configurable cactus bamboo and reed growth heights
|
||||
|
||||
Bamboo - Both the minimum fully-grown heights and the maximum are configurable
|
||||
- Machine_Maker
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java b/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BambooStalkBlock.java
|
||||
@@ -0,0 +0,0 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
|
||||
if (random.nextFloat() < (world.spigotConfig.bambooModifier / (100.0f * 3)) && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
|
||||
int i = this.getHeightBelowUpToMax(world, pos) + 1;
|
||||
|
||||
- if (i < 16) {
|
||||
+ if (i < world.paperConfig().maxGrowthHeight.bamboo.max) { // Paper
|
||||
this.growBamboo(state, world, pos, random, i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
|
||||
int i = this.getHeightAboveUpToMax(world, pos);
|
||||
int j = this.getHeightBelowUpToMax(world, pos);
|
||||
|
||||
- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooStalkBlock.STAGE) != 1;
|
||||
+ return i + j + 1 < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && (Integer) world.getBlockState(pos.above(i)).getValue(BambooStalkBlock.STAGE) != 1; // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
|
||||
BlockPos blockposition1 = pos.above(i);
|
||||
BlockState iblockdata1 = world.getBlockState(blockposition1);
|
||||
|
||||
- if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here
|
||||
+ if (k >= world.paperConfig().maxGrowthHeight.bamboo.max || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
|
||||
}
|
||||
|
||||
int j = (Integer) state.getValue(BambooStalkBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1;
|
||||
- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1;
|
||||
+ int k = (height < world.paperConfig().maxGrowthHeight.bamboo.min || random.nextFloat() >= 0.25F) && height != (world.paperConfig().maxGrowthHeight.bamboo.max - 1) ? 0 : 1; // Paper
|
||||
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) {
|
||||
@@ -0,0 +0,0 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
|
||||
protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) {
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) {
|
||||
+ for (i = 0; i < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper
|
||||
;
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class BambooStalkBlock extends Block implements BonemealableBlock {
|
||||
protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) {
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) {
|
||||
+ for (i = 0; i < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper
|
||||
;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
|
||||
@@ -0,0 +0,0 @@ public class CactusBlock extends Block {
|
||||
;
|
||||
}
|
||||
|
||||
- if (i < 3) {
|
||||
+ if (i < world.paperConfig().maxGrowthHeight.cactus) { // Paper - Configurable growth height
|
||||
int j = (Integer) state.getValue(CactusBlock.AGE);
|
||||
|
||||
int modifier = world.spigotConfig.cactusModifier; // Spigot - SPIGOT-7159: Better modifier resolution
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
|
||||
@@ -0,0 +0,0 @@ public class SugarCaneBlock extends Block {
|
||||
;
|
||||
}
|
||||
|
||||
- if (i < 3) {
|
||||
+ if (i < world.paperConfig().maxGrowthHeight.reeds) { // Paper - Configurable growth height
|
||||
int j = (Integer) state.getValue(SugarCaneBlock.AGE);
|
||||
|
||||
int modifier = world.spigotConfig.caneModifier; // Spigot - SPIGOT-7159: Better modifier resolution
|
30
patches/server/Configurable-fishing-time-ranges.patch
Normal file
30
patches/server/Configurable-fishing-time-ranges.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Tue, 1 Mar 2016 13:14:11 -0600
|
||||
Subject: [PATCH] Configurable fishing time ranges
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
|
||||
this.noCulling = true;
|
||||
this.luck = Math.max(0, luckOfTheSeaLevel);
|
||||
this.lureSpeed = Math.max(0, lureLevel);
|
||||
+ // Paper start
|
||||
+ minWaitTime = world.paperConfig().fishingTimeRange.minimum;
|
||||
+ maxWaitTime = world.paperConfig().fishingTimeRange.maximum;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public FishingHook(EntityType<? extends FishingHook> type, Level world) {
|
||||
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
|
||||
} else {
|
||||
// CraftBukkit start - logic to modify fishing wait time
|
||||
this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
|
||||
- this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0;
|
||||
+ this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed * 20 * 5 >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed * 20 * 5) : 0; // Paper - Fix Lure infinite loop
|
||||
// CraftBukkit end
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Tue, 1 Mar 2016 14:14:15 -0600
|
||||
Subject: [PATCH] Drop falling block and tnt entities at the specified height
|
||||
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity {
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
+
|
||||
+ // Paper start - Configurable EntityFallingBlock height nerf
|
||||
+ if (this.level.paperConfig().fixes.fallingBlockHeightNerf.test(v -> this.getY() > v)) {
|
||||
+ if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
|
||||
+ this.spawnAtLocation(block);
|
||||
+ }
|
||||
+
|
||||
+ this.discard();
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (!this.level.isClientSide) {
|
||||
BlockPos blockposition = this.blockPosition();
|
||||
boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
@@ -0,0 +0,0 @@ public class PrimedTnt extends Entity implements TraceableEntity {
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
+ // Paper start - Configurable TNT entity height nerf
|
||||
+ if (this.level.paperConfig().fixes.tntEntityHeightNerf.test(v -> this.getY() > v)) {
|
||||
+ this.discard();
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.setDeltaMovement(this.getDeltaMovement().scale(0.98D));
|
||||
if (this.onGround) {
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D));
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
|
||||
@@ -0,0 +0,0 @@ public class MinecartTNT extends AbstractMinecart {
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (this.fuse > 0) {
|
||||
+ // Paper start - Configurable TNT entity height nerf
|
||||
+ if (this.level.paperConfig().fixes.tntEntityHeightNerf.test(v -> this.getY() > v)) {
|
||||
+ this.discard();
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
--this.fuse;
|
||||
this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D);
|
||||
} else if (this.fuse == 0) {
|
158
patches/server/Entity-Origin-API.patch
Normal file
158
patches/server/Entity-Origin-API.patch
Normal file
@@ -0,0 +1,158 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Tue, 1 Mar 2016 23:45:08 -0600
|
||||
Subject: [PATCH] Entity Origin API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
entity.valid = true; // CraftBukkit
|
||||
+ // Paper start - Set origin location when the entity is being added to the world
|
||||
+ if (entity.getOriginVector() == null) {
|
||||
+ entity.setOrigin(entity.getBukkitEntity().getLocation());
|
||||
+ }
|
||||
+ // Default to current world if unknown, gross assumption but entities rarely change world
|
||||
+ if (entity.getOriginWorld() == null) {
|
||||
+ entity.setOrigin(entity.getOriginVector().toLocation(getWorld()));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void onTrackingEnd(Entity entity) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
public long activatedTick = Integer.MIN_VALUE;
|
||||
public void inactiveTick() { }
|
||||
// Spigot end
|
||||
+ // Paper start
|
||||
+ @javax.annotation.Nullable
|
||||
+ private org.bukkit.util.Vector origin;
|
||||
+ @javax.annotation.Nullable
|
||||
+ private UUID originWorld;
|
||||
+
|
||||
+ public void setOrigin(@javax.annotation.Nonnull Location location) {
|
||||
+ this.origin = location.toVector();
|
||||
+ this.originWorld = location.getWorld().getUID();
|
||||
+ }
|
||||
|
||||
+ @javax.annotation.Nullable
|
||||
+ public org.bukkit.util.Vector getOriginVector() {
|
||||
+ return this.origin != null ? this.origin.clone() : null;
|
||||
+ }
|
||||
+
|
||||
+ @javax.annotation.Nullable
|
||||
+ public UUID getOriginWorld() {
|
||||
+ return this.originWorld;
|
||||
+ }
|
||||
+ // Paper end
|
||||
public float getBukkitYaw() {
|
||||
return this.yRot;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
this.bukkitEntity.storeBukkitValues(nbt);
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Save the entity's origin location
|
||||
+ if (this.origin != null) {
|
||||
+ UUID originWorld = this.originWorld != null ? this.originWorld : this.level != null ? this.level.getWorld().getUID() : null;
|
||||
+ if (originWorld != null) {
|
||||
+ nbt.putUUID("Paper.OriginWorld", originWorld);
|
||||
+ }
|
||||
+ nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ()));
|
||||
+ }
|
||||
+ // Paper end
|
||||
return nbt;
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Paper start - Restore the entity's origin location
|
||||
+ ListTag originTag = nbt.getList("Paper.Origin", 6);
|
||||
+ if (!originTag.isEmpty()) {
|
||||
+ UUID originWorld = null;
|
||||
+ if (nbt.contains("Paper.OriginWorld")) {
|
||||
+ originWorld = nbt.getUUID("Paper.OriginWorld");
|
||||
+ } else if (this.level != null) {
|
||||
+ originWorld = this.level.getWorld().getUID();
|
||||
+ }
|
||||
+ this.originWorld = originWorld;
|
||||
+ origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded");
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity {
|
||||
this.blockState = Blocks.SAND.defaultBlockState();
|
||||
}
|
||||
|
||||
+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility
|
||||
+ if (nbt.contains("SourceLoc_x")) {
|
||||
+ int srcX = nbt.getInt("SourceLoc_x");
|
||||
+ int srcY = nbt.getInt("SourceLoc_y");
|
||||
+ int srcZ = nbt.getInt("SourceLoc_z");
|
||||
+ this.setOrigin(new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void setHurtsEntities(float fallHurtAmount, int fallHurtMax) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
|
||||
@@ -0,0 +0,0 @@ public class PrimedTnt extends Entity implements TraceableEntity {
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag nbt) {
|
||||
this.setFuse(nbt.getShort("Fuse"));
|
||||
+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility
|
||||
+ if (nbt.contains("SourceLoc_x")) {
|
||||
+ int srcX = nbt.getInt("SourceLoc_x");
|
||||
+ int srcY = nbt.getInt("SourceLoc_y");
|
||||
+ int srcZ = nbt.getInt("SourceLoc_z");
|
||||
+ this.setOrigin(new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Nullable
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public Location getOrigin() {
|
||||
+ Vector originVector = this.getHandle().getOriginVector();
|
||||
+ if (originVector == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ World world = this.getWorld();
|
||||
+ if (this.getHandle().getOriginWorld() != null) {
|
||||
+ world = org.bukkit.Bukkit.getWorld(this.getHandle().getOriginWorld());
|
||||
+ }
|
||||
+
|
||||
+ //noinspection ConstantConditions
|
||||
+ return originVector.toLocation(world);
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
213
patches/server/Further-improve-server-tick-loop.patch
Normal file
213
patches/server/Further-improve-server-tick-loop.patch
Normal file
@@ -0,0 +1,213 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 1 Mar 2016 23:09:29 -0600
|
||||
Subject: [PATCH] Further improve server tick loop
|
||||
|
||||
Improves how the catchup buffer is handled, allowing it to roll both ways
|
||||
increasing the effeciency of the thread sleep so it only will sleep once.
|
||||
|
||||
Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions
|
||||
|
||||
Previous implementation did not calculate TPS correctly.
|
||||
Switch to a realistic rolling average and factor in std deviation as an extra reporting variable
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public org.bukkit.command.ConsoleCommandSender console;
|
||||
public org.bukkit.command.RemoteConsoleCommandSender remoteConsole;
|
||||
public ConsoleReader reader;
|
||||
- public static int currentTick = (int) (System.currentTimeMillis() / 50);
|
||||
+ public static int currentTick = 0; // Paper - Further improve tick loop
|
||||
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
||||
public int autosavePeriod;
|
||||
public Commands vanillaCommandDispatcher;
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Spigot start
|
||||
public static final int TPS = 20;
|
||||
public static final int TICK_TIME = 1000000000 / MinecraftServer.TPS;
|
||||
- private static final int SAMPLE_INTERVAL = 100;
|
||||
+ private static final int SAMPLE_INTERVAL = 20; // Paper
|
||||
public final double[] recentTps = new double[ 3 ];
|
||||
// Spigot end
|
||||
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
{
|
||||
return ( avg * exp ) + ( tps * ( 1 - exp ) );
|
||||
}
|
||||
+
|
||||
+ // Paper start - Further improve server tick loop
|
||||
+ private static final long SEC_IN_NANO = 1000000000;
|
||||
+ private static final long MAX_CATCHUP_BUFFER = TICK_TIME * TPS * 60L;
|
||||
+ private long lastTick = 0;
|
||||
+ private long catchupTime = 0;
|
||||
+ public final RollingAverage tps1 = new RollingAverage(60);
|
||||
+ public final RollingAverage tps5 = new RollingAverage(60 * 5);
|
||||
+ public final RollingAverage tps15 = new RollingAverage(60 * 15);
|
||||
+
|
||||
+ public static class RollingAverage {
|
||||
+ private final int size;
|
||||
+ private long time;
|
||||
+ private java.math.BigDecimal total;
|
||||
+ private int index = 0;
|
||||
+ private final java.math.BigDecimal[] samples;
|
||||
+ private final long[] times;
|
||||
+
|
||||
+ RollingAverage(int size) {
|
||||
+ this.size = size;
|
||||
+ this.time = size * SEC_IN_NANO;
|
||||
+ this.total = dec(TPS).multiply(dec(SEC_IN_NANO)).multiply(dec(size));
|
||||
+ this.samples = new java.math.BigDecimal[size];
|
||||
+ this.times = new long[size];
|
||||
+ for (int i = 0; i < size; i++) {
|
||||
+ this.samples[i] = dec(TPS);
|
||||
+ this.times[i] = SEC_IN_NANO;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static java.math.BigDecimal dec(long t) {
|
||||
+ return new java.math.BigDecimal(t);
|
||||
+ }
|
||||
+ public void add(java.math.BigDecimal x, long t) {
|
||||
+ time -= times[index];
|
||||
+ total = total.subtract(samples[index].multiply(dec(times[index])));
|
||||
+ samples[index] = x;
|
||||
+ times[index] = t;
|
||||
+ time += t;
|
||||
+ total = total.add(x.multiply(dec(t)));
|
||||
+ if (++index == size) {
|
||||
+ index = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public double getAverage() {
|
||||
+ return total.divide(dec(time), 30, java.math.RoundingMode.HALF_UP).doubleValue();
|
||||
+ }
|
||||
+ }
|
||||
+ private static final java.math.BigDecimal TPS_BASE = new java.math.BigDecimal(1E9).multiply(new java.math.BigDecimal(SAMPLE_INTERVAL));
|
||||
+ // Paper End
|
||||
// Spigot End
|
||||
|
||||
public static volatile RuntimeException chunkSystemCrash; // Paper - rewrite chunk system
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
// Spigot start
|
||||
Arrays.fill( recentTps, 20 );
|
||||
- long curTime, tickSection = Util.getMillis(), tickCount = 1;
|
||||
+ long start = System.nanoTime(), curTime, tickSection = start; // Paper - Further improve server tick loop
|
||||
+ lastTick = start - TICK_TIME; // Paper
|
||||
while (this.running) {
|
||||
// Paper start - rewrite chunk system
|
||||
// guarantee that nothing can stop the server from halting if it can at least still tick
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
throw this.chunkSystemCrash;
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
- long i = (curTime = Util.getMillis()) - this.nextTickTime;
|
||||
+ long i = ((curTime = System.nanoTime()) / (1000L * 1000L)) - this.nextTickTime; // Paper
|
||||
|
||||
if (i > 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit
|
||||
long j = i / 50L;
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
++MinecraftServer.currentTickLong; // Paper
|
||||
- if ( tickCount++ % MinecraftServer.SAMPLE_INTERVAL == 0 )
|
||||
+ if ( ++MinecraftServer.currentTick % MinecraftServer.SAMPLE_INTERVAL == 0 )
|
||||
{
|
||||
- double currentTps = 1E3 / ( curTime - tickSection ) * MinecraftServer.SAMPLE_INTERVAL;
|
||||
- this.recentTps[0] = MinecraftServer.calcTps( this.recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min)
|
||||
- this.recentTps[1] = MinecraftServer.calcTps( this.recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min)
|
||||
- this.recentTps[2] = MinecraftServer.calcTps( this.recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min)
|
||||
+ final long diff = curTime - tickSection;
|
||||
+ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP);
|
||||
+ tps1.add(currentTps, diff);
|
||||
+ tps5.add(currentTps, diff);
|
||||
+ tps15.add(currentTps, diff);
|
||||
+ // Backwards compat with bad plugins
|
||||
+ this.recentTps[0] = tps1.getAverage();
|
||||
+ this.recentTps[1] = tps5.getAverage();
|
||||
+ this.recentTps[2] = tps15.getAverage();
|
||||
+ // Paper end
|
||||
tickSection = curTime;
|
||||
}
|
||||
// Spigot end
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
|
||||
}
|
||||
|
||||
- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit
|
||||
+ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time
|
||||
+ lastTick = curTime;
|
||||
this.nextTickTime += 50L;
|
||||
this.startMetricsRecordingTick();
|
||||
this.profiler.push("tick");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
|
||||
return CraftMagicNumbers.INSTANCE;
|
||||
}
|
||||
|
||||
+ // Paper - Add getTPS API - Further improve tick loop
|
||||
+ @Override
|
||||
+ public double[] getTPS() {
|
||||
+ return new double[] {
|
||||
+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(),
|
||||
+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(),
|
||||
+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage()
|
||||
+ };
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
// Spigot start
|
||||
private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot()
|
||||
{
|
||||
diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java
|
||||
+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
|
||||
@@ -0,0 +0,0 @@ public class TicksPerSecondCommand extends Command
|
||||
return true;
|
||||
}
|
||||
|
||||
- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " );
|
||||
- for ( double tps : MinecraftServer.getServer().recentTps )
|
||||
- {
|
||||
- sb.append( this.format( tps ) );
|
||||
- sb.append( ", " );
|
||||
+ // Paper start - Further improve tick handling
|
||||
+ double[] tps = org.bukkit.Bukkit.getTPS();
|
||||
+ String[] tpsAvg = new String[tps.length];
|
||||
+
|
||||
+ for ( int i = 0; i < tps.length; i++) {
|
||||
+ tpsAvg[i] = TicksPerSecondCommand.format( tps[i] );
|
||||
+ }
|
||||
+ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", "));
|
||||
+ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) {
|
||||
+ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)");
|
||||
+ if (!hasShownMemoryWarning) {
|
||||
+ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention.");
|
||||
+ hasShownMemoryWarning = true;
|
||||
+ }
|
||||
}
|
||||
- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) );
|
||||
- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: "
|
||||
- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)");
|
||||
+ // Paper end
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
- private String format(double tps)
|
||||
+ private boolean hasShownMemoryWarning; // Paper
|
||||
+ private static String format(double tps) // Paper - Made static
|
||||
{
|
||||
return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString()
|
||||
- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 );
|
||||
+ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise
|
||||
}
|
||||
}
|
157
patches/server/Implement-Paper-VersionChecker.patch
Normal file
157
patches/server/Implement-Paper-VersionChecker.patch
Normal file
@@ -0,0 +1,157 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Mon, 27 May 2019 03:40:05 -0500
|
||||
Subject: [PATCH] Implement Paper VersionChecker
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import com.destroystokyo.paper.util.VersionFetcher;
|
||||
+import com.google.common.base.Charsets;
|
||||
+import com.google.common.io.Resources;
|
||||
+import com.google.gson.*;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.event.ClickEvent;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+
|
||||
+import javax.annotation.Nonnull;
|
||||
+import javax.annotation.Nullable;
|
||||
+import java.io.*;
|
||||
+import java.net.HttpURLConnection;
|
||||
+import java.net.URL;
|
||||
+import java.util.stream.StreamSupport;
|
||||
+
|
||||
+public class PaperVersionFetcher implements VersionFetcher {
|
||||
+ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end
|
||||
+ private static final String GITHUB_BRANCH_NAME = "master";
|
||||
+ private static final String DOWNLOAD_PAGE = "https://papermc.io/downloads";
|
||||
+ private static @Nullable String mcVer;
|
||||
+
|
||||
+ @Override
|
||||
+ public long getCacheTime() {
|
||||
+ return 720000;
|
||||
+ }
|
||||
+
|
||||
+ @Nonnull
|
||||
+ @Override
|
||||
+ public Component getVersionMessage(@Nonnull String serverVersion) {
|
||||
+ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]");
|
||||
+ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]);
|
||||
+ }
|
||||
+
|
||||
+ private static @Nullable String getMinecraftVersion() {
|
||||
+ if (mcVer == null) {
|
||||
+ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion());
|
||||
+ if (matcher.find()) {
|
||||
+ String result = matcher.group();
|
||||
+ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-'
|
||||
+ } else {
|
||||
+ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!");
|
||||
+ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString());
|
||||
+ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return mcVer;
|
||||
+ }
|
||||
+
|
||||
+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) {
|
||||
+ int distance;
|
||||
+ try {
|
||||
+ int jenkinsBuild = Integer.parseInt(versionInfo);
|
||||
+ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion());
|
||||
+ } catch (NumberFormatException ignored) {
|
||||
+ versionInfo = versionInfo.replace("\"", "");
|
||||
+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo);
|
||||
+ }
|
||||
+
|
||||
+ switch (distance) {
|
||||
+ case -1:
|
||||
+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW);
|
||||
+ case 0:
|
||||
+ return Component.text("You are running the latest version", NamedTextColor.GREEN);
|
||||
+ case -2:
|
||||
+ return Component.text("Unknown version", NamedTextColor.YELLOW);
|
||||
+ default:
|
||||
+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW)
|
||||
+ .append(Component.newline())
|
||||
+ .append(Component.text("Download the new version at: ")
|
||||
+ .append(Component.text(DOWNLOAD_PAGE, NamedTextColor.GOLD)
|
||||
+ .hoverEvent(Component.text("Click to open", NamedTextColor.WHITE))
|
||||
+ .clickEvent(ClickEvent.openUrl(DOWNLOAD_PAGE))));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) {
|
||||
+ if (siteApiVersion == null) { return -1; }
|
||||
+ try {
|
||||
+ try (BufferedReader reader = Resources.asCharSource(
|
||||
+ new URL("https://api.papermc.io/v2/projects/paper/versions/" + siteApiVersion),
|
||||
+ Charsets.UTF_8
|
||||
+ ).openBufferedStream()) {
|
||||
+ JsonObject json = new Gson().fromJson(reader, JsonObject.class);
|
||||
+ JsonArray builds = json.getAsJsonArray("builds");
|
||||
+ int latest = StreamSupport.stream(builds.spliterator(), false)
|
||||
+ .mapToInt(e -> e.getAsInt())
|
||||
+ .max()
|
||||
+ .getAsInt();
|
||||
+ return latest - jenkinsBuild;
|
||||
+ } catch (JsonSyntaxException ex) {
|
||||
+ ex.printStackTrace();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ } catch (IOException e) {
|
||||
+ e.printStackTrace();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Contributed by Techcable <Techcable@outlook.com> in GH-65
|
||||
+ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) {
|
||||
+ try {
|
||||
+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection();
|
||||
+ connection.connect();
|
||||
+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit
|
||||
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
|
||||
+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
|
||||
+ String status = obj.get("status").getAsString();
|
||||
+ switch (status) {
|
||||
+ case "identical":
|
||||
+ return 0;
|
||||
+ case "behind":
|
||||
+ return obj.get("behind_by").getAsInt();
|
||||
+ default:
|
||||
+ return -1;
|
||||
+ }
|
||||
+ } catch (JsonSyntaxException | NumberFormatException e) {
|
||||
+ e.printStackTrace();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ } catch (IOException e) {
|
||||
+ e.printStackTrace();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
public String getTimingsServerName() {
|
||||
return io.papermc.paper.configuration.GlobalConfiguration.get().timings.serverName;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
|
||||
+ return new com.destroystokyo.paper.PaperVersionFetcher();
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
/**
|
212
patches/server/MC-Dev-fixes.patch
Normal file
212
patches/server/MC-Dev-fixes.patch
Normal file
@@ -0,0 +1,212 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 30 Mar 2016 19:36:20 -0400
|
||||
Subject: [PATCH] MC Dev fixes
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/Util.java
|
||||
+++ b/src/main/java/net/minecraft/Util.java
|
||||
@@ -0,0 +0,0 @@ public class Util {
|
||||
}
|
||||
|
||||
public static <K> Hash.Strategy<K> identityStrategy() {
|
||||
- return Util.IdentityStrategy.INSTANCE;
|
||||
+ return (Hash.Strategy<K>) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix
|
||||
}
|
||||
|
||||
public static <V> CompletableFuture<List<V>> sequence(List<? extends CompletableFuture<V>> futures) {
|
||||
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
|
||||
if (this.index == l) {
|
||||
return this.endOfData();
|
||||
} else {
|
||||
- int i = this.index % i;
|
||||
- int j = this.index / i;
|
||||
- int k = j % j;
|
||||
- int l = j / j;
|
||||
+ int offsetX = this.index % i; // Paper - decomp fix
|
||||
+ int u = this.index / i; // Paper - decomp fix
|
||||
+ int offsetY = u % j; // Paper - decomp fix
|
||||
+ int offsetZ = u / j; // Paper - decomp fix
|
||||
++this.index;
|
||||
- return this.cursor.set(startX + i, startY + k, startZ + l);
|
||||
+ return this.cursor.set(startX + offsetX, startY + offsetY, startZ + offsetZ); // Paper - decomp fix
|
||||
}
|
||||
}
|
||||
};
|
||||
diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
|
||||
+++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
|
||||
@@ -0,0 +0,0 @@ public class BuiltInRegistries {
|
||||
LOADERS.put(resourceLocation, () -> {
|
||||
return initializer.run(registry);
|
||||
});
|
||||
- WRITABLE_REGISTRY.register(key, registry, lifecycle);
|
||||
+ WRITABLE_REGISTRY.register((ResourceKey) key, registry, lifecycle); // Paper - decompile fix
|
||||
return registry;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java
|
||||
+++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
|
||||
@@ -0,0 +0,0 @@ public class ComponentUtils {
|
||||
ComponentContents string = text.getContents();
|
||||
if (string instanceof TranslatableContents) {
|
||||
TranslatableContents translatableContents = (TranslatableContents)string;
|
||||
- String string = translatableContents.getKey();
|
||||
String string2 = translatableContents.getFallback();
|
||||
- return string2 != null || Language.getInstance().has(string);
|
||||
+ return string2 != null || Language.getInstance().has(translatableContents.getKey()); // Paper - decompile fix
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
||||
+++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
||||
@@ -0,0 +0,0 @@ public class RegistryDataLoader {
|
||||
return new RegistryOps.RegistryInfoLookup() {
|
||||
@Override
|
||||
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryRef) {
|
||||
- return Optional.ofNullable(map.get(registryRef));
|
||||
+ return Optional.ofNullable((RegistryOps.RegistryInfo<T>) map.get(registryRef)); // Paper - decompile fix
|
||||
}
|
||||
};
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
PackRepository resourcepackrepository = this.packRepository;
|
||||
|
||||
Objects.requireNonNull(this.packRepository);
|
||||
- return stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error
|
||||
+ return stream.<Pack>map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error // todo: is this needed anymore?
|
||||
}, this).thenCompose((immutablelist) -> {
|
||||
MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/Ticket.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/Ticket.java
|
||||
@@ -0,0 +0,0 @@ public final class Ticket<T> implements Comparable<Ticket<?>> {
|
||||
return i;
|
||||
} else {
|
||||
int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type));
|
||||
- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key);
|
||||
+ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/util/SortedArraySet.java
|
||||
+++ b/src/main/java/net/minecraft/util/SortedArraySet.java
|
||||
@@ -0,0 +0,0 @@ public class SortedArraySet<T> extends AbstractSet<T> {
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> SortedArraySet<T> create(int initialCapacity) {
|
||||
- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder());
|
||||
+ return new SortedArraySet<>(initialCapacity, Comparator.<T>naturalOrder()); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public static <T> SortedArraySet<T> create(Comparator<T> comparator) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
@@ -0,0 +0,0 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Rider
|
||||
@Override
|
||||
protected void customServerAiStep() {
|
||||
this.level.getProfiler().push("camelBrain");
|
||||
- Brain<?> brain = this.getBrain();
|
||||
+ Brain<Camel> brain = (Brain<Camel>) this.getBrain(); // Paper - decompile fix
|
||||
brain.tick((ServerLevel)this.level, this);
|
||||
this.level.getProfiler().pop();
|
||||
this.level.getProfiler().push("camelActivityUpdate");
|
||||
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
|
||||
@@ -0,0 +0,0 @@ public class Frog extends Animal implements VariantHolder<FrogVariant> {
|
||||
|
||||
@Override
|
||||
public Brain<Frog> getBrain() {
|
||||
- return super.getBrain();
|
||||
+ return (Brain<Frog>) super.getBrain(); // Paper - decompile fix
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
@@ -0,0 +0,0 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
||||
|
||||
@Override
|
||||
public Brain<Hoglin> getBrain() {
|
||||
- return super.getBrain();
|
||||
+ return (Brain<Hoglin>) super.getBrain(); // Paper - decompile fix
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
@@ -0,0 +0,0 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
|
||||
}
|
||||
|
||||
this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> {
|
||||
- return (entry1.getValue()); // CraftBukkit
|
||||
+ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* // todo: is this needed anymore?
|
||||
}));
|
||||
this.byName = Maps.newHashMap(builder.build()); // CraftBukkit
|
||||
RecipeManager.LOGGER.info("Loaded {} recipes", map1.size());
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
@@ -0,0 +0,0 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
}
|
||||
|
||||
private static <T, C extends PalettedContainerRO<T>> Codec<C> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T defaultValue, PalettedContainerRO.Unpacker<T, C> reader) {
|
||||
- return RecordCodecBuilder.<PalettedContainerRO.PackedData>create((instance) -> {
|
||||
+ return RecordCodecBuilder.<PalettedContainerRO.PackedData<T>>create((instance) -> { // Paper - decompile fix
|
||||
return instance.group(entryCodec.mapResult(ExtraCodecs.orElsePartial(defaultValue)).listOf().fieldOf("palette").forGetter(PalettedContainerRO.PackedData::paletteEntries), Codec.LONG_STREAM.optionalFieldOf("data").forGetter(PalettedContainerRO.PackedData::storage)).apply(instance, PalettedContainerRO.PackedData::new);
|
||||
}).comapFlatMap((serialized) -> {
|
||||
return reader.read(idList, provider, serialized);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
||||
@@ -0,0 +0,0 @@ public class EntityLookup<T extends EntityAccess> {
|
||||
public <U extends T> void getEntities(EntityTypeTest<T, U> filter, AbortableIterationConsumer<U> consumer) {
|
||||
for(T entityAccess : this.byId.values()) {
|
||||
U entityAccess2 = (U)((EntityAccess)filter.tryCast(entityAccess));
|
||||
- if (entityAccess2 != null && consumer.accept((T)entityAccess2).shouldAbort()) {
|
||||
+ if (entityAccess2 != null && consumer.accept(entityAccess2).shouldAbort()) { // Paper - decompile fix
|
||||
return;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySection.java b/src/main/java/net/minecraft/world/level/entity/EntitySection.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/entity/EntitySection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/entity/EntitySection.java
|
||||
@@ -0,0 +0,0 @@ public class EntitySection<T extends EntityAccess> {
|
||||
} else {
|
||||
for(T entityAccess : collection) {
|
||||
U entityAccess2 = (U)((EntityAccess)type.tryCast(entityAccess));
|
||||
- if (entityAccess2 != null && entityAccess.getBoundingBox().intersects(box) && consumer.accept((T)entityAccess2).shouldAbort()) {
|
||||
+ if (entityAccess2 != null && entityAccess.getBoundingBox().intersects(box) && consumer.accept(entityAccess2).shouldAbort()) { // Paper - decompile fix
|
||||
return AbortableIterationConsumer.Continuation.ABORT;
|
||||
}
|
||||
}
|
7760
patches/server/MC-Utils.patch
Normal file
7760
patches/server/MC-Utils.patch
Normal file
File diff suppressed because it is too large
Load Diff
25
patches/server/Only-refresh-abilities-if-needed.patch
Normal file
25
patches/server/Only-refresh-abilities-if-needed.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Tue, 1 Mar 2016 23:12:03 -0600
|
||||
Subject: [PATCH] Only refresh abilities if needed
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
@Override
|
||||
public void setFlying(boolean value) {
|
||||
+ boolean needsUpdate = getHandle().getAbilities().flying != value; // Paper - Only refresh abilities if needed
|
||||
if (!this.getAllowFlight() && value) {
|
||||
throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false");
|
||||
}
|
||||
|
||||
this.getHandle().getAbilities().flying = value;
|
||||
- this.getHandle().onUpdateAbilities();
|
||||
+ if (needsUpdate) this.getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed
|
||||
}
|
||||
|
||||
@Override
|
731
patches/server/Paper-Metrics.patch
Normal file
731
patches/server/Paper-Metrics.patch
Normal file
@@ -0,0 +1,731 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Fri, 24 Mar 2017 23:56:01 -0500
|
||||
Subject: [PATCH] Paper Metrics
|
||||
|
||||
Removes Spigot's mcstats metrics in favor of a system using bStats
|
||||
|
||||
To disable for privacy or other reasons go to the bStats folder in your plugins folder
|
||||
and edit the config.yml file present there.
|
||||
|
||||
Please keep in mind the data collected is anonymous and collection should have no
|
||||
tangible effect on server performance. The data is used to allow the authors of
|
||||
PaperMC to track version and platform usage so that we can make better management
|
||||
decisions on behalf of the project.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.configuration.file.YamlConfiguration;
|
||||
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import org.json.simple.JSONArray;
|
||||
+import org.json.simple.JSONObject;
|
||||
+
|
||||
+import javax.net.ssl.HttpsURLConnection;
|
||||
+import java.io.ByteArrayOutputStream;
|
||||
+import java.io.DataOutputStream;
|
||||
+import java.io.File;
|
||||
+import java.io.IOException;
|
||||
+import java.net.URL;
|
||||
+import java.util.*;
|
||||
+import java.util.concurrent.Callable;
|
||||
+import java.util.concurrent.Executors;
|
||||
+import java.util.concurrent.ScheduledExecutorService;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.logging.Logger;
|
||||
+import java.util.regex.Matcher;
|
||||
+import java.util.regex.Pattern;
|
||||
+import java.util.zip.GZIPOutputStream;
|
||||
+
|
||||
+/**
|
||||
+ * bStats collects some data for plugin authors.
|
||||
+ *
|
||||
+ * Check out https://bStats.org/ to learn more about bStats!
|
||||
+ */
|
||||
+public class Metrics {
|
||||
+
|
||||
+ // Executor service for requests
|
||||
+ // We use an executor service because the Bukkit scheduler is affected by server lags
|
||||
+ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
+
|
||||
+ // The version of this bStats class
|
||||
+ public static final int B_STATS_VERSION = 1;
|
||||
+
|
||||
+ // The url to which the data is sent
|
||||
+ private static final String URL = "https://bStats.org/submitData/server-implementation";
|
||||
+
|
||||
+ // Should failed requests be logged?
|
||||
+ private static boolean logFailedRequests = false;
|
||||
+
|
||||
+ // The logger for the failed requests
|
||||
+ private static Logger logger = Logger.getLogger("bStats");
|
||||
+
|
||||
+ // The name of the server software
|
||||
+ private final String name;
|
||||
+
|
||||
+ // The uuid of the server
|
||||
+ private final String serverUUID;
|
||||
+
|
||||
+ // A list with all custom charts
|
||||
+ private final List<CustomChart> charts = new ArrayList<>();
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param name The name of the server software.
|
||||
+ * @param serverUUID The uuid of the server.
|
||||
+ * @param logFailedRequests Whether failed requests should be logged or not.
|
||||
+ * @param logger The logger for the failed requests.
|
||||
+ */
|
||||
+ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) {
|
||||
+ this.name = name;
|
||||
+ this.serverUUID = serverUUID;
|
||||
+ Metrics.logFailedRequests = logFailedRequests;
|
||||
+ Metrics.logger = logger;
|
||||
+
|
||||
+ // Start submitting the data
|
||||
+ startSubmitting();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Adds a custom chart.
|
||||
+ *
|
||||
+ * @param chart The chart to add.
|
||||
+ */
|
||||
+ public void addCustomChart(CustomChart chart) {
|
||||
+ if (chart == null) {
|
||||
+ throw new IllegalArgumentException("Chart cannot be null!");
|
||||
+ }
|
||||
+ charts.add(chart);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Starts the Scheduler which submits our data every 30 minutes.
|
||||
+ */
|
||||
+ private void startSubmitting() {
|
||||
+ final Runnable submitTask = this::submitData;
|
||||
+
|
||||
+ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the
|
||||
+ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay.
|
||||
+ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency!
|
||||
+ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it!
|
||||
+ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
|
||||
+ long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
|
||||
+ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
|
||||
+ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the plugin specific data.
|
||||
+ *
|
||||
+ * @return The plugin specific data.
|
||||
+ */
|
||||
+ private JSONObject getPluginData() {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+
|
||||
+ data.put("pluginName", name); // Append the name of the server software
|
||||
+ JSONArray customCharts = new JSONArray();
|
||||
+ for (CustomChart customChart : charts) {
|
||||
+ // Add the data of the custom charts
|
||||
+ JSONObject chart = customChart.getRequestJsonObject();
|
||||
+ if (chart == null) { // If the chart is null, we skip it
|
||||
+ continue;
|
||||
+ }
|
||||
+ customCharts.add(chart);
|
||||
+ }
|
||||
+ data.put("customCharts", customCharts);
|
||||
+
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the server specific data.
|
||||
+ *
|
||||
+ * @return The server specific data.
|
||||
+ */
|
||||
+ private JSONObject getServerData() {
|
||||
+ // OS specific data
|
||||
+ String osName = System.getProperty("os.name");
|
||||
+ String osArch = System.getProperty("os.arch");
|
||||
+ String osVersion = System.getProperty("os.version");
|
||||
+ int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
+
|
||||
+ JSONObject data = new JSONObject();
|
||||
+
|
||||
+ data.put("serverUUID", serverUUID);
|
||||
+
|
||||
+ data.put("osName", osName);
|
||||
+ data.put("osArch", osArch);
|
||||
+ data.put("osVersion", osVersion);
|
||||
+ data.put("coreCount", coreCount);
|
||||
+
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Collects the data and sends it afterwards.
|
||||
+ */
|
||||
+ private void submitData() {
|
||||
+ final JSONObject data = getServerData();
|
||||
+
|
||||
+ JSONArray pluginData = new JSONArray();
|
||||
+ pluginData.add(getPluginData());
|
||||
+ data.put("plugins", pluginData);
|
||||
+
|
||||
+ try {
|
||||
+ // We are still in the Thread of the timer, so nothing get blocked :)
|
||||
+ sendData(data);
|
||||
+ } catch (Exception e) {
|
||||
+ // Something went wrong! :(
|
||||
+ if (logFailedRequests) {
|
||||
+ logger.log(Level.WARNING, "Could not submit stats of " + name, e);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the data to the bStats server.
|
||||
+ *
|
||||
+ * @param data The data to send.
|
||||
+ * @throws Exception If the request failed.
|
||||
+ */
|
||||
+ private static void sendData(JSONObject data) throws Exception {
|
||||
+ if (data == null) {
|
||||
+ throw new IllegalArgumentException("Data cannot be null!");
|
||||
+ }
|
||||
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
|
||||
+
|
||||
+ // Compress the data to save bandwidth
|
||||
+ byte[] compressedData = compress(data.toString());
|
||||
+
|
||||
+ // Add headers
|
||||
+ connection.setRequestMethod("POST");
|
||||
+ connection.addRequestProperty("Accept", "application/json");
|
||||
+ connection.addRequestProperty("Connection", "close");
|
||||
+ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
|
||||
+ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
||||
+ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
|
||||
+ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
|
||||
+
|
||||
+ // Send data
|
||||
+ connection.setDoOutput(true);
|
||||
+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
|
||||
+ outputStream.write(compressedData);
|
||||
+ outputStream.flush();
|
||||
+ outputStream.close();
|
||||
+
|
||||
+ connection.getInputStream().close(); // We don't care about the response - Just send our data :)
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gzips the given String.
|
||||
+ *
|
||||
+ * @param str The string to gzip.
|
||||
+ * @return The gzipped String.
|
||||
+ * @throws IOException If the compression failed.
|
||||
+ */
|
||||
+ private static byte[] compress(final String str) throws IOException {
|
||||
+ if (str == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
+ GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
||||
+ gzip.write(str.getBytes("UTF-8"));
|
||||
+ gzip.close();
|
||||
+ return outputStream.toByteArray();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom chart.
|
||||
+ */
|
||||
+ public static abstract class CustomChart {
|
||||
+
|
||||
+ // The id of the chart
|
||||
+ final String chartId;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ */
|
||||
+ CustomChart(String chartId) {
|
||||
+ if (chartId == null || chartId.isEmpty()) {
|
||||
+ throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
||||
+ }
|
||||
+ this.chartId = chartId;
|
||||
+ }
|
||||
+
|
||||
+ private JSONObject getRequestJsonObject() {
|
||||
+ JSONObject chart = new JSONObject();
|
||||
+ chart.put("chartId", chartId);
|
||||
+ try {
|
||||
+ JSONObject data = getChartData();
|
||||
+ if (data == null) {
|
||||
+ // If the data is null we don't send the chart.
|
||||
+ return null;
|
||||
+ }
|
||||
+ chart.put("data", data);
|
||||
+ } catch (Throwable t) {
|
||||
+ if (logFailedRequests) {
|
||||
+ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ return chart;
|
||||
+ }
|
||||
+
|
||||
+ protected abstract JSONObject getChartData() throws Exception;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom simple pie.
|
||||
+ */
|
||||
+ public static class SimplePie extends CustomChart {
|
||||
+
|
||||
+ private final Callable<String> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public SimplePie(String chartId, Callable<String> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ String value = callable.call();
|
||||
+ if (value == null || value.isEmpty()) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ data.put("value", value);
|
||||
+ return data;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom advanced pie.
|
||||
+ */
|
||||
+ public static class AdvancedPie extends CustomChart {
|
||||
+
|
||||
+ private final Callable<Map<String, Integer>> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ JSONObject values = new JSONObject();
|
||||
+ Map<String, Integer> map = callable.call();
|
||||
+ if (map == null || map.isEmpty()) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ boolean allSkipped = true;
|
||||
+ for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
+ if (entry.getValue() == 0) {
|
||||
+ continue; // Skip this invalid
|
||||
+ }
|
||||
+ allSkipped = false;
|
||||
+ values.put(entry.getKey(), entry.getValue());
|
||||
+ }
|
||||
+ if (allSkipped) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ data.put("values", values);
|
||||
+ return data;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom drilldown pie.
|
||||
+ */
|
||||
+ public static class DrilldownPie extends CustomChart {
|
||||
+
|
||||
+ private final Callable<Map<String, Map<String, Integer>>> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ JSONObject values = new JSONObject();
|
||||
+ Map<String, Map<String, Integer>> map = callable.call();
|
||||
+ if (map == null || map.isEmpty()) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ boolean reallyAllSkipped = true;
|
||||
+ for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
|
||||
+ JSONObject value = new JSONObject();
|
||||
+ boolean allSkipped = true;
|
||||
+ for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
|
||||
+ value.put(valueEntry.getKey(), valueEntry.getValue());
|
||||
+ allSkipped = false;
|
||||
+ }
|
||||
+ if (!allSkipped) {
|
||||
+ reallyAllSkipped = false;
|
||||
+ values.put(entryValues.getKey(), value);
|
||||
+ }
|
||||
+ }
|
||||
+ if (reallyAllSkipped) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ data.put("values", values);
|
||||
+ return data;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom single line chart.
|
||||
+ */
|
||||
+ public static class SingleLineChart extends CustomChart {
|
||||
+
|
||||
+ private final Callable<Integer> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public SingleLineChart(String chartId, Callable<Integer> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ int value = callable.call();
|
||||
+ if (value == 0) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ data.put("value", value);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom multi line chart.
|
||||
+ */
|
||||
+ public static class MultiLineChart extends CustomChart {
|
||||
+
|
||||
+ private final Callable<Map<String, Integer>> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ JSONObject values = new JSONObject();
|
||||
+ Map<String, Integer> map = callable.call();
|
||||
+ if (map == null || map.isEmpty()) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ boolean allSkipped = true;
|
||||
+ for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
+ if (entry.getValue() == 0) {
|
||||
+ continue; // Skip this invalid
|
||||
+ }
|
||||
+ allSkipped = false;
|
||||
+ values.put(entry.getKey(), entry.getValue());
|
||||
+ }
|
||||
+ if (allSkipped) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ data.put("values", values);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom simple bar chart.
|
||||
+ */
|
||||
+ public static class SimpleBarChart extends CustomChart {
|
||||
+
|
||||
+ private final Callable<Map<String, Integer>> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ JSONObject values = new JSONObject();
|
||||
+ Map<String, Integer> map = callable.call();
|
||||
+ if (map == null || map.isEmpty()) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
+ JSONArray categoryValues = new JSONArray();
|
||||
+ categoryValues.add(entry.getValue());
|
||||
+ values.put(entry.getKey(), categoryValues);
|
||||
+ }
|
||||
+ data.put("values", values);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a custom advanced bar chart.
|
||||
+ */
|
||||
+ public static class AdvancedBarChart extends CustomChart {
|
||||
+
|
||||
+ private final Callable<Map<String, int[]>> callable;
|
||||
+
|
||||
+ /**
|
||||
+ * Class constructor.
|
||||
+ *
|
||||
+ * @param chartId The id of the chart.
|
||||
+ * @param callable The callable which is used to request the chart data.
|
||||
+ */
|
||||
+ public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
|
||||
+ super(chartId);
|
||||
+ this.callable = callable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected JSONObject getChartData() throws Exception {
|
||||
+ JSONObject data = new JSONObject();
|
||||
+ JSONObject values = new JSONObject();
|
||||
+ Map<String, int[]> map = callable.call();
|
||||
+ if (map == null || map.isEmpty()) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ boolean allSkipped = true;
|
||||
+ for (Map.Entry<String, int[]> entry : map.entrySet()) {
|
||||
+ if (entry.getValue().length == 0) {
|
||||
+ continue; // Skip this invalid
|
||||
+ }
|
||||
+ allSkipped = false;
|
||||
+ JSONArray categoryValues = new JSONArray();
|
||||
+ for (int categoryValue : entry.getValue()) {
|
||||
+ categoryValues.add(categoryValue);
|
||||
+ }
|
||||
+ values.put(entry.getKey(), categoryValues);
|
||||
+ }
|
||||
+ if (allSkipped) {
|
||||
+ // Null = skip the chart
|
||||
+ return null;
|
||||
+ }
|
||||
+ data.put("values", values);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ public static class PaperMetrics {
|
||||
+ public static void startMetrics() {
|
||||
+ // Get the config file
|
||||
+ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml");
|
||||
+ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
|
||||
+
|
||||
+ // Check if the config file exists
|
||||
+ if (!config.isSet("serverUuid")) {
|
||||
+
|
||||
+ // Add default values
|
||||
+ config.addDefault("enabled", true);
|
||||
+ // Every server gets it's unique random id.
|
||||
+ config.addDefault("serverUuid", UUID.randomUUID().toString());
|
||||
+ // Should failed request be logged?
|
||||
+ config.addDefault("logFailedRequests", false);
|
||||
+
|
||||
+ // Inform the server owners about bStats
|
||||
+ config.options().header(
|
||||
+ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
|
||||
+ "To honor their work, you should not disable it.\n" +
|
||||
+ "This has nearly no effect on the server performance!\n" +
|
||||
+ "Check out https://bStats.org/ to learn more :)"
|
||||
+ ).copyDefaults(true);
|
||||
+ try {
|
||||
+ config.save(configFile);
|
||||
+ } catch (IOException ignored) {
|
||||
+ }
|
||||
+ }
|
||||
+ // Load the data
|
||||
+ String serverUUID = config.getString("serverUuid");
|
||||
+ boolean logFailedRequests = config.getBoolean("logFailedRequests", false);
|
||||
+ // Only start Metrics, if it's enabled in the config
|
||||
+ if (config.getBoolean("enabled", true)) {
|
||||
+ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger());
|
||||
+
|
||||
+ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> {
|
||||
+ String minecraftVersion = Bukkit.getVersion();
|
||||
+ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1);
|
||||
+ return minecraftVersion;
|
||||
+ }));
|
||||
+
|
||||
+ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size()));
|
||||
+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : "offline"));
|
||||
+ final String paperVersion;
|
||||
+ final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion();
|
||||
+ if (implVersion != null) {
|
||||
+ final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1);
|
||||
+ paperVersion = "git-Paper-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash);
|
||||
+ } else {
|
||||
+ paperVersion = "unknown";
|
||||
+ }
|
||||
+ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> paperVersion));
|
||||
+
|
||||
+ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> {
|
||||
+ Map<String, Map<String, Integer>> map = new HashMap<>();
|
||||
+ String javaVersion = System.getProperty("java.version");
|
||||
+ Map<String, Integer> entry = new HashMap<>();
|
||||
+ entry.put(javaVersion, 1);
|
||||
+
|
||||
+ // http://openjdk.java.net/jeps/223
|
||||
+ // Java decided to change their versioning scheme and in doing so modified the java.version system
|
||||
+ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier
|
||||
+ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+
|
||||
+ String majorVersion = javaVersion.split("\\.")[0];
|
||||
+ String release;
|
||||
+
|
||||
+ int indexOf = javaVersion.lastIndexOf('.');
|
||||
+
|
||||
+ if (majorVersion.equals("1")) {
|
||||
+ release = "Java " + javaVersion.substring(0, indexOf);
|
||||
+ } else {
|
||||
+ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it
|
||||
+ // valid strings for the major may potentially include values such as -ea to deannotate a pre release
|
||||
+ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion);
|
||||
+ if (versionMatcher.find()) {
|
||||
+ majorVersion = versionMatcher.group(0);
|
||||
+ }
|
||||
+ release = "Java " + majorVersion;
|
||||
+ }
|
||||
+ map.put(release, entry);
|
||||
+
|
||||
+ return map;
|
||||
+ }));
|
||||
+
|
||||
+ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> {
|
||||
+ Map<String, Map<String, Integer>> map = new HashMap<>();
|
||||
+
|
||||
+ // count legacy plugins
|
||||
+ int legacy = 0;
|
||||
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
+ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) {
|
||||
+ legacy++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // insert real value as lower dimension
|
||||
+ Map<String, Integer> entry = new HashMap<>();
|
||||
+ entry.put(String.valueOf(legacy), 1);
|
||||
+
|
||||
+ // create buckets as higher dimension
|
||||
+ if (legacy == 0) {
|
||||
+ map.put("0 \uD83D\uDE0E", entry); // :sunglasses:
|
||||
+ } else if (legacy <= 5) {
|
||||
+ map.put("1-5", entry);
|
||||
+ } else if (legacy <= 10) {
|
||||
+ map.put("6-10", entry);
|
||||
+ } else if (legacy <= 25) {
|
||||
+ map.put("11-25", entry);
|
||||
+ } else if (legacy <= 50) {
|
||||
+ map.put("26-50", entry);
|
||||
+ } else {
|
||||
+ map.put("50+ \uD83D\uDE2D", entry); // :cry:
|
||||
+ }
|
||||
+
|
||||
+ return map;
|
||||
+ }));
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
paperConfigurations.initializeGlobalConfiguration();
|
||||
paperConfigurations.initializeWorldDefaultsConfiguration();
|
||||
io.papermc.paper.command.PaperCommands.registerCommands(this);
|
||||
+ com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics();
|
||||
// Paper end
|
||||
|
||||
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -0,0 +0,0 @@ public class SpigotConfig
|
||||
MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() );
|
||||
}
|
||||
|
||||
+ /* // Paper - Replace with our own
|
||||
if ( SpigotConfig.metrics == null )
|
||||
{
|
||||
try
|
||||
@@ -0,0 +0,0 @@ public class SpigotConfig
|
||||
Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex );
|
||||
}
|
||||
}
|
||||
+ */ // Paper end
|
||||
}
|
||||
|
||||
public static void readConfig(Class<?> clazz, Object instance) // Paper - package-private -> public
|
7348
patches/server/Paper-Plugins.patch
Normal file
7348
patches/server/Paper-Plugins.patch
Normal file
File diff suppressed because it is too large
Load Diff
620
patches/server/Paper-command.patch
Normal file
620
patches/server/Paper-command.patch
Normal file
@@ -0,0 +1,620 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Mon, 29 Feb 2016 21:02:09 -0600
|
||||
Subject: [PATCH] Paper command
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/command/CommandUtil.java b/src/main/java/io/papermc/paper/command/CommandUtil.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/CommandUtil.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command;
|
||||
+
|
||||
+import com.google.common.base.Functions;
|
||||
+import com.google.common.collect.Iterables;
|
||||
+import com.google.common.collect.Lists;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.List;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class CommandUtil {
|
||||
+ private CommandUtil() {
|
||||
+ }
|
||||
+
|
||||
+ // Code from Mojang - copyright them
|
||||
+ public static List<String> getListMatchingLast(
|
||||
+ final CommandSender sender,
|
||||
+ final String[] args,
|
||||
+ final String... matches
|
||||
+ ) {
|
||||
+ return getListMatchingLast(sender, args, Arrays.asList(matches));
|
||||
+ }
|
||||
+
|
||||
+ public static boolean matches(final String s, final String s1) {
|
||||
+ return s1.regionMatches(true, 0, s, 0, s.length());
|
||||
+ }
|
||||
+
|
||||
+ public static List<String> getListMatchingLast(
|
||||
+ final CommandSender sender,
|
||||
+ final String[] strings,
|
||||
+ final Collection<?> collection
|
||||
+ ) {
|
||||
+ String last = strings[strings.length - 1];
|
||||
+ ArrayList<String> results = Lists.newArrayList();
|
||||
+
|
||||
+ if (!collection.isEmpty()) {
|
||||
+ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ String s1 = (String) iterator.next();
|
||||
+
|
||||
+ if (matches(last, s1) && (sender.hasPermission(PaperCommand.BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) {
|
||||
+ results.add(s1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (results.isEmpty()) {
|
||||
+ iterator = collection.iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ Object object = iterator.next();
|
||||
+
|
||||
+ if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) {
|
||||
+ results.add(String.valueOf(object));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return results;
|
||||
+ }
|
||||
+ // end copy stuff
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command;
|
||||
+
|
||||
+import io.papermc.paper.command.subcommands.EntityCommand;
|
||||
+import io.papermc.paper.command.subcommands.HeapDumpCommand;
|
||||
+import io.papermc.paper.command.subcommands.ReloadCommand;
|
||||
+import io.papermc.paper.command.subcommands.VersionCommand;
|
||||
+import it.unimi.dsi.fastutil.Pair;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Collections;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.List;
|
||||
+import java.util.Locale;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+import java.util.stream.Collectors;
|
||||
+import net.minecraft.Util;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.permissions.Permission;
|
||||
+import org.bukkit.permissions.PermissionDefault;
|
||||
+import org.bukkit.plugin.PluginManager;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class PaperCommand extends Command {
|
||||
+ static final String BASE_PERM = "bukkit.command.paper.";
|
||||
+ // subcommand label -> subcommand
|
||||
+ private static final Map<String, PaperSubcommand> SUBCOMMANDS = Util.make(() -> {
|
||||
+ final Map<Set<String>, PaperSubcommand> commands = new HashMap<>();
|
||||
+
|
||||
+ commands.put(Set.of("heap"), new HeapDumpCommand());
|
||||
+ commands.put(Set.of("entity"), new EntityCommand());
|
||||
+ commands.put(Set.of("reload"), new ReloadCommand());
|
||||
+ commands.put(Set.of("version"), new VersionCommand());
|
||||
+
|
||||
+ return commands.entrySet().stream()
|
||||
+ .flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
||||
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
+ });
|
||||
+ // alias -> subcommand label
|
||||
+ private static final Map<String, String> ALIASES = Util.make(() -> {
|
||||
+ final Map<String, Set<String>> aliases = new HashMap<>();
|
||||
+
|
||||
+ aliases.put("version", Set.of("ver"));
|
||||
+
|
||||
+ return aliases.entrySet().stream()
|
||||
+ .flatMap(entry -> entry.getValue().stream().map(s -> Map.entry(s, entry.getKey())))
|
||||
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
+ });
|
||||
+
|
||||
+ public PaperCommand(final String name) {
|
||||
+ super(name);
|
||||
+ this.description = "Paper related commands";
|
||||
+ this.usageMessage = "/paper [" + String.join(" | ", SUBCOMMANDS.keySet()) + "]";
|
||||
+ final List<String> permissions = new ArrayList<>();
|
||||
+ permissions.add("bukkit.command.paper");
|
||||
+ permissions.addAll(SUBCOMMANDS.keySet().stream().map(s -> BASE_PERM + s).toList());
|
||||
+ this.setPermission(String.join(";", permissions));
|
||||
+ final PluginManager pluginManager = Bukkit.getServer().getPluginManager();
|
||||
+ for (final String perm : permissions) {
|
||||
+ pluginManager.addPermission(new Permission(perm, PermissionDefault.OP));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static boolean testPermission(final CommandSender sender, final String permission) {
|
||||
+ if (sender.hasPermission(BASE_PERM + permission) || sender.hasPermission("bukkit.command.paper")) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ sender.sendMessage(text("I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.", RED));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(
|
||||
+ final CommandSender sender,
|
||||
+ final String alias,
|
||||
+ final String[] args,
|
||||
+ final @Nullable Location location
|
||||
+ ) throws IllegalArgumentException {
|
||||
+ if (args.length <= 1) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, SUBCOMMANDS.keySet());
|
||||
+ }
|
||||
+
|
||||
+ final @Nullable Pair<String, PaperSubcommand> subCommand = resolveCommand(args[0]);
|
||||
+ if (subCommand != null) {
|
||||
+ return subCommand.second().tabComplete(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length));
|
||||
+ }
|
||||
+
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean execute(
|
||||
+ final CommandSender sender,
|
||||
+ final String commandLabel,
|
||||
+ final String[] args
|
||||
+ ) {
|
||||
+ if (!testPermission(sender)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (args.length == 0) {
|
||||
+ sender.sendMessage(text("Usage: " + this.usageMessage, RED));
|
||||
+ return false;
|
||||
+ }
|
||||
+ final @Nullable Pair<String, PaperSubcommand> subCommand = resolveCommand(args[0]);
|
||||
+
|
||||
+ if (subCommand == null) {
|
||||
+ sender.sendMessage(text("Usage: " + this.usageMessage, RED));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (!testPermission(sender, subCommand.first())) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
+ return subCommand.second().execute(sender, subCommand.first(), choppedArgs);
|
||||
+ }
|
||||
+
|
||||
+ private static @Nullable Pair<String, PaperSubcommand> resolveCommand(String label) {
|
||||
+ label = label.toLowerCase(Locale.ENGLISH);
|
||||
+ @Nullable PaperSubcommand subCommand = SUBCOMMANDS.get(label);
|
||||
+ if (subCommand == null) {
|
||||
+ final @Nullable String command = ALIASES.get(label);
|
||||
+ if (command != null) {
|
||||
+ label = command;
|
||||
+ subCommand = SUBCOMMANDS.get(command);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (subCommand != null) {
|
||||
+ return Pair.of(label, subCommand);
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommands.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.command.Command;
|
||||
+
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Map;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class PaperCommands {
|
||||
+
|
||||
+ private PaperCommands() {
|
||||
+ }
|
||||
+
|
||||
+ private static final Map<String, Command> COMMANDS = new HashMap<>();
|
||||
+ static {
|
||||
+ COMMANDS.put("paper", new PaperCommand("paper"));
|
||||
+ }
|
||||
+
|
||||
+ public static void registerCommands(final MinecraftServer server) {
|
||||
+ COMMANDS.forEach((s, command) -> {
|
||||
+ server.server.getCommandMap().register(s, "Paper", command);
|
||||
+ });
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperSubcommand.java b/src/main/java/io/papermc/paper/command/PaperSubcommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperSubcommand.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command;
|
||||
+
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public interface PaperSubcommand {
|
||||
+ boolean execute(CommandSender sender, String subCommand, String[] args);
|
||||
+
|
||||
+ default List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java b/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import com.google.common.collect.Maps;
|
||||
+import io.papermc.paper.command.CommandUtil;
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import java.util.Locale;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+import java.util.stream.Collectors;
|
||||
+
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.event.ClickEvent;
|
||||
+import net.kyori.adventure.text.event.HoverEvent;
|
||||
+import net.minecraft.core.registries.BuiltInRegistries;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.level.ServerChunkCache;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.world.entity.EntityType;
|
||||
+import net.minecraft.world.level.ChunkPos;
|
||||
+import org.apache.commons.lang3.tuple.MutablePair;
|
||||
+import org.apache.commons.lang3.tuple.Pair;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.HeightMap;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class EntityCommand implements PaperSubcommand {
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ this.listEntities(sender, args);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ if (args.length == 1) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, "help", "list");
|
||||
+ } else if (args.length == 2) {
|
||||
+ return CommandUtil.getListMatchingLast(sender, args, BuiltInRegistries.ENTITY_TYPE.keySet().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new));
|
||||
+ }
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Ported from MinecraftForge - author: LexManos <LexManos@gmail.com> - License: LGPLv2.1
|
||||
+ */
|
||||
+ private void listEntities(final CommandSender sender, final String[] args) {
|
||||
+ // help
|
||||
+ if (args.length < 1 || !args[0].toLowerCase(Locale.ENGLISH).equals("list")) {
|
||||
+ sender.sendMessage(text("Use /paper entity [list] help for more information on a specific command", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if ("list".equals(args[0].toLowerCase(Locale.ENGLISH))) {
|
||||
+ String filter = "*";
|
||||
+ if (args.length > 1) {
|
||||
+ if (args[1].toLowerCase(Locale.ENGLISH).equals("help")) {
|
||||
+ sender.sendMessage(text("Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter.", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ filter = args[1];
|
||||
+ }
|
||||
+ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?");
|
||||
+ Set<ResourceLocation> names = BuiltInRegistries.ENTITY_TYPE.keySet().stream()
|
||||
+ .filter(n -> n.toString().matches(cleanfilter))
|
||||
+ .collect(Collectors.toSet());
|
||||
+ if (names.isEmpty()) {
|
||||
+ sender.sendMessage(text("Invalid filter, does not match any entities. Use /paper entity list for a proper list", RED));
|
||||
+ sender.sendMessage(text("Usage: /paper entity list [filter] [worldName]", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ String worldName;
|
||||
+ if (args.length > 2) {
|
||||
+ worldName = args[2];
|
||||
+ } else if (sender instanceof Player) {
|
||||
+ worldName = ((Player) sender).getWorld().getName();
|
||||
+ } else {
|
||||
+ sender.sendMessage(text("Please specify the name of a world", RED));
|
||||
+ sender.sendMessage(text("To do so without a filter, specify '*' as the filter", RED));
|
||||
+ sender.sendMessage(text("Usage: /paper entity list [filter] [worldName]", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ Map<ResourceLocation, MutablePair<Integer, Map<ChunkPos, Integer>>> list = Maps.newHashMap();
|
||||
+ @Nullable World bukkitWorld = Bukkit.getWorld(worldName);
|
||||
+ if (bukkitWorld == null) {
|
||||
+ sender.sendMessage(text("Could not load world for " + worldName + ". Please select a valid world.", RED));
|
||||
+ sender.sendMessage(text("Usage: /paper entity list [filter] [worldName]", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ ServerLevel world = ((CraftWorld) bukkitWorld).getHandle();
|
||||
+ Map<ResourceLocation, Integer> nonEntityTicking = Maps.newHashMap();
|
||||
+ ServerChunkCache chunkProviderServer = world.getChunkSource();
|
||||
+ world.getAllEntities().forEach(e -> {
|
||||
+ ResourceLocation key = EntityType.getKey(e.getType());
|
||||
+
|
||||
+ MutablePair<Integer, Map<ChunkPos, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
|
||||
+ ChunkPos chunk = e.chunkPosition();
|
||||
+ info.left++;
|
||||
+ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1);
|
||||
+ if (!chunkProviderServer.isPositionTicking(e)) {
|
||||
+ nonEntityTicking.merge(key, 1, Integer::sum);
|
||||
+ }
|
||||
+ });
|
||||
+ if (names.size() == 1) {
|
||||
+ ResourceLocation name = names.iterator().next();
|
||||
+ Pair<Integer, Map<ChunkPos, Integer>> info = list.get(name);
|
||||
+ int nonTicking = nonEntityTicking.getOrDefault(name, 0);
|
||||
+ if (info == null) {
|
||||
+ sender.sendMessage(text("No entities found.", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking);
|
||||
+ info.getRight().entrySet().stream()
|
||||
+ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString()))
|
||||
+ .limit(10).forEach(e -> {
|
||||
+ final int x = (e.getKey().x << 4) + 8;
|
||||
+ final int z = (e.getKey().z << 4) + 8;
|
||||
+ final Component message = text(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isPositionTicking(e.getKey().toLong()) ? " (Ticking)" : " (Non-Ticking)"))
|
||||
+ .hoverEvent(HoverEvent.showText(text("Click to teleport to chunk", GREEN)))
|
||||
+ .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/minecraft:execute as @s in " + world.getWorld().getKey() + " run tp " + x + " " + (world.getWorld().getHighestBlockYAt(x, z, HeightMap.MOTION_BLOCKING) + 1) + " " + z));
|
||||
+ sender.sendMessage(message);
|
||||
+ });
|
||||
+ } else {
|
||||
+ List<Pair<ResourceLocation, Integer>> info = list.entrySet().stream()
|
||||
+ .filter(e -> names.contains(e.getKey()))
|
||||
+ .map(e -> Pair.of(e.getKey(), e.getValue().left))
|
||||
+ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString()))
|
||||
+ .toList();
|
||||
+
|
||||
+ if (info.isEmpty()) {
|
||||
+ sender.sendMessage(text("No entities found.", RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int count = info.stream().mapToInt(Pair::getRight).sum();
|
||||
+ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum();
|
||||
+ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount);
|
||||
+ info.forEach(e -> {
|
||||
+ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), 0);
|
||||
+ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey());
|
||||
+ });
|
||||
+ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/HeapDumpCommand.java b/src/main/java/io/papermc/paper/command/subcommands/HeapDumpCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/HeapDumpCommand.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import java.time.LocalDateTime;
|
||||
+import java.time.format.DateTimeFormatter;
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftServer;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.YELLOW;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class HeapDumpCommand implements PaperSubcommand {
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ this.dumpHeap(sender);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ private void dumpHeap(final CommandSender sender) {
|
||||
+ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps");
|
||||
+ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now());
|
||||
+
|
||||
+ Command.broadcastCommandMessage(sender, text("Writing JVM heap data...", YELLOW));
|
||||
+
|
||||
+ java.nio.file.Path file = CraftServer.dumpHeap(dir, name);
|
||||
+ if (file != null) {
|
||||
+ Command.broadcastCommandMessage(sender, text("Heap dump saved to " + file, GREEN));
|
||||
+ } else {
|
||||
+ Command.broadcastCommandMessage(sender, text("Failed to write heap dump, see server log for details", RED));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/ReloadCommand.java b/src/main/java/io/papermc/paper/command/subcommands/ReloadCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/ReloadCommand.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftServer;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
|
||||
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class ReloadCommand implements PaperSubcommand {
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ this.doReload(sender);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ private void doReload(final CommandSender sender) {
|
||||
+ Command.broadcastCommandMessage(sender, text("Please note that this command is not supported and may cause issues.", RED));
|
||||
+ Command.broadcastCommandMessage(sender, text("If you encounter any issues please use the /stop command to restart your server.", RED));
|
||||
+
|
||||
+ MinecraftServer server = ((CraftServer) sender.getServer()).getServer();
|
||||
+ server.paperConfigurations.reloadConfigs(server);
|
||||
+ server.server.reloadCount++;
|
||||
+
|
||||
+ Command.broadcastCommandMessage(sender, text("Paper config reload complete.", GREEN));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java b/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class VersionCommand implements PaperSubcommand {
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version");
|
||||
+ if (ver != null) {
|
||||
+ ver.execute(sender, "paper", new String[0]);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
// Paper start
|
||||
paperConfigurations.initializeGlobalConfiguration();
|
||||
paperConfigurations.initializeWorldDefaultsConfiguration();
|
||||
+ io.papermc.paper.command.PaperCommands.registerCommands(this);
|
||||
// Paper end
|
||||
|
||||
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
|
||||
this.commandMap.clearCommands();
|
||||
this.reloadData();
|
||||
org.spigotmc.SpigotConfig.registerCommands(); // Spigot
|
||||
+ io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
|
||||
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
||||
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
||||
|
||||
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
|
||||
// Spigot end
|
||||
|
||||
// Paper start
|
||||
+ @SuppressWarnings({"rawtypes", "unchecked"})
|
||||
+ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) {
|
||||
+ try {
|
||||
+ java.nio.file.Files.createDirectories(dir);
|
||||
+
|
||||
+ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer();
|
||||
+ java.nio.file.Path file;
|
||||
+
|
||||
+ try {
|
||||
+ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean");
|
||||
+ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz);
|
||||
+ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class);
|
||||
+ file = dir.resolve(name + ".phd");
|
||||
+ m.invoke(openj9Mbean, "heap", file.toString());
|
||||
+ } catch (ClassNotFoundException e) {
|
||||
+ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
|
||||
+ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz);
|
||||
+ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class);
|
||||
+ file = dir.resolve(name + ".hprof");
|
||||
+ m.invoke(hotspotMBean, file.toString(), true);
|
||||
+ }
|
||||
+
|
||||
+ return file;
|
||||
+ } catch (Throwable t) {
|
||||
+ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t);
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
private Iterable<? extends net.kyori.adventure.audience.Audience> adventure$audiences;
|
||||
@Override
|
||||
public Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
|
4672
patches/server/Paper-config-files.patch
Normal file
4672
patches/server/Paper-config-files.patch
Normal file
File diff suppressed because it is too large
Load Diff
163
patches/server/Player-affects-spawning-API.patch
Normal file
163
patches/server/Player-affects-spawning-API.patch
Normal file
@@ -0,0 +1,163 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Tue, 1 Mar 2016 14:47:52 -0600
|
||||
Subject: [PATCH] Player affects spawning API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
|
||||
@@ -0,0 +0,0 @@ public final class EntitySelector {
|
||||
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
|
||||
|
||||
private EntitySelector() {}
|
||||
+ // Paper start
|
||||
+ public static final Predicate<Entity> PLAYER_AFFECTS_SPAWNING = (entity) -> {
|
||||
+ return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning;
|
||||
+ };
|
||||
+ // Paper end
|
||||
|
||||
public static Predicate<Entity> withinDistance(double x, double y, double z, double max) {
|
||||
double d4 = max * max;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements Targeting {
|
||||
if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
|
||||
this.discard();
|
||||
} else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) {
|
||||
- Player entityhuman = this.level.getNearestPlayer(this, -1.0D);
|
||||
+ Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper
|
||||
|
||||
if (entityhuman != null) {
|
||||
double d0 = entityhuman.distanceToSqr((Entity) this);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
|
||||
@@ -0,0 +0,0 @@ public class SkeletonTrapGoal extends Goal {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return this.horse.level.hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D);
|
||||
+ return this.horse.level.hasNearbyAlivePlayerThatAffectsSpawning(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); // Paper - Affects Spawning API
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
||||
@@ -0,0 +0,0 @@ public class Silverfish extends Monster {
|
||||
if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) {
|
||||
Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true);
|
||||
|
||||
- return entityhuman == null;
|
||||
+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
|
||||
if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level, blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.REINFORCEMENT, blockposition, this.level.random)) {
|
||||
entityzombie.setPos((double) i1, (double) j1, (double) k1);
|
||||
- if (!this.level.hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level.isUnobstructed(entityzombie) && this.level.noCollision((Entity) entityzombie) && !this.level.containsAnyLiquid(entityzombie.getBoundingBox())) {
|
||||
+ if (!this.level.hasNearbyAlivePlayerThatAffectsSpawning((double) i1, (double) j1, (double) k1, 7.0D) && this.level.isUnobstructed(entityzombie) && this.level.noCollision((Entity) entityzombie) && !this.level.containsAnyLiquid(entityzombie.getBoundingBox())) { // Paper - Affects Spawning API
|
||||
entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit
|
||||
entityzombie.finalizeSpawn(worldserver, this.level.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.REINFORCEMENT, (SpawnGroupData) null, (CompoundTag) null);
|
||||
worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity {
|
||||
@Nullable
|
||||
public FishingHook fishing;
|
||||
protected float hurtDir;
|
||||
+ // Paper start
|
||||
+ public boolean affectsSpawning = true;
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public boolean fauxSleeping;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
|
||||
}
|
||||
|
||||
public boolean isNearPlayer(Level world, BlockPos pos) {
|
||||
- return world.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange);
|
||||
+ return world.hasNearbyAlivePlayerThatAffectsSpawning((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - Affects Spawning API
|
||||
}
|
||||
|
||||
public void clientTick(Level world, BlockPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
@@ -0,0 +0,0 @@ public interface EntityGetter {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ default @Nullable Player findNearbyPlayer(Entity entity, double maxDistance, @Nullable Predicate<Entity> predicate) {
|
||||
+ return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, predicate);
|
||||
+ }
|
||||
+ // Paper end
|
||||
@Nullable
|
||||
default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate<Entity> targetPredicate) {
|
||||
double d = -1.0D;
|
||||
@@ -0,0 +0,0 @@ public interface EntityGetter {
|
||||
return this.getNearestPlayer(x, y, z, maxDistance, predicate);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ default boolean hasNearbyAlivePlayerThatAffectsSpawning(double x, double y, double z, double range) {
|
||||
+ for (Player player : this.players()) {
|
||||
+ if (EntitySelector.PLAYER_AFFECTS_SPAWNING.test(player)) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check
|
||||
+ double distanceSqr = player.distanceToSqr(x, y, z);
|
||||
+ if (range < 0.0D || distanceSqr < range * range) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) {
|
||||
for(Player player : this.players()) {
|
||||
if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
@Override
|
||||
public String getLocale() {
|
||||
return this.getHandle().locale;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ // Paper start
|
||||
+ public void setAffectsSpawning(boolean affects) {
|
||||
+ this.getHandle().affectsSpawning = affects;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public boolean getAffectsSpawning() {
|
||||
+ return this.getHandle().affectsSpawning;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void updateCommands() {
|
||||
if (this.getHandle().connection == null) return;
|
157
patches/server/Remap-fixes.patch
Normal file
157
patches/server/Remap-fixes.patch
Normal file
@@ -0,0 +1,157 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Wood <kyle@denwav.dev>
|
||||
Date: Fri, 11 Jun 2021 05:25:03 -0500
|
||||
Subject: [PATCH] Remap fixes
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
|
||||
|
||||
public static Iterable<BlockPos> withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) {
|
||||
int i = rangeX + rangeY + rangeZ;
|
||||
- int j = center.getX();
|
||||
- int k = center.getY();
|
||||
- int l = center.getZ();
|
||||
+ // Paper start - rename variables to fix conflict with anonymous class (remap fix)
|
||||
+ int centerX = center.getX();
|
||||
+ int centerY = center.getY();
|
||||
+ int centerZ = center.getZ();
|
||||
+ // Paper end
|
||||
return () -> {
|
||||
return new AbstractIterator<BlockPos>() {
|
||||
private final BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
|
||||
@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
|
||||
protected BlockPos computeNext() {
|
||||
if (this.zMirror) {
|
||||
this.zMirror = false;
|
||||
- this.cursor.setZ(l - (this.cursor.getZ() - l));
|
||||
+ this.cursor.setZ(centerZ - (this.cursor.getZ() - centerZ)); // Paper - remap fix
|
||||
return this.cursor;
|
||||
} else {
|
||||
BlockPos blockPos;
|
||||
@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
|
||||
int k = this.currentDepth - Math.abs(i) - Math.abs(j);
|
||||
if (k <= rangeZ) {
|
||||
this.zMirror = k != 0;
|
||||
- blockPos = this.cursor.set(j + i, k + j, l + k);
|
||||
+ blockPos = this.cursor.set(centerX + i, centerY + j, centerZ + k); // Paper - remap fix
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
@@ -0,0 +0,0 @@ public class BehaviorUtils {
|
||||
|
||||
return optional.map((uuid) -> {
|
||||
return ((ServerLevel) entity.level).getEntity(uuid);
|
||||
- }).map((entity) -> {
|
||||
+ }).map((entity1) -> { // Paper - remap fix
|
||||
LivingEntity entityliving1;
|
||||
|
||||
- if (entity instanceof LivingEntity) {
|
||||
- LivingEntity entityliving2 = (LivingEntity) entity;
|
||||
+ if (entity1 instanceof LivingEntity) { // Paper - remap fix
|
||||
+ LivingEntity entityliving2 = (LivingEntity) entity1; // Paper - remap fix
|
||||
|
||||
entityliving1 = entityliving2;
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
@@ -0,0 +0,0 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
|
||||
Builder<ResourceLocation, Recipe<?>> builder = ImmutableMap.builder();
|
||||
|
||||
recipes.forEach((irecipe) -> {
|
||||
- Map<ResourceLocation, Recipe<?>> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes) -> {
|
||||
+ Map<ResourceLocation, Recipe<?>> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes_) -> { // Paper - remap fix
|
||||
return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit
|
||||
});
|
||||
ResourceLocation minecraftkey = irecipe.getId();
|
||||
diff --git a/src/test/java/org/bukkit/DyeColorsTest.java b/src/test/java/org/bukkit/DyeColorsTest.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/test/java/org/bukkit/DyeColorsTest.java
|
||||
+++ b/src/test/java/org/bukkit/DyeColorsTest.java
|
||||
@@ -0,0 +0,0 @@ import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
-import net.minecraft.world.item.DyeColor;
|
||||
import org.bukkit.support.AbstractTestingBase;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -0,0 +0,0 @@ public class DyeColorsTest extends AbstractTestingBase {
|
||||
@Test
|
||||
public void checkColor() {
|
||||
Color color = this.dye.getColor();
|
||||
- float[] nmsColorArray = DyeColor.byId(this.dye.getWoolData()).getTextureDiffuseColors();
|
||||
+ float[] nmsColorArray = net.minecraft.world.item.DyeColor.byId(this.dye.getWoolData()).getTextureDiffuseColors(); // Paper - remap fix
|
||||
Color nmsColor = Color.fromRGB((int) (nmsColorArray[0] * 255), (int) (nmsColorArray[1] * 255), (int) (nmsColorArray[2] * 255));
|
||||
assertThat(color, is(nmsColor));
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class DyeColorsTest extends AbstractTestingBase {
|
||||
@Test
|
||||
public void checkFireworkColor() {
|
||||
Color color = this.dye.getFireworkColor();
|
||||
- int nmsColor = DyeColor.byId(this.dye.getWoolData()).getFireworkColor();
|
||||
+ int nmsColor = net.minecraft.world.item.DyeColor.byId(this.dye.getWoolData()).getFireworkColor(); // Paper - remap fix
|
||||
assertThat(color, is(Color.fromRGB(nmsColor)));
|
||||
}
|
||||
}
|
||||
diff --git a/src/test/java/org/bukkit/entity/EntityTypesTest.java b/src/test/java/org/bukkit/entity/EntityTypesTest.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/test/java/org/bukkit/entity/EntityTypesTest.java
|
||||
+++ b/src/test/java/org/bukkit/entity/EntityTypesTest.java
|
||||
@@ -0,0 +0,0 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
-import net.minecraft.world.entity.EntityType;
|
||||
import org.bukkit.support.AbstractTestingBase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -0,0 +0,0 @@ public class EntityTypesTest extends AbstractTestingBase {
|
||||
public void testMaps() {
|
||||
Set<EntityType> allBukkit = Arrays.stream(EntityType.values()).filter((b) -> b.getName() != null).collect(Collectors.toSet());
|
||||
|
||||
- for (EntityType<?> nms : BuiltInRegistries.ENTITY_TYPE) {
|
||||
- ResourceLocation key = EntityType.getKey(nms);
|
||||
+ for (net.minecraft.world.entity.EntityType<?> nms : BuiltInRegistries.ENTITY_TYPE) { // Paper - remap fix
|
||||
+ ResourceLocation key = net.minecraft.world.entity.EntityType.getKey(nms); // Paper - remap fix
|
||||
|
||||
org.bukkit.entity.EntityType bukkit = org.bukkit.entity.EntityType.fromName(key.getPath());
|
||||
Assert.assertNotNull("Missing nms->bukkit " + key, bukkit);
|
||||
diff --git a/src/test/java/org/bukkit/entity/PandaGeneTest.java b/src/test/java/org/bukkit/entity/PandaGeneTest.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/test/java/org/bukkit/entity/PandaGeneTest.java
|
||||
+++ b/src/test/java/org/bukkit/entity/PandaGeneTest.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
-import net.minecraft.world.entity.animal.Panda;
|
||||
import org.bukkit.craftbukkit.entity.CraftPanda;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -0,0 +0,0 @@ public class PandaGeneTest {
|
||||
@Test
|
||||
public void testBukkit() {
|
||||
for (Panda.Gene gene : Panda.Gene.values()) {
|
||||
- Panda.Gene nms = CraftPanda.toNms(gene);
|
||||
+ net.minecraft.world.entity.animal.Panda.Gene nms = CraftPanda.toNms(gene); // Paper - remap fix
|
||||
|
||||
Assert.assertNotNull("NMS gene null for " + gene, nms);
|
||||
Assert.assertEquals("Recessive status did not match " + gene, gene.isRecessive(), nms.isRecessive());
|
||||
@@ -0,0 +0,0 @@ public class PandaGeneTest {
|
||||
|
||||
@Test
|
||||
public void testNMS() {
|
||||
- for (Panda.Gene gene : Panda.Gene.values()) {
|
||||
+ for (net.minecraft.world.entity.animal.Panda.Gene gene : net.minecraft.world.entity.animal.Panda.Gene.values()) { // Paper - remap fix
|
||||
org.bukkit.entity.Panda.Gene bukkit = CraftPanda.fromNms(gene);
|
||||
|
||||
Assert.assertNotNull("Bukkit gene null for " + gene, bukkit);
|
18181
patches/server/Rewrite-chunk-system.patch
Normal file
18181
patches/server/Rewrite-chunk-system.patch
Normal file
File diff suppressed because it is too large
Load Diff
22916
patches/server/Rewrite-dataconverter-system.patch
Normal file
22916
patches/server/Rewrite-dataconverter-system.patch
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,104 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
|
||||
Date: Tue, 1 Mar 2016 14:32:43 -0600
|
||||
Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang
|
||||
stats
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
@DontObfuscate
|
||||
public String getServerModName() {
|
||||
- return "Spigot"; // Spigot - Spigot > // CraftBukkit - cb > vanilla!
|
||||
+ return "Paper"; // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
|
||||
}
|
||||
|
||||
public SystemReport fillSystemReport(SystemReport details) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -0,0 +0,0 @@ import org.yaml.snakeyaml.error.MarkedYAMLException;
|
||||
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
|
||||
|
||||
public final class CraftServer implements Server {
|
||||
- private final String serverName = "CraftBukkit";
|
||||
+ private final String serverName = "Paper"; // Paper
|
||||
private final String serverVersion;
|
||||
private final String bukkitVersion = Versioning.getBukkitVersion();
|
||||
private final Logger logger = Logger.getLogger("Minecraft");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -0,0 +0,0 @@ public class Main {
|
||||
deadline.add(Calendar.DAY_OF_YEAR, -3);
|
||||
if (buildDate.before(deadline.getTime())) {
|
||||
System.err.println("*** Error, this build is outdated ***");
|
||||
- System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***");
|
||||
+ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper
|
||||
System.err.println("*** Server will start in 20 seconds ***");
|
||||
Thread.sleep(TimeUnit.SECONDS.toMillis(20));
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Log Java and OS versioning to help with debugging plugin issues
|
||||
+ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean();
|
||||
+ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
|
||||
+ if (runtimeMX != null && osMX != null) {
|
||||
+ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")";
|
||||
+ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")";
|
||||
+
|
||||
+ System.out.println("System Info: " + javaInfo + " " + osInfo);
|
||||
+ } else {
|
||||
+ System.out.println("Unable to read system info");
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
System.out.println("Loading libraries, please wait...");
|
||||
net.minecraft.server.Main.main(options);
|
||||
} catch (Throwable t) {
|
||||
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
|
||||
private WatchdogThread(long timeoutTime, boolean restart)
|
||||
{
|
||||
- super( "Spigot Watchdog Thread" );
|
||||
+ super( "Paper Watchdog Thread" );
|
||||
this.timeoutTime = timeoutTime;
|
||||
this.restart = restart;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
{
|
||||
Logger log = Bukkit.getServer().getLogger();
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." );
|
||||
+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
|
||||
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
|
||||
log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" );
|
||||
log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" );
|
||||
log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" );
|
||||
- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" );
|
||||
+ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" );
|
||||
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" );
|
||||
- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() );
|
||||
+ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() );
|
||||
//
|
||||
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
|
||||
{
|
||||
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
}
|
||||
//
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" );
|
||||
+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
|
||||
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system
|
||||
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
5298
patches/server/Starlight.patch
Normal file
5298
patches/server/Starlight.patch
Normal file
File diff suppressed because it is too large
Load Diff
281
patches/server/Test-changes.patch
Normal file
281
patches/server/Test-changes.patch
Normal file
@@ -0,0 +1,281 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 13 Feb 2023 14:14:56 -0800
|
||||
Subject: [PATCH] Test changes
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -0,0 +0,0 @@ dependencies {
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion
|
||||
implementation("org.ow2.asm:asm:9.4")
|
||||
implementation("org.ow2.asm:asm-commons:9.4") // Paper - ASM event executor generation
|
||||
+ testImplementation("org.mockito:mockito-core:4.9.0") // Paper - switch to mockito
|
||||
implementation("commons-lang:commons-lang:2.6")
|
||||
runtimeOnly("org.xerial:sqlite-jdbc:3.36.0.3")
|
||||
runtimeOnly("com.mysql:mysql-connector-j:8.0.32")
|
||||
diff --git a/src/test/java/io/papermc/paper/testing/DummyServer.java b/src/test/java/io/papermc/paper/testing/DummyServer.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/testing/DummyServer.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.testing;
|
||||
+
|
||||
+import java.util.logging.Logger;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.Material;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.Server;
|
||||
+import org.bukkit.command.SimpleCommandMap;
|
||||
+import org.bukkit.craftbukkit.CraftRegistry;
|
||||
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemFactory;
|
||||
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.bukkit.plugin.PluginManager;
|
||||
+import org.bukkit.plugin.SimplePluginManager;
|
||||
+import org.bukkit.support.AbstractTestingBase;
|
||||
+import org.mockito.Mockito;
|
||||
+
|
||||
+import static org.mockito.Mockito.any;
|
||||
+import static org.mockito.Mockito.mock;
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+public final class DummyServer {
|
||||
+
|
||||
+ @SuppressWarnings({"deprecation", "removal"})
|
||||
+ public static void setup() {
|
||||
+ //noinspection ConstantValue
|
||||
+ if (Bukkit.getServer() != null) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final Server dummyServer = mock(Server.class, Mockito.withSettings().stubOnly());
|
||||
+
|
||||
+ final Logger logger = Logger.getLogger(DummyServer.class.getCanonicalName());
|
||||
+ when(dummyServer.getLogger()).thenReturn(logger);
|
||||
+ when(dummyServer.getName()).thenReturn(DummyServer.class.getSimpleName());
|
||||
+ when(dummyServer.getVersion()).thenReturn("Version_" + DummyServer.class.getPackage().getImplementationVersion());
|
||||
+ when(dummyServer.getBukkitVersion()).thenReturn("BukkitVersion_" + DummyServer.class.getPackage().getImplementationVersion());
|
||||
+
|
||||
+ final Thread currentThread = Thread.currentThread();
|
||||
+ when(dummyServer.isPrimaryThread()).thenAnswer(ignored -> Thread.currentThread().equals(currentThread));
|
||||
+
|
||||
+ when(dummyServer.getItemFactory()).thenReturn(CraftItemFactory.instance());
|
||||
+
|
||||
+ when(dummyServer.getUnsafe()).thenAnswer(ignored -> CraftMagicNumbers.INSTANCE); // lambda for lazy load
|
||||
+
|
||||
+ when(dummyServer.createBlockData(any(Material.class))).thenAnswer(invocation -> {
|
||||
+ return CraftBlockData.newData(invocation.getArgument(0, Material.class), null);
|
||||
+ });
|
||||
+
|
||||
+ when(dummyServer.getLootTable(any(NamespacedKey.class))).thenAnswer(invocation -> {
|
||||
+ final NamespacedKey key = invocation.getArgument(0, NamespacedKey.class);
|
||||
+ return new org.bukkit.craftbukkit.CraftLootTable(key, AbstractTestingBase.DATA_PACK.getLootTables().get(CraftNamespacedKey.toMinecraft(key)));
|
||||
+ });
|
||||
+
|
||||
+ when(dummyServer.getRegistry(any())).thenAnswer(invocation -> {
|
||||
+ // LazyRegistry because the vanilla data hasn't been bootstrapped yet.
|
||||
+ return new LazyRegistry(() -> CraftRegistry.createRegistry(invocation.getArgument(0, Class.class), AbstractTestingBase.REGISTRY_CUSTOM));
|
||||
+ });
|
||||
+
|
||||
+ final PluginManager pluginManager = new SimplePluginManager(dummyServer, new SimpleCommandMap(dummyServer));
|
||||
+ when(dummyServer.getPluginManager()).thenReturn(pluginManager);
|
||||
+
|
||||
+ Bukkit.setServer(dummyServer);
|
||||
+
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/test/java/io/papermc/paper/testing/LazyRegistry.java b/src/test/java/io/papermc/paper/testing/LazyRegistry.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/testing/LazyRegistry.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.testing;
|
||||
+
|
||||
+import java.util.Iterator;
|
||||
+import java.util.function.Supplier;
|
||||
+import org.bukkit.Keyed;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.Registry;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+public record LazyRegistry(Supplier<Registry<Keyed>> supplier) implements Registry<Keyed> {
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Iterator<Keyed> iterator() {
|
||||
+ return this.supplier().get().iterator();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable Keyed get(@NotNull final NamespacedKey key) {
|
||||
+ return this.supplier().get().get(key);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
||||
+++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
||||
@@ -0,0 +0,0 @@ package org.bukkit.support;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
-import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.commands.Commands;
|
||||
@@ -0,0 +0,0 @@ public abstract class AbstractTestingBase {
|
||||
LayeredRegistryAccess<RegistryLayer> layers = RegistryLayer.createRegistryAccess();
|
||||
layers = WorldLoader.loadAndReplaceLayer(resourceManager, layers, RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES);
|
||||
REGISTRY_CUSTOM = layers.compositeAccess().freeze();
|
||||
+ io.papermc.paper.testing.DummyServer.setup(); // Paper
|
||||
// Register vanilla pack
|
||||
DATA_PACK = ReloadableServerResources.loadResources(resourceManager, REGISTRY_CUSTOM, FeatureFlags.REGISTRY.allFlags(), Commands.CommandSelection.DEDICATED, 0, MoreExecutors.directExecutor(), MoreExecutors.directExecutor()).join();
|
||||
// Bind tags
|
||||
@@ -0,0 +0,0 @@ public abstract class AbstractTestingBase {
|
||||
// Biome shortcut
|
||||
BIOMES = REGISTRY_CUSTOM.registryOrThrow(Registries.BIOME);
|
||||
|
||||
- DummyServer.setup();
|
||||
DummyEnchantments.setup();
|
||||
|
||||
ImmutableList.Builder<Material> builder = ImmutableList.builder();
|
||||
diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java
|
||||
deleted file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- a/src/test/java/org/bukkit/support/DummyServer.java
|
||||
+++ /dev/null
|
||||
@@ -0,0 +0,0 @@
|
||||
-package org.bukkit.support;
|
||||
-
|
||||
-import java.lang.reflect.InvocationHandler;
|
||||
-import java.lang.reflect.Method;
|
||||
-import java.lang.reflect.Proxy;
|
||||
-import java.util.HashMap;
|
||||
-import java.util.logging.Logger;
|
||||
-import org.bukkit.Bukkit;
|
||||
-import org.bukkit.Material;
|
||||
-import org.bukkit.NamespacedKey;
|
||||
-import org.bukkit.Server;
|
||||
-import org.bukkit.craftbukkit.CraftLootTable;
|
||||
-import org.bukkit.craftbukkit.CraftRegistry;
|
||||
-import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
-import org.bukkit.craftbukkit.inventory.CraftItemFactory;
|
||||
-import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
-import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
-import org.bukkit.craftbukkit.util.Versioning;
|
||||
-
|
||||
-public final class DummyServer implements InvocationHandler {
|
||||
- private static interface MethodHandler {
|
||||
- Object handle(DummyServer server, Object[] args);
|
||||
- }
|
||||
- private static final HashMap<Method, MethodHandler> methods = new HashMap<Method, MethodHandler>();
|
||||
- static {
|
||||
- try {
|
||||
- methods.put(
|
||||
- Server.class.getMethod("getItemFactory"),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return CraftItemFactory.instance();
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(
|
||||
- Server.class.getMethod("getName"),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return DummyServer.class.getName();
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(
|
||||
- Server.class.getMethod("getVersion"),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return DummyServer.class.getPackage().getImplementationVersion();
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(
|
||||
- Server.class.getMethod("getBukkitVersion"),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return Versioning.getBukkitVersion();
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(
|
||||
- Server.class.getMethod("getLogger"),
|
||||
- new MethodHandler() {
|
||||
- final Logger logger = Logger.getLogger(DummyServer.class.getCanonicalName());
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return logger;
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(
|
||||
- Server.class.getMethod("getUnsafe"),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return CraftMagicNumbers.INSTANCE;
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(
|
||||
- Server.class.getMethod("createBlockData", Material.class),
|
||||
- new MethodHandler() {
|
||||
- final Logger logger = Logger.getLogger(DummyServer.class.getCanonicalName());
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return CraftBlockData.newData((Material) args[0], null);
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(Server.class.getMethod("getLootTable", NamespacedKey.class),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- NamespacedKey key = (NamespacedKey) args[0];
|
||||
- return new CraftLootTable(key, AbstractTestingBase.DATA_PACK.getLootTables().get(CraftNamespacedKey.toMinecraft(key)));
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- methods.put(Server.class.getMethod("getRegistry", Class.class),
|
||||
- new MethodHandler() {
|
||||
- @Override
|
||||
- public Object handle(DummyServer server, Object[] args) {
|
||||
- return CraftRegistry.createRegistry((Class) args[0], AbstractTestingBase.REGISTRY_CUSTOM);
|
||||
- }
|
||||
- }
|
||||
- );
|
||||
- Bukkit.setServer(Proxy.getProxyClass(Server.class.getClassLoader(), Server.class).asSubclass(Server.class).getConstructor(InvocationHandler.class).newInstance(new DummyServer()));
|
||||
- } catch (Throwable t) {
|
||||
- throw new Error(t);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- public static void setup() {}
|
||||
-
|
||||
- private DummyServer() {};
|
||||
-
|
||||
- @Override
|
||||
- public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
- MethodHandler handler = DummyServer.methods.get(method);
|
||||
- if (handler != null) {
|
||||
- return handler.handle(this, args);
|
||||
- }
|
||||
- throw new UnsupportedOperationException(String.valueOf(method));
|
||||
- }
|
||||
-}
|
2121
patches/server/Timings-v2.patch
Normal file
2121
patches/server/Timings-v2.patch
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user