More more more more more more more more more more more more more more work

This commit is contained in:
Nassim Jahnke 2021-11-24 17:06:46 +01:00 committed by MiniDigger | Martin
parent 45c36e5d0c
commit 97a4a70766
33 changed files with 301 additions and 326 deletions

View file

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Gerrygames <gecam59@gmail.com>
Date: Thu, 16 Jul 2020 10:40:10 +0200
Subject: [PATCH] Support hex colors in getLastColors
diff --git a/src/main/java/org/bukkit/ChatColor.java b/src/main/java/org/bukkit/ChatColor.java
index 44d597d7a6f66a18b8037e971170ff7cea5e825f..4594701d77c5d0f744bece871b98d9f6f73eb5a7 100644
--- a/src/main/java/org/bukkit/ChatColor.java
+++ b/src/main/java/org/bukkit/ChatColor.java
@@ -363,6 +363,7 @@ public enum ChatColor {
return new String(b);
}
+ private static final Pattern HEX_COLOR_PATTERN = Pattern.compile(COLOR_CHAR + "x(?>" + COLOR_CHAR + "[0-9a-f]){6}", Pattern.CASE_INSENSITIVE); // Paper - Support hex colors in getLastColors
/**
* Gets the ChatColors used at the end of the given input string.
*
@@ -380,6 +381,15 @@ public enum ChatColor {
for (int index = length - 1; index > -1; index--) {
char section = input.charAt(index);
if (section == COLOR_CHAR && index < length - 1) {
+ // Paper start - Support hex colors
+ if (index > 11 && input.charAt(index - 12) == COLOR_CHAR && (input.charAt(index - 11) == 'x' || input.charAt(index - 11) == 'X')) {
+ String color = input.substring(index - 12, index + 2);
+ if (HEX_COLOR_PATTERN.matcher(color).matches()) {
+ result = color + result;
+ break;
+ }
+ }
+ // Paper end
char c = input.charAt(index + 1);
ChatColor color = getByChar(c);

View file

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 22 Aug 2020 23:59:25 +0200
Subject: [PATCH] Add #setMaxPlayers API
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 51eb99fd09ab546ebdf0c5ab5a76492a31a93139..9a1da52ce6d255715e1f765f491a9e20e47da400 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -172,6 +172,17 @@ public final class Bukkit {
return server.getMaxPlayers();
}
+ // Paper start
+ /**
+ * Set the maximum amount of players which can login to this server.
+ *
+ * @param maxPlayers the amount of players this server allows
+ */
+ public static void setMaxPlayers(int maxPlayers) {
+ server.setMaxPlayers(maxPlayers);
+ }
+ // Paper end
+
/**
* Get the game port that the server runs on.
*
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 849384a6fc7380c5344430beb08210c102c39407..8a10350c4ed5e8f3de5a1cd7fb5064b01d7dd7c2 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -145,6 +145,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
public int getMaxPlayers();
+ // Paper start
+ /**
+ * Set the maximum amount of players which can login to this server.
+ *
+ * @param maxPlayers the amount of players this server allows
+ */
+ public void setMaxPlayers(int maxPlayers);
+ // Paper end
+
/**
* Get the game port that the server runs on.
*

View file

@ -1,65 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 16:32:03 +0200
Subject: [PATCH] Add moon phase API
diff --git a/src/main/java/io/papermc/paper/world/MoonPhase.java b/src/main/java/io/papermc/paper/world/MoonPhase.java
new file mode 100644
index 0000000000000000000000000000000000000000..df05153397b42930cd53d37b30824c7e5f008f7e
--- /dev/null
+++ b/src/main/java/io/papermc/paper/world/MoonPhase.java
@@ -0,0 +1,36 @@
+package io.papermc.paper.world;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum MoonPhase {
+ FULL_MOON(0L),
+ WANING_GIBBOUS(1L),
+ LAST_QUARTER(2L),
+ WANING_CRESCENT(3L),
+ NEW_MOON(4L),
+ WAXING_CRESCENT(5L),
+ FIRST_QUARTER(6L),
+ WAXING_GIBBOUS(7L);
+
+ private final long day;
+
+ MoonPhase(long day) {
+ this.day = day;
+ }
+
+ private static final Map<Long, MoonPhase> BY_DAY = new HashMap<>();
+
+ static {
+ for (MoonPhase phase : values()) {
+ BY_DAY.put(phase.day, phase);
+ }
+ }
+
+ @NotNull
+ public static MoonPhase getPhase(long day) {
+ return BY_DAY.get(day % 8L);
+ }
+}
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index bcac107353149d0129571a3548965a407aa7640c..ef960a72bc10d43690c89ff412dc1b3edb7bdd34 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -68,6 +68,12 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* @return The amount of Players in this world
*/
int getPlayerCount();
+
+ /**
+ * @return the current moon phase at the current time in the world
+ */
+ @NotNull
+ io.papermc.paper.world.MoonPhase getMoonPhase();
// Paper end
/**

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 23 Aug 2020 19:36:08 +0200
Subject: [PATCH] Add playPickupItemAnimation to LivingEntity
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index 5ab8db52160049e36464df4e20e374b8849ef29c..1b6c2b2cfb910e7651e7f18ea407e31db685af8a 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -822,5 +822,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
* @param jumping entity jump state
*/
void setJumping(boolean jumping);
+
+ /**
+ * Plays pickup item animation towards this entity.
+ * <p>
+ * <b>This will remove the item on the client.</b>
+ * <p>
+ * Quantity is inferred to be that of the {@link Item}.
+ *
+ * @param item item to pickup
+ */
+ default void playPickupItemAnimation(@NotNull Item item) {
+ playPickupItemAnimation(item, item.getItemStack().getAmount());
+ }
+
+ /**
+ * Plays pickup item animation towards this entity.
+ * <p>
+ * <b>This will remove the item on the client.</b>
+ *
+ * @param item item to pickup
+ * @param quantity quantity of item
+ */
+ void playPickupItemAnimation(@NotNull Item item, int quantity);
// Paper end
}

