even MOOOOOOOOOOOOAAAAAAAAAAAAAAAARRRRRRRRRRRRR patches

This commit is contained in:
Jake Potrebic
2021-11-24 12:43:28 -08:00
parent 5b5f1caeb9
commit 416ee76329
37 changed files with 11 additions and 445 deletions

View File

@@ -1,119 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Thu, 29 Apr 2021 21:19:33 +0200
Subject: [PATCH] Add Channel initialization listeners
diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.network;
+
+import io.netty.channel.Channel;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * Internal API to register channel initialization listeners.
+ * <p>
+ * This is not officially supported API and we make no guarantees to the existence or state of this interface.
+ */
+@FunctionalInterface
+public interface ChannelInitializeListener {
+
+ void afterInitChannel(@NonNull Channel channel);
+}
diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.network;
+
+import io.netty.channel.Channel;
+import net.kyori.adventure.key.Key;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Internal API to register channel initialization listeners.
+ * <p>
+ * This is not officially supported API and we make no guarantees to the existence or state of this class.
+ */
+public final class ChannelInitializeListenerHolder {
+
+ private static final Map<Key, ChannelInitializeListener> LISTENERS = new HashMap<>();
+ private static final Map<Key, ChannelInitializeListener> IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS);
+
+ private ChannelInitializeListenerHolder() {
+ }
+
+ /**
+ * Registers whether an initialization listener is registered under the given key.
+ *
+ * @param key key
+ * @return whether an initialization listener is registered under the given key
+ */
+ public static boolean hasListener(@NonNull Key key) {
+ return LISTENERS.containsKey(key);
+ }
+
+ /**
+ * Registers a channel initialization listener called after ServerConnection is initialized.
+ *
+ * @param key key
+ * @param listener initialization listeners
+ */
+ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) {
+ LISTENERS.put(key, listener);
+ }
+
+ /**
+ * Removes and returns an initialization listener registered by the given key if present.
+ *
+ * @param key key
+ * @return removed initialization listener if present
+ */
+ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) {
+ return LISTENERS.remove(key);
+ }
+
+ /**
+ * Returns an immutable map of registered initialization listeners.
+ *
+ * @return immutable map of registered initialization listeners
+ */
+ public static @NonNull Map<Key, ChannelInitializeListener> getListeners() {
+ return IMMUTABLE_VIEW;
+ }
+
+ /**
+ * Calls the registered listeners with the given channel.
+ *
+ * @param channel channel
+ */
+ public static void callListeners(@NonNull Channel channel) {
+ for (ChannelInitializeListener listener : LISTENERS.values()) {
+ listener.afterInitChannel(channel);
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
@@ -0,0 +0,0 @@ public class ServerConnectionListener {
pending.add((Connection) object); // Paper
channel.pipeline().addLast("packet_handler", (ChannelHandler) object);
((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object));
+ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper
}
}).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
}

View File

@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 18 Apr 2021 21:27:01 +0100
Subject: [PATCH] Add bypass host check
Paper.bypassHostCheck
Seriously, fix your firewalls. -.-
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request");
private final MinecraftServer server;
private final Connection connection;
+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper
public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) {
this.server = server;
@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
// Spigot Start
//if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above!
String[] split = packet.hostName.split("\00");
- if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) {
+ if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.BYPASS_HOSTCHECK || ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper
packet.hostName = split[0];
connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getPort());
connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] );

View File

@@ -1,65 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HexedHero <6012891+HexedHero@users.noreply.github.com>
Date: Thu, 6 May 2021 14:56:43 +0100
Subject: [PATCH] Add more WanderingTrader API
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
@Nullable
private BlockPos wanderTarget;
private int despawnDelay;
+ // Paper start - Add more WanderingTrader API
+ public boolean canDrinkPotion = true;
+ public boolean canDrinkMilk = true;
+ // Paper end
public WanderingTrader(EntityType<? extends WanderingTrader> type, Level world) {
super(type, world);
@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
protected void registerGoals() {
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> {
- return this.level.isNight() && !entityvillagertrader.isInvisible();
+ return this.canDrinkPotion && this.level.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API
}));
this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> {
- return this.level.isDay() && entityvillagertrader.isInvisible();
+ return canDrinkMilk && this.level.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API
}));
this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this));
this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D));
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java
@@ -0,0 +0,0 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande
public void setDespawnDelay(int despawnDelay) {
this.getHandle().setDespawnDelay(despawnDelay);
}
+
+ // Paper start - Add more WanderingTrader API
+ @Override
+ public void setCanDrinkPotion(boolean bool) {
+ getHandle().canDrinkPotion = bool;
+ }
+
+ @Override
+ public boolean canDrinkPotion() {
+ return getHandle().canDrinkPotion;
+ }
+
+ @Override
+ public void setCanDrinkMilk(boolean bool) {
+ getHandle().canDrinkMilk = bool;
+ }
+
+ @Override
+ public boolean canDrinkMilk() {
+ return getHandle().canDrinkMilk;
+ }
+ // Paper end
}

View File

