Things, and Starlight (maybe)

This commit is contained in:
Nassim Jahnke
2022-06-08 13:44:30 +02:00
parent 7feebbe413
commit d9a947b54c
29 changed files with 94 additions and 80 deletions

View File

@@ -1,95 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Tue, 5 Oct 2021 20:04:21 +0200
Subject: [PATCH] Add config option for logging player ip addresses
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 {
}
}
+ public static boolean logPlayerIpAddresses = true;
+ private static void playerIpAddresses() {
+ logPlayerIpAddresses = getBoolean("settings.log-player-ip-addresses", logPlayerIpAddresses);
+ }
+
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/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -0,0 +0,0 @@ public class PacketUtils {
packet.handle(listener);
} catch (Exception exception) {
net.minecraft.network.Connection networkmanager = listener.getConnection();
+ String playerIP = com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? String.valueOf(networkmanager.getRemoteAddress()) : "<ip address withheld>"; // Paper
if (networkmanager.getPlayer() != null) {
- LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), exception);
+ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), playerIP, exception); // Paper
} else {
- LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), exception);
+ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, playerIP, exception); // Paper
}
net.minecraft.network.chat.TextComponent error = new net.minecraft.network.chat.TextComponent("Packet processing error");
networkmanager.send(new net.minecraft.network.protocol.game.ClientboundDisconnectPacket(error), (future) -> {
diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
+++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
buf.release();
this.buf = null;
- LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress());
+ LOGGER.debug("Ping: (1.6) from {}", com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? ctx.channel().remoteAddress() : "<ip address withheld>"); // Paper
InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port);
com.destroystokyo.paper.event.server.PaperServerListPingEvent event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(
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 {
throw new ReportedException(CrashReport.forThrowable(exception, "Ticking memory connection"));
}
- ServerConnectionListener.LOGGER.warn("Failed to handle packet for {}", networkmanager.getRemoteAddress(), exception);
+ ServerConnectionListener.LOGGER.warn("Failed to handle packet for {}", com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? String.valueOf(networkmanager.getRemoteAddress()) : "<ip address withheld>", exception); // Paper
TextComponent chatcomponenttext = new TextComponent("Internal server error");
networkmanager.send(new ClientboundDisconnectPacket(chatcomponenttext), (future) -> {
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
}
public String getUserName() {
- return this.gameProfile != null ? this.gameProfile + " (" + this.connection.getRemoteAddress() + ")" : String.valueOf(this.connection.getRemoteAddress());
+ // Paper start
+ String ip = com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? String.valueOf(this.connection.getRemoteAddress()) : "<ip address withheld>";
+ return this.gameProfile != null ? this.gameProfile + " (" + ip + ")" : String.valueOf(ip);
+ // Paper end
}
@Override
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 {
final String s1;
if (connection.getRemoteAddress() != null) {
- s1 = connection.getRemoteAddress().toString();
+ s1 = com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? connection.getRemoteAddress().toString() : "<ip address withheld>"; // Paper
} else {
s1 = "local";
}

View File

@@ -1,79 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: egg82 <eggys82@gmail.com>
Date: Sat, 11 Sep 2021 22:55:14 +0200
Subject: [PATCH] Add root/admin user detection
This patch detects whether or not the server is currently executing as a privileged user and spits out a warning.
The warning serves as a sort-of PSA for newer server admins who don't understand the risks of running as root.
We've seen plenty of bad/malicious plugins hit markets, and there's been a few close-calls with exploits in the past.
Hopefully this helps mitigate some potential damage to servers, even if it is just a warning.
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
diff --git a/src/main/java/io/papermc/paper/util/ServerEnvironment.java b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.util;
+
+import com.sun.security.auth.module.NTSystem;
+import com.sun.security.auth.module.UnixSystem;
+import org.apache.commons.lang.SystemUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+
+public class ServerEnvironment {
+ private static final boolean RUNNING_AS_ROOT_OR_ADMIN;
+ private static final String WINDOWS_HIGH_INTEGRITY_LEVEL = "S-1-16-12288";
+
+ static {
+ if (SystemUtils.IS_OS_WINDOWS) {
+ RUNNING_AS_ROOT_OR_ADMIN = Set.of(new NTSystem().getGroupIDs()).contains(WINDOWS_HIGH_INTEGRITY_LEVEL);
+ } else {
+ boolean isRunningAsRoot = false;
+ if (new UnixSystem().getUid() == 0) {
+ // Due to an OpenJDK bug (https://bugs.openjdk.java.net/browse/JDK-8274721), UnixSystem#getUid incorrectly
+ // returns 0 when the user doesn't have a username. Because of this, we'll have to double-check if the user ID is
+ // actually 0 by running the id -u command.
+ try {
+ Process process = new ProcessBuilder("id", "-u").start();
+ process.waitFor();
+ InputStream inputStream = process.getInputStream();
+ isRunningAsRoot = new String(inputStream.readAllBytes()).trim().equals("0");
+ } catch (InterruptedException | IOException ignored) {
+ isRunningAsRoot = false;
+ }
+ }
+ RUNNING_AS_ROOT_OR_ADMIN = isRunningAsRoot;
+ }
+ }
+
+ public static boolean userIsRootOrAdmin() {
+ return RUNNING_AS_ROOT_OR_ADMIN;
+ }
+}
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
DedicatedServer.LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
}
+ // Paper start - detect running as root
+ if (io.papermc.paper.util.ServerEnvironment.userIsRootOrAdmin()) {
+ DedicatedServer.LOGGER.warn("****************************");
+ DedicatedServer.LOGGER.warn("YOU ARE RUNNING THIS SERVER AS AN ADMINISTRATIVE OR ROOT USER. THIS IS NOT ADVISED.");
+ DedicatedServer.LOGGER.warn("YOU ARE OPENING YOURSELF UP TO POTENTIAL RISKS WHEN DOING THIS.");
+ DedicatedServer.LOGGER.warn("FOR MORE INFORMATION, SEE https://madelinemiller.dev/blog/root-minecraft-server/");
+ DedicatedServer.LOGGER.warn("****************************");
+ }
+ // Paper end
+
DedicatedServer.LOGGER.info("Loading properties");
DedicatedServerProperties dedicatedserverproperties = this.settings.getProperties();

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Mon, 21 Jun 2021 22:12:53 -0400
Subject: [PATCH] Always allow item changing in Fireball
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Fireball.java b/src/main/java/net/minecraft/world/entity/projectile/Fireball.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Fireball.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Fireball.java
@@ -0,0 +0,0 @@ public abstract class Fireball extends AbstractHurtingProjectile implements Item
}
public void setItem(ItemStack stack) {
- if (!stack.is(Items.FIRE_CHARGE) || stack.hasTag()) {
+ if (true || !stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { // Paper - always allow item changing
this.getEntityData().set(Fireball.DATA_ITEM_STACK, (ItemStack) Util.make(stack.copy(), (itemstack1) -> {
itemstack1.setCount(1);
}));

View File

@@ -1,133 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 31 Oct 2021 21:34:00 -0700
Subject: [PATCH] Async catch modifications to critical entity state
These used to be here from Spigot, but were dropped with 1.17.
Now in 1.17, this state is _even more_ critical than it was before,
so these must exist to catch stupid plugins.
diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
+++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
private boolean addEntityUuid(T entity) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity add by UUID"); // Paper
if (!this.knownUuids.add(entity.getUUID())) {
// Paper start
T conflict = this.visibleEntityStorage.getEntity(entity.getUUID());
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
private boolean addEntity(T entity, boolean existing) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity add"); // Paper
if (!this.addEntityUuid(entity)) {
return false;
} else {
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
void startTicking(T entity) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity start ticking"); // Paper
this.callbacks.onTickingStart(entity);
}
void stopTicking(T entity) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity stop ticking"); // Paper
this.callbacks.onTickingEnd(entity);
}
void startTracking(T entity) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity start tracking"); // Paper
this.visibleEntityStorage.add(entity);
this.callbacks.onTrackingStart(entity);
}
void stopTracking(T entity) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity stop tracking"); // Paper
this.callbacks.onTrackingEnd(entity);
this.visibleEntityStorage.remove(entity);
}
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
public void updateChunkStatus(ChunkPos chunkPos, Visibility trackingStatus) {
+ org.spigotmc.AsyncCatcher.catchOp("Update chunk status"); // Paper
long i = chunkPos.toLong();
if (trackingStatus == Visibility.HIDDEN) {
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
public void ensureChunkQueuedForLoad(long chunkPos) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk save"); // Paper
PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_b = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(chunkPos);
if (persistententitysectionmanager_b == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) {
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
private void requestChunkLoad(long chunkPos) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk load request"); // Paper
this.chunkLoadStatuses.put(chunkPos, PersistentEntitySectionManager.ChunkLoadStatus.PENDING);
ChunkPos chunkcoordintpair = new ChunkPos(chunkPos);
CompletableFuture completablefuture = this.permanentStorage.loadEntities(chunkcoordintpair);
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
private boolean processChunkUnload(long chunkPos) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk unload process"); // Paper
boolean flag = this.storeChunkSections(chunkPos, (entityaccess) -> {
entityaccess.getPassengersAndSelf().forEach(this::unloadEntity);
}, true); // CraftBukkit - add boolean for event call
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
private void processPendingLoads() {
+ org.spigotmc.AsyncCatcher.catchOp("Entity chunk process pending loads"); // Paper
ChunkEntities<T> chunkentities; // CraftBukkit - decompile error
while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) {
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
public void tick() {
+ org.spigotmc.AsyncCatcher.catchOp("Entity manager tick"); // Paper
this.processPendingLoads();
this.processUnloads();
}
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
public void autoSave() {
+ org.spigotmc.AsyncCatcher.catchOp("Entity manager autosave"); // Paper
this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error
boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN;
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
}
public void saveAll() {
+ org.spigotmc.AsyncCatcher.catchOp("Entity manager save"); // Paper
LongSet longset = this.getAllChunksToSave();
while (!longset.isEmpty()) {
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
long i = SectionPos.asLong(blockposition); final long newSectionPos = i; // Paper - diff on change, new position section
if (i != this.currentSectionKey) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity move"); // Paper
PersistentEntitySectionManager.this.entitySliceManager.moveEntity((Entity)this.entity); // Paper
Visibility visibility = this.currentSection.getStatus(); final Visibility oldVisibility = visibility; // Paper - diff on change - this should be OLD section visibility
// Paper start
@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
@Override
public void onRemove(Entity.RemovalReason reason) {
+ org.spigotmc.AsyncCatcher.catchOp("Entity remove"); // Paper
if (!this.currentSection.remove(this.entity)) {
PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason});
}

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: stonar96 <minecraft.stonar96@gmail.com>
Date: Sun, 12 Sep 2021 00:14:21 +0200
Subject: [PATCH] Check requirement before suggesting root nodes
Child nodes are handled by CommandDispatcher#parse checking
requirements.
Vanilla clients only send ServerboundCommandSuggestionPacket when
encountering a command node with ASK_SERVER suggestions, however a
modified client can send this packet whenever it wants.
diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java
+++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
@@ -0,0 +0,0 @@ public class CommandDispatcher<S> {
int i = 0;
for (final CommandNode<S> node : parent.getChildren()) {
CompletableFuture<Suggestions> future = Suggestions.empty();
+ // Paper start - Don't suggest if the requirement isn't met
+ if (parent != this.root || node.canUse(context.getSource())) {
try {
- if (node.canUse(parse.getContext().getSource())) future = node.listSuggestions(context.build(truncatedInput), new SuggestionsBuilder(truncatedInput, truncatedInputLowerCase, start)); // CraftBukkit
+ future = node.listSuggestions(context.build(truncatedInput), new SuggestionsBuilder(truncatedInput, truncatedInputLowerCase, start)); // CraftBukkit
} catch (final CommandSyntaxException ignored) {
}
+ }
+ // Paper end
futures[i++] = future;
}

View File

@@ -1,110 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Tue, 31 Aug 2021 17:05:27 +0200
Subject: [PATCH] Configurable feature seeds
Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com>
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -0,0 +0,0 @@ public class TimingsExport extends Thread {
JSONObject object = new JSONObject();
for (String key : config.getKeys(false)) {
String fullKey = (parentKey != null ? parentKey + "." + key : key);
- if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) {
+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld") || key.equals("feature-seeds")) {
continue;
}
final Object val = config.get(key);
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 {
return table;
}
+ public it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<net.minecraft.resources.ResourceLocation> featureSeeds = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
+ private void featureSeeds() {
+ featureSeeds.defaultReturnValue(-1);
+ final boolean randomise = getBoolean("feature-seeds.generate-random-seeds-for-all", false);
+ final ConfigurationSection defaultSection = config.getConfigurationSection("world-settings.default.feature-seeds");
+ final ConfigurationSection section = config.getConfigurationSection("world-settings." + worldName + ".feature-seeds");
+ final net.minecraft.core.Registry<net.minecraft.world.level.levelgen.feature.ConfiguredFeature<?, ?>> registry
+ = net.minecraft.server.MinecraftServer.getServer().registryAccess().registryOrThrow(net.minecraft.core.Registry.CONFIGURED_FEATURE_REGISTRY);
+ if (section != null) {
+ loadFeatureSeeds(section, registry);
+ }
+
+ // Also use default set seeds if not already set per world
+ loadFeatureSeeds(defaultSection, registry);
+
+ if (randomise) {
+ final Map<String, Object> randomisedSeeds = new HashMap<>();
+ final java.util.Random random = new java.security.SecureRandom();
+ for (final net.minecraft.resources.ResourceLocation resourceLocation : registry.keySet()) {
+ if (featureSeeds.containsKey(resourceLocation)) {
+ continue;
+ }
+
+ final long seed = random.nextLong();
+ randomisedSeeds.put("world-settings." + worldName + ".feature-seeds." + resourceLocation.getPath(), seed);
+ featureSeeds.put(resourceLocation, seed);
+ }
+ if (!randomisedSeeds.isEmpty()) {
+ config.addDefaults(randomisedSeeds);
+ }
+ }
+ }
+
+ private void loadFeatureSeeds(final ConfigurationSection section, final net.minecraft.core.Registry<net.minecraft.world.level.levelgen.feature.ConfiguredFeature<?, ?>> registry) {
+ for (final String key : section.getKeys(false)) {
+ if (!(section.get(key) instanceof Number)) {
+ continue;
+ }
+
+ final net.minecraft.resources.ResourceLocation location = new net.minecraft.resources.ResourceLocation(key);
+ if (!registry.containsKey(location)) {
+ logError("Invalid feature resource location: " + location);
+ continue;
+ }
+
+ featureSeeds.putIfAbsent(location, section.getLong(key));
+ }
+ }
+
public int getBehaviorTickRate(String typeName, String entityType, int def) {
return getIntOrDefault(behaviorTickRates, typeName, entityType, def);
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
int j = list.size();
try {
- Registry<PlacedFeature> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY);
+ Registry<PlacedFeature> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY); // Paper - diff on change
int k = Math.max(GenerationStep.Decoration.values().length, j);
for (int l = 0; l < k; ++l) {
@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
return (String) optional.orElseGet(placedfeature::toString);
};
- seededrandom.setFeatureSeed(i, l1, l);
+ // Paper start - change populationSeed used in random
+ long featurePopulationSeed = i;
+ final net.minecraft.resources.ResourceLocation location = iregistry1.getKey(placedfeature);
+ final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig.featureSeeds.getLong(location);
+ if (configFeatureSeed != -1) {
+ featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above
+ }
+ seededrandom.setFeatureSeed(featurePopulationSeed, l1, l);
+ // Paper end
try {
generatoraccessseed.setCurrentlyGenerating(supplier1);

View File

@@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 16 Oct 2021 01:36:00 -0700
Subject: [PATCH] Do not overload I/O threads with chunk data while flush
saving
If the chunk count is high, then the memory used by the
chunks adds up and could cause problems. By flushing
every so many chunks, the server will not become
stressed for memory. It will also not increase the total
time to save, as flush saving performs a full flush at
the end anyways.
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 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper end
protected void saveAllChunks(boolean flush) {
+ // Paper start - do not overload I/O threads with too much work when saving
+ int[] saved = new int[1];
+ int maxAsyncSaves = 50;
+ Runnable onChunkSave = () -> {
+ if (++saved[0] >= maxAsyncSaves) {
+ saved[0] = 0;
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.flush();
+ }
+ };
+ // Paper end - do not overload I/O threads with too much work when saving
if (flush) {
List<ChunkHolder> list = (List) this.updatingChunks.getVisibleValuesCopy().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper
MutableBoolean mutableboolean = new MutableBoolean();
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}).filter((ichunkaccess) -> {
return ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk;
}).filter(this::save).forEach((ichunkaccess) -> {
+ onChunkSave.run(); // Paper - do not overload I/O threads with too much work when saving
mutableboolean.setTrue();
});
} while (mutableboolean.isTrue());

View File

@@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Fri, 3 Sep 2021 15:50:25 +0100
Subject: [PATCH] Do not process entity loads in CraftChunk#getEntities
This re-introduces the issue behind #5872 but fixes #6543
The logic here is generally flawed however somewhat of a nuance,
upstream uses managedBlock which is basically needed to process
the posted entity adds, but, has the side-effect of processing any
chunk loads which has the naunce of stacking up and either causing a
massive performance hit, or can potentially lead the server to crash.
This issue is particularly noticable on paper due to the cumulative efforts
to drastically improve chunk loading speeds which means that there is much more
of a chance that we're about to eat a dirtload of chunk load callbacks, thus
making this issue much more of an issue
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk {
this.getWorld().getChunkAt(x, z); // Transient load for this tick
}
- PersistentEntitySectionManager<net.minecraft.world.entity.Entity> entityManager = this.getCraftWorld().getHandle().entityManager;
- long pair = ChunkPos.asLong(x, z);
-
- if (entityManager.areEntitiesLoaded(pair)) {
- return getCraftWorld().getHandle().getChunkEntities(this.x, this.z); // Paper - optimise this
- }
-
- entityManager.ensureChunkQueuedForLoad(pair); // Start entity loading
-
- // SPIGOT-6772: Use entity mailbox and re-schedule entities if they get unloaded
- ProcessorMailbox<Runnable> mailbox = ((EntityStorage) entityManager.permanentStorage).entityDeserializerQueue;
- BooleanSupplier supplier = () -> {
- // only execute inbox if our entities are not present
- if (entityManager.areEntitiesLoaded(pair)) {
- return true;
- }
-
- if (!entityManager.isPending(pair)) {
- // Our entities got unloaded, this should normally not happen.
- entityManager.ensureChunkQueuedForLoad(pair); // Re-start entity loading
- }
-
- // tick loading inbox, which loads the created entities to the world
- // (if present)
- entityManager.tick();
- // check if our entities are loaded
- return entityManager.areEntitiesLoaded(pair);
- };
-
- // now we wait until the entities are loaded,
- // the converting from NBT to entity object is done on the main Thread which is why we wait
- while (!supplier.getAsBoolean()) {
- if (mailbox.size() != 0) {
- mailbox.run();
- } else {
- Thread.yield();
- LockSupport.parkNanos("waiting for entity loading", 100000L);
- }
- }
-
return getCraftWorld().getHandle().getChunkEntities(this.x, this.z); // Paper - optimise this
}

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Tue, 14 Sep 2021 16:24:45 +0200
Subject: [PATCH] Don't log debug logging being disabled
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/SpigotConfig.java
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
@@ -0,0 +0,0 @@ public class SpigotConfig
Bukkit.getLogger().info( "Debug logging is enabled" );
} else
{
- Bukkit.getLogger().info( "Debug logging is disabled" );
+ // Bukkit.getLogger().info( "Debug logging is disabled" ); // Paper - Don't log if debug logging isn't enabled.
}
}

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: stonar96 <minecraft.stonar96@gmail.com>
Date: Sun, 12 Sep 2021 00:14:21 +0200
Subject: [PATCH] Don't respond to ServerboundCommandSuggestionPacket when
tab-complete is disabled
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 end
// CraftBukkit end
+ // Paper start - Don't suggest if tab-complete is disabled
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {
+ return;
+ }
+ // Paper end
StringReader stringreader = new StringReader(packet.getCommand());
if (stringreader.canRead() && stringreader.peek() == '/') {

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Tue, 28 Sep 2021 09:47:47 +0200
Subject: [PATCH] Ensure valid vehicle status
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 {
}
}
- if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) {
+ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper
// CraftBukkit end
CompoundTag nbttagcompound2 = new CompoundTag();
CompoundTag nbttagcompound3 = new CompoundTag();

View File

@@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Sun, 24 Oct 2021 15:49:35 +0200
Subject: [PATCH] Fix Bukkit NamespacedKey shenanigans
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java
@@ -0,0 +0,0 @@ public class PaperMinecartLootableInventory implements PaperLootableEntityInvent
@Override
public org.bukkit.loot.LootTable getLootTable() {
- return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null;
+ return entity.lootTable != null && !entity.lootTable.getPath().isEmpty() ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null;
}
@Override
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java
@@ -0,0 +0,0 @@ public class PaperTileEntityLootableInventory implements PaperLootableBlockInven
@Override
public org.bukkit.loot.LootTable getLootTable() {
- return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null;
+ return tileEntityLootable.lootTable != null && !tileEntityLootable.lootTable.getPath().isEmpty() ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null;
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
@@ -0,0 +0,0 @@ public final class CraftNamespacedKey {
return null;
}
ResourceLocation minecraft = ResourceLocation.tryParse(string);
- return (minecraft == null) ? null : CraftNamespacedKey.fromMinecraft(minecraft);
+ return (minecraft == null || minecraft.getPath().isEmpty()) ? null : CraftNamespacedKey.fromMinecraft(minecraft); // Paper - Bukkit's parser does not match Vanilla for empty paths
}
public static NamespacedKey fromString(String string) {

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Tue, 7 Sep 2021 21:29:38 +0100
Subject: [PATCH] Fix CocaoDecorator causing a crash when trying to generate
without logs
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
@@ -0,0 +0,0 @@ public class CocoaDecorator extends TreeDecorator {
@Override
public void place(LevelSimulatedReader world, BiConsumer<BlockPos, BlockState> replacer, Random random, List<BlockPos> logPositions, List<BlockPos> leavesPositions) {
+ if (logPositions.isEmpty()) return; // Paper
if (!(random.nextFloat() >= this.probability)) {
int i = logPositions.get(0).getY();
logPositions.stream().filter((pos) -> {

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Oct 2021 22:31:51 -0700
Subject: [PATCH] Fix CraftCriteria defaults map
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
@@ -0,0 +0,0 @@ final class CraftCriteria {
}
static CraftCriteria getFromNMS(Objective objective) {
- return CraftCriteria.DEFAULTS.get(objective.getCriteria().getName());
+ return java.util.Objects.requireNonNullElseGet(CraftCriteria.DEFAULTS.get(objective.getCriteria().getName()), () -> new CraftCriteria(objective.getCriteria())); // Paper
}
static CraftCriteria getFromBukkit(String name) {
@@ -0,0 +0,0 @@ final class CraftCriteria {
if (criteria != null) {
return criteria;
}
+ // Paper start - fix criteria defaults
+ var nmsCriteria = ObjectiveCriteria.byName(name);
+ if (nmsCriteria.isPresent()) {
+ return new CraftCriteria(nmsCriteria.get());
+ }
+ // Paper end
return new CraftCriteria(name);
}

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 2 Sep 2021 00:24:06 -0700
Subject: [PATCH] Fix merchant inventory not closing on entity removal
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 {
// Spigot end
// Spigot Start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
+ // Paper start
+ if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
+ merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
+ }
+ // Paper end
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) {
h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper
}

View File

@@ -1,71 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <git@lynxplay.dev>
Date: Sat, 6 Nov 2021 23:15:20 +0100
Subject: [PATCH] Fix setPatternColor on tropical fish bucket meta
Prior to this commit, the tropical fish bucket meta would set the body
color to the previous metas pattern colour when updating the pattern
colour.
This commit hence simply fixes this by using the proper body colour
value when updating the pattern color.
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
@@ -0,0 +0,0 @@ class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishB
if (this.variant == null) {
this.variant = 0;
}
- this.variant = CraftTropicalFish.getData(color, this.getPatternColor(), this.getPattern());
+ this.variant = CraftTropicalFish.getData(color, this.getBodyColor(), this.getPattern()); // Paper - properly set tropical fish pattern color without mutating body color
}
@Override
diff --git a/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java b/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.inventory;
+
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.TropicalFish;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.TropicalFishBucketMeta;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CraftMetaTropicalFishBucketTest extends AbstractTestingBase {
+
+ @Test
+ public void testAllCombinations() {
+ final var rawMeta = new ItemStack(Material.TROPICAL_FISH_BUCKET).getItemMeta();
+ Assert.assertTrue("Meta was not a tropical fish bucket", rawMeta instanceof TropicalFishBucketMeta);
+
+ final var meta = (TropicalFishBucketMeta) rawMeta;
+
+ for (final var bodyColor : DyeColor.values()) {
+ for (final var pattern : TropicalFish.Pattern.values()) {
+ for (final var patternColor : DyeColor.values()) {
+ meta.setBodyColor(bodyColor);
+ Assert.assertEquals("Body color did not match post body color!", bodyColor, meta.getBodyColor());
+
+ meta.setPattern(pattern);
+ Assert.assertEquals("Pattern did not match post pattern!", pattern, meta.getPattern());
+ Assert.assertEquals("Body color did not match post pattern!", bodyColor, meta.getBodyColor());
+
+ meta.setPatternColor(patternColor);
+ Assert.assertEquals("Pattern did not match post pattern color!", pattern, meta.getPattern());
+ Assert.assertEquals("Body color did not match post pattern color!", bodyColor, meta.getBodyColor());
+ Assert.assertEquals("Pattern color did not match post pattern color!", patternColor, meta.getPatternColor());
+ }
+ }
+ }
+ }
+
+}

View File

@@ -1,367 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 6 Oct 2021 20:50:48 -0700
Subject: [PATCH] Fix upstreams block state factories
Sometimes, blocks are changed and then logic is called before the associated
tile entity is removed. When this happens, the factories were relying on the
block at the position, not the tile entity. This change prioritizes using the
tile entity type to determine the block state factory and falls back on
the material type of the block at that location.
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -0,0 +0,0 @@ public abstract class BlockEntity {
// Paper end
if (this.level == null) return null;
org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
- if (block.getType() == org.bukkit.Material.AIR) return null;
+ // if (block.getType() == org.bukkit.Material.AIR) return null; // Paper - actually get the tile entity if it still exists
org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
if (state instanceof InventoryHolder) return (InventoryHolder) state;
return null;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
@@ -0,0 +0,0 @@ import org.bukkit.World;
import org.bukkit.block.TileState;
import org.bukkit.persistence.PersistentDataContainer;
-public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState {
+public abstract class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState { // Paper - revert upstream's revert of the block state changes
private final T tileEntity;
private final T snapshot;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
import net.minecraft.world.level.block.entity.BellBlockEntity;
import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.BlockEntityType; // Paper
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
@@ -0,0 +0,0 @@ public final class CraftBlockStates {
private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<CraftBlockState>(CraftBlockState.class) {
@Override
public CraftBlockState createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
- // SPIGOT-6754, SPIGOT-6817: Restore previous behaviour for tile entities with removed blocks (loot generation post-destroy)
- if (tileEntity != null) {
- // block with unhandled TileEntity:
- return new CraftBlockEntityState<>(world, tileEntity);
- }
+ // Paper - revert upstream's revert of the block state changes. Block entities that have already had the block type set to AIR are still valid, upstream decided to ignore them
Preconditions.checkState(tileEntity == null, "Unexpected BlockState for %s", CraftMagicNumbers.getMaterial(blockData.getBlock()));
return new CraftBlockState(world, blockPosition, blockData);
}
};
+ // Paper start
+ private static final Map<BlockEntityType<?>, BlockStateFactory<?>> FACTORIES_BY_BLOCK_ENTITY_TYPE = new HashMap<>();
+ private static void register(BlockEntityType<?> type, BlockStateFactory<?> factory) {
+ FACTORIES_BY_BLOCK_ENTITY_TYPE.put(type, factory);
+ }
+ // Paper end
static {
- register(
- Arrays.asList(
- Material.ACACIA_SIGN,
- Material.ACACIA_WALL_SIGN,
- Material.BIRCH_SIGN,
- Material.BIRCH_WALL_SIGN,
- Material.CRIMSON_SIGN,
- Material.CRIMSON_WALL_SIGN,
- Material.DARK_OAK_SIGN,
- Material.DARK_OAK_WALL_SIGN,
- Material.JUNGLE_SIGN,
- Material.JUNGLE_WALL_SIGN,
- Material.OAK_SIGN,
- Material.OAK_WALL_SIGN,
- Material.SPRUCE_SIGN,
- Material.SPRUCE_WALL_SIGN,
- Material.WARPED_SIGN,
- Material.WARPED_WALL_SIGN
- ), CraftSign.class, CraftSign::new, SignBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.CREEPER_HEAD,
- Material.CREEPER_WALL_HEAD,
- Material.DRAGON_HEAD,
- Material.DRAGON_WALL_HEAD,
- Material.PLAYER_HEAD,
- Material.PLAYER_WALL_HEAD,
- Material.SKELETON_SKULL,
- Material.SKELETON_WALL_SKULL,
- Material.WITHER_SKELETON_SKULL,
- Material.WITHER_SKELETON_WALL_SKULL,
- Material.ZOMBIE_HEAD,
- Material.ZOMBIE_WALL_HEAD
- ), CraftSkull.class, CraftSkull::new, SkullBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.COMMAND_BLOCK,
- Material.REPEATING_COMMAND_BLOCK,
- Material.CHAIN_COMMAND_BLOCK
- ), CraftCommandBlock.class, CraftCommandBlock::new, CommandBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.BLACK_BANNER,
- Material.BLACK_WALL_BANNER,
- Material.BLUE_BANNER,
- Material.BLUE_WALL_BANNER,
- Material.BROWN_BANNER,
- Material.BROWN_WALL_BANNER,
- Material.CYAN_BANNER,
- Material.CYAN_WALL_BANNER,
- Material.GRAY_BANNER,
- Material.GRAY_WALL_BANNER,
- Material.GREEN_BANNER,
- Material.GREEN_WALL_BANNER,
- Material.LIGHT_BLUE_BANNER,
- Material.LIGHT_BLUE_WALL_BANNER,
- Material.LIGHT_GRAY_BANNER,
- Material.LIGHT_GRAY_WALL_BANNER,
- Material.LIME_BANNER,
- Material.LIME_WALL_BANNER,
- Material.MAGENTA_BANNER,
- Material.MAGENTA_WALL_BANNER,
- Material.ORANGE_BANNER,
- Material.ORANGE_WALL_BANNER,
- Material.PINK_BANNER,
- Material.PINK_WALL_BANNER,
- Material.PURPLE_BANNER,
- Material.PURPLE_WALL_BANNER,
- Material.RED_BANNER,
- Material.RED_WALL_BANNER,
- Material.WHITE_BANNER,
- Material.WHITE_WALL_BANNER,
- Material.YELLOW_BANNER,
- Material.YELLOW_WALL_BANNER
- ), CraftBanner.class, CraftBanner::new, BannerBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.SHULKER_BOX,
- Material.WHITE_SHULKER_BOX,
- Material.ORANGE_SHULKER_BOX,
- Material.MAGENTA_SHULKER_BOX,
- Material.LIGHT_BLUE_SHULKER_BOX,
- Material.YELLOW_SHULKER_BOX,
- Material.LIME_SHULKER_BOX,
- Material.PINK_SHULKER_BOX,
- Material.GRAY_SHULKER_BOX,
- Material.LIGHT_GRAY_SHULKER_BOX,
- Material.CYAN_SHULKER_BOX,
- Material.PURPLE_SHULKER_BOX,
- Material.BLUE_SHULKER_BOX,
- Material.BROWN_SHULKER_BOX,
- Material.GREEN_SHULKER_BOX,
- Material.RED_SHULKER_BOX,
- Material.BLACK_SHULKER_BOX
- ), CraftShulkerBox.class, CraftShulkerBox::new, ShulkerBoxBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.BLACK_BED,
- Material.BLUE_BED,
- Material.BROWN_BED,
- Material.CYAN_BED,
- Material.GRAY_BED,
- Material.GREEN_BED,
- Material.LIGHT_BLUE_BED,
- Material.LIGHT_GRAY_BED,
- Material.LIME_BED,
- Material.MAGENTA_BED,
- Material.ORANGE_BED,
- Material.PINK_BED,
- Material.PURPLE_BED,
- Material.RED_BED,
- Material.WHITE_BED,
- Material.YELLOW_BED
- ), CraftBed.class, CraftBed::new, BedBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.BEEHIVE,
- Material.BEE_NEST
- ), CraftBeehive.class, CraftBeehive::new, BeehiveBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.CAMPFIRE,
- Material.SOUL_CAMPFIRE
- ), CraftCampfire.class, CraftCampfire::new, CampfireBlockEntity::new
- );
-
- register(
- Arrays.asList(
- Material.CHEST,
- Material.TRAPPED_CHEST
- ), CraftChest.class, CraftChest::new, ChestBlockEntity::new
- );
-
- register(Material.BARREL, CraftBarrel.class, CraftBarrel::new, BarrelBlockEntity::new);
- register(Material.BEACON, CraftBeacon.class, CraftBeacon::new, BeaconBlockEntity::new);
- register(Material.BELL, CraftBell.class, CraftBell::new, BellBlockEntity::new);
- register(Material.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new, BlastFurnaceBlockEntity::new);
- register(Material.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new, BrewingStandBlockEntity::new);
- register(Material.COMPARATOR, CraftComparator.class, CraftComparator::new, ComparatorBlockEntity::new);
- register(Material.CONDUIT, CraftConduit.class, CraftConduit::new, ConduitBlockEntity::new);
- register(Material.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new, DaylightDetectorBlockEntity::new);
- register(Material.DISPENSER, CraftDispenser.class, CraftDispenser::new, DispenserBlockEntity::new);
- register(Material.DROPPER, CraftDropper.class, CraftDropper::new, DropperBlockEntity::new);
- register(Material.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new, EnchantmentTableBlockEntity::new);
- register(Material.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new, EnderChestBlockEntity::new);
- register(Material.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new, TheEndGatewayBlockEntity::new);
- register(Material.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new, TheEndPortalBlockEntity::new);
- register(Material.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new, FurnaceBlockEntity::new);
- register(Material.HOPPER, CraftHopper.class, CraftHopper::new, HopperBlockEntity::new);
- register(Material.JIGSAW, CraftJigsaw.class, CraftJigsaw::new, JigsawBlockEntity::new);
- register(Material.JUKEBOX, CraftJukebox.class, CraftJukebox::new, JukeboxBlockEntity::new);
- register(Material.LECTERN, CraftLectern.class, CraftLectern::new, LecternBlockEntity::new);
- register(Material.MOVING_PISTON, CraftMovingPiston.class, CraftMovingPiston::new, PistonMovingBlockEntity::new);
- register(Material.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new, SculkSensorBlockEntity::new);
- register(Material.SMOKER, CraftSmoker.class, CraftSmoker::new, SmokerBlockEntity::new);
- register(Material.SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new, SpawnerBlockEntity::new);
- register(Material.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new, StructureBlockEntity::new);
+ // Paper start - simplify
+ register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
+ register(BlockEntityType.SKULL, CraftSkull.class, CraftSkull::new);
+ register(BlockEntityType.COMMAND_BLOCK, CraftCommandBlock.class, CraftCommandBlock::new);
+ register(BlockEntityType.BANNER, CraftBanner.class, CraftBanner::new);
+ register(BlockEntityType.SHULKER_BOX, CraftShulkerBox.class, CraftShulkerBox::new);
+ register(BlockEntityType.BED, CraftBed.class, CraftBed::new);
+ register(BlockEntityType.BEEHIVE, CraftBeehive.class, CraftBeehive::new);
+ register(BlockEntityType.CAMPFIRE, CraftCampfire.class, CraftCampfire::new);
+ register(BlockEntityType.CHEST, CraftChest.class, CraftChest::new); // Paper - split up chests due to different block entity types
+ register(BlockEntityType.TRAPPED_CHEST, CraftChest.class, CraftChest::new); // Paper - split up chests due to different block entity types
+ register(BlockEntityType.BARREL, CraftBarrel.class, CraftBarrel::new);
+ register(BlockEntityType.BEACON, CraftBeacon.class, CraftBeacon::new);
+ register(BlockEntityType.BELL, CraftBell.class, CraftBell::new);
+ register(BlockEntityType.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new);
+ register(BlockEntityType.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new);
+ register(BlockEntityType.COMPARATOR, CraftComparator.class, CraftComparator::new);
+ register(BlockEntityType.CONDUIT, CraftConduit.class, CraftConduit::new);
+ register(BlockEntityType.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new);
+ register(BlockEntityType.DISPENSER, CraftDispenser.class, CraftDispenser::new);
+ register(BlockEntityType.DROPPER, CraftDropper.class, CraftDropper::new);
+ register(BlockEntityType.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new);
+ register(BlockEntityType.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new);
+ register(BlockEntityType.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new);
+ register(BlockEntityType.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new);
+ register(BlockEntityType.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new);
+ register(BlockEntityType.HOPPER, CraftHopper.class, CraftHopper::new);
+ register(BlockEntityType.JIGSAW, CraftJigsaw.class, CraftJigsaw::new);
+ register(BlockEntityType.JUKEBOX, CraftJukebox.class, CraftJukebox::new);
+ register(BlockEntityType.LECTERN, CraftLectern.class, CraftLectern::new);
+ register(BlockEntityType.PISTON, CraftMovingPiston.class, CraftMovingPiston::new);
+ register(BlockEntityType.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new);
+ register(BlockEntityType.SMOKER, CraftSmoker.class, CraftSmoker::new);
+ register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
+ register(BlockEntityType.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new);
+ // Paper end
}
private static void register(Material blockType, BlockStateFactory<?> factory) {
@@ -0,0 +0,0 @@ public final class CraftBlockStates {
}
private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
- Material blockType,
+ net.minecraft.world.level.block.entity.BlockEntityType<? extends T> blockEntityType, // Paper
Class<B> blockStateType,
- BiFunction<World, T, B> blockStateConstructor,
- BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
+ BiFunction<World, T, B> blockStateConstructor // Paper
) {
- CraftBlockStates.register(Collections.singletonList(blockType), blockStateType, blockStateConstructor, tileEntityConstructor);
- }
-
- private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
- List<Material> blockTypes,
- Class<B> blockStateType,
- BiFunction<World, T, B> blockStateConstructor,
- BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
- ) {
- BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, tileEntityConstructor);
- for (Material blockType : blockTypes) {
- CraftBlockStates.register(blockType, factory);
+ // Paper start
+ BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, blockEntityType::create);
+ for (net.minecraft.world.level.block.Block block : blockEntityType.validBlocks) {
+ CraftBlockStates.register(CraftMagicNumbers.getMaterial(block), factory);
}
+ CraftBlockStates.register(blockEntityType, factory);
+ // Paper end
}
private static BlockStateFactory<?> getFactory(Material material) {
return CraftBlockStates.FACTORIES.getOrDefault(material, DEFAULT_FACTORY);
}
+ // Paper start
+ private static BlockStateFactory<?> getFactory(Material material, BlockEntityType<?> type) {
+ if (type != null) {
+ return CraftBlockStates.FACTORIES_BY_BLOCK_ENTITY_TYPE.getOrDefault(type, getFactory(material));
+ } else {
+ return getFactory(material);
+ }
+ }
+ // Paper end
+
public static Class<? extends CraftBlockState> getBlockStateType(Material material) {
Preconditions.checkNotNull(material, "material is null");
return CraftBlockStates.getFactory(material).blockStateType;
}
+ // Paper start
+ public static Class<? extends CraftBlockState> getBlockStateType(BlockEntityType<?> blockEntityType) {
+ Preconditions.checkNotNull(blockEntityType, "blockEntityType is null");
+ return CraftBlockStates.getFactory(null, blockEntityType).blockStateType;
+ }
+ // Paper end
+
public static BlockState getBlockState(Block block) {
// Paper start
return CraftBlockStates.getBlockState(block, true);
@@ -0,0 +0,0 @@ public final class CraftBlockStates {
if (world != null && tileEntity == null && CraftBlockStates.isTileEntityOptional(material)) {
factory = CraftBlockStates.DEFAULT_FACTORY;
} else {
- factory = CraftBlockStates.getFactory(material);
+ factory = CraftBlockStates.getFactory(material, tileEntity != null ? tileEntity.getType() : null); // Paper
}
return factory.createBlockState(world, blockPosition, blockData, tileEntity);
}
diff --git a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
@@ -0,0 +0,0 @@ public class BlockStateTest extends AbstractTestingBase {
}
}
}
+
+ @Test
+ public void testBlockEntityTypes() {
+ for (var blockEntityType : Registry.BLOCK_ENTITY_TYPE) {
+ org.junit.Assert.assertNotNull(CraftBlockStates.getBlockStateType(blockEntityType));
+ }
+ }
}

View File

@@ -1,72 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lexikiq <noellekiq@gmail.com>
Date: Mon, 21 Jun 2021 23:21:58 -0400
Subject: [PATCH] Preserve overstacked loot
Preserves overstacked items in loot tables, such as shulker box drops, to prevent the items
from being deleted (as they'd overflow past the bounds of the container)-- or worse, causing
chunk bans via the large amount of NBT created by unstacking the items.
Fixes GH-5140 and GH-4748.
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 {
allowPlayerCrammingDamage = getBoolean("allow-player-cramming-damage", allowPlayerCrammingDamage);
}
+ public boolean splitOverstackedLoot = true;
+ private void splitOverstackedLoot() {
+ splitOverstackedLoot = getBoolean("split-overstacked-loot", splitOverstackedLoot);
+ }
+
private com.google.common.collect.Table<String, String, Integer> sensorTickRates;
private com.google.common.collect.Table<String, String, Integer> behaviorTickRates;
private void tickRates() {
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
@@ -0,0 +0,0 @@ public class LootTable {
this.compositeFunction = LootItemFunctions.compose(functions);
}
+ @Deprecated // Paper - preserve overstacked items
public static Consumer<ItemStack> createStackSplitter(Consumer<ItemStack> lootConsumer) {
+ // Paper start - preserve overstacked items
+ return createStackSplitter(lootConsumer, null);
+ }
+
+ public static Consumer<ItemStack> createStackSplitter(Consumer<ItemStack> lootConsumer, @org.jetbrains.annotations.Nullable net.minecraft.server.level.ServerLevel world) {
+ boolean skipSplitter = world != null && !world.paperConfig.splitOverstackedLoot;
+ // Paper end
return (itemstack) -> {
- if (itemstack.getCount() < itemstack.getMaxStackSize()) {
+ if (skipSplitter || itemstack.getCount() < itemstack.getMaxStackSize()) { // Paper - preserve overstacked items
lootConsumer.accept(itemstack);
} else {
int i = itemstack.getCount();
@@ -0,0 +0,0 @@ public class LootTable {
}
public void getRandomItems(LootContext context, Consumer<ItemStack> lootConsumer) {
- this.getRandomItemsRaw(context, LootTable.createStackSplitter(lootConsumer));
+ this.getRandomItemsRaw(context, LootTable.createStackSplitter(lootConsumer, context.getLevel())); // Paper - preserve overstacked items
}
public List<ItemStack> getRandomItems(LootContext context) {
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java
+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java
@@ -0,0 +0,0 @@ public class SetContainerContents extends LootItemConditionalFunction {
NonNullList<ItemStack> nonNullList = NonNullList.create();
this.entries.forEach((entry) -> {
entry.expand(context, (choice) -> {
- choice.createItemStack(LootTable.createStackSplitter(nonNullList::add), context);
+ choice.createItemStack(LootTable.createStackSplitter(nonNullList::add, context.getLevel()), context); // Paper - preserve overstacked items
});
});
CompoundTag compoundTag = new CompoundTag();

View File

@@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Thu, 25 Nov 2021 10:25:09 +0100
Subject: [PATCH] Prevent excessive velocity through repeated crits
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 {
return this.hasEffect(MobEffects.JUMP) ? (double) (0.1F * (float) (this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D;
}
+ protected long lastJumpTime = 0L; // Paper
protected void jumpFromGround() {
double d0 = (double) this.getJumpPower() + this.getJumpBoostPower();
Vec3 vec3d = this.getDeltaMovement();
+ // Paper start
+ long time = System.nanoTime();
+ boolean canCrit = true;
+ if (this instanceof net.minecraft.world.entity.player.Player) {
+ canCrit = false;
+ if (time - this.lastJumpTime > (long)(0.250e9)) {
+ this.lastJumpTime = time;
+ canCrit = true;
+ }
+ }
+ // Paper end
this.setDeltaMovement(vec3d.x, d0, vec3d.z);
if (this.isSprinting()) {
float f = this.getYRot() * 0.017453292F;
+ if (canCrit) // Paper
this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F)));
}

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Mon, 30 Aug 2021 15:22:18 +0200
Subject: [PATCH] Prevent softlocked end exit portal generation
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -0,0 +0,0 @@ public class EndDragonFight {
}
}
+ // Paper start - Prevent "softlocked" exit portal generation
+ if (this.portalLocation.getY() <= this.level.getMinBuildHeight()) {
+ this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
+ }
+ // Paper end
endPodiumFeature.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation);
}

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 30 Aug 2021 04:26:40 -0700
Subject: [PATCH] Reduce worldgen thread worker count for low core count CPUs
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -0,0 +0,0 @@ public class Util {
private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority
// Paper start - use simpler thread pool that allows 1 thread
- int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1));
+ // Paper start - also try to avoid suffocating the system with the worldgen workers
+ int cpus = Runtime.getRuntime().availableProcessors() / 2;
+ int i;
+ if (cpus <= 4) {
+ i = cpus <= 2 ? 1 : 2;
+ } else if (cpus <= 8) {
+ // [5, 8]
+ i = Math.max(3, cpus - 2);
+ } else {
+ i = cpus * 2 / 3;
+ }
+ i = Math.min(8, i);
+ // Paper end - also try to avoid suffocating the system with the worldgen workers
i = Integer.getInteger("Paper.WorkerThreadCount", i);
ExecutorService executorService;

View File

@@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Fri, 26 Nov 2021 15:09:58 -0800
Subject: [PATCH] Remove client-side code using deprecated for removal
AccessController
Fixes warnings on build
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -0,0 +0,0 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.spi.FileSystemProvider;
-import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.time.Duration;
@@ -0,0 +0,0 @@ public class Util {
}
public void openUrl(URL url) {
- try {
- Process process = AccessController.doPrivileged((PrivilegedExceptionAction<Process>)(() -> {
- return Runtime.getRuntime().exec(this.getOpenUrlArguments(url));
- }));
-
- for(String string : IOUtils.readLines(process.getErrorStream())) {
- Util.LOGGER.error(string);
- }
-
- process.getInputStream().close();
- process.getErrorStream().close();
- process.getOutputStream().close();
- } catch (IOException | PrivilegedActionException var5) {
- Util.LOGGER.error("Couldn't open url '{}'", url, var5);
- }
+ throw new IllegalStateException("This method is not useful on dedicated servers."); // Paper
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Mon, 21 Jun 2021 21:55:23 -0400
Subject: [PATCH] Update head rotation in missing places
In certain areas the player's head rotation could be desynced when teleported/moved.
This is because bukkit uses a separate head rotation field for yaw.
This issue only applies to players.
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.setXRot(Mth.clamp(pitch, -90.0F, 90.0F) % 360.0F);
this.yRotO = this.getYRot();
this.xRotO = this.getXRot();
+ this.setYHeadRot(yaw); // Paper - Update head rotation
}
public void absMoveTo(double x, double y, double z) {
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.setXRot(pitch);
this.setOldPosAndRot();
this.reapplyPosition();
+ this.setYHeadRot(yaw); // Paper - Update head rotation
}
public final void setOldPosAndRot() {

View File

@@ -1,364 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Mon, 26 Jul 2021 02:15:17 -0400
Subject: [PATCH] Use Velocity compression and cipher natives
diff --git a/build.gradle.kts b/build.gradle.kts
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -0,0 +0,0 @@ dependencies {
runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.2")
implementation("net.fabricmc:mapping-io:0.3.0") // Paper - needed to read mappings for stacktrace deobfuscation
+ // Paper start - Use Velocity cipher
+ implementation("com.velocitypowered:velocity-native:1.1.0-SNAPSHOT") {
+ isTransitive = false
+ }
+ // Paper end
testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test
testImplementation("junit:junit:4.13.2")
diff --git a/src/main/java/net/minecraft/network/CipherDecoder.java b/src/main/java/net/minecraft/network/CipherDecoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/CipherDecoder.java
+++ b/src/main/java/net/minecraft/network/CipherDecoder.java
@@ -0,0 +0,0 @@ import java.util.List;
import javax.crypto.Cipher;
public class CipherDecoder extends MessageToMessageDecoder<ByteBuf> {
- private final CipherBase cipher;
+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper
- public CipherDecoder(Cipher cipher) {
- this.cipher = new CipherBase(cipher);
+ public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper
+ this.cipher = cipher; // Paper
}
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
- list.add(this.cipher.decipher(channelHandlerContext, byteBuf));
+ // Paper start
+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
+ try {
+ cipher.process(compatible);
+ list.add(compatible);
+ } catch (Exception e) {
+ compatible.release(); // compatible will never be used if we throw an exception
+ throw e;
+ }
+ // Paper end
}
+
+ // Paper start
+ @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ cipher.close();
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/network/CipherEncoder.java b/src/main/java/net/minecraft/network/CipherEncoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/CipherEncoder.java
+++ b/src/main/java/net/minecraft/network/CipherEncoder.java
@@ -0,0 +0,0 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import javax.crypto.Cipher;
+import java.util.List;
-public class CipherEncoder extends MessageToByteEncoder<ByteBuf> {
- private final CipherBase cipher;
+public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder<ByteBuf> { // Paper - change superclass
+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper
- public CipherEncoder(Cipher cipher) {
- this.cipher = new CipherBase(cipher);
+ public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper
+ this.cipher = cipher; // Paper
}
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception {
- this.cipher.encipher(byteBuf, byteBuf2);
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
+ // Paper start
+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
+ try {
+ cipher.process(compatible);
+ list.add(compatible);
+ } catch (Exception e) {
+ compatible.release(); // compatible will never be used if we throw an exception
+ throw e;
+ }
+ // Paper end
}
+
+ // Paper start
+ @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ cipher.close();
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/CompressionDecoder.java
+++ b/src/main/java/net/minecraft/network/CompressionDecoder.java
@@ -0,0 +0,0 @@ public class CompressionDecoder extends ByteToMessageDecoder {
public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152;
public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608;
private final Inflater inflater;
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper
private int threshold;
private boolean validateDecompressed;
+ // Paper start
public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) {
+ this(null, compressionThreshold, rejectsBadPackets);
+ }
+ public CompressionDecoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold, boolean rejectsBadPackets) {
this.threshold = compressionThreshold;
this.validateDecompressed = rejectsBadPackets;
- this.inflater = new Inflater();
+ this.inflater = compressor == null ? new Inflater() : null;
+ this.compressor = compressor;
+ // Paper end
}
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
@@ -0,0 +0,0 @@ public class CompressionDecoder extends ByteToMessageDecoder {
}
}
+ // Paper start
+ if (this.inflater != null) {
byte[] bs = new byte[friendlyByteBuf.readableBytes()];
friendlyByteBuf.readBytes(bs);
this.inflater.setInput(bs);
@@ -0,0 +0,0 @@ public class CompressionDecoder extends ByteToMessageDecoder {
this.inflater.inflate(cs);
list.add(Unpooled.wrappedBuffer(cs));
this.inflater.reset();
+ return;
+ }
+
+ int claimedUncompressedSize = i; // OBFHELPER
+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
+ ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelHandlerContext.alloc(), this.compressor, claimedUncompressedSize);
+ try {
+ this.compressor.inflate(compatibleIn, uncompressed, claimedUncompressedSize);
+ list.add(uncompressed);
+ byteBuf.clear();
+ } catch (Exception e) {
+ uncompressed.release();
+ throw e;
+ } finally {
+ compatibleIn.release();
+ }
+ // Paper end
}
}
}
+ // Paper start
+ @Override
+ public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
+ if (this.compressor != null) {
+ this.compressor.close();
+ }
+ }
+ // Paper end
+
public void setThreshold(int compressionThreshold, boolean rejectsBadPackets) {
this.threshold = compressionThreshold;
this.validateDecompressed = rejectsBadPackets;
diff --git a/src/main/java/net/minecraft/network/CompressionEncoder.java b/src/main/java/net/minecraft/network/CompressionEncoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/CompressionEncoder.java
+++ b/src/main/java/net/minecraft/network/CompressionEncoder.java
@@ -0,0 +0,0 @@ import io.netty.handler.codec.MessageToByteEncoder;
import java.util.zip.Deflater;
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
- private final byte[] encodeBuf = new byte[8192];
+ private final byte[] encodeBuf; // Paper
private final Deflater deflater;
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper
private int threshold;
+ // Paper start
public CompressionEncoder(int compressionThreshold) {
+ this(null, compressionThreshold);
+ }
+ public CompressionEncoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold) {
this.threshold = compressionThreshold;
- this.deflater = new Deflater();
+ if (compressor == null) {
+ this.encodeBuf = new byte[8192];
+ this.deflater = new Deflater();
+ } else {
+ this.encodeBuf = null;
+ this.deflater = null;
+ }
+ this.compressor = compressor;
+ // Paper end
}
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) {
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper
int i = byteBuf.readableBytes();
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf2);
if (i < this.threshold) {
friendlyByteBuf.writeVarInt(0);
friendlyByteBuf.writeBytes(byteBuf);
} else {
+ // Paper start
+ if (this.deflater != null) {
byte[] bs = new byte[i];
byteBuf.readBytes(bs);
friendlyByteBuf.writeVarInt(bs.length);
@@ -0,0 +0,0 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
}
this.deflater.reset();
+ return;
+ }
+
+ friendlyByteBuf.writeVarInt(i);
+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
+ try {
+ this.compressor.deflate(compatibleIn, byteBuf2);
+ } finally {
+ compatibleIn.release();
+ }
+ // Paper end
}
}
+ // Paper start
+ @Override
+ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{
+ if (this.compressor != null) {
+ // We allocate bytes to be compressed plus 1 byte. This covers two cases:
+ //
+ // - Compression
+ // According to https://github.com/ebiggers/libdeflate/blob/master/libdeflate.h#L103,
+ // if the data compresses well (and we do not have some pathological case) then the maximum
+ // size the compressed size will ever be is the input size minus one.
+ // - Uncompressed
+ // This is fairly obvious - we will then have one more than the uncompressed size.
+ int initialBufferSize = msg.readableBytes() + 1;
+ return com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), this.compressor, initialBufferSize);
+ }
+
+ return super.allocateBuffer(ctx, msg, preferDirect);
+ }
+
+ @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ if (this.compressor != null) {
+ this.compressor.close();
+ }
+ }
+ // Paper end
+
public int getThreshold() {
return this.threshold;
}
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return networkmanager;
}
- public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
- this.encrypted = true;
- this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
- this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
+ // Paper start
+// public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
+// this.encrypted = true;
+// this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
+// this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
+// }
+
+ public void setupEncryption(javax.crypto.SecretKey key) throws net.minecraft.util.CryptException {
+ if (!this.encrypted) {
+ try {
+ com.velocitypowered.natives.encryption.VelocityCipher decryption = com.velocitypowered.natives.util.Natives.cipher.get().forDecryption(key);
+ com.velocitypowered.natives.encryption.VelocityCipher encryption = com.velocitypowered.natives.util.Natives.cipher.get().forEncryption(key);
+
+ this.encrypted = true;
+ this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryption));
+ this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryption));
+ } catch (java.security.GeneralSecurityException e) {
+ throw new net.minecraft.util.CryptException(e);
+ }
+ }
}
+ // Paper end
public boolean isEncrypted() {
return this.encrypted;
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
if (compressionThreshold >= 0) {
+ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); // Paper
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets);
} else {
- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets));
+ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper
}
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold);
} else {
- this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold));
+ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper
}
} else {
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
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 {
ServerConnectionListener.LOGGER.info("Using default channel type");
}
+ // Paper start - indicate Velocity natives in use
+ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity.");
+ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
+ // Paper end
+
this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) {
try {
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
}
SecretKey secretkey = packet.getSecretKey(privatekey);
- Cipher cipher = Crypt.getCipher(2, secretkey);
- Cipher cipher1 = Crypt.getCipher(1, secretkey);
+ // Paper start
+// Cipher cipher = Crypt.getCipher(2, secretkey);
+// Cipher cipher1 = Crypt.getCipher(1, secretkey);
+ // Paper end
s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16);
this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING;
- this.connection.setEncryptionKey(cipher, cipher1);
+ this.connection.setupEncryption(secretkey); // Paper
} catch (CryptException cryptographyexception) {
throw new IllegalStateException("Protocol error", cryptographyexception);
}

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 10 Sep 2021 15:49:12 -0700
Subject: [PATCH] VanillaCommandWrapper didnt account for entity senders
diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
@@ -0,0 +0,0 @@ public final class VanillaCommandWrapper extends BukkitCommand {
}
public static CommandSourceStack getListener(CommandSender sender) {
- if (sender instanceof Player) {
- return ((CraftPlayer) sender).getHandle().createCommandSourceStack();
+ // Paper start - account for other entity command senders
+ if (sender instanceof org.bukkit.craftbukkit.entity.CraftEntity craftEntity) {
+ return craftEntity.getHandle().createCommandSourceStack();
+ // Paper end
}
if (sender instanceof BlockCommandSender) {
return ((CraftBlockCommandSender) sender).getWrapper();

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sulu5890 <sulu@sulu.me>
Date: Sun, 24 Oct 2021 22:48:14 -0500
Subject: [PATCH] don't attempt to teleport dead entities
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
// CraftBukkit start
public void postTick() {
// No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle
- if (!(this instanceof ServerPlayer)) {
+ if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities
this.handleNetherPortal();
}
}

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 11 Jul 2021 12:52:56 -0700
Subject: [PATCH] fix various menus with empty level accesses
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
@@ -0,0 +0,0 @@ public interface ContainerLevelAccess {
public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) {
return Optional.empty();
}
+ // Paper start
+ @Override
+ public org.bukkit.Location getLocation() {
+ return null;
+ }
+ // Paper end
};
static ContainerLevelAccess create(final Level world, final BlockPos pos) {

View File

@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 13 Sep 2021 18:55:45 -0700
Subject: [PATCH] prevent unintended light block manipulation
diff --git a/src/main/java/net/minecraft/world/level/block/LightBlock.java b/src/main/java/net/minecraft/world/level/block/LightBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/LightBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LightBlock.java
@@ -0,0 +0,0 @@ public class LightBlock extends Block implements SimpleWaterloggedBlock {
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (!world.isClientSide) {
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return InteractionResult.FAIL; } // Paper
world.setBlock(pos, state.cycle(LEVEL), 2);
return InteractionResult.SUCCESS;
} else {