View file

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eearslya Sleiarion <eearslya@gmail.com>
Date: Mon, 24 Jun 2019 21:27:39 -0700
Subject: [PATCH] Add BellRingEvent
Add a new event, BellRingEvent, to trigger whenever a player rings a
village bell. Passes along the bell block and the player who rang it.
diff --git a/src/main/java/io/papermc/paper/event/block/BellRingEvent.java b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..881e545df51409e6101b4bb49f699655a744f13f
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java
@@ -0,0 +1,55 @@
+package io.papermc.paper.event.block;
+
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.block.BlockEvent;
+import org.bukkit.potion.PotionEffect;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when a bell is rung.
+ */
+public class BellRingEvent extends BlockEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancelled;
+ private final Entity entity;
+
+ public BellRingEvent(@NotNull Block block, @Nullable Entity entity) {
+ super(block);
+ this.entity = entity;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ /**
+ * Gets the entity that rang the bell.
+ *
+ * @return the ringer or null if none
+ */
+ @Nullable
+ public Entity getEntity() {
+ return entity;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View file

@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DigitalRegent <misterwener@gmail.com>
Date: Mon, 6 Apr 2020 20:30:09 +0200
Subject: [PATCH] Brand support
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 7d4959a96e0cbf9b9e8a980ae4711d02ecd1a430..d0d44acb364bafca80e6efa04532b66663ca336a 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -2244,6 +2244,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
// Paper end
}
+ // Paper start - brand support
+ /**
+ * Returns player's client brand name. If the client didn't send this information, the brand name will be null.<br>
+ * For the Notchian client this name defaults to <code>vanilla</code>. Some modified clients report other names such as <code>forge</code>.<br>
+ * @return client brand name
+ */
+ @Nullable
+ String getClientBrandName();
+ // Paper end
+
@NotNull
@Override
Spigot spigot();

View file

@ -1,81 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Fri, 29 May 2020 23:32:14 -0400
Subject: [PATCH] Improve Chunk Status Transition Speed
When a chunk is loaded from disk that has already been generated,
the server has to promote the chunk through the system to reach
it's current desired status level.
This results in every single status transition going from the main thread
to the world gen threads, only to discover it has no work it actually
needs to do.... and then it returns back to main.
This back and forth costs a lot of time and can really delay chunk loads
when the server is under high TPS due to their being a lot of time in
between chunk load times, as well as hogs up the chunk threads from doing
actual generation and light work.
Additionally, the whole task system uses a lot of CPU on the server threads anyways.
So by optimizing status transitions for status's that are already complete,
we can run them to the desired level while on main thread (where it has
to happen anyways) instead of ever jumping to world gen thread.
This will improve chunk loading effeciency to be reduced down to the following
scenario / path:
1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue
2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread
3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue
4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks)
5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task
6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done
7) MAIN: Task returns to main, finish processing to FULL/TICKING status
Previously would have hopped to SERVER around 12+ times there extra.
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index e317c73b430105052cbf28502916adc3bd60846b..96759f349e10c8ef634a11a6b48f9affae77d65a 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -244,6 +244,13 @@ public class ChunkHolder {
// Paper end - optimise isOutsideOfRange
long lastAutoSaveTime; // Paper - incremental autosave
long inactiveTimeStart; // Paper - incremental autosave
+ // Paper start - optimize chunk status progression without jumping through thread pool
+ public boolean canAdvanceStatus() {
+ ChunkStatus status = getChunkHolderStatus();
+ ChunkAccess chunk = getAvailableChunkNow();
+ return chunk != null && (status == null || chunk.getStatus().isOrAfter(getNextStatus(status)));
+ }
+ // Paper end
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index f43e8bb6b1c6c204b35ea64b47f6d6f558d0f7a5..047f1772c8f9346ba4541d46af8e144141865cfb 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -786,7 +786,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return either.mapLeft((list) -> {
return (LevelChunk) list.get(list.size() / 2);
});
- }, this.mainThreadExecutor);
+ }, this.mainInvokingExecutor); // Paper
}
@Nullable
@@ -1237,6 +1237,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return "chunkGenerate " + requiredStatus.getName();
});
Executor executor = (runnable) -> {
+ // Paper start - optimize chunk status progression without jumping through thread pool
+ if (holder.canAdvanceStatus()) {
+ this.mainInvokingExecutor.execute(runnable);
+ return;
+ }
+ // Paper end
this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
};

View file