@@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 24 Dec 2020 12:27:41 -0800
Subject: [PATCH] Added PlayerBedFailEnterEvent
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -0,0 +0,0 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
BlockPos finalblockposition = pos;
// CraftBukkit end
player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> {
+ // Paper start - PlayerBedFailEnterEvent
+ if (entityhuman_enumbedresult != null) {
+ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), !world.dimensionType().bedWorks(), io.papermc.paper.adventure.PaperAdventure.asAdventure(entityhuman_enumbedresult.getMessage()));
+ if (!event.callEvent()) {
+ return;
+ }
+ // Paper end
// CraftBukkit start - handling bed explosion from below here
- if (!world.dimensionType().bedWorks()) {
+ if (event.getWillExplode()) { // Paper
this.explodeBed(finaliblockdata, world, finalblockposition);
} else
// CraftBukkit end
if (entityhuman_enumbedresult != null) {
- player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true);
+ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper
+ if(message != null) player.displayClientMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), true); // Paper
}
+ } // Paper
});
return InteractionResult.SUCCESS;

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 21 Apr 2021 15:58:19 -0700
Subject: [PATCH] Added PlayerDeepSleepEvent
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 {
if (this.isSleeping()) {
++this.sleepCounter;
+ // Paper start
+ if (this.sleepCounter == 100) {
+ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((org.bukkit.entity.Player) getBukkitEntity()).callEvent()) { this.sleepCounter = Integer.MIN_VALUE; }
+ }
+ // Paper end
if (this.sleepCounter > 100) {
this.sleepCounter = 100;
}

View File

@@ -1,132 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Thu, 1 Apr 2021 00:34:02 -0700
Subject: [PATCH] Allow for Component suggestion tooltips in
AsyncTabCompleteEvent
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// Paper start - async tab completion
com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event;
- java.util.List<String> completions = new java.util.ArrayList<>();
String buffer = packet.getCommand();
- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), completions,
+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(),
buffer, true, null);
event.callEvent();
- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions();
+ java.util.List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions();
// If the event isn't handled, we can assume that we have no completions, and so we'll ask the server
if (!event.isHandled()) {
if (!event.isCancelled()) {
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
});
}
} else if (!completions.isEmpty()) {
- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength());
+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength());
- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1);
- completions.forEach(builder::suggest);
+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1);
+ completions.forEach(completion -> {
+ if (completion.tooltip() == null) {
+ builder.suggest(completion.suggestion());
+ } else {
+ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip()));
+ }
+ });
com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join();
com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, buffer);
suggestEvent.setCancelled(suggestions.isEmpty());
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
final CraftServer server = this.server.server;
final String buffer = line.line();
// Async Tab Complete
- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event;
- java.util.List<String> completions = new java.util.ArrayList<>();
- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions,
- buffer, true, null);
+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event =
+ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null);
event.callEvent();
- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions();
+ final List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions();
if (event.isCancelled() || event.isHandled()) {
// Still fire sync event with the provided completions, if someone is listening
if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) {
- List<String> finalCompletions = completions;
+ List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> finalCompletions = new java.util.ArrayList<>(completions);
Waitable<List<String>> syncCompletions = new Waitable<List<String>>() {
@Override
protected List<String> evaluate() {
- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions);
+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer,
+ finalCompletions.stream()
+ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion)
+ .collect(java.util.stream.Collectors.toList()));
return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of();
}
};
server.getServer().processQueue.add(syncCompletions);
try {
- completions = syncCompletions.get();
+ final List<String> legacyCompletions = syncCompletions.get();
+ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed
+ // add any new suggestions
+ for (final String completion : legacyCompletions) {
+ if (notNewSuggestion(completions, completion)) {
+ continue;
+ }
+ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion));
+ }
} catch (InterruptedException | ExecutionException e1) {
e1.printStackTrace();
}
}
if (!completions.isEmpty()) {
- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList()));
+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) {
+ if (completion.suggestion().isEmpty()) {
+ continue;
+ }
+ candidates.add(new Candidate(
+ completion.suggestion(),
+ completion.suggestion(),
+ null,
+ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null),
+ null,
+ null,
+ false
+ ));
+ }
}
return;
}
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
Thread.currentThread().interrupt();
}
}
+
+ // Paper start
+ private boolean notNewSuggestion(final List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> completions, final String completion) {
+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) {
+ if (it.suggestion().equals(completion)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ // Paper end
}

View File

@@ -1,301 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Tue, 30 Mar 2021 16:06:08 -0700
Subject: [PATCH] Enhance console tab completions for brigadier commands
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -0,0 +0,0 @@ public class PaperConfig {
private static void fixEntityPositionDesync() {
fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync);
}
+
+ public static boolean enableBrigadierConsoleHighlighting = true;
+ public static boolean enableBrigadierConsoleCompletions = true;
+ private static void consoleSettings() {
+ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting);
+ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions);
+ }
}
diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
@@ -0,0 +0,0 @@ public final class PaperConsole extends SimpleTerminalConsole {
@Override
protected LineReader buildReader(LineReaderBuilder builder) {
- return super.buildReader(builder
+ builder
.appName("Paper")
.variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history"))
.completer(new ConsoleCommandCompleter(this.server))
- );
+ .option(LineReader.Option.COMPLETE_IN_WORD, true);
+ if (com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleHighlighting) {
+ builder.highlighter(new io.papermc.paper.console.BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack()));
+ }
+ return super.buildReader(builder);
}
@Override
diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.console;
+
+import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion;
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.ParseResults;
+import com.mojang.brigadier.StringReader;
+import com.mojang.brigadier.suggestion.Suggestion;
+import io.papermc.paper.adventure.PaperAdventure;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.network.chat.ComponentUtils;
+import net.minecraft.server.dedicated.DedicatedServer;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jline.reader.Candidate;
+import org.jline.reader.LineReader;
+import org.jline.reader.ParsedLine;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion;
+
+public final class BrigadierCommandCompleter {
+ private final CommandSourceStack commandSourceStack;
+ private final DedicatedServer server;
+
+ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) {
+ this.server = server;
+ this.commandSourceStack = commandSourceStack;
+ }
+
+ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List<Candidate> candidates, final @NonNull List<Completion> existing) {
+ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) {
+ this.addCandidates(candidates, Collections.emptyList(), existing);
+ return;
+ }
+ final CommandDispatcher<CommandSourceStack> dispatcher = this.server.getCommands().getDispatcher();
+ final ParseResults<CommandSourceStack> results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack);
+ this.addCandidates(
+ candidates,
+ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(),
+ existing
+ );
+ }
+
+ private void addCandidates(
+ final @NonNull List<Candidate> candidates,
+ final @NonNull List<Suggestion> brigSuggestions,
+ final @NonNull List<Completion> existing
+ ) {
+ final List<Completion> completions = new ArrayList<>();
+ brigSuggestions.forEach(it -> completions.add(toCompletion(it)));
+ for (final Completion completion : existing) {
+ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) {
+ continue;
+ }
+ completions.add(completion);
+ }
+ for (final Completion completion : completions) {
+ if (completion.suggestion().isEmpty()) {
+ continue;
+ }
+ candidates.add(toCandidate(completion));
+ }
+ }
+
+ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) {
+ final String suggestionText = completion.suggestion();
+ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null);
+ return new Candidate(
+ suggestionText,
+ suggestionText,
+ null,
+ suggestionTooltip,
+ null,
+ null,
+ false
+ );
+ }
+
+ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) {
+ if (suggestion.getTooltip() == null) {
+ return completion(suggestion.getText());
+ }
+ return completion(suggestion.getText(), PaperAdventure.asAdventure(ComponentUtils.fromMessage(suggestion.getTooltip())));
+ }
+
+ static @NonNull StringReader prepareStringReader(final @NonNull String line) {
+ final StringReader stringReader = new StringReader(line);
+ if (stringReader.canRead() && stringReader.peek() == '/') {
+ stringReader.skip();
+ }
+ return stringReader;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.console;
+
+import com.mojang.brigadier.ParseResults;
+import com.mojang.brigadier.context.ParsedCommandNode;
+import com.mojang.brigadier.tree.LiteralCommandNode;
+import java.util.regex.Pattern;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.server.dedicated.DedicatedServer;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jline.reader.Highlighter;
+import org.jline.reader.LineReader;
+import org.jline.utils.AttributedString;
+import org.jline.utils.AttributedStringBuilder;
+import org.jline.utils.AttributedStyle;
+
+public final class BrigadierCommandHighlighter implements Highlighter {
+ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE};
+ private final CommandSourceStack commandSourceStack;
+ private final DedicatedServer server;
+
+ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) {
+ this.server = server;
+ this.commandSourceStack = commandSourceStack;
+ }
+
+ @Override
+ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) {
+ final AttributedStringBuilder builder = new AttributedStringBuilder();
+ final ParseResults<CommandSourceStack> results = this.server.getCommands().getDispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack);
+ int pos = 0;
+ if (buffer.startsWith("/")) {
+ builder.append("/", AttributedStyle.DEFAULT);
+ pos = 1;
+ }
+ int component = -1;
+ for (final ParsedCommandNode<CommandSourceStack> node : results.getContext().getLastChild().getNodes()) {
+ if (node.getRange().getStart() >= buffer.length()) {
+ break;
+ }
+ final int start = node.getRange().getStart();
+ final int end = Math.min(node.getRange().getEnd(), buffer.length());
+ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT);
+ if (node.getNode() instanceof LiteralCommandNode) {
+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT);
+ } else {
+ if (++component >= COLORS.length) {
+ component = 0;
+ }
+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component]));
+ }
+ pos = end;
+ }
+ if (pos < buffer.length()) {
+ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
+ }
+ return builder.toAttributedString();
+ }
+
+ @Override
+ public void setErrorPattern(final Pattern errorPattern) {}
+
+ @Override
+ public void setErrorIndex(final int errorIndex) {}
+}
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
thread.setDaemon(true);
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER));
- thread.start();
+ // thread.start(); // Paper - moved down
DedicatedServer.LOGGER.info("Starting minecraft server version {}", SharedConstants.getCurrentVersion().getName());
if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) {
DedicatedServer.LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
DedicatedServer.LOGGER.error("Unable to load server configuration", e);
return false;
}
+ thread.start(); // Paper - start console thread after MinecraftServer.console & PaperConfig are initialized
com.destroystokyo.paper.PaperConfig.registerCommands();
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // load mappings for stacktrace deobf and etc.
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
@@ -0,0 +0,0 @@ import org.bukkit.event.server.TabCompleteEvent;
public class ConsoleCommandCompleter implements Completer {
private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer
+ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper
public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer
this.server = server;
+ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.createCommandSourceStack()); // Paper
}
// Paper start - Change method signature for JLine update
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
}
}
- if (!completions.isEmpty()) {
+ if (false && !completions.isEmpty()) {
for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) {
if (completion.suggestion().isEmpty()) {
continue;
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
));
}
}
+ this.addCompletions(reader, line, candidates, completions);
return;
}
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
try {
List<String> offers = waitable.get();
if (offers == null) {
+ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper
return; // Paper - Method returns void
}
// Paper start - JLine update
+ /*
for (String completion : offers) {
if (completion.isEmpty()) {
continue;
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
candidates.add(new Candidate(completion));
}
+ */
+ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList()));
// Paper end
// Paper start - JLine handles cursor now
@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer {
}
return false;
}
+
+ private void addCompletions(final LineReader reader, final ParsedLine line, final List<Candidate> candidates, final List<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> existing) {
+ this.brigadierCompleter.complete(reader, line, candidates, existing);
+ }
// Paper end
}

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 26 Mar 2021 11:23:17 +0100
Subject: [PATCH] Expose protocol version
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 io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) {
return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()];
}
+
+ @Override
+ public int getProtocolVersion() {
+ return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion();
+ }
// Paper end
/**

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: chickeneer <emcchickeneer@gmail.com>
Date: Fri, 19 Mar 2021 00:33:15 -0500
Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly
When the active item is not cleared, the item is still readied
for use and will repeatedly trigger the PlayerItemConsumeEvent
till their item is switched.
This patch clears the active item when the event is cancelled
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
+ this.stopUsingItem(); // Paper - event is using an item, clear active item to reset its use
// Update client
((ServerPlayer) this).getBukkitEntity().updateInventory();
((ServerPlayer) this).getBukkitEntity().updateScaledHealth();

View File

@@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HexedHero <6012891+HexedHero@users.noreply.github.com>
Date: Fri, 23 Apr 2021 22:42:42 +0100
Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end
portal
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
// Paper start
boolean isBedSpawn = false;
+ boolean isAnchorSpawn = false;
boolean isRespawn = false;
boolean isLocAltered = false; // Paper - Fix SPIGOT-5989
// Paper end
@@ -0,0 +0,0 @@ public abstract class PlayerList {
if (optional.isPresent()) {
BlockState iblockdata = worldserver1.getBlockState(blockposition);
boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR);
+ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal
Vec3 vec3d = (Vec3) optional.get();
float f1;
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
Player respawnPlayer = entityplayer1.getBukkitEntity();
- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2);
+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal
this.cserver.getPluginManager().callEvent(respawnEvent);
// Spigot Start
if (entityplayer.connection.isDisconnected()) {

View File

@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 4 Apr 2021 14:25:04 -0400
Subject: [PATCH] Fix checkReach check for Shulker boxes
diff --git a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java
@@ -0,0 +0,0 @@ public class ShulkerBoxMenu extends AbstractContainerMenu {
@Override
public boolean stillValid(Player player) {
+ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox
return this.container.stillValid(player);
}

View File

@@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alphaesia <creepashadowz@gmail.com>
Date: Fri, 23 Apr 2021 09:57:56 +1200
Subject: [PATCH] Fix duplicating /give items on item drop cancel
Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication).
For every stack of items to give, /give puts the item stack straight
into the player's inventory. However, it also summons a "fake item"
at the player's location. When the PlayerDropItemEvent for this fake
item is cancelled, the server attempts to put the item back into the
player's inventory. The result is that the fake item, which is never
meant to be obtained, is combined with the real items injected directly
into the player's inventory. This means more items than the amount
specified in /give are given to the player - one for every stack of
items given. (e.g. /give @s dirt 1 gives you 2 dirt).
While this isn't a big issue for general building usage, it can affect
e.g. adventure maps where the number of items the player receives is
important (and you want to restrict the player from throwing items).
If there are any overflow items that didn't make it into the inventory
(insufficient space), those items are dropped as a real item instead
of a fake one. While cancelling this drop would also result in the
server attempting to put those items into the inventory, since it is
full this has no effect.
Just ignoring cancellation of the PlayerDropItemEvent seems like the
cleanest and least intrusive way to fix it.
diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java
+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java
@@ -0,0 +0,0 @@ public class GiveCommand {
boolean bl = serverPlayer.getInventory().add(itemStack);
if (bl && itemStack.isEmpty()) {
itemStack.setCount(1);
- ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false);
+ ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel
if (itemEntity2 != null) {
itemEntity2.makeFakeItem();
}
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 ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) {
+ // Paper start - Fix duplicating /give items on item drop cancel
+ return this.drop(stack, throwRandomly, retainOwnership, false);
+ }
+
+ @Nullable
+ public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership, boolean alwaysSucceed) {
+ // Paper end
if (stack.isEmpty()) {
return null;
} else {
@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity {
PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop);
this.level.getCraftServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) {
+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel
org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand();
if (retainOwnership && (cur == null || cur.getAmount() == 0)) {
// The complete stack was dropped

View File

@@ -1,55 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Sat, 24 Apr 2021 02:09:32 -0700
Subject: [PATCH] Implement methods to convert between Component and
Brigadier's Message
diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.brigadier;
+
+import com.mojang.brigadier.Message;
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.ComponentLike;
+import net.minecraft.network.chat.ComponentUtils;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import static java.util.Objects.requireNonNull;
+
+public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider {
+ INSTANCE;
+
+ PaperBrigadierProviderImpl() {
+ PaperBrigadierProvider.initialize(this);
+ }
+
+ @Override
+ public @NonNull Message message(final @NonNull ComponentLike componentLike) {
+ requireNonNull(componentLike, "componentLike");
+ return PaperAdventure.asVanilla(componentLike.asComponent());
+ }
+
+ @Override
+ public @NonNull Component componentFromMessage(final @NonNull Message message) {
+ requireNonNull(message, "message");
+ return PaperAdventure.asAdventure(ComponentUtils.fromMessage(message));
+ }
+}
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
com.destroystokyo.paper.PaperConfig.registerCommands();
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // load mappings for stacktrace deobf and etc.
+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider
// Paper end
this.setPvpAllowed(dedicatedserverproperties.pvp);

View File

@@ -1,103 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 9 Aug 2020 08:59:25 +0300
Subject: [PATCH] Incremental player saving
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -0,0 +0,0 @@ public class PaperConfig {
set("settings.unsupported-settings.allow-tnt-duplication", null);
}
+ public static int playerAutoSaveRate = -1;
+ public static int maxPlayerAutoSavePerTick = 10;
+ private static void playerAutoSaveRate() {
+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1);
+ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1);
+ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended"
+ // 10 should be safe for everyone unless you mass spamming player auto save
+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20;
+ }
+ }
}
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
if (this.playerList != null) {
MinecraftServer.LOGGER.info("Saving players");
- this.playerList.saveAll();
this.playerList.removeAll(this.isRestarting); // Paper
try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets
}
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit // Paper - move down
// MinecraftServer.LOGGER.debug("Autosave started"); // Paper
serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper
+ // Paper start
+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate;
+ if (playerSaveInterval < 0) {
+ playerSaveInterval = autosavePeriod;
+ }
+ // Paper end
this.profiler.push("save");
- if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // Paper - moved from above
- this.playerList.saveAll();
+ if (playerSaveInterval > 0) { // Paper
+ this.playerList.savePlayers(playerSaveInterval); // Paper
// this.saveAllChunks(true, false, false); // Paper - saved incrementally below
} // Paper start
for (ServerLevel level : this.getAllLevels()) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder
private static final Logger LOGGER = LogManager.getLogger();
+ public long lastSave = MinecraftServer.currentTick; // Paper
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
public ServerGamePacketListenerImpl connection;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug)
+ player.lastSave = MinecraftServer.currentTick; // Paper
this.playerIo.save(player);
ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
public void saveAll() {
- net.minecraft.server.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
+ // Paper start - incremental player saving
+ savePlayers(null);
+ }
+ public void savePlayers(Integer interval) {
+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
MinecraftTimings.savePlayers.startTiming(); // Paper
+ int numSaved = 0;
+ long now = MinecraftServer.currentTick;
for (int i = 0; i < this.players.size(); ++i) {
- this.save(this.players.get(i));
+ ServerPlayer entityplayer = this.players.get(i);
+ if (interval == null || now - entityplayer.lastSave >= interval) {
+ this.save(entityplayer);
+ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; }
+ }
+ // Paper end
}
MinecraftTimings.savePlayers.stopTiming(); // Paper
return null; }); // Paper - ensure main

View File

@@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spyridon Pagkalos <spyridon@ender.gr>
Date: Thu, 25 Mar 2021 20:28:04 +0200
Subject: [PATCH] Introduce beacon activation/deactivation events
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
}
}
+ // Paper start - beacon activation/deactivation events
+ if (i1 <= 0 && blockEntity.levels > 0) {
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent();
+ } else if (i1 > 0 && blockEntity.levels <= 0) {
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
+ }
+ // Paper end
if (blockEntity.lastCheckY >= l) {
blockEntity.lastCheckY = world.getMinBuildHeight() - 1;
@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
@Override
public void setRemoved() {
+ // Paper start - BeaconDeactivatedEvent
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition);
+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
+ // Paper end
BeaconBlockEntity.playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE);
super.setRemoved();
}

View File

@@ -1,94 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 7 Jul 2020 10:52:34 -0700
Subject: [PATCH] More World API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ());
}
+ // Paper start
+ @Override
+ public Location locateNearestBiome(Location origin, Biome biome, int radius) {
+ return this.locateNearestBiome(origin, biome, radius, 8);
+ }
+
+ @Override
+ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) {
+ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ());
+ BlockPos nearest = getHandle().findNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY), biome), originPos, radius, step);
+ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ());
+ }
+
+ @Override
+ public boolean isUltrawarm() {
+ return getHandle().dimensionType().ultraWarm();
+ }
+
+ @Override
+ public double getCoordinateScale() {
+ return getHandle().dimensionType().coordinateScale();
+ }
+
+ @Override
+ public boolean hasSkylight() {
+ return getHandle().dimensionType().hasSkyLight();
+ }
+
+ @Override
+ public boolean hasBedrockCeiling() {
+ return getHandle().dimensionType().hasSkyLight();
+ }
+
+ @Override
+ public boolean doesBedWork() {
+ return getHandle().dimensionType().bedWorks();
+ }
+
+ @Override
+ public boolean doesRespawnAnchorWork() {
+ return getHandle().dimensionType().respawnAnchorWorks();
+ }
+
+ @Override
+ public boolean isFixedTime() {
+ return getHandle().dimensionType().hasFixedTime();
+ }
+
+ @Override
+ public Collection<org.bukkit.Material> getInfiniburn() {
+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().infiniburn().getValues().iterator(), CraftMagicNumbers::getMaterial));
+ }
+
+ @Override
+ public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) {
+ getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.Registry.GAME_EVENT.get(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position));
+ }
+ // Paper end
+
@Override
public Raid locateNearestRaid(Location location, int radius) {
Validate.notNull(location, "Location cannot be null");
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftVector.java b/src/main/java/org/bukkit/craftbukkit/util/CraftVector.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftVector.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftVector.java
@@ -0,0 +0,0 @@ public final class CraftVector {
public static net.minecraft.world.phys.Vec3 toNMS(org.bukkit.util.Vector bukkit) {
return new net.minecraft.world.phys.Vec3(bukkit.getX(), bukkit.getY(), bukkit.getZ());
}
+ // Paper start
+ public static org.bukkit.util.Vector toBukkit(net.minecraft.core.BlockPos blockPosition) {
+ return new org.bukkit.util.Vector(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
+ }
+
+ public static net.minecraft.core.BlockPos toBlockPos(org.bukkit.util.Vector bukkit) {
+ return new net.minecraft.core.BlockPos(bukkit.getX(), bukkit.getY(), bukkit.getZ());
+ }
+ // Paper end
}

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 26 Apr 2021 01:27:08 +0100
Subject: [PATCH] Send empty commands if tab completion is disabled
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -0,0 +0,0 @@ public class Commands {
}
public void sendCommands(ServerPlayer player) {
- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot
+ // Paper start - Send empty commands if tab completion is disabled
+ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot
+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>()));
+ return;
+ }
+ // Paper end
// CraftBukkit start
// Register Vanilla commands into builtRoot as before
// Paper start - Async command map building

View File

@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Mon, 5 Apr 2021 16:58:20 -0400
Subject: [PATCH] Set area affect cloud rotation
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
entity.moveTo(location.getX(), location.getY(), location.getZ());
} else if (AreaEffectCloud.class.isAssignableFrom(clazz)) {
entity = new net.minecraft.world.entity.AreaEffectCloud(world, x, y, z);
+ entity.moveTo(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation
} else if (EvokerFangs.class.isAssignableFrom(clazz)) {
entity = new net.minecraft.world.entity.projectile.EvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null);
} else if (Marker.class.isAssignableFrom(clazz)) {

View File

@@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 22 Apr 2021 17:17:47 -0700
Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
case PERFORM_RESPAWN:
if (this.player.wonGame) {
this.player.wonGame = false;
- this.player = this.server.getPlayerList().respawn(this.player, true);
+ this.player = this.server.getPlayerList().moveToWorld(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument
CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD);
} else {
if (this.player.getHealth() > 0.0F) {
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation) {
+ // Paper start
+ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]);
+ }
+
+ public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) {
+ // Paper end
entityplayer.stopRiding(); // CraftBukkit
this.players.remove(entityplayer);
this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
Player respawnPlayer = entityplayer1.getBukkitEntity();
- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal
+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.<org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag>builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal
this.cserver.getPluginManager().callEvent(respawnEvent);
// Spigot Start
if (entityplayer.connection.isDisconnected()) {

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 22 Apr 2021 16:45:28 -0700
Subject: [PATCH] add consumeFuel to FurnaceBurnEvent
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) {
// CraftBukkit end
flag1 = true;
- if (!itemstack.isEmpty()) {
+ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper
Item item = itemstack.getItem();
itemstack.shrink(1);

View File

@@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 22 Apr 2021 00:28:11 -0700
Subject: [PATCH] add get-set drop chance to EntityEquipment
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
@@ -0,0 +0,0 @@ public class CraftEntityEquipment implements EntityEquipment {
public void setBootsDropChance(float chance) {
this.setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance);
}
+ // Paper start
+ @Override
+ public float getDropChance(EquipmentSlot slot) {
+ return getDropChance(CraftEquipmentSlot.getNMS(slot));
+ }
+
+ @Override
+ public void setDropChance(EquipmentSlot slot, float chance) {
+ setDropChance(CraftEquipmentSlot.getNMS(slot), chance);
+ }
+ // Paper end
private void setDropChance(net.minecraft.world.entity.EquipmentSlot slot, float chance) {
Preconditions.checkArgument(this.entity.getHandle() instanceof Mob, "Cannot set drop chance for non-Mob entity");
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
@@ -0,0 +0,0 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
public void setBootsDropChance(float chance) {
throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory");
}
+ // Paper start
+ @Override
+ public float getDropChance(EquipmentSlot slot) {
+ return 1;
+ }
+
+ @Override
+ public void setDropChance(EquipmentSlot slot, float chance) {
+ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory");
+ }
+ // Paper end
}

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 8 Apr 2021 17:36:10 -0700
Subject: [PATCH] add isDeeplySleeping to HumanEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
}
}
+ // Paper start
+ @Override
+ public boolean isDeeplySleeping() {
+ return getHandle().isSleepingLongEnough();
+ }
+ // Paper end
+
@Override
public int getSleepTicks() {
return this.getHandle().sleepCounter;

View File

@@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Thu, 18 Mar 2021 21:38:01 +0100
Subject: [PATCH] fix PigZombieAngerEvent cancellation
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java
@@ -0,0 +0,0 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
private static final int ALERT_RANGE_Y = 10;
private static final UniformInt ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6);
private int ticksUntilNextAlert;
+ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper
public ZombifiedPiglin(EntityType<? extends ZombifiedPiglin> type, Level world) {
super(type, world);
@@ -0,0 +0,0 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
protected void addBehaviourGoals() {
this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false));
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error
+ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error // Paper - assign field
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true));
}
@@ -0,0 +0,0 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
this.level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
this.setPersistentAngerTarget(null);
+ pathfinderGoalHurtByTarget.stop(); // Paper - clear goalTargets to fix cancellation
return;
}
this.setRemainingPersistentAngerTime(event.getNewAnger());

View File

@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: chickeneer <emcchickeneer@gmail.com>
Date: Thu, 22 Apr 2021 19:02:07 -0700
Subject: [PATCH] fix PlayerItemHeldEvent firing twice
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
if (this.player.isImmobile()) return; // CraftBukkit
if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) {
+ if (packet.getSlot() == this.player.getInventory().selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change
PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot());
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled()) {

View File

@@ -1,333 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 9 Jun 2019 03:53:22 +0100
Subject: [PATCH] incremental chunk saving
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
}
+ public int autoSavePeriod = -1;
+ private void autoSavePeriod() {
+ autoSavePeriod = getInt("auto-save-interval", -1);
+ if (autoSavePeriod > 0) {
+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)");
+ } else if (autoSavePeriod < 0) {
+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod;
+ }
+ }
+
+ public int maxAutoSaveChunksPerTick = 24;
+ private void maxAutoSaveChunksPerTick() {
+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24);
+ }
+
private boolean getBoolean(String path, boolean def) {
config.addDefault("world-settings.default." + path, def);
return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path));
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 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 boolean serverAutoSave = false; // Paper
public Commands vanillaCommandDispatcher;
public boolean forceTicks; // Paper
// CraftBukkit end
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.status.getPlayers().setSample(agameprofile);
}
- if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit
- MinecraftServer.LOGGER.debug("Autosave started");
+ // if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit // Paper - move down
+ // MinecraftServer.LOGGER.debug("Autosave started"); // Paper
+ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper
this.profiler.push("save");
+ if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // Paper - moved from above
this.playerList.saveAll();
- this.saveAllChunks(true, false, false);
- this.profiler.pop();
- MinecraftServer.LOGGER.debug("Autosave finished");
+ // this.saveAllChunks(true, false, false); // Paper - saved incrementally below
+ } // Paper start
+ for (ServerLevel level : this.getAllLevels()) {
+ if (level.paperConfig.autoSavePeriod > 0) {
+ level.saveIncrementally(this.serverAutoSave);
+ }
}
+ // Paper end
+ this.profiler.pop();
+ // MinecraftServer.LOGGER.debug("Autosave finished"); // Paper
+ //} // Paper
this.profiler.push("snooper");
if (((DedicatedServer) this).getProperties().snooperEnabled && !this.snooper.isStarted() && this.tickCount > 100) { // Spigot
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -0,0 +0,0 @@ public class ChunkHolder {
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
}
// Paper end - optimise isOutsideOfRange
+ long lastAutoSaveTime; // Paper - incremental autosave
+ long inactiveTimeStart; // Paper - incremental autosave
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
@@ -0,0 +0,0 @@ public class ChunkHolder {
boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER);
boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER);
+ boolean prevHasBeenLoaded = this.wasAccessibleSinceLastSave; // Paper
this.wasAccessibleSinceLastSave |= flag3;
+ // Paper start - incremental autosave
+ if (this.wasAccessibleSinceLastSave & !prevHasBeenLoaded) {
+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime;
+ if (timeSinceAutoSave < 0) {
+ // safest bet is to assume autosave is needed here
+ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod;
+ }
+ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave;
+ this.chunkMap.autoSaveQueue.add(this);
+ }
+ // Paper end
if (!flag2 && flag3) {
int expectCreateCount = ++this.fullChunkCreateCount; // Paper
this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this);
@@ -0,0 +0,0 @@ public class ChunkHolder {
}
public void refreshAccessibility() {
+ boolean prev = this.wasAccessibleSinceLastSave; // Paper
this.wasAccessibleSinceLastSave = ChunkHolder.getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER);
+ // Paper start - incremental autosave
+ if (prev != this.wasAccessibleSinceLastSave) {
+ if (this.wasAccessibleSinceLastSave) {
+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime;
+ if (timeSinceAutoSave < 0) {
+ // safest bet is to assume autosave is needed here
+ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod;
+ }
+ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave;
+ this.chunkMap.autoSaveQueue.add(this);
+ } else {
+ this.inactiveTimeStart = this.chunkMap.level.getGameTime();
+ this.chunkMap.autoSaveQueue.remove(this);
+ }
+ }
+ // Paper end
}
+ // Paper start - incremental autosave
+ public boolean setHasBeenLoaded() {
+ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER);
+ return this.wasAccessibleSinceLastSave;
+ }
+ // Paper end
+
public void replaceProtoChunk(ImposterProtoChunk chunk) {
for (int i = 0; i < this.futures.length(); ++i) {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = (CompletableFuture) this.futures.get(i);
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.phys.Vec3;
+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
+ // Paper start - incremental autosave
+ final ObjectRBTreeSet<ChunkHolder> autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> {
+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime);
+ if (timeCompare != 0) {
+ return timeCompare;
+ }
+
+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.pos), MCUtil.getCoordinateKey(playerchunk2.pos));
+ });
+
+ protected void saveIncrementally() {
+ int savedThisTick = 0;
+ // optimized since we search far less chunks to hit ones that need to be saved
+ List<ChunkHolder> reschedule = new java.util.ArrayList<>(this.level.paperConfig.maxAutoSaveChunksPerTick);
+ long currentTick = this.level.getGameTime();
+ long maxSaveTime = currentTick - this.level.paperConfig.autoSavePeriod;
+
+ for (Iterator<ChunkHolder> iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) {
+ ChunkHolder playerchunk = iterator.next();
+ if (playerchunk.lastAutoSaveTime > maxSaveTime) {
+ break;
+ }
+
+ iterator.remove();
+
+ ChunkAccess ichunkaccess = playerchunk.getChunkToSave().getNow(null);
+ if (ichunkaccess instanceof LevelChunk) {
+ boolean shouldSave = ((LevelChunk)ichunkaccess).lastSaveTime <= maxSaveTime;
+
+ if (shouldSave && this.save(ichunkaccess) && this.level.entityManager.storeChunkSections(playerchunk.pos.toLong(), entity -> {})) {
+ ++savedThisTick;
+
+ if (!playerchunk.setHasBeenLoaded()) {
+ // do not fall through to reschedule logic
+ playerchunk.inactiveTimeStart = currentTick;
+ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) {
+ break;
+ }
+ continue;
+ }
+ }
+ }
+
+ reschedule.add(playerchunk);
+
+ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) {
+ break;
+ }
+ }
+
+ for (int i = 0, len = reschedule.size(); i < len; ++i) {
+ ChunkHolder playerchunk = reschedule.get(i);
+ playerchunk.lastAutoSaveTime = this.level.getGameTime();
+ this.autoSaveQueue.add(playerchunk);
+ }
+ }
+ // Paper end
+
protected void saveAllChunks(boolean flush) {
if (flush) {
List<ChunkHolder> list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList());
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
asyncSaveData, chunk);
chunk.setUnsaved(false);
+ chunk.setLastSaved(this.level.getGameTime()); // Paper - track last saved time
}
// Paper end
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.level.unload(chunk);
}
+ this.autoSaveQueue.remove(holder); // Paper
this.lightEngine.updateChunkStatus(ichunkaccess.getPos());
this.lightEngine.tryScheduleUpdate();
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (!chunk.isUnsaved()) {
return false;
} else {
+ chunk.setLastSaved(this.level.getGameTime()); // Paper - track save time
chunk.setUnsaved(false);
ChunkPos chunkcoordintpair = chunk.getPos();
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
} // Paper - Timings
}
+ // Paper start - duplicate save, but call incremental
+ public void saveIncrementally() {
+ this.runDistanceManagerUpdates();
+ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings
+ this.chunkMap.saveIncrementally();
+ } // Paper - Timings
+ }
+ // Paper end
+
@Override
public void close() throws IOException {
// CraftBukkit start
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 {
return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
}
+ // Paper start - derived from below
+ public void saveIncrementally(boolean doFull) {
+ ServerChunkCache chunkproviderserver = this.getChunkSource();
+
+ if (doFull) {
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld()));
+ }
+
+ try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) {
+ if (doFull) {
+ this.saveLevelData();
+ }
+
+ this.timings.worldSaveChunks.startTiming(); // Paper
+ if (!this.noSave()) chunkproviderserver.saveIncrementally();
+ this.timings.worldSaveChunks.stopTiming(); // Paper
+
+ // Copied from save()
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
+ if (doFull) { // Paper
+ ServerLevel worldserver1 = this;
+
+ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings());
+ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save());
+ this.convertable.saveDataTag(this.server.registryHolder, this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
+ }
+ // CraftBukkit end
+ }
+ }
+ // Paper end
+
public void save(@Nullable ProgressListener progressListener, boolean flush, boolean flag1) {
ServerChunkCache chunkproviderserver = this.getChunkSource();
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess {
return GameEventDispatcher.NOOP;
}
+ default void setLastSaved(long ticks) {}
// Paper start
default boolean generateFlatBedrock() {
if (this.getLevel() != null) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess {
private final ShortList[] postProcessing;
private TickList<Block> blockTicks;
private TickList<Fluid> liquidTicks;
+ // Paper start - track last save time
+ public long lastSaveTime;
+ @Override
+ public void setLastSaved(long ticks) {
+ this.lastSaveTime = ticks;
+ }
+ // Paper end
private volatile boolean unsaved;
private long inhabitedTime;
@Nullable