More more more more more more more more more more patches

This commit is contained in:
Nassim Jahnke
2022-06-08 15:12:28 +02:00
parent bf30d497ba
commit 7c319bce76
35 changed files with 72 additions and 2494 deletions

View File

@ -1,179 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Tue, 1 Feb 2022 15:51:55 -0700
Subject: [PATCH] API for creating command sender which forwards feedback
diff --git a/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.commands;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import java.util.UUID;
+import java.util.function.Consumer;
+import net.kyori.adventure.audience.MessageType;
+import net.kyori.adventure.identity.Identity;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import net.minecraft.commands.CommandSource;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.phys.Vec2;
+import net.minecraft.world.phys.Vec3;
+import org.bukkit.command.CommandSender;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.command.ServerCommandSender;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public final class FeedbackForwardingSender extends ServerCommandSender {
+ private final Consumer<? super Component> feedback;
+ private final CraftServer server;
+
+ public FeedbackForwardingSender(final Consumer<? super Component> feedback, final CraftServer server) {
+ super(((ServerCommandSender) server.getConsoleSender()).perm);
+ this.server = server;
+ this.feedback = feedback;
+ }
+
+ @Override
+ public void sendMessage(final String message) {
+ this.sendMessage(LegacyComponentSerializer.legacySection().deserialize(message));
+ }
+
+ @Override
+ public void sendMessage(final String... messages) {
+ for (final String message : messages) {
+ this.sendMessage(message);
+ }
+ }
+
+ @Override
+ public void sendMessage(final Identity identity, final Component message, final MessageType type) {
+ this.feedback.accept(message);
+ }
+
+ @Override
+ public String getName() {
+ return "FeedbackForwardingSender";
+ }
+
+ @Override
+ public Component name() {
+ return Component.text(this.getName());
+ }
+
+ @Override
+ public boolean isOp() {
+ return true;
+ }
+
+ @Override
+ public void setOp(final boolean value) {
+ throw new UnsupportedOperationException("Cannot change operator status of " + this.getClass().getName());
+ }
+
+ public CommandSourceStack asVanilla() {
+ final @Nullable ServerLevel overworld = this.server.getServer().overworld();
+ return new CommandSourceStack(
+ new Source(this),
+ overworld == null ? Vec3.ZERO : Vec3.atLowerCornerOf(overworld.getSharedSpawnPos()),
+ Vec2.ZERO,
+ overworld,
+ 4,
+ this.getName(),
+ new TextComponent(this.getName()),
+ this.server.getServer(),
+ null
+ );
+ }
+
+ private record Source(FeedbackForwardingSender sender) implements CommandSource {
+ @Override
+ public void sendMessage(final net.minecraft.network.chat.Component message, final UUID sender) {
+ this.sender.sendMessage(Identity.identity(sender), PaperAdventure.asAdventure(message));
+ }
+
+ @Override
+ public boolean acceptsSuccess() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsFailure() {
+ return true;
+ }
+
+ @Override
+ public boolean shouldInformAdmins() {
+ return false;
+ }
+
+ @Override
+ public CommandSender getBukkitSender(final CommandSourceStack stack) {
+ return this.sender;
+ }
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return console.console;
}
+ // Paper start
+ @Override
+ public CommandSender createCommandSender(final java.util.function.Consumer<? super net.kyori.adventure.text.Component> feedback) {
+ return new io.papermc.paper.commands.FeedbackForwardingSender(feedback, this);
+ }
+ // Paper end
+
public EntityMetadataStore getEntityMetadata() {
return this.entityMetadata;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java
@@ -0,0 +0,0 @@ import org.bukkit.plugin.Plugin;
public abstract class ServerCommandSender implements CommandSender {
private static PermissibleBase blockPermInst;
- private final PermissibleBase perm;
+ public final PermissibleBase perm; // Paper
private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
+ // Paper start
+ public ServerCommandSender(final PermissibleBase permissibleBase) {
+ this.perm = permissibleBase;
+ }
+ // Paper end
+
public ServerCommandSender() {
if (this instanceof CraftBlockCommandSender) {
if (ServerCommandSender.blockPermInst == null) {
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 {
if (sender instanceof ProxiedCommandSender) {
return ((ProxiedNativeCommandSender) sender).getHandle();
}
+ // Paper start
+ if (sender instanceof io.papermc.paper.commands.FeedbackForwardingSender feedback) {
+ return feedback.asVanilla();
+ }
+ // Paper end
throw new IllegalArgumentException("Cannot make " + sender + " a vanilla command listener");
}

View File

@ -1,88 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 3 Jan 2021 20:03:35 -0800
Subject: [PATCH] Add GameEvent tags
diff --git a/src/main/java/io/papermc/paper/CraftGameEventTag.java b/src/main/java/io/papermc/paper/CraftGameEventTag.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/CraftGameEventTag.java
@@ -0,0 +0,0 @@
+package io.papermc.paper;
+
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.tags.TagKey;
+import org.bukkit.GameEvent;
+import org.bukkit.craftbukkit.tag.CraftTag;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class CraftGameEventTag extends CraftTag<net.minecraft.world.level.gameevent.GameEvent, GameEvent> {
+
+ public CraftGameEventTag(net.minecraft.core.Registry<net.minecraft.world.level.gameevent.GameEvent> registry, TagKey<net.minecraft.world.level.gameevent.GameEvent> tag) {
+ super(registry, tag);
+ }
+
+ private static final Map<GameEvent, ResourceKey<net.minecraft.world.level.gameevent.GameEvent>> KEY_CACHE = Collections.synchronizedMap(new IdentityHashMap<>());
+ @Override
+ public boolean isTagged(@NotNull GameEvent gameEvent) {
+ return registry.getHolderOrThrow(KEY_CACHE.computeIfAbsent(gameEvent, event -> ResourceKey.create(Registry.GAME_EVENT_REGISTRY, CraftNamespacedKey.toMinecraft(event.getKey())))).is(tag);
+ }
+
+ @Override
+ public @NotNull Set<GameEvent> getValues() {
+ return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(nms.value()))), nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
+import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner;
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return (org.bukkit.Tag<T>) new CraftEntityTag(Registry.ENTITY_TYPE, entityTagKey);
}
}
+ // Paper start
+ case org.bukkit.Tag.REGISTRY_GAME_EVENTS -> {
+ Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class, "Game Event namespace must have GameEvent type");
+ TagKey<GameEvent> gameEventTagKey = TagKey.create(Registry.GAME_EVENT_REGISTRY, key);
+ if (Registry.GAME_EVENT.isKnownTagName(gameEventTagKey)) {
+ return (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(Registry.GAME_EVENT, gameEventTagKey);
+ }
+ }
+ // Paper end
default -> throw new IllegalArgumentException();
}
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
Registry<EntityType<?>> entityTags = Registry.ENTITY_TYPE;
return entityTags.getTags().map(pair -> (org.bukkit.Tag<T>) new CraftEntityTag(entityTags, pair.getFirst())).collect(ImmutableList.toImmutableList());
}
+ // Paper start
+ case org.bukkit.Tag.REGISTRY_GAME_EVENTS -> {
+ Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class);
+ Registry<GameEvent> gameEvents = Registry.GAME_EVENT;
+ return gameEvents.getTags().map(pair -> (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(gameEvents, pair.getFirst())).collect(ImmutableList.toImmutableList());
+ // Paper end
+ }
default -> throw new IllegalArgumentException();
}
}