@ -1,79 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Sun, 5 Jul 2020 22:38:18 -0400
Subject: [PATCH] Optimize NetworkManager Exception Handling
diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java
index 6611aebafb14b83bce3eeb87701e2edc8a0828ab..bb3b450c7e81ba47e1e8b2244d331f2ce44a7ee1 100644
--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java
+++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java
@@ -275,6 +275,7 @@ public enum ConnectionProtocol {
@Nullable
public Packet<?> createPacket(int id, FriendlyByteBuf buf) {
+ if (id < 0 || id >= this.idToDeserializer.size()) return null; // Paper
Function<FriendlyByteBuf, ? extends Packet<T>> function = this.idToDeserializer.get(id);
return function != null ? function.apply(buf) : null;
}
diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java
index 5356f6484751e4b4740720aecac90bdfe044283b..ed54479b14dcfc736ac90749106557f0ff537550 100644
--- a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java
+++ b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java
@@ -8,9 +8,20 @@ import io.netty.handler.codec.CorruptedFrameException;
import java.util.List;
public class Varint21FrameDecoder extends ByteToMessageDecoder {
+ private final byte[] lenBuf = new byte[3]; // Paper
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) {
+ // Paper start - if channel is not active just discard the packet
+ if (!channelHandlerContext.channel().isActive()) {
+ byteBuf.skipBytes(byteBuf.readableBytes());
+ return;
+ }
+ // Paper end
byteBuf.markReaderIndex();
+ // Paper start - reuse temporary length buffer
+ byte[] abyte = lenBuf;
+ java.util.Arrays.fill(abyte, (byte) 0);
+ // Paper end
byte[] bs = new byte[3];
for(int i = 0; i < bs.length; ++i) {
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
index 449f1b2f5dca350dc0912e14c8c2bf3eb4652b92..bcf53ec07b8eeec7a88fb67e6fb908362e6f51b0 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -1,6 +1,9 @@
package net.minecraft.network.protocol;
+import net.minecraft.network.Connection;
import net.minecraft.network.PacketListener;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import co.aikar.timings.MinecraftTimings; // Paper
@@ -32,6 +35,21 @@ public class PacketUtils {
try (Timing ignored = timing.startTiming()) { // Paper - timings
packet.handle(listener);
} // Paper - timings
+ // Paper start
+ catch (Exception e) {
+ Connection networkmanager = listener.getConnection();
+ if (networkmanager.getPlayer() != null) {
+ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e);
+ } else {
+ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e);
+ }
+ TextComponent error = new TextComponent("Packet processing error");
+ networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> {
+ networkmanager.disconnect(error);
+ });
+ networkmanager.setReadOnly();
+ }
+ // Paper end
} else {
PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet);
}

