even MOOOOOOOOOOOOAAAAAAAAAAAAAAAARRRRRRRRRRRRR patches
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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] );
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
@@ -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();
|
||||
@@ -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()) {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)) {
|
||||
@@ -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()) {
|
||||
@@ -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);
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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());
|
||||
@@ -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()) {
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user