View File

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 13 Jan 2022 23:05:53 -0800
Subject: [PATCH] Add config for stronghold seed
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 k = concentricringsstructureplacement.spread();
Random random = new Random();
+ // Paper start
+ if (this.conf.strongholdSeed != null && this.structureSets.getResourceKey(holder).orElse(null) == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS) {
+ random.setSeed(this.conf.strongholdSeed);
+ } else {
+ // Paper end
random.setSeed(this.ringPlacementSeed);
+ } // Paper
double d0 = random.nextDouble() * 3.141592653589793D * 2.0D;
int l = 0;
int i1 = 0;
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
@@ -0,0 +0,0 @@ public class SpigotWorldConfig
public int mansionSeed;
public int fossilSeed;
public int portalSeed;
+ public Long strongholdSeed; // Paper
private void initWorldGenSeeds()
{
this.villageSeed = this.getInt( "seed-village", 10387312 );
@@ -0,0 +0,0 @@ public class SpigotWorldConfig
this.mansionSeed = this.getInt( "seed-mansion", 10387319 );
this.fossilSeed = this.getInt( "seed-fossil", 14357921 );
this.portalSeed = this.getInt( "seed-portal", 34222645 );
+ // Paper start
+ final String strongholdSeedString = this.getString("seed-stronghold", "default");
+ this.strongholdSeed = org.apache.commons.lang3.math.NumberUtils.isParsable(strongholdSeedString) ? Long.parseLong(strongholdSeedString) : null;
+ // Paper end
this.log( "Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed
+ " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed );
}

View File

@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Doc <nachito94@msn.com>
Date: Mon, 2 Aug 2021 11:24:39 -0400
Subject: [PATCH] Add configurable height for slime spawn
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 {
allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false);
}
+ public double slimeMaxSpawnHeightInSwamp = 70;
+ public double slimeMinSpawnHeightInSwamp = 50;
+ public double slimeMaxSpawnHeightInSlimeChunks = 40;
+ private void slimeSpawnHeight() {
+ slimeMaxSpawnHeightInSwamp = getDouble("slime-spawn-height.swamp-biome.maximum", this.slimeMaxSpawnHeightInSwamp);
+ slimeMinSpawnHeightInSwamp = getDouble("slime-spawn-height.swamp-biome.minimum", this.slimeMinSpawnHeightInSwamp);
+ slimeMaxSpawnHeightInSlimeChunks = getDouble("slime-spawn-height.slime-chunk.maximum", this.slimeMaxSpawnHeightInSlimeChunks);
+ }
+
+
public int portalSearchRadius;
public int portalCreateRadius;
public boolean portalSearchVanillaDimensionScaling;
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy {
public static boolean checkSlimeSpawnRules(EntityType<Slime> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) {
if (world.getDifficulty() != Difficulty.PEACEFUL) {
- if (world.getBiome(pos).is(Biomes.SWAMP) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
+ // Paper start - Replace rules for Height in Swamp Biome
+ final double maxHeightSwamp = world.getMinecraftWorld().paperConfig.slimeMaxSpawnHeightInSwamp;
+ final double minHeightSwamp = world.getMinecraftWorld().paperConfig.slimeMinSpawnHeightInSwamp;
+ if (world.getBiome(pos).is(Biomes.SWAMP) && pos.getY() > minHeightSwamp && pos.getY() < maxHeightSwamp && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
+ // Paper end
return checkMobSpawnRules(type, world, spawnReason, pos, random);
}
@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy {
ChunkPos chunkcoordintpair = new ChunkPos(pos);
boolean flag = world.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
- if (random.nextInt(10) == 0 && flag && pos.getY() < 40) {
+ // Paper start - Replace rules for Height in Slime Chunks
+ final double maxHeightSlimeChunk = world.getMinecraftWorld().paperConfig.slimeMaxSpawnHeightInSlimeChunks;
+ if (random.nextInt(10) == 0 && flag && pos.getY() < maxHeightSlimeChunk) {
+ // Paper end
return checkMobSpawnRules(type, world, spawnReason, pos, random);
}
}

View File

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Sat, 12 Feb 2022 12:40:50 -0700
Subject: [PATCH] Add missing Validate calls to CraftServer#getSpawnLimit
Copies appropriate checks from CraftWorld#getSpawnLimit
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
@Override
public int getSpawnLimit(SpawnCategory spawnCategory) {
// Paper start
+ Validate.notNull(spawnCategory, "SpawnCategory cannot be null");
+ Validate.isTrue(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory." + spawnCategory + " does not have a spawn limit.");
return this.getSpawnLimitUnsafe(spawnCategory);
}
public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {

View File

@ -1,155 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 16 Oct 2021 22:57:31 -0700
Subject: [PATCH] Add missing block data mins and maxes
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftLeaves.java b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftLeaves.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftLeaves.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftLeaves.java
@@ -0,0 +0,0 @@ package org.bukkit.craftbukkit.block.data.type;
import org.bukkit.block.data.type.Leaves;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
-public class CraftLeaves extends CraftBlockData implements Leaves {
+public abstract class CraftLeaves extends CraftBlockData implements Leaves { // Paper - make abstract (not used anyways)
private static final net.minecraft.world.level.block.state.properties.IntegerProperty DISTANCE = getInteger("distance");
private static final net.minecraft.world.level.block.state.properties.BooleanProperty PERSISTENT = getBoolean("persistent");
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCandle.java
@@ -0,0 +0,0 @@ public final class CraftCandle extends org.bukkit.craftbukkit.block.data.CraftBl
public int getMaximumCandles() {
return getMax(CraftCandle.CANDLES);
}
+ // Paper start
+ @Override
+ public int getMinimumCandles() {
+ return getMin(CraftCandle.CANDLES);
+ }
+ // Paper end
// org.bukkit.craftbukkit.block.data.CraftLightable
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCauldron.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCauldron.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCauldron.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCauldron.java
@@ -0,0 +0,0 @@ public final class CraftCauldron extends org.bukkit.craftbukkit.block.data.Craft
public int getMaximumLevel() {
return getMax(CraftCauldron.LEVEL);
}
+
+ // Paper start
+ @Override
+ public int getMinimumLevel() {
+ return getMin(CraftCauldron.LEVEL);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftComposter.java
@@ -0,0 +0,0 @@ public final class CraftComposter extends org.bukkit.craftbukkit.block.data.Craf
public int getMaximumLevel() {
return getMax(CraftComposter.LEVEL);
}
+
+ // Paper start
+ @Override
+ public int getMinimumLevel() {
+ return getMin(CraftComposter.LEVEL);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftFluids.java
@@ -0,0 +0,0 @@ public final class CraftFluids extends org.bukkit.craftbukkit.block.data.CraftBl
public int getMaximumLevel() {
return getMax(CraftFluids.LEVEL);
}
+
+ // Paper start
+ @Override
+ public int getMinimumLevel() {
+ return getMin(CraftFluids.LEVEL);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLayeredCauldron.java
@@ -0,0 +0,0 @@ public final class CraftLayeredCauldron extends org.bukkit.craftbukkit.block.dat
public int getMaximumLevel() {
return getMax(CraftLayeredCauldron.LEVEL);
}
+
+ // Paper start
+ @Override
+ public int getMinimumLevel() {
+ return getMin(CraftLayeredCauldron.LEVEL);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLeaves.java
@@ -0,0 +0,0 @@ public final class CraftLeaves extends org.bukkit.craftbukkit.block.data.CraftBl
public void setDistance(int distance) {
set(CraftLeaves.DISTANCE, distance);
}
+
+ // Paper start
+ @Override
+ public int getMaximumDistance() {
+ return getMax(CraftLeaves.DISTANCE);
+ }
+
+ @Override
+ public int getMinimumDistance() {
+ return getMin(CraftLeaves.DISTANCE);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftLight.java
@@ -0,0 +0,0 @@ public final class CraftLight extends org.bukkit.craftbukkit.block.data.CraftBlo
return getMax(CraftLight.LEVEL);
}
+ // Paper start
+ @Override
+ public int getMinimumLevel() {
+ return getMin(CraftLight.LEVEL);
+ }
+ // Paper end
+
// org.bukkit.craftbukkit.block.data.CraftWaterlogged
private static final net.minecraft.world.level.block.state.properties.BooleanProperty WATERLOGGED = getBoolean(net.minecraft.world.level.block.LightBlock.class, "waterlogged");
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPowderSnowCauldron.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPowderSnowCauldron.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPowderSnowCauldron.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftPowderSnowCauldron.java
@@ -0,0 +0,0 @@ public final class CraftPowderSnowCauldron extends org.bukkit.craftbukkit.block.
public int getMaximumLevel() {
return getMax(CraftPowderSnowCauldron.LEVEL);
}
+
+ // Paper start
+ @Override
+ public int getMinimumLevel() {
+ return getMin(CraftPowderSnowCauldron.LEVEL);
+ }
+ // Paper end
}

View File

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: u9g <winworkswow@gmail.com>
Date: Mon, 3 Jan 2022 23:32:42 -0500
Subject: [PATCH] Add new overload to PersistentDataContainer#has
Adds the new overload: PersistentDataContainer#has(NamespacedKey key)
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
@@ -0,0 +0,0 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
public void clear() {
this.customDataTags.clear();
}
+
+ @Override
+ public boolean has(NamespacedKey key) {
+ Validate.notNull(key, "The provided key for the custom value was null");
+
+ return this.customDataTags.containsKey(key.toString());
+ }
// Paper end
}

View File

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MCMDEV <john-m.1@gmx.de>
Date: Fri, 24 Sep 2021 17:59:21 +0200
Subject: [PATCH] Added getHostname to AsyncPlayerPreLoginEvent
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
// Paper start
com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); // Paper - add rawAddress
+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile, ServerLoginPacketListenerImpl.this.hostname); // Paper - add rawAddress & hostname
server.getPluginManager().callEvent(asyncEvent);
profile = asyncEvent.getPlayerProfile();
profile.complete(true); // Paper - setPlayerProfileAPI

View File

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 19 Aug 2021 18:45:42 -0700
Subject: [PATCH] Configurable sculk sensor listener range
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
@@ -0,0 +0,0 @@ public class SculkSensorBlockEntity extends BlockEntity implements VibrationList
public void load(CompoundTag nbt) {
super.load(nbt);
this.lastVibrationFrequency = nbt.getInt("last_vibration_frequency");
+ if (nbt.contains(PAPER_LISTENER_RANGE_NBT_KEY)) this.listener.listenerRange = nbt.getInt(PAPER_LISTENER_RANGE_NBT_KEY); // Paper
}
+ private static final String PAPER_LISTENER_RANGE_NBT_KEY = "Paper.ListenerRange"; // Paper
@Override
protected void saveAdditional(CompoundTag nbt) {
super.saveAdditional(nbt);
nbt.putInt("last_vibration_frequency", this.lastVibrationFrequency);
+ if (this.listener.listenerRange != ((SculkSensorBlock) net.minecraft.world.level.block.Blocks.SCULK_SENSOR).getListenerRange()) nbt.putInt(PAPER_LISTENER_RANGE_NBT_KEY, this.listener.listenerRange); // Paper - only save if it's different from the default
}
public VibrationListener getListener() {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkSensor.java
@@ -0,0 +0,0 @@ public class CraftSculkSensor extends CraftBlockEntityState<SculkSensorBlockEnti
Preconditions.checkArgument(0 <= lastVibrationFrequency && lastVibrationFrequency <= 15, "Vibration frequency must be between 0-15");
getSnapshot().lastVibrationFrequency = lastVibrationFrequency;
}
+ // Paper start
+ @Override
+ public int getListenerRange() {
+ return this.getSnapshot().getListener().listenerRange;
+ }
+
+ @Override
+ public void setListenerRange(int range) {
+ Preconditions.checkArgument(range > 0, "Vibration listener range must be greater than 0");
+ this.getSnapshot().getListener().listenerRange = range;
+ }
+ // Paper end
}

View File

@ -1,239 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 7 Oct 2021 14:34:55 -0700
Subject: [PATCH] Custom Potion Mixes
diff --git a/src/main/java/io/papermc/paper/potion/PaperPotionMix.java b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.potion;
+
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.crafting.Ingredient;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.inventory.CraftRecipe;
+
+public record PaperPotionMix(ItemStack result, Ingredient input, Ingredient ingredient) {
+
+ public PaperPotionMix(PotionMix potionMix) {
+ this(CraftItemStack.asNMSCopy(potionMix.getResult()), CraftRecipe.toIngredient(potionMix.getInput(), true), CraftRecipe.toIngredient(potionMix.getIngredient(), true));
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
this.resources.managers.updateRegistryTags(this.registryAccess());
io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
+ net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
if (Thread.currentThread() != this.serverThread) return; // Paper
//this.getPlayerList().saveAll(); // Paper - we don't need to do this
diff --git a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
@@ -0,0 +0,0 @@ public class BrewingStandMenu extends AbstractContainerMenu {
}
public static boolean mayPlaceItem(ItemStack stack) {
- return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE);
+ return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || PotionBrewing.isCustomInput(stack); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java b/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
@@ -0,0 +0,0 @@ public class PotionBrewing {
public static final int BREWING_TIME_SECONDS = 20;
private static final List<PotionBrewing.Mix<Potion>> POTION_MIXES = Lists.newArrayList();
private static final List<PotionBrewing.Mix<Item>> CONTAINER_MIXES = Lists.newArrayList();
+ private static final it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<org.bukkit.NamespacedKey, io.papermc.paper.potion.PaperPotionMix> CUSTOM_MIXES = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Paper
private static final List<Ingredient> ALLOWED_CONTAINERS = Lists.newArrayList();
private static final Predicate<ItemStack> ALLOWED_CONTAINER = (stack) -> {
for(Ingredient ingredient : ALLOWED_CONTAINERS) {
@@ -0,0 +0,0 @@ public class PotionBrewing {
};
public static boolean isIngredient(ItemStack stack) {
- return isContainerIngredient(stack) || isPotionIngredient(stack);
+ return isContainerIngredient(stack) || isPotionIngredient(stack) || isCustomIngredient(stack); // Paper
}
protected static boolean isContainerIngredient(ItemStack stack) {
@@ -0,0 +0,0 @@ public class PotionBrewing {
}
public static boolean hasMix(ItemStack input, ItemStack ingredient) {
+ // Paper start
+ if (hasCustomMix(input, ingredient)) {
+ return true;
+ }
+ // Paper end
if (!ALLOWED_CONTAINER.test(input)) {
return false;
} else {
@@ -0,0 +0,0 @@ public class PotionBrewing {
public static ItemStack mix(ItemStack ingredient, ItemStack input) {
if (!input.isEmpty()) {
+ // Paper start
+ for (var mix : CUSTOM_MIXES.values()) {
+ if (mix.input().test(input) && mix.ingredient().test(ingredient)) {
+ return mix.result().copy();
+ }
+ }
+ // Paper end
Potion potion = PotionUtils.getPotion(input);
Item item = input.getItem();
int i = 0;
@@ -0,0 +0,0 @@ public class PotionBrewing {
return input;
}
+ // Paper start
+ public static boolean isCustomIngredient(ItemStack stack) {
+ for (var mix : CUSTOM_MIXES.values()) {
+ if (mix.ingredient().test(stack)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isCustomInput(ItemStack stack) {
+ for (var mix : CUSTOM_MIXES.values()) {
+ if (mix.input().test(stack)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasCustomMix(ItemStack input, ItemStack ingredient) {
+ for (var mix : CUSTOM_MIXES.values()) {
+ if (mix.input().test(input) && mix.ingredient().test(ingredient)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void addPotionMix(io.papermc.paper.potion.PotionMix mix) {
+ if (CUSTOM_MIXES.containsKey(mix.getKey())) {
+ throw new IllegalArgumentException("Duplicate recipe ignored with ID " + mix.getKey());
+ }
+ CUSTOM_MIXES.putAndMoveToFirst(mix.getKey(), new io.papermc.paper.potion.PaperPotionMix(mix));
+ }
+
+ public static boolean removePotionMix(org.bukkit.NamespacedKey key) {
+ return CUSTOM_MIXES.remove(key) != null;
+ }
+
+ public static void reload() {
+ POTION_MIXES.clear();
+ CONTAINER_MIXES.clear();
+ ALLOWED_CONTAINERS.clear();
+ CUSTOM_MIXES.clear();
+ bootStrap();
+ }
+ // Paper end
+
public static void bootStrap() {
addContainer(Items.POTION);
addContainer(Items.SPLASH_POTION);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
@Override
public boolean canPlaceItem(int slot, ItemStack stack) {
- return slot == 3 ? PotionBrewing.isIngredient(stack) : (slot == 4 ? stack.is(Items.BLAZE_POWDER) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) && this.getItem(slot).isEmpty());
+ return slot == 3 ? PotionBrewing.isIngredient(stack) : (slot == 4 ? stack.is(Items.BLAZE_POWDER) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || PotionBrewing.isCustomInput(stack)) && this.getItem(slot).isEmpty()); // Paper
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper
public static Exception excessiveVelEx; // Paper - Velocity warnings
private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); // Paper
+ private final CraftPotionBrewer potionBrewer = new CraftPotionBrewer(); // Paper
static {
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
Enchantments.SHARPNESS.getClass();
org.bukkit.enchantments.Enchantment.stopAcceptingRegistrations();
- Potion.setPotionBrewer(new CraftPotionBrewer());
+ Potion.setPotionBrewer(potionBrewer); // Paper
MobEffects.BLINDNESS.getClass();
PotionEffectType.stopAcceptingRegistrations();
// Ugly hack :(
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return datapackManager;
}
+ @Override
+ public CraftPotionBrewer getPotionBrewer() {
+ return this.potionBrewer;
+ }
+
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
@@ -0,0 +0,0 @@ public interface CraftRecipe extends Recipe {
void addToCraftingManager();
default Ingredient toNMS(RecipeChoice bukkit, boolean requireNotEmpty) {
+ // Paper start
+ return toIngredient(bukkit, requireNotEmpty);
+ }
+ static Ingredient toIngredient(RecipeChoice bukkit, boolean requireNotEmpty) {
+ // Paper end
Ingredient stack;
if (bukkit == null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
@@ -0,0 +0,0 @@ public class CraftPotionBrewer implements PotionBrewer {
public PotionEffect createEffect(PotionEffectType potion, int duration, int amplifier) {
return new PotionEffect(potion, potion.isInstant() ? 1 : (int) (duration * potion.getDurationModifier()), amplifier);
}
+
+ // Paper start
+ @Override
+ public void addPotionMix(io.papermc.paper.potion.PotionMix potionMix) {
+ net.minecraft.world.item.alchemy.PotionBrewing.addPotionMix(potionMix);
+ }
+
+ @Override
+ public void removePotionMix(org.bukkit.NamespacedKey key) {
+ net.minecraft.world.item.alchemy.PotionBrewing.removePotionMix(key);
+ }
+
+ @Override
+ public void resetPotionMixes() {
+ net.minecraft.world.item.alchemy.PotionBrewing.reload();
+ }
+ // Paper end
}

View File

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Tue, 7 Dec 2021 19:34:23 -0500
Subject: [PATCH] Dolphin API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java
@@ -0,0 +0,0 @@ public class CraftDolphin extends CraftWaterMob implements Dolphin {
public EntityType getType() {
return EntityType.DOLPHIN;
}
+
+ @Override
+ public int getMoistness() {
+ return this.getHandle().getMoistnessLevel();
+ }
+
+ @Override
+ public void setMoistness(int moistness) {
+ this.getHandle().setMoisntessLevel(moistness);
+ }
+
+ @Override
+ public void setHasFish(boolean hasFish) {
+ this.getHandle().setGotFish(hasFish);
+ }
+
+ @Override
+ public boolean hasFish() {
+ return this.getHandle().gotFish();
+ }
+
+ @Override
+ public org.bukkit.Location getTreasureLocation() {
+ return net.minecraft.server.MCUtil.toLocation(this.getHandle().level, this.getHandle().getTreasurePos());
+ }
+
+ @Override
+ public void setTreasureLocation(org.bukkit.Location location) {
+ this.getHandle().setTreasurePos(net.minecraft.server.MCUtil.toBlockPosition(location));
+ }
}

View File

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Tue, 28 Dec 2021 07:19:01 -0800
Subject: [PATCH] Execute chunk tasks fairly for worlds while waiting for next
tick
Currently, only the first world would have had tasks executed.
This might result in chunks loading far slower in the nether,
for example.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick
return true;
} else {
+ boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
if (this.haveTime()) {
Iterator iterator = this.getAllLevels().iterator();
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
ServerLevel worldserver = (ServerLevel) iterator.next();
if (worldserver.getChunkSource().pollTask()) {
- return true;
+ ret = true; // Paper - force execution of all worlds, do not just bias the first
}
}
}
- return false;
+ return ret; // Paper - force execution of all worlds, do not just bias the first
}
}

View File

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Thu, 23 Dec 2021 23:59:12 -0500
Subject: [PATCH] Fix Entity Position Desync
If entities were teleported in the first tick it would not be send to the client.
This excludes hanging entities, as this fix caused problematic behavior due to them having their own
position field.
This also fixes desync caused be relatively teleporting paintings. (https://bugs.mojang.com/browse/MC-249169)
This is caused by the fact that setPacketCoordinates isn't called on paintings when they are spawned (unlike every other entity, like XP orbs)
on the client for some reason. This causes it to be relatively teleported to the world origin (0,0,0).
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ public class ServerEntity {
}
// CraftBukkit end
- if (this.tickCount > 0 || this.entity instanceof AbstractArrow) {
+ if (!(this.entity instanceof net.minecraft.world.entity.decoration.HangingEntity) || this.tickCount > 0 || this.entity instanceof AbstractArrow) { // Paper - Always update position
// Paper start - remove allocation of Vec3D here
long k = ClientboundMoveEntityPacket.entityToPacket(vec3d_dx);
long l = ClientboundMoveEntityPacket.entityToPacket(vec3d_dy);
long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d_dz);
// Paper end - remove allocation of Vec3D here
boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L;
+ if (this.entity instanceof net.minecraft.world.entity.decoration.Painting) {flag4 = true;} // Paper - Always send exact position for paintings
if (!flag4 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround() && !(com.destroystokyo.paper.PaperConfig.sendFullPosForHardCollidingEntities && this.entity.hardCollides())) { // Paper - send full pos for hard colliding entities to prevent collision problems due to desync
if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) {

View File

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 1 Mar 2022 12:45:50 -0800
Subject: [PATCH] Fix Fluid tags isTagged method
diff --git a/src/main/java/org/bukkit/craftbukkit/tag/CraftFluidTag.java b/src/main/java/org/bukkit/craftbukkit/tag/CraftFluidTag.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/tag/CraftFluidTag.java
+++ b/src/main/java/org/bukkit/craftbukkit/tag/CraftFluidTag.java
@@ -0,0 +0,0 @@ public class CraftFluidTag extends CraftTag<net.minecraft.world.level.material.F
@Override
public boolean isTagged(Fluid fluid) {
- return CraftMagicNumbers.getFluid(fluid).is(tag);
+ return registry.getHolderOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.Registry.FLUID_REGISTRY, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(fluid.getKey()))).is(tag); // Paper
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
return CraftMagicNumbers.MATERIAL_BLOCK.get(material);
}
- public static net.minecraft.world.level.material.Fluid getFluid(Fluid fluid) {
+ public static net.minecraft.world.level.material.Fluid getFluid(Material fluid) { // Paper - wrong type
return CraftMagicNumbers.MATERIAL_FLUID.get(fluid);
}

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kieran Wallbanks <kieran.wallbanks@gmail.com>
Date: Mon, 21 Jun 2021 14:23:50 +0100
Subject: [PATCH] Fix NotePlayEvent
diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
@@ -0,0 +0,0 @@ public class NoteBlock extends Block {
private void playNote(Level world, BlockPos blockposition, BlockState data) { // CraftBukkit
if (world.getBlockState(blockposition.above()).isAir()) {
// CraftBukkit start
- org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, blockposition, data.getValue(NoteBlock.INSTRUMENT), data.getValue(NoteBlock.NOTE));
- if (!event.isCancelled()) {
+ // Paper start - move NotePlayEvent call to fix instrument/note changes
world.blockEvent(blockposition, this, 0, 0);
- }
+ // Paper end
// CraftBukkit end
}
@@ -0,0 +0,0 @@ public class NoteBlock extends Block {
@Override
public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
- int k = (Integer) state.getValue(NoteBlock.NOTE);
+ // Paper start - move NotePlayEvent call to fix instrument/note changes
+ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(INSTRUMENT), state.getValue(NOTE));
+ if (event.isCancelled()) return false;
+ int k = event.getNote().getId();
float f = (float) Math.pow(2.0D, (double) (k - 12) / 12.0D);
- world.playSound((Player) null, pos, ((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).getSoundEvent(), SoundSource.RECORDS, 3.0F, f);
+ world.playSound(null, pos, org.bukkit.craftbukkit.block.data.CraftBlockData.toNMS(event.getInstrument(), NoteBlockInstrument.class).getSoundEvent(), SoundSource.RECORDS, 3.0F, f);
+ // Paper end
world.addParticle(ParticleTypes.NOTE, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.2D, (double) pos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D);
return true;
}

View File

@ -1,74 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 1 Mar 2022 14:12:17 -0800
Subject: [PATCH] Fix World#locateNearestStructure
1.18.2 switched to TagKeys to reference tags of objects, and this method
impl needs to be changed to reflect that
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.resources.managers.updateRegistryTags(this.registryAccess());
io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
+ // Paper start - clear cache cause datapacks can add more configured structures
+ for (ServerLevel level : this.levels.values()) {
+ level.getWorld().structureCache.clear();
+ }
+ // Paper end
new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
if (Thread.currentThread() != this.serverThread) return; // Paper
//this.getPlayerList().saveAll(); // Paper - we don't need to do this
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 {
if (optional.isEmpty()) {
return null;
} else {
- Pair<BlockPos, Holder<ConfiguredStructureFeature<?, ?>>> pair = this.getChunkSource().getGenerator().findNearestMapFeature(this, (HolderSet) optional.get(), pos, radius, skipExistingChunks);
+ // Paper start
+ return this.findNearestMapFeature(optional.get(), pos, radius, skipExistingChunks);
+ }
+ }
+ }
+ public @Nullable BlockPos findNearestMapFeature(HolderSet<ConfiguredStructureFeature<?, ?>> holderSet, BlockPos pos, int radius, boolean skipExistingChunks) {
+ {
+ {
+ Pair<BlockPos, Holder<ConfiguredStructureFeature<?, ?>>> pair = this.getChunkSource().getGenerator().findNearestMapFeature(this, holderSet, pos, radius, skipExistingChunks);
+ // Paper end
return pair != null ? (BlockPos) pair.getFirst() : null;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
+ public final Map<StructureType, List<Holder.Reference<net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature<?, ?>>>> structureCache = new java.util.HashMap<>(); // Paper
@Override
public Location locateNearestStructure(Location origin, StructureType structureType, int radius, boolean findUnexplored) {
BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ());
- BlockPos nearest = this.getHandle().findNearestMapFeature(TagKey.create(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY, CraftNamespacedKey.toMinecraft(structureType.getKey())), originPos, radius, findUnexplored);
+ // Paper start - fix because you can't just create random TagKeys
+ if (!this.getHandle().serverLevelData.worldGenSettings().generateFeatures()) { // from ServerLevel#findNearestMapFeature
+ return null;
+ }
+ final List<Holder.Reference<net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature<?, ?>>> features = this.structureCache.computeIfAbsent(structureType, (type) -> {
+ final Registry<net.minecraft.world.level.levelgen.feature.StructureFeature<?>> structureFeatureRegistry = this.getHandle().registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY);
+ return this.getHandle().registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY).holders().filter(holder -> {
+ return structureType.getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(Objects.requireNonNull(structureFeatureRegistry.getKey(holder.value().feature))));
+ }).toList();
+ });
+ BlockPos nearest = this.getHandle().findNearestMapFeature(net.minecraft.core.HolderSet.direct(features), originPos, radius, findUnexplored);
+ // Paper end
return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ());
}

View File

@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 8 Oct 2021 13:12:58 -0700
Subject: [PATCH] Fix cancelled powdered snow bucket placement
Cancelling the placement of powdered snow from the powdered
snow bucket didn't revert grass that became snowy because of the
placement.
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -0,0 +0,0 @@ public class BlockItem extends Item {
blockstate.update(true, false);
if (this instanceof SolidBucketItem) {
+ ((ServerPlayer) entityhuman).connection.send(new net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket(world, blockposition.below())); // Paper - update block below
((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
}
return InteractionResult.FAIL;
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -0,0 +0,0 @@ public final class ItemStack {
int oldCount = this.getCount();
ServerLevel world = (ServerLevel) itemactioncontext.getLevel();
- if (!(this.getItem() instanceof BucketItem || this.getItem() instanceof SolidBucketItem)) { // if not bucket
+ if (!(this.getItem() instanceof BucketItem/* || this.getItem() instanceof SolidBucketItem*/)) { // if not bucket // Paper - capture block states for snow buckets
world.captureBlockStates = true;
// special case bonemeal
if (this.getItem() == Items.BONE_MEAL) {
@@ -0,0 +0,0 @@ public final class ItemStack {
world.capturedBlockStates.clear();
if (blocks.size() > 1) {
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ());
- } else if (blocks.size() == 1) {
+ } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - don't call event twice for snow buckets
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ());
}

View File

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 4 Mar 2022 20:35:19 +0100
Subject: [PATCH] Fix falling block spawn methods
Restores the API behavior from previous versions of the server
- Do not call API events
- Do not replace the existing block in the world
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
// Paper end
} else if (FallingBlock.class.isAssignableFrom(clazz)) {
BlockPos pos = new BlockPos(x, y, z);
- entity = FallingBlockEntity.fall(world, pos, this.getHandle().getBlockState(pos));
+ entity = new FallingBlockEntity(world, x, y, z, this.getHandle().getBlockState(pos)); // Paper
} else if (Projectile.class.isAssignableFrom(clazz)) {
if (Snowball.class.isAssignableFrom(clazz)) {
entity = new net.minecraft.world.entity.projectile.Snowball(world, x, y, z);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Validate.notNull(material, "Material cannot be null");
Validate.isTrue(material.isBlock(), "Material must be a block");
- FallingBlockEntity entity = FallingBlockEntity.fall(world, new BlockPos(location.getX(), location.getY(), location.getZ()), CraftMagicNumbers.getBlock(material).defaultBlockState(), SpawnReason.CUSTOM);
+ // Paper start - restore API behavior for spawning falling blocks
+ FallingBlockEntity entity = new FallingBlockEntity(this.world, location.getX(), location.getY(), location.getZ(), CraftMagicNumbers.getBlock(material).defaultBlockState()); // Paper
+ entity.time = 1;
+
+ this.world.addFreshEntity(entity, SpawnReason.CUSTOM);
+ // Paper end
return (FallingBlock) entity.getBukkitEntity();
}
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Validate.notNull(location, "Location cannot be null");
Validate.notNull(data, "BlockData cannot be null");
- FallingBlockEntity entity = FallingBlockEntity.fall(world, new BlockPos(location.getX(), location.getY(), location.getZ()), ((CraftBlockData) data).getState(), SpawnReason.CUSTOM);
+ // Paper start - restore API behavior for spawning falling blocks
+ FallingBlockEntity entity = new FallingBlockEntity(this.world, location.getX(), location.getY(), location.getZ(), ((CraftBlockData) data).getState());
+ entity.time = 1;
+
+ this.world.addFreshEntity(entity, SpawnReason.CUSTOM);
+ // Paper end
return (FallingBlock) entity.getBukkitEntity();
}

View File

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 16 Jan 2022 10:34:02 -0800
Subject: [PATCH] Fix xp reward for baby zombies
The field that tracks the xpReward was not
getting reset if the death was cancelled
so this resets it after each call to
Zombie#getExperienceReward
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
@Override
protected int getExperienceReward(Player player) {
+ final int previousReward = this.xpReward; // Paper - store previous value to reset after calculating XP reward
if (this.isBaby()) {
this.xpReward = (int) ((double) this.xpReward * 2.5D);
}
- return super.getExperienceReward(player);
+ // Paper start - only change the XP reward for the calculations in the super method
+ int reward = super.getExperienceReward(player);
+ this.xpReward = previousReward;
+ return reward;
+ // Paper end
}
@Override

View File

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Wed, 2 Mar 2022 09:45:56 +0100
Subject: [PATCH] Force close world loading screen
Dead players would be stuck in the world loading screen and other players may
miss messages and similar sent in the join event if chunk loading is slow.
Paper already circumvents falling through the world before chunks are loaded,
so we do not need that. The client only needs the chunk it is currently in to
be loaded to close the loading screen, so we just send an empty one.
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
// Paper start - move vehicle into method so it can be called above - short circuit around that code
onPlayerJoinFinish(player, worldserver1, s1);
+ // Send empty chunk, so players aren't stuck in the world loading screen
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY)
+ .getHolderOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
+ worldserver1.getLightEngine(), null, null, true, false)
+ );
}
private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) {
// Paper end

View File

@ -1,82 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 26 Dec 2021 20:27:43 -0500
Subject: [PATCH] Freeze Tick Lock API
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 {
private org.bukkit.util.Vector origin;
@javax.annotation.Nullable
private UUID originWorld;
+ public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.setRemainingFireTicks(this.remainingFireTicks - 1);
}
- if (this.getTicksFrozen() > 0) {
+ if (this.getTicksFrozen() > 0 && !freezeLocked) { // Paper - Freeze Tick Lock API
this.setTicksFrozen(0);
this.level.levelEvent((Player) null, 1009, this.blockPosition, 1);
}
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (fromNetherPortal) {
nbt.putBoolean("Paper.FromNetherPortal", true);
}
+ if (freezeLocked) {
+ nbt.putBoolean("Paper.FreezeLock", true);
+ }
// Paper end
return nbt;
} catch (Throwable throwable) {
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (spawnReason == null) {
spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT;
}
+ if (nbt.contains("Paper.FreezeLock")) {
+ freezeLocked = nbt.getBoolean("Paper.FreezeLock");
+ }
// Paper end
} catch (Throwable throwable) {
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 {
boolean flag1 = this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES);
int i;
- if (!this.level.isClientSide && !this.isDeadOrDying()) {
+ if (!this.level.isClientSide && !this.isDeadOrDying() && !freezeLocked) { // Paper - Freeze Tick Lock API
i = this.getTicksFrozen();
if (this.isInPowderSnow && this.canFreeze()) {
this.setTicksFrozen(Math.min(this.getTicksRequiredToFreeze(), i + 1));
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return this.getHandle().isFullyFrozen();
}
+ // Paper Start - Freeze Tick Lock API
+ @Override
+ public boolean isFreezeTickingLocked() {
+ return this.entity.freezeLocked;
+ }
+
+ @Override
+ public void lockFreezeTicks(boolean locked) {
+ this.entity.freezeLocked = locked;
+ }
+ // Paper end - Freeze Tick Lock API
@Override
public void remove() {
this.entity.discard();

View File

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 13 Jan 2022 15:20:47 -0800
Subject: [PATCH] Furnace RecipesUsed API
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java
@@ -0,0 +0,0 @@ public abstract class CraftFurnace<T extends AbstractFurnaceBlockEntity> extends
snapshot.cookSpeedMultiplier = multiplier;
snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot.recipeType, snapshot, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier
}
+
+ @Override
+ public int getRecipeUsedCount(org.bukkit.NamespacedKey furnaceRecipe) {
+ return this.getSnapshot().getRecipesUsed().getInt(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe));
+ }
+
+ @Override
+ public boolean hasRecipeUsedCount(org.bukkit.NamespacedKey furnaceRecipe) {
+ return this.getSnapshot().getRecipesUsed().containsKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe));
+ }
+
+ @Override
+ public void setRecipeUsedCount(org.bukkit.inventory.CookingRecipe<?> furnaceRecipe, int count) {
+ final net.minecraft.resources.ResourceLocation location = org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe.getKey());
+ java.util.Optional<? extends net.minecraft.world.item.crafting.Recipe<?>> nmsRecipe = (this.isPlaced() ? this.world.getHandle().getRecipeManager() : net.minecraft.server.MinecraftServer.getServer().getRecipeManager()).byKey(location);
+ com.google.common.base.Preconditions.checkArgument(nmsRecipe.isPresent() && nmsRecipe.get() instanceof net.minecraft.world.item.crafting.AbstractCookingRecipe, furnaceRecipe.getKey() + " is not recognized as a valid and registered furnace recipe");
+ if (count > 0) {
+ this.getSnapshot().getRecipesUsed().put(location, count);
+ } else {
+ this.getSnapshot().getRecipesUsed().removeInt(location);
+ }
+ }
+
+ @Override
+ public void setRecipesUsed(java.util.Map<org.bukkit.inventory.CookingRecipe<?>, Integer> recipesUsed) {
+ this.getSnapshot().getRecipesUsed().clear();
+ recipesUsed.forEach((recipe, integer) -> {
+ if (integer != null) {
+ this.setRecipeUsedCount(recipe, integer);
+ }
+ });
+ }
// Paper end
}

View File

@ -1,97 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Mon, 31 Jan 2022 11:21:50 +0100
Subject: [PATCH] Implement regenerateChunk
Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ import org.bukkit.util.Vector;
public class CraftWorld extends CraftRegionAccessor implements World {
public static final int CUSTOM_DIMENSION_OFFSET = 10;
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
+ private static final ChunkStatus[] REGEN_CHUNK_STATUSES = {ChunkStatus.BIOMES, ChunkStatus.NOISE, ChunkStatus.SURFACE, ChunkStatus.CARVERS, ChunkStatus.LIQUID_CARVERS, ChunkStatus.FEATURES}; // Paper - implement regenerate chunk method
private final ServerLevel world;
private WorldBorder worldBorder;
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean regenerateChunk(int x, int z) {
org.spigotmc.AsyncCatcher.catchOp("chunk regenerate"); // Spigot
- throw new UnsupportedOperationException("Not supported in this Minecraft version! Unless you can fix it, this is not a bug :)");
- /*
- if (!unloadChunk0(x, z, false)) {
- return false;
- }
-
- final long chunkKey = ChunkCoordIntPair.pair(x, z);
- world.getChunkProvider().unloadQueue.remove(chunkKey);
+ // Paper start - implement regenerateChunk method
+ final ServerLevel serverLevel = this.world;
+ final net.minecraft.server.level.ServerChunkCache serverChunkCache = serverLevel.getChunkSource();
+ final ChunkPos chunkPos = new ChunkPos(x, z);
+ final net.minecraft.world.level.chunk.LevelChunk levelChunk = serverChunkCache.getChunk(chunkPos.x, chunkPos.z, true);
+ for (final BlockPos blockPos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), serverLevel.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), serverLevel.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ())) {
+ levelChunk.removeBlockEntity(blockPos);
+ serverLevel.setBlock(blockPos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), 16);
+ }
+
+ for (final ChunkStatus chunkStatus : REGEN_CHUNK_STATUSES) {
+ final List<ChunkAccess> list = new ArrayList<>();
+ final int range = Math.max(1, chunkStatus.getRange());
+ for (int chunkX = chunkPos.z - range; chunkX <= chunkPos.z + range; chunkX++) {
+ for (int chunkZ = chunkPos.x - range; chunkZ <= chunkPos.x + range; chunkZ++) {
+ ChunkAccess chunkAccess = serverChunkCache.getChunk(chunkZ, chunkX, chunkStatus.getParent(), true);
+ if (chunkAccess instanceof ImposterProtoChunk accessProtoChunk) {
+ chunkAccess = new ImposterProtoChunk(accessProtoChunk.getWrapped(), true);
+ } else if (chunkAccess instanceof net.minecraft.world.level.chunk.LevelChunk accessLevelChunk) {
+ chunkAccess = new ImposterProtoChunk(accessLevelChunk, true);
+ }
+ list.add(chunkAccess);
+ }
+ }
- net.minecraft.server.Chunk chunk = world.getChunkProvider().generateChunk(x, z);
- PlayerChunk playerChunk = world.getPlayerChunkMap().getChunk(x, z);
- if (playerChunk != null) {
- playerChunk.chunk = chunk;
+ final com.mojang.datafixers.util.Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = chunkStatus.generate(
+ Runnable::run,
+ serverLevel,
+ serverChunkCache.getGenerator(),
+ serverLevel.getStructureManager(),
+ serverChunkCache.getLightEngine(),
+ chunk -> {
+ throw new UnsupportedOperationException("Not creating full chunks here");
+ },
+ list,
+ true
+ ).join();
+ if (chunkStatus == ChunkStatus.NOISE) {
+ either.left().ifPresent(chunk -> net.minecraft.world.level.levelgen.Heightmap.primeHeightmaps(chunk, ChunkStatus.POST_FEATURES));
+ }
}
- if (chunk != null) {
- refreshChunk(x, z);
+ for (final BlockPos blockPos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), serverLevel.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), serverLevel.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ())) {
+ serverChunkCache.blockChanged(blockPos);
}
- return chunk != null;
- */
+ final Set<ChunkPos> chunksToRelight = new HashSet<>(9);
+ for (int chunkX = chunkPos.x - 1; chunkX <= chunkPos.x + 1 ; chunkX++) {
+ for (int chunkZ = chunkPos.z - 1; chunkZ <= chunkPos.z + 1 ; chunkZ++) {
+ chunksToRelight.add(new ChunkPos(chunkX, chunkZ));
+ }
+ }
+ serverChunkCache.getLightEngine().relight(chunksToRelight, pos -> {}, relit -> {});
+ return true;
+ // Paper end
}
@Override

View File

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Mon, 17 Jan 2022 19:47:19 +0100
Subject: [PATCH] Kick on main for illegal chars
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
for (int i = 0; i < s.length(); ++i) {
if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) {
+ this.server.scheduleOnMain(() -> { // Paper - push to main for event firing
this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - add cause
+ }); // Paper - push to main for event firing
return;
}
}

View File

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <git@lynxplay.dev>
Date: Sat, 12 Feb 2022 03:20:36 +0100
Subject: [PATCH] Log exceptions thrown during chat processing
Previously the async chat executor service would take chat handling
using the #submit method, which wraps the logic in a future task.
The future takes full ownership of the task, including any potential
exception, meaning that the uncaught exception handler never gets
notified about potential exceptions thrown during async chat logic.
As the chat task does neither need to be cancelled nor returns something
required later on, this commit moves from #submit to #execute, skipping
any future task creation. This properly propagates any exception upwards
to the worker thread in the executor service, allowing the server to
catch and properly log the exception to the console.
diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundChatPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundChatPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundChatPacket.java
@@ -0,0 +0,0 @@ public class ServerboundChatPacket implements Packet<ServerGamePacketListener> {
public void handle(final ServerGamePacketListener listener) {
if ( !this.message.startsWith("/") )
{
- ServerboundChatPacket.executors.submit( new Runnable()
+ ServerboundChatPacket.executors.execute( new Runnable() // Paper - Use #execute to propagate exceptions up instead of swallowing them
{
@Override

View File

@ -1,91 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 27 May 2021 21:58:24 -0700
Subject: [PATCH] More PotionEffectType API
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
@@ -0,0 +0,0 @@ public class CraftPotionEffectType extends PotionEffectType {
public Color getColor() {
return Color.fromRGB(this.handle.getColor());
}
+ // Paper start
+ @Override
+ public org.bukkit.NamespacedKey getKey() {
+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.MOB_EFFECT.getKey(this.handle));
+ }
+
+ @Override
+ public java.util.Map<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> getEffectAttributes() {
+ // re-create map each time because a nms MobEffect can have its attributes modified
+ final java.util.Map<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> attributeMap = new java.util.HashMap<>();
+ this.handle.getAttributeModifiers().forEach((attribute, attributeModifier) -> {
+ attributeMap.put(org.bukkit.craftbukkit.attribute.CraftAttributeMap.fromMinecraft(attribute.toString()), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier));
+ });
+ return java.util.Map.copyOf(attributeMap);
+ }
+
+ @Override
+ public double getAttributeModifierAmount(org.bukkit.attribute.Attribute attribute, int effectAmplifier) {
+ com.google.common.base.Preconditions.checkArgument(effectAmplifier >= 0, "effectAmplifier must be greater than or equal to 0");
+ net.minecraft.world.entity.ai.attributes.Attribute nmsAttribute = org.bukkit.craftbukkit.attribute.CraftAttributeMap.toMinecraft(attribute);
+ com.google.common.base.Preconditions.checkArgument(this.handle.getAttributeModifiers().containsKey(nmsAttribute), attribute + " is not present on " + this.getKey());
+ return this.handle.getAttributeModifierValue(effectAmplifier, this.handle.getAttributeModifiers().get(nmsAttribute));
+ }
+
+ @Override
+ public PotionEffectType.Category getEffectCategory() {
+ return fromNMS(handle.getCategory());
+ }
+
+ @Override
+ public String translationKey() {
+ return this.handle.getDescriptionId();
+ }
+
+ public static PotionEffectType.Category fromNMS(net.minecraft.world.effect.MobEffectCategory mobEffectInfo) {
+ return switch (mobEffectInfo) {
+ case BENEFICIAL -> PotionEffectType.Category.BENEFICIAL;
+ case HARMFUL -> PotionEffectType.Category.HARMFUL;
+ case NEUTRAL -> PotionEffectType.Category.NEUTRAL;
+ };
+ }
+ // Paper end
}
diff --git a/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java b/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/io/papermc/paper/effects/EffectCategoryTest.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.effects;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import net.minecraft.world.effect.MobEffectCategory;
+import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
+import org.bukkit.potion.PotionEffectType;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class EffectCategoryTest {
+
+ @Test
+ public void testEffectCategoriesExist() {
+ for (MobEffectCategory mobEffectInfo : MobEffectCategory.values()) {
+ assertNotNull(mobEffectInfo + " is missing a bukkit equivalent", CraftPotionEffectType.fromNMS(mobEffectInfo));
+ }
+ }
+
+ @Test
+ public void testCategoryHasEquivalentColors() {
+ for (MobEffectCategory mobEffectInfo : MobEffectCategory.values()) {
+ PotionEffectType.Category bukkitEffectCategory = CraftPotionEffectType.fromNMS(mobEffectInfo);
+ assertEquals(mobEffectInfo.getTooltipFormatting().name() + " doesn't equal " + bukkitEffectCategory.getColor(), bukkitEffectCategory.getColor(), PaperAdventure.asAdventure(mobEffectInfo.getTooltipFormatting()));
+ }
+ }
+}

View File

@ -1,74 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brody Beckwith <brody@beckwith.dev>
Date: Fri, 14 Jan 2022 00:41:11 -0500
Subject: [PATCH] Multi Block Change API Implementation
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
@@ -0,0 +0,0 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet<ClientGamePa
}
+ // Paper start
+ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<BlockState> blockChanges, boolean suppressLightUpdates) {
+ this.sectionPos = sectionPos;
+ this.positions = blockChanges.keySet().toShortArray();
+ this.states = blockChanges.values().toArray(new BlockState[0]);
+ this.suppressLightUpdates = suppressLightUpdates;
+ }
+ // Paper end
+
@Override
public void write(FriendlyByteBuf buf) {
buf.writeLong(this.sectionPos.asLong());
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.advancements.AdvancementProgress;
import net.minecraft.core.BlockPos;
+import net.minecraft.core.SectionPos; // Paper
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.ChatType;
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().connection.send(packet);
}
+ // Paper start
+ @Override
+ public void sendMultiBlockChange(Map<Location, BlockData> blockChanges, boolean suppressLightUpdates) {
+ if (this.getHandle().connection == null) return;
+
+ Map<SectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState>> sectionMap = new HashMap<>();
+
+ for (Map.Entry<Location, BlockData> entry : blockChanges.entrySet()) {
+ Location location = entry.getKey();
+ if (!location.getWorld().equals(this.getWorld())) continue;
+
+ BlockData blockData = entry.getValue();
+ BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ SectionPos sectionPos = SectionPos.of(blockPos);
+
+ it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState> sectionData = sectionMap.computeIfAbsent(sectionPos, key -> new it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap<>());
+ sectionData.put(SectionPos.sectionRelativePos(blockPos), ((CraftBlockData) blockData).getState());
+ }
+
+ for (Map.Entry<SectionPos, it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState>> entry : sectionMap.entrySet()) {
+ SectionPos sectionPos = entry.getKey();
+ it.unimi.dsi.fastutil.shorts.Short2ObjectMap<net.minecraft.world.level.block.state.BlockState> blockData = entry.getValue();
+
+ net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket packet = new net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket(sectionPos, blockData, suppressLightUpdates);
+ this.getHandle().connection.send(packet);
+ }
+ }
+ // Paper end
+
@Override
public void sendBlockDamage(Location loc, float progress) {
Preconditions.checkArgument(loc != null, "loc must not be null");

View File

@ -1,126 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Tue, 21 Sep 2021 18:17:33 -0500
Subject: [PATCH] Multiple Entries with Scoreboards
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
@@ -0,0 +0,0 @@ public class ClientboundSetPlayerTeamPacket implements Packet<ClientGamePacketLi
return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), ImmutableList.of(playerName));
}
+ // Paper start
+ public static ClientboundSetPlayerTeamPacket createMultiplePlayerPacket(PlayerTeam team, Collection<String> players, ClientboundSetPlayerTeamPacket.Action operation) {
+ return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), players);
+ }
+ // Paper end
+
public ClientboundSetPlayerTeamPacket(FriendlyByteBuf buf) {
this.name = buf.readUtf();
this.method = buf.readByte();
diff --git a/src/main/java/net/minecraft/server/ServerScoreboard.java b/src/main/java/net/minecraft/server/ServerScoreboard.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/ServerScoreboard.java
+++ b/src/main/java/net/minecraft/server/ServerScoreboard.java
@@ -0,0 +0,0 @@ public class ServerScoreboard extends Scoreboard {
}
}
+ // Paper start
+ public boolean addPlayersToTeam(java.util.Collection<String> players, PlayerTeam team) {
+ boolean anyAdded = false;
+ for (String playerName : players) {
+ if (super.addPlayerToTeam(playerName, team)) {
+ anyAdded = true;
+ }
+ }
+
+ if (anyAdded) {
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, players, ClientboundSetPlayerTeamPacket.Action.ADD));
+ this.setDirty();
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // Paper end
+
@Override
public void removePlayerFromTeam(String playerName, PlayerTeam team) {
super.removePlayerFromTeam(playerName, team);
@@ -0,0 +0,0 @@ public class ServerScoreboard extends Scoreboard {
this.setDirty();
}
+ // Paper start
+ public void removePlayersFromTeam(java.util.Collection<String> players, PlayerTeam team) {
+ for (String playerName : players) {
+ super.removePlayerFromTeam(playerName, team);
+ }
+
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, players, ClientboundSetPlayerTeamPacket.Action.REMOVE));
+ this.setDirty();
+ }
+ // Paper end
+
@Override
public void onObjectiveAdded(Objective objective) {
super.onObjectiveAdded(objective);
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
@@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
scoreboard.board.addPlayerToTeam(entry, team);
}
+ // Paper start
+ @Override
+ public void addEntities(java.util.Collection<org.bukkit.entity.Entity> entities) throws IllegalStateException, IllegalArgumentException {
+ this.addEntries(entities.stream().map(entity -> ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName()).toList());
+ }
+
+ @Override
+ public void addEntries(java.util.Collection<String> entries) throws IllegalStateException, IllegalArgumentException {
+ Validate.notNull(entries, "Entries cannot be null");
+ CraftScoreboard scoreboard = this.checkState();
+
+ ((net.minecraft.server.ServerScoreboard) scoreboard.board).addPlayersToTeam(entries, this.team);
+ }
+ // Paper end
+
@Override
public boolean removePlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException {
Validate.notNull(player, "OfflinePlayer cannot be null");
@@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
return true;
}
+ // Paper start
+ @Override
+ public boolean removeEntities(java.util.Collection<org.bukkit.entity.Entity> entities) throws IllegalStateException, IllegalArgumentException {
+ return this.removeEntries(entities.stream().map(entity -> ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName()).toList());
+ }
+
+ @Override
+ public boolean removeEntries(java.util.Collection<String> entries) throws IllegalStateException, IllegalArgumentException {
+ Validate.notNull(entries, "Entry cannot be null");
+ CraftScoreboard scoreboard = this.checkState();
+
+ for (String entry : entries) {
+ if (this.team.getPlayers().contains(entry)) {
+ ((net.minecraft.server.ServerScoreboard) scoreboard.board).removePlayersFromTeam(entries, this.team);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ // Paper end
+
@Override
public boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException {
Validate.notNull(player, "OfflinePlayer cannot be null");

View File

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 19 Feb 2022 20:15:41 -0800
Subject: [PATCH] Option to have default CustomSpawners in custom worlds
By default, only LevelStem's that specifically match the ResourceKey for
OVERWORLD will have the 5 (currently) impls of CustomSpawner (for
phantoms, wandering traders, etc.). This adds an option to instead of
just looking at the LevelStem key, look at the DimensionType key which
is one level below that. Defaults to off to keep vanilla behavior.
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 {
globalMaxConcurrentChunkLoads = getDouble("settings.chunk-loading.global-max-concurrent-loads", 500.0);
playerMaxChunkLoadRate = getDouble("settings.chunk-loading.player-max-chunk-load-rate", -1.0);
}
+
+ public static boolean useDimensionTypeForCustomSpawners;
+ private static void useDimensionTypeForCustomSpawners() {
+ useDimensionTypeForCustomSpawners = getBoolean("settings.use-dimension-type-for-custom-spawners", false);
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.commandStorage = new CommandStorage(worldpersistentdata);
} else {
ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11);
- world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, holder, worldloadlistener, chunkgenerator, flag, j, ImmutableList.of(), true, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
+ // Paper start - option to use the dimension_type to check if spawners should be added. I imagine mojang will add some datapack-y way of managing this in the future.
+ final List<CustomSpawner> spawners;
+ if (com.destroystokyo.paper.PaperConfig.useDimensionTypeForCustomSpawners && this.registryHolder.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getResourceKey(holder.value()).orElseThrow() == DimensionType.OVERWORLD_LOCATION) {
+ spawners = list;
+ } else {
+ spawners = Collections.emptyList();
+ }
+ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, holder, worldloadlistener, chunkgenerator, flag, j, spawners, true, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
+ // Paper end
}
worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified());

View File

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Tue, 22 Feb 2022 14:21:35 -0800
Subject: [PATCH] Put world into worldlist before initing the world
Some parts of legacy conversion will need the overworld
to get the legacy structure data storage
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified());
+ this.levels.put(world.dimension(), world); // Paper - move up
this.initWorld(world, worlddata, worldData, worlddata.worldGenSettings());
- this.levels.put(world.dimension(), world);
+ // Paper - move up
this.getPlayerList().addWorldborderListener(world);
if (worlddata.getCustomBossEvents() != null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return null;
}
+ console.levels.put(internal.dimension(), internal); // Paper - move up
this.console.initWorld(internal, worlddata, worlddata, worlddata.worldGenSettings());
internal.setSpawnSettings(true, true);
- console.levels.put(internal.dimension(), internal);
+ // Paper - move up
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API

View File

@ -1,249 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 21 Mar 2021 16:25:42 -0700
Subject: [PATCH] Replace ticket level propagator
Mojang's propagator is slow, and this isn't surprising
given it's built on the same utilities the vanilla light engine
is built on. The simple propagator I wrote is approximately 4x
faster when simulating player movement. For a long time timing
reports have shown this function take up significant tick, (
approx 10% or more), and async sampling data shows the level
propagation alone takes up a significant amount. So this
should help with that. A big side effect is that mid-tick
will be more effective, since more time will be allocated
to actually processing chunk tasks vs the ticket level updates.
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import org.slf4j.Logger;
+import it.unimi.dsi.fastutil.longs.Long2IntLinkedOpenHashMap; // Paper
public abstract class DistanceManager {
static final Logger LOGGER = LogUtils.getLogger();
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
private static final int BLOCK_TICKING_LEVEL_THRESHOLD = 33;
final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
public final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets = new Long2ObjectOpenHashMap();
- private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker();
+ //private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); // Paper - replace ticket level propagator
public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used
//private final TickingTracker tickingTicketsTracker = new TickingTracker(); // Paper - no longer used
//private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); // Paper - no longer used
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
this.chunkMap = chunkMap; // Paper
}
+ // Paper start - replace ticket level propagator
+ protected final Long2IntLinkedOpenHashMap ticketLevelUpdates = new Long2IntLinkedOpenHashMap() {
+ @Override
+ protected void rehash(int newN) {
+ // no downsizing allowed
+ if (newN < this.n) {
+ return;
+ }
+ super.rehash(newN);
+ }
+ };
+ protected final io.papermc.paper.util.misc.Delayed8WayDistancePropagator2D ticketLevelPropagator = new io.papermc.paper.util.misc.Delayed8WayDistancePropagator2D(
+ (long coordinate, byte oldLevel, byte newLevel) -> {
+ DistanceManager.this.ticketLevelUpdates.putAndMoveToLast(coordinate, convertBetweenTicketLevels(newLevel));
+ }
+ );
+ // function for converting between ticket levels and propagator levels and vice versa
+ // the problem is the ticket level propagator will propagate from a set source down to zero, whereas mojang expects
+ // levels to propagate from a set value up to a maximum value. so we need to convert the levels we put into the propagator
+ // and the levels we get out of the propagator
+
+ // this maps so that GOLDEN_TICKET + 1 will be 0 in the propagator, GOLDEN_TICKET will be 1, and so on
+ // we need GOLDEN_TICKET+1 as 0 because anything >= GOLDEN_TICKET+1 should be unloaded
+ public static int convertBetweenTicketLevels(final int level) {
+ return ChunkMap.MAX_CHUNK_DISTANCE - level + 1;
+ }
+
+ protected final int getPropagatedTicketLevel(final long coordinate) {
+ return convertBetweenTicketLevels(this.ticketLevelPropagator.getLevel(coordinate));
+ }
+
+ protected final void updateTicketLevel(final long coordinate, final int ticketLevel) {
+ if (ticketLevel > ChunkMap.MAX_CHUNK_DISTANCE) {
+ this.ticketLevelPropagator.removeSource(coordinate);
+ } else {
+ this.ticketLevelPropagator.setSource(coordinate, convertBetweenTicketLevels(ticketLevel));
+ }
+ }
+ // Paper end - replace ticket level propagator
+
protected void purgeStaleTickets() {
++this.ticketTickCounter;
ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().fastIterator();
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
}
if (flag) {
- this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt((SortedArraySet) entry.getValue()), false);
+ this.updateTicketLevel(entry.getLongKey(), getTicketLevelAt(entry.getValue())); // Paper - replace ticket level propagator
}
if (((SortedArraySet) entry.getValue()).isEmpty()) {
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
@Nullable
protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k);
+ protected long ticketLevelUpdateCount; // Paper - replace ticket level propagator
public boolean runAllUpdates(ChunkMap chunkStorage) {
//this.f.a(); // Paper - no longer used
//this.tickingTicketsTracker.runAllUpdates(); // Paper - no longer used
org.spigotmc.AsyncCatcher.catchOp("DistanceManagerTick"); // Paper
//this.playerTicketManager.runAllUpdates(); // Paper - no longer used
- int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE);
- boolean flag = i != 0;
+ boolean flag = this.ticketLevelPropagator.propagateUpdates(); // Paper - replace ticket level propagator
if (flag) {
;
}
- // Paper start
- if (!this.pendingChunkUpdates.isEmpty()) {
- this.pollingPendingChunkUpdates = true; try { // Paper - Chunk priority
- while(!this.pendingChunkUpdates.isEmpty()) {
- ChunkHolder remove = this.pendingChunkUpdates.remove();
- remove.isUpdateQueued = false;
- remove.updateFutures(chunkStorage, this.mainThreadExecutor);
- }
- } finally { this.pollingPendingChunkUpdates = false; } // Paper - Chunk priority
- // Paper end
- return true;
- } else {
- if (!this.ticketsToRelease.isEmpty()) {
- LongIterator longiterator = this.ticketsToRelease.iterator();
+ // Paper start - replace level propagator
+ ticket_update_loop:
+ while (!this.ticketLevelUpdates.isEmpty()) {
+ flag = true;
- while (longiterator.hasNext()) {
- long j = longiterator.nextLong();
+ boolean oldPolling = this.pollingPendingChunkUpdates;
+ this.pollingPendingChunkUpdates = true;
+ try {
+ for (java.util.Iterator<Long2IntMap.Entry> iterator = this.ticketLevelUpdates.long2IntEntrySet().fastIterator(); iterator.hasNext();) {
+ Long2IntMap.Entry entry = iterator.next();
+ long key = entry.getLongKey();
+ int newLevel = entry.getIntValue();
+ ChunkHolder chunk = this.getChunk(key);
+
+ if (chunk == null && newLevel > ChunkMap.MAX_CHUNK_DISTANCE) {
+ // not loaded and it shouldn't be loaded!
+ continue;
+ }
- if (this.getTickets(j).stream().anyMatch((ticket) -> {
- return ticket.getType() == TicketType.PLAYER;
- })) {
- ChunkHolder playerchunk = chunkStorage.getUpdatingChunkIfPresent(j);
+ int currentLevel = chunk == null ? ChunkMap.MAX_CHUNK_DISTANCE + 1 : chunk.getTicketLevel();
- if (playerchunk == null) {
- throw new IllegalStateException();
+ if (currentLevel == newLevel) {
+ // nothing to do
+ continue;
+ }
+
+ this.updateChunkScheduling(key, newLevel, chunk, currentLevel);
+ }
+
+ long recursiveCheck = ++this.ticketLevelUpdateCount;
+ while (!this.ticketLevelUpdates.isEmpty()) {
+ long key = this.ticketLevelUpdates.firstLongKey();
+ int newLevel = this.ticketLevelUpdates.removeFirstInt();
+ ChunkHolder chunk = this.getChunk(key);
+
+ if (chunk == null) {
+ if (newLevel <= ChunkMap.MAX_CHUNK_DISTANCE) {
+ throw new IllegalStateException("Expected chunk holder to be created");
}
+ // not loaded and it shouldn't be loaded!
+ continue;
+ }
- CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture = playerchunk.getEntityTickingChunkFuture();
+ int currentLevel = chunk.oldTicketLevel;
- completablefuture.thenAccept((either) -> {
- this.mainThreadExecutor.execute(() -> {
- this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> {
- }, j, false));
- });
- });
+ if (currentLevel == newLevel) {
+ // nothing to do
+ continue;
+ }
+
+ chunk.updateFutures(chunkStorage, this.mainThreadExecutor);
+ if (recursiveCheck != this.ticketLevelUpdateCount) {
+ // back to the start, we must create player chunks and update the ticket level fields before
+ // processing the actual level updates
+ continue ticket_update_loop;
}
}
- this.ticketsToRelease.clear();
- }
+ for (;;) {
+ if (recursiveCheck != this.ticketLevelUpdateCount) {
+ continue ticket_update_loop;
+ }
+ ChunkHolder pendingUpdate = this.pendingChunkUpdates.poll();
+ if (pendingUpdate == null) {
+ break;
+ }
- return flag;
+ pendingUpdate.updateFutures(chunkStorage, this.mainThreadExecutor);
+ }
+ } finally {
+ this.pollingPendingChunkUpdates = oldPolling;
+ }
}
+
+ return flag;
+ // Paper end - replace level propagator
}
boolean pollingPendingChunkUpdates = false; // Paper - Chunk priority
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
ticket1.setCreatedTick(this.ticketTickCounter);
if (ticket.getTicketLevel() < j) {
- this.ticketTracker.update(i, ticket.getTicketLevel(), true);
+ this.updateTicketLevel(i, ticket.getTicketLevel()); // Paper - replace ticket level propagator
}
return ticket == ticket1; // CraftBukkit
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
// Paper start - Chunk priority
int newLevel = getTicketLevelAt(arraysetsorted);
if (newLevel > oldLevel) {
- this.ticketTracker.update(i, newLevel, false);
+ this.updateTicketLevel(i, newLevel); // Paper // Paper - replace ticket level propagator
}
// Paper end
return removed; // CraftBukkit
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
SortedArraySet<Ticket<?>> tickets = entry.getValue();
if (tickets.remove(target)) {
// copied from removeTicket
- this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt(tickets), false);
+ this.updateTicketLevel(entry.getLongKey(), getTicketLevelAt(tickets)); // Paper - replace ticket level propagator
// can't use entry after it's removed
if (tickets.isEmpty()) {

View File

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 7 Jan 2022 11:45:15 +0100
Subject: [PATCH] Reset placed block on exception
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -0,0 +0,0 @@ public class BlockItem extends Item {
if (this instanceof WaterLilyBlockItem || this instanceof SolidBucketItem) {
blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos());
}
+ final org.bukkit.block.BlockState oldBlockstate = blockstate != null ? blockstate : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); // Paper
// CraftBukkit end
if (iblockdata == null) {
@@ -0,0 +0,0 @@ public class BlockItem extends Item {
if (iblockdata1.is(iblockdata.getBlock())) {
iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1);
+ // Paper start - reset block on exception
+ try {
this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1);
+ } catch (Exception e) {
+ oldBlockstate.update(true, false);
+ if (entityhuman instanceof ServerPlayer player) {
+ org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), e);
+ player.getBukkitEntity().kickPlayer("Packet processing error");
+ return InteractionResult.FAIL;
+ }
+ throw e; // Rethrow exception if not placed by a player
+ }
+ // Paper end
iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack);
// CraftBukkit start
if (blockstate != null) {

View File

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 12 Jul 2021 12:28:29 +0100
Subject: [PATCH] Use a CHM for StructureTemplate.Pallete cache
fixes a CME due to this collection being shared across threads
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
@@ -0,0 +0,0 @@ public class StructureTemplate {
public static final class Palette {
private final List<StructureTemplate.StructureBlockInfo> blocks;
- private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newHashMap();
+ private final Map<Block, List<StructureTemplate.StructureBlockInfo>> cache = Maps.newConcurrentMap(); // Paper
Palette(List<StructureTemplate.StructureBlockInfo> infos) {
this.blocks = infos;