View file

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Wyatt Childers <wchilders@nearce.com>
Date: Sat, 4 Jul 2020 23:07:43 -0400
Subject: [PATCH] Optimize the advancement data player iteration to be O(N)
rather than O(N^2)
diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java
index 3d82f984648605d58fae3c57f145d0da8a2ae225..bd858a9da2f2442be85f36bb2de0dac46d0c68d7 100644
--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java
+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java
@@ -437,6 +437,16 @@ public class PlayerAdvancements {
}
private void ensureVisibility(Advancement advancement) {
+ // Paper start
+ ensureVisibility(advancement, IterationEntryPoint.ROOT);
+ }
+ private enum IterationEntryPoint {
+ ROOT,
+ ITERATOR,
+ PARENT_OF_ITERATOR
+ }
+ private void ensureVisibility(Advancement advancement, IterationEntryPoint entryPoint) {
+ // Paper end
boolean flag = this.shouldBeVisible(advancement);
boolean flag1 = this.visible.contains(advancement);
@@ -452,15 +462,23 @@ public class PlayerAdvancements {
}
if (flag != flag1 && advancement.getParent() != null) {
- this.ensureVisibility(advancement.getParent());
+ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise
+ // market that we're entering from the parent of an iterator.
+ this.ensureVisibility(advancement.getParent(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT);
}
+ // If this is true, we've went through a child iteration, entered the parent, processed the parent
+ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing.
+ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) {
+ return;
+ } // Paper end
+
Iterator iterator = advancement.getChildren().iterator();
while (iterator.hasNext()) {
Advancement advancement1 = (Advancement) iterator.next();
- this.ensureVisibility(advancement1);
+ this.ensureVisibility(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration
}
}

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Wed, 8 Jul 2020 11:24:30 -0500
Subject: [PATCH] Fix arrows never despawning MC-125757
This forces the despawn counter to start ticking regardless of
state after the arrow has been alive for 200 ticks (10 seconds)
instead of getting stuck in a never despawn state (bubble columns,
etc).
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
index 65faf775b786f9c237ee33c1fb0f8ab9f37d738c..6636845ea044c3810e1880aad8b679134cd33668 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
@@ -198,6 +198,7 @@ public abstract class AbstractArrow extends Projectile {
++this.inGroundTime;
} else {
+ if (tickCount > 200) this.tickDespawn(); // Paper - tick despawnCounter regardless after 10 seconds
this.inGroundTime = 0;
Vec3 vec3d2 = this.position();

View file

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 11 Jul 2020 03:54:28 -0400
Subject: [PATCH] Thread Safe Vanilla Command permission checking
Datapacks check this on load and are built concurrently. This was breaking them badly due
to race conditions.
Plus, .canUse we want to be safe for async anyways.
diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java
index 2b87c6eb28d4db634dd6d8ee42ff3aa78ed7cb68..f64aa22ed6fcb4af67317b99f459ee5296392548 100644
--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java
+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java
@@ -74,10 +74,10 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
public synchronized boolean canUse(final S source) {
if (source instanceof CommandSourceStack) {
try {
- ((CommandSourceStack) source).currentCommand = this;
+ ((CommandSourceStack) source).currentCommand.put(Thread.currentThread(), this); // Paper
return this.requirement.test(source);
} finally {
- ((CommandSourceStack) source).currentCommand = null;
+ ((CommandSourceStack) source).currentCommand.remove(Thread.currentThread()); // Paper
}
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
index a59d14e61fcbca7861a5593d0717b81262ccbdc5..71e29d29ed5c2d61832e2f124967bb223708406f 100644
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
@@ -9,8 +9,10 @@ import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BinaryOperator;
import java.util.stream.Stream;
import javax.annotation.Nullable;
@@ -54,7 +56,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy
private final ResultConsumer<CommandSourceStack> consumer;
private final EntityAnchorArgument.Anchor anchor;
private final Vec2 rotation;
- public volatile CommandNode currentCommand; // CraftBukkit
+ public Map<Thread, CommandNode> currentCommand = new ConcurrentHashMap<>(); // CraftBukkit // Paper
public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String name, Component displayName, MinecraftServer server, @Nullable Entity entity) {
this(output, pos, rot, world, level, name, displayName, server, entity, false, (commandcontext, flag, j) -> {
@@ -175,9 +177,11 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy
@Override
public boolean hasPermission(int level) {
// CraftBukkit start
- CommandNode currentCommand = this.currentCommand;
+ // Paper start - fix concurrency issue
+ CommandNode currentCommand = this.currentCommand.get(Thread.currentThread());
if (currentCommand != null) {
return this.hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand));
+ // Paper end
}
// CraftBukkit end

View file

@ -1,53 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Wed, 15 Jul 2020 19:34:11 -0700
Subject: [PATCH] Move range check for block placing up
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 36a69fb0a9cd81ceb0f9cbe6549fc89bd643c77c..51303e89ec160f3715e538903ae98be993d59150 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1661,6 +1661,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
}
// Spigot end
+ // Paper start
+ private boolean isOutsideOfReach(double x, double y, double z) {
+ Location eyeLoc = this.getCraftPlayer().getEyeLocation();
+ double reachDistance = NumberConversions.square(eyeLoc.getX() - x) + NumberConversions.square(eyeLoc.getY() - y) + NumberConversions.square(eyeLoc.getZ() - z);
+ return reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED);
+ }
+ // Paper end
+
@Override
public void handleUseItemOn(ServerboundUseItemOnPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
@@ -1673,17 +1681,22 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
BlockPos blockposition = movingobjectpositionblock.getBlockPos();
Direction enumdirection = movingobjectpositionblock.getDirection();
+ // Paper start - move check up and check actual location as well
+ final Vec3 clickedLocation = movingobjectpositionblock.getLocation();
+ if (isOutsideOfReach(blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D)
+ || !Double.isFinite(clickedLocation.x) || !Double.isFinite(clickedLocation.y) || !Double.isFinite(clickedLocation.z)
+ || isOutsideOfReach(clickedLocation.x, clickedLocation.y, clickedLocation.z)) {
+ return;
+ }
+ // Paper end - move check up
+
this.player.resetLastActionTime();
int i = this.player.level.getMaxBuildHeight();
if (blockposition.getY() < i) {
if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) {
// CraftBukkit start - Check if we can actually do something over this large a distance
- Location eyeLoc = this.getCraftPlayer().getEyeLocation();
- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ());
- if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? ServerGamePacketListenerImpl.CREATIVE_PLACE_DISTANCE_SQUARED : ServerGamePacketListenerImpl.SURVIVAL_PLACE_DISTANCE_SQUARED)) {
- return;
- }
+ // Paper - move check up
this.player.stopUsingItem(); // SPIGOT-4706
// CraftBukkit end
InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock);

View file

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Wed, 15 Jul 2020 21:42:52 -0400
Subject: [PATCH] Fix SPIGOT-5989
Before this fix, if a player was respawning to a respawn anchor and
the respawn location was modified away from the anchor with the
PlayerRespawnEvent, the anchor would still lose some charge.
This fixes that by checking if the modified spawn location is
still at a respawn anchor.
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0e3726495ef10717627dcf4297c944da5e0689b7..34f56db51e2c6a1c451f95d0fa3cb5c368b1ecf7 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -79,6 +79,7 @@ import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.RespawnAnchorBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.border.BorderChangeListener;
import net.minecraft.world.level.border.WorldBorder;
@@ -830,6 +831,7 @@ public abstract class PlayerList {
// Paper start
boolean isBedSpawn = false;
boolean isRespawn = false;
+ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989
// Paper end
// CraftBukkit start - fire PlayerRespawnEvent
@@ -840,7 +842,7 @@ public abstract class PlayerList {
Optional optional;
if (blockposition != null) {
- optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag);
+ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989
} else {
optional = Optional.empty();
}
@@ -884,7 +886,12 @@ public abstract class PlayerList {
}
// Spigot End
- location = respawnEvent.getRespawnLocation();
+ // Paper start - Fix SPIGOT-5989
+ if (!location.equals(respawnEvent.getRespawnLocation()) ) {
+ location = respawnEvent.getRespawnLocation();
+ isLocAltered = true;
+ }
+ // Paper end
if (!flag) entityplayer.reset(); // SPIGOT-4785
isRespawn = true; // Paper
} else {
@@ -922,8 +929,12 @@ public abstract class PlayerList {
}
// entityplayer1.syncInventory();
entityplayer1.setHealth(entityplayer1.getHealth());
- if (flag2) {
- entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F));
+ // Paper start - Fix SPIGOT-5989
+ if (flag2 && !isLocAltered) {
+ BlockState data = worldserver1.getBlockState(blockposition);
+ worldserver1.setBlock(blockposition, data.setValue(RespawnAnchorBlock.CHARGE, data.getValue(RespawnAnchorBlock.CHARGE) - 1), 3);
+ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F));
+ // Paper end
}
// Added from changeDimension
this.sendAllPlayerInfo(entityplayer); // Update health, etc...

View file

@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 10 Jul 2020 13:12:33 -0500
Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 7ce854edba32ffcafaa5268d4bb2822a5233e40b..3d6e09a3f028e50c08cbbb6b426f5b044c7b9e67 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -129,11 +129,20 @@ public class Main {
return;
}
- File file = (File) optionset.valueOf("universe"); // CraftBukkit
+ // Paper start - fix SPIGOT-5824
+ File file;
+ File userCacheFile = new File("usercache.json");
+ if (optionset.has("universe")) {
+ file = (File) optionset.valueOf("universe"); // CraftBukkit
+ userCacheFile = new File(file, "usercache.json");
+ } else {
+ file = new File(bukkitConfiguration.getString("settings.world-container", "."));
+ }
+ // Paper end - fix SPIGOT-5824
YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper
MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService();
GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository();
- GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName()));
+ GameProfileCache usercache = new GameProfileCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container
// CraftBukkit start
String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName);
LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath());

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 10 Jul 2020 12:38:12 -0500
Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 3d6e09a3f028e50c08cbbb6b426f5b044c7b9e67..ea136b9ad3a2a07076e12b8656c68f63aa4718c8 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -129,6 +129,7 @@ public class Main {
return;
}
+ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init
// Paper start - fix SPIGOT-5824
File file;
File userCacheFile = new File("usercache.json");

View file

@ -1,82 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Mon, 13 Jul 2020 06:22:54 -0700
Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in
login
Move the criterion storage to the AdvancementDataPlayer object
itself, so the criterion object stores no references - and thus
needs no cleanup.
diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
index 584f48aba7bfec07a75b5a37da4ba7439610543c..c25c1cfca010ed625b6faf310be2edeccd6667bc 100644
--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
+++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
@@ -14,22 +14,24 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.storage.loot.LootContext;
public abstract class SimpleCriterionTrigger<T extends AbstractCriterionTriggerInstance> implements CriterionTrigger<T> {
- private final Map<PlayerAdvancements, Set<CriterionTrigger.Listener<T>>> players = Maps.newIdentityHashMap();
+ //private final Map<PlayerAdvancements, Set<CriterionTrigger.Listener<T>>> players = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak
+
+ public SimpleCriterionTrigger() {}
@Override
public final void addPlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener<T> conditions) {
- this.players.computeIfAbsent(manager, (managerx) -> {
+ manager.criterionData.computeIfAbsent(this, (managerx) -> { // Paper - fix AdvancementDataPlayer leak
return Sets.newHashSet();
}).add(conditions);
}
@Override
public final void removePlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener<T> conditions) {
- Set<CriterionTrigger.Listener<T>> set = this.players.get(manager);
+ Set<CriterionTrigger.Listener<T>> set = (Set) manager.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak
if (set != null) {
set.remove(conditions);
if (set.isEmpty()) {
- this.players.remove(manager);
+ manager.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak
}
}
@@ -37,7 +39,7 @@ public abstract class SimpleCriterionTrigger<T extends AbstractCriterionTriggerI
@Override
public final void removePlayerListeners(PlayerAdvancements tracker) {
- this.players.remove(tracker);
+ tracker.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak
}
protected abstract T createInstance(JsonObject obj, EntityPredicate.Composite playerPredicate, DeserializationContext predicateDeserializer);
@@ -50,7 +52,7 @@ public abstract class SimpleCriterionTrigger<T extends AbstractCriterionTriggerI
protected void trigger(ServerPlayer player, Predicate<T> tester) {
PlayerAdvancements playerAdvancements = player.getAdvancements();
- Set<CriterionTrigger.Listener<T>> set = this.players.get(playerAdvancements);
+ Set<CriterionTrigger.Listener<T>> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak
if (set != null && !set.isEmpty()) {
LootContext lootContext = EntityPredicate.createContext(player, player);
List<CriterionTrigger.Listener<T>> list = null;
diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java
index ce02a467c1c3434f2cdb112ceb9794196069a820..e05e5710c81b7dbb648afbfe16f843e7ae310752 100644
--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java
+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java
@@ -39,6 +39,7 @@ import net.minecraft.advancements.Criterion;
import net.minecraft.advancements.CriterionProgress;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.advancements.CriterionTriggerInstance;
+import net.minecraft.advancements.critereon.SimpleCriterionTrigger;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.game.ClientboundSelectAdvancementsTabPacket;
@@ -70,6 +71,8 @@ public class PlayerAdvancements {
private Advancement lastSelectedTab;
private boolean isFirstPacket = true;
+ public final Map<SimpleCriterionTrigger, Set<CriterionTrigger.Listener>> criterionData = Maps.newIdentityHashMap(); // Paper - fix advancement data player leakage
+
public PlayerAdvancements(DataFixer dataFixer, PlayerList playerManager, ServerAdvancementManager advancementLoader, File advancementFile, ServerPlayer owner) {
this.dataFixer = dataFixer;
this.playerList = playerManager;

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 26 Jul 2020 12:11:39 +0100
Subject: [PATCH] Add missing strikeLighting call to
World#spigot()#strikeLightningEffect
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 228406d41c2e4d1615329752bbc9e609acbe2d36..35414a944fdbff16005185a22ea845cc2f7163e7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1999,6 +1999,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
lightning.moveTo( loc.getX(), loc.getY(), loc.getZ() );
lightning.visualOnly = true;
lightning.isSilent = isSilent;
+ world.strikeLightning( lightning );
return (LightningStrike) lightning.getBukkitEntity();
}
};

View file

@ -1,84 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Fri, 24 Jul 2020 15:56:05 -0700
Subject: [PATCH] Fix some rails connecting improperly
diff --git a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java
index 41c23abf78c2ca95c26633860adb9360139b3ceb..1242eb55996bca8a63bd7b95d01d0299fb36d105 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java
@@ -65,6 +65,7 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
state = this.updateDir(world, pos, state, true);
if (this.isStraight) {
state.neighborChanged(world, pos, this, pos, notify);
+ state = world.getBlockState(pos); // Paper - don't desync, update again
}
return state;
diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java
index 2335e7af6bc16a0d65c7818c316f3194c680c69d..63c7f2cf530ac9562960ae5a3cbc6e511a009377 100644
--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java
@@ -70,6 +70,7 @@ public class DetectorRailBlock extends BaseRailBlock {
private void checkPressed(Level world, BlockPos pos, BlockState state) {
if (this.canSurvive(state, world, pos)) {
+ if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything
boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED);
boolean flag1 = false;
List<AbstractMinecart> list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (entity) -> {
diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java
index a205e04bce8706302e4a077646749d05dee98251..2a642275522c1d718dd6052f5ac942579cc31e9e 100644
--- a/src/main/java/net/minecraft/world/level/block/RailState.java
+++ b/src/main/java/net/minecraft/world/level/block/RailState.java
@@ -17,6 +17,12 @@ public class RailState {
private final boolean isStraight;
private final List<BlockPos> connections = Lists.newArrayList();
+ // Paper start - prevent desync
+ public boolean isValid() {
+ return this.level.getBlockState(this.pos).getBlock() == this.state.getBlock();
+ }
+ // Paper end - prevent desync
+
public RailState(Level world, BlockPos pos, BlockState state) {
this.level = world;
this.pos = pos;
@@ -143,6 +149,11 @@ public class RailState {
}
private void connectTo(RailState placementHelper) {
+ // Paper start - prevent desync
+ if (!this.isValid() || !placementHelper.isValid()) {
+ return;
+ }
+ // Paper end - prevent desync
this.connections.add(placementHelper.pos);
BlockPos blockPos = this.pos.north();
BlockPos blockPos2 = this.pos.south();
@@ -333,10 +344,15 @@ public class RailState {
this.state = this.state.setValue(this.block.getShapeProperty(), railShape2);
if (forceUpdate || this.level.getBlockState(this.pos) != this.state) {
this.level.setBlock(this.pos, this.state, 3);
+ // Paper start - prevent desync
+ if (!this.isValid()) {
+ return this;
+ }
+ // Paper end - prevent desync
for(int i = 0; i < this.connections.size(); ++i) {
RailState railState = this.getRail(this.connections.get(i));
- if (railState != null) {
+ if (railState != null && railState.isValid()) { // Paper - prevent desync
railState.removeSoftConnections();
if (railState.canConnectTo(this)) {
railState.connectTo(this);
@@ -349,6 +365,6 @@ public class RailState {
}
public BlockState getState() {
- return this.state;
+ return this.level.getBlockState(this.pos); // Paper - prevent desync
}
}

View file

@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: mbax <matt@phozop.net>
Date: Mon, 17 Aug 2020 12:17:37 -0400
Subject: [PATCH] Fix regex mistake in CB NBT int deserialization
The existing regex is too open and allows for the absence of any actual
number data, detecting an NBT entry of just the letter "i" in upper or
lower case. This causes a single-character NBT entry to be processed as
an integer ending in "i", passing an empty String to to Integer.parseInt,
triggering an exception in loading the item.
This commit forces numbers to be present prior to the ending "i"
letter.
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java
index a7f4054002bd176fccf8357e9a23de66dd9e0dc5..207e4302161b3abe2ade56c9dc9c31820010fa42 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java
@@ -19,7 +19,7 @@ import net.minecraft.nbt.TagParser;
public class CraftNBTTagConfigSerializer {
private static final Pattern ARRAY = Pattern.compile("^\\[.*]");
- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE);
+ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex
private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE);
private static final TagParser MOJANGSON_PARSER = new TagParser(new StringReader(""));

View file

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach@zachbr.io>
Date: Tue, 23 Jul 2019 20:44:47 -0500
Subject: [PATCH] Do not let the server load chunks from newer versions
If the server attempts to load a chunk generated by a newer version of
the game, immediately stop the server to prevent data corruption.
You can override this functionality at your own peril.
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index ed05a11f5038fdac90576ca33a0b710c83ab39a1..80b9f3547bc30cb470d272132e96fcce188efd91 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -96,10 +96,25 @@ public class ChunkSerializer {
holder.tasks.forEach(Runnable::run);
return holder.protoChunk;
}
+
+ // Paper start
+ private static final int CURRENT_DATA_VERSION = SharedConstants.getCurrentVersion().getWorldVersion();
+ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion");
+ // Paper end
+
public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) {
java.util.ArrayDeque<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>();
// Paper end
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
+ // Paper start - Do NOT attempt to load chunks saved with newer versions
+ if (nbt.contains("DataVersion", 99)) {
+ int dataVersion = nbt.getInt("DataVersion");
+ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) {
+ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace();
+ System.exit(1);
+ }
+ }
+ // Paper end
BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource();
CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate
ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate

View file

@ -1,91 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DigitalRegent <misterwener@gmail.com>
Date: Sat, 11 Apr 2020 13:10:58 +0200
Subject: [PATCH] Brand support
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index ce4f1ab41ec2e5f656114fbd7b6f825bccf15d17..76794189454f5dd935fcd77e3c89a1ce58a9b570 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
import com.google.common.primitives.Floats;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.StringReader;
+import io.netty.buffer.Unpooled;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry;
@@ -38,6 +39,7 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.Connection;
+import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
@@ -258,6 +260,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80);
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
+ private String clientBrandName = null; // Paper - Brand name
+
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) {
this.server = server;
this.connection = connection;
@@ -2992,6 +2996,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register");
private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister");
+ private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support
+
@Override
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
@@ -3019,6 +3025,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
try {
byte[] data = new byte[packet.data.readableBytes()];
packet.data.readBytes(data);
+ // Paper start - Brand support
+ if (packet.identifier.equals(MINECRAFT_BRAND)) {
+ try {
+ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUtf(256);
+ } catch (StringIndexOutOfBoundsException ex) {
+ this.clientBrandName = "illegal";
+ }
+ }
+ // Paper end
this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data);
} catch (Exception ex) {
ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex);
@@ -3028,6 +3043,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
}
+ // Paper start - brand support
+ public String getClientBrandName() {
+ return clientBrandName;
+ }
+ // Paper end
+
public final boolean isDisconnected() {
return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 21a2f83aa91a41ea1f4e9e87e804d587838c0d45..c15d0bc8df85b81f8dec2d17b3b6eee9ef9ad1c8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2484,6 +2484,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
// Paper end
};
+ // Paper start - brand support
+ @Override
+ public String getClientBrandName() {
+ return getHandle().connection != null ? getHandle().connection.getClientBrandName() : null;
+ }
+ // Paper end
+
public Player.Spigot spigot()
{
return this.spigot;

View file

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 22 Aug 2020 23:59:30 +0200
Subject: [PATCH] Add #setMaxPlayers API
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 9a73364f4d56f3a7cecb27bc8034166b8f5731b9..4d1d5dacb175e7059a6af036432ef891bcf77970 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -145,7 +145,7 @@ public abstract class PlayerList {
public final PlayerDataStorage playerIo;
private boolean doWhiteList;
private final RegistryAccess.RegistryHolder registryHolder;
- protected final int maxPlayers;
+ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter
private int viewDistance;
private boolean allowCheatsForAllPlayers;
private static final boolean ALLOW_LOGOUTIVATOR = false;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 81effb4bc34d3cb4325510c1b0de39956961c427..ab7eae6483a8981f6324f9da671b3d41667c3768 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -636,6 +636,13 @@ public final class CraftServer implements Server {
return this.playerList.getMaxPlayers();
}
+ // Paper start
+ @Override
+ public void setMaxPlayers(int maxPlayers) {
+ this.playerList.setMaxPlayers(maxPlayers);
+ }
+ // Paper end
+
// NOTE: These are dependent on the corresponding call in MinecraftServer
// so if that changes this will need to as well
@Override

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 23 Aug 2020 19:36:22 +0200
Subject: [PATCH] Add playPickupItemAnimation to LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index e6ea5c09adbb3a20114d42ab3ac01969b64dfb28..95f08ceb8cf7ea91a6b7b53ada22b30965384083 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -838,5 +838,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
((Mob) getHandle()).getJumpControl().jump();
}
}
+
+ @Override
+ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) {
+ getHandle().take(((CraftItem) item).getHandle(), quantity);
+ }
// Paper end
}

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sun, 23 Aug 2020 19:01:04 +0200
Subject: [PATCH] Don't require FACING data
diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
index 0c286d7254f653bc855b1cb329fa76e3c1669b3c..05c0f0049421bc897f8e722331e30a6756ebbeea 100644
--- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
@@ -14,20 +14,22 @@ import org.bukkit.event.block.BlockDispenseEvent;
// CraftBukkit end
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
+ private Direction enumdirection; // Paper
public DefaultDispenseItemBehavior() {}
@Override
public final ItemStack dispense(BlockSource pointer, ItemStack stack) {
+ enumdirection = pointer.getBlockState().getValue(DispenserBlock.FACING); // Paper - cache facing direction
ItemStack itemstack1 = this.execute(pointer, stack);
this.playSound(pointer);
- this.playAnimation(pointer, (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction
return itemstack1;
}
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
- Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+ // Paper - cached enum direction
Position iposition = DispenserBlock.getDispensePosition(pointer);
ItemStack itemstack1 = stack.split(1);

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 22 Aug 2020 23:36:21 +0200
Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 86d060691405401fe8ae8ae8ef59322ee841b196..1b13c67441c46208a9b2adde5ca109f90bbb92e2 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1707,6 +1707,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
//ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c()));
this.levelData.setSpawn(pos, angle);
+ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper
if (this.keepSpawnInMemory) {
// if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add
this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 35414a944fdbff16005185a22ea845cc2f7163e7..60077813fabb0b26b23a051598cb03115a3afcc2 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -245,11 +245,13 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public boolean setSpawnLocation(int x, int y, int z, float angle) {
try {
Location previousLocation = this.getSpawnLocation();
- world.levelData.setSpawn(new BlockPos(x, y, z), angle);
+ world.setDefaultSpawnPos(new BlockPos(x, y, z), angle); // Paper - use WorldServer#setSpawn
+ // Paper start - move to nms.World
// Notify anyone who's listening.
- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
- this.server.getPluginManager().callEvent(event);
+ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
+ // server.getPluginManager().callEvent(event);
+ // Paper end
return true;
} catch (Exception e) {

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 16:32:11 +0200
Subject: [PATCH] Add moon phase API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 60077813fabb0b26b23a051598cb03115a3afcc2..c21b98fbd9b410e0e993f3073e5cbb37015776eb 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -183,6 +183,11 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public int getPlayerCount() {
return world.players().size();
}
+
+ @Override
+ public io.papermc.paper.world.MoonPhase getMoonPhase() {
+ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L);
+ }
// Paper end
private static final Random rand = new Random();

View file

@ -1,61 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: commandblockguy <commandblockguy1@gmail.com>
Date: Fri, 14 Aug 2020 14:44:14 -0500
Subject: [PATCH] Prevent headless pistons from being created
Prevent headless pistons from being created by explosions or tree/mushroom growth.
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 64ccc906fef2c0988c30d289c392b13221b9b4c1..6b725dc2217e68255286caad6a0820bcccffb6da 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -465,6 +465,12 @@ public class PaperConfig {
set("settings.unsupported-settings.allow-tnt-duplication", null);
}
+ public static boolean allowHeadlessPistons;
+ private static void allowHeadlessPistons() {
+ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons.");
+ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false);
+ }
+
public static int playerAutoSaveRate = -1;
public static int maxPlayerAutoSavePerTick = 10;
private static void playerAutoSaveRate() {
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 1575fb0bbad6e11f25fb9ce51fd1f15a1b11e0fe..132140e00865fcf84ebe03ffcbc2f30ac11a0b35 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -15,6 +15,7 @@ import java.util.Random;
import java.util.Set;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
@@ -35,6 +36,8 @@ import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.piston.PistonHeadBlock;
+import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.FluidState;
@@ -189,6 +192,15 @@ public class Explosion {
if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) {
set.add(blockposition);
+ // Paper start - prevent headless pistons from forming
+ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) {
+ BlockEntity extension = this.level.getBlockEntity(blockposition);
+ if (extension instanceof PistonMovingBlockEntity && ((PistonMovingBlockEntity) extension).isSourcePiston()) {
+ Direction direction = iblockdata.getValue(PistonHeadBlock.FACING);
+ set.add(blockposition.relative(direction.getOpposite()));
+ }
+ }
+ // Paper end
}
d4 += d0 * 0.30000001192092896D;

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eearslya Sleiarion <eearslya@gmail.com>
Date: Sun, 23 Aug 2020 13:04:02 +0200
Subject: [PATCH] Add BellRingEvent
Add a new event, BellRingEvent, to trigger whenever a player rings a
village bell. Passes along the bell block and the player who rang it.
diff --git a/src/main/java/net/minecraft/world/level/block/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java
index 3392d9b45d4bfba7ad3e3a84cdd4f2a29b58e4ff..1864984197a6b28cccb3a57b6856f61766d6a467 100644
--- a/src/main/java/net/minecraft/world/level/block/BellBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java
@@ -3,6 +3,7 @@ package net.minecraft.world.level.block;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
+import net.minecraft.server.MCUtil;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
@@ -131,6 +132,7 @@ public class BellBlock extends BaseEntityBlock {
direction = world.getBlockState(pos).getValue(FACING);
}
+ if (!new io.papermc.paper.event.block.BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, pos)), entity == null ? null : entity.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent
((BellBlockEntity)blockEntity).onHit(direction);
world.playSound((Player)null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F);
world.gameEvent(entity, GameEvent.RING_BELL, pos);

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 15:47:34 +0200
Subject: [PATCH] Add zombie targets turtle egg config
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index f9caed53ffc10300511b576cf822864b101df83d..483f7f790173f1fc30f2b2b98e543098114c4cab 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -57,6 +57,11 @@ public class PaperWorldConfig {
}
}
+ public boolean zombiesTargetTurtleEggs = true;
+ private void zombiesTargetTurtleEggs() {
+ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index 20d8e705ea432df64917b59f8290aa5400795f4b..c210f83044ec2cddbfb776094da3d7f5f21df23b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -109,7 +109,7 @@ public class Zombie extends Monster {
@Override
protected void registerGoals() {
- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3));
+ if (level.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
this.addBehaviourGoals();

View file

@ -1,58 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 19 Aug 2020 05:05:54 +0100
Subject: [PATCH] Buffer joins to world
This patch buffers the number of logins which will attempt to join
the world per tick, this attempts to reduce the impact that join floods
has on the server
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 6b725dc2217e68255286caad6a0820bcccffb6da..6733e78ba6bf2993bb2adde4cf9f1f6ca366679c 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -481,4 +481,9 @@ public class PaperConfig {
maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20;
}
}
+
+ public static int maxJoinsPerTick;
+ private static void maxJoinsPerTick() {
+ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3);
+ }
}
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 3faf9bc694016f3f46576a549814ff8e6070598a..7f6405ac44fef423dc8b21f3dbeaae26a1005077 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -37,6 +37,7 @@ import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
+import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RunningOnDifferentThreadException;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
@@ -373,10 +374,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
// Paper end
+ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper
+ private static int joinAttemptsThisTick; // Paper
+ private static int currTick; // Paper
public void tick() {
this.flushQueue();
+ // Paper start
+ if (currTick != MinecraftServer.currentTick) {
+ currTick = MinecraftServer.currentTick;
+ joinAttemptsThisTick = 0;
+ }
+ // Paper end
if (this.packetListener instanceof ServerLoginPacketListenerImpl) {
+ if ( ((ServerLoginPacketListenerImpl) this.packetListener).state != ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT // Paper
+ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick
((ServerLoginPacketListenerImpl) this.packetListener).tick();
+ } // Paper
}
if (this.packetListener instanceof ServerGamePacketListenerImpl) {

File diff suppressed because it is too large Load diff