Compare commits

..
78 Commits
Author SHA1 Message Date
Owen1212055 427c3062d7 Update to paperweight release 2025-03-13 22:48:15 -04:00
Bjarne Koll d837c9f3c3 Fixup incorrect diff comments 2025-03-13 23:14:21 +01:00
Lulu13022002 840583cc5e bypass lastLavaContact 2025-03-13 22:31:01 +01:00
Owen1212055 96e5ceb147 Fix the fix 2025-03-13 16:19:46 -04:00
Owen1212055 d52684e325 Fixes 2025-03-13 16:14:38 -04:00
Lulu13022002 c8f9c17638 update tag usage in item meta and fix maxDomestication default 2025-03-13 19:46:14 +01:00
Owen1212055 dbc5747dad Redo createWithoutValidityChecks
Instead go with a static flag marked on creation. This prevents the agressive rewrite needed.
2025-03-13 14:43:52 -04:00
Owen1212055 75297490ed Better delegate #setItemSlot 2025-03-13 14:23:38 -04:00
Lulu13022002 8849f5b24e some fixes 2025-03-13 18:28:19 +01:00
Bjarne Koll d5c6a22613 Correct DataFixer 2025-03-13 16:59:47 +01:00
Bjarne Koll a85a2db790 And some more work 2025-03-13 15:15:11 +01:00
Tamion af241555be TadPole 2025-03-13 13:49:24 +01:00
Nassim Jahnke 57c3792405 MobSpawnSettings 2025-03-13 13:45:47 +01:00
Tamion 1bb6118750 OceanRuinPieces 2025-03-13 13:34:14 +01:00
Bjarne Koll df9ce9405e Next bit of work 2025-03-13 12:44:43 +01:00
Bjarne Koll 218bb00997 CompoundTag readQuiet 2025-03-13 12:22:37 +01:00
Owen1212055 e0e6ae86a8 DispenseItemBehavior:
Note this patch may need to be redone as their is now a success method that needs to be called.
2025-03-13 01:55:34 -04:00
Jake Potrebic fc231e5b78 Container & RandomizableContainer 2025-03-12 22:29:18 -07:00
Bjarne Koll a0a0bec65c Use correct depth limit 2025-03-13 02:02:46 +01:00
Bjarne Koll b803be88ee Drop old TagParser attempt hunk 2025-03-13 02:00:57 +01:00
Bjarne Koll ab3b3f2564 A potentially better attempt at TagParser 2025-03-13 02:00:12 +01:00
Bjarne Koll aa15ca8009 Possible incorrect attempt at TagParser 2025-03-13 01:36:48 +01:00
Bjarne Koll 41d9ab1aeb DataFixer 2025-03-13 01:36:48 +01:00
Bjarne Koll 34ee6e5d49 ScoreboardSaveData 2025-03-13 01:36:48 +01:00
Jake Potrebic cefefc9591 Raid & Raids 2025-03-12 17:06:50 -07:00
Bjarne Koll befe2439b8 PlayerList 2025-03-13 00:24:22 +01:00
Bjarne Koll c2811eddbe Smithing recipes 2025-03-13 00:24:22 +01:00
Bjarne Koll e205825404 ArmorStand and ItemFrame 2025-03-13 00:24:22 +01:00
Lulu13022002 72e7cc1a3c cauldron 2025-03-12 23:23:59 +01:00
Lulu13022002 6eed97a251 vehicle lootable 2025-03-12 22:54:38 +01:00
Lulu13022002 eebde33db3 axolotl 2025-03-12 22:35:00 +01:00
Lulu13022002 461c531e0a piston 2025-03-12 22:17:46 +01:00
Warrior 51e8551ea0 Some npcs 2025-03-12 22:14:10 +01:00
Nassim Jahnke 90805c262c Some monsters 2025-03-12 22:07:17 +01:00
Lulu13022002 ad5d426e62 more entities 2025-03-12 22:00:18 +01:00
Tamion 91c0d9f374 StructureTemplate 2025-03-12 21:40:12 +01:00
Lulu13022002 c8b5eb5db7 dragon phases 2025-03-12 21:40:36 +01:00
Warrior afeb8e951f Last world/entity patches 2025-03-12 21:33:40 +01:00
Lulu13022002 75d19e26d7 more entities 2025-03-12 21:32:01 +01:00
Warrior 6e5effa052 2 Goals 2025-03-12 21:20:39 +01:00
Tamion 4fb84d6047 Rotations/Direction 2025-03-12 21:12:33 +01:00
Lulu13022002 0a41b4eeaf some entities 2025-03-12 21:12:48 +01:00
Warrior 4b53e74746 Remaining projectile classes 2025-03-12 20:58:38 +01:00
Lulu13022002 bea046e78d projectiles 2025-03-12 20:56:26 +01:00
Tamion d933a7b302 fix PatrolSpawner diff 2025-03-12 20:44:10 +01:00
Warrior 641505fee5 Fix missed arrow diff 2025-03-12 20:39:33 +01:00
Warrior c99e67a4fd Some projectiles 2025-03-12 20:35:49 +01:00
Tamion d4ea8628e2 Patrol/PhantomSpawner 2025-03-12 20:29:31 +01:00
Owen1212055 2379365a2b Patches 2025-03-12 15:27:33 -04:00
Owen1212055 eee862f577 ServerGamePacketListenerImpl.java.patch diff
A couple of notes:
-Player movement no longer calls this.player.absMoveTo(d, d1, d2, f, f1); ?
- Do we still need the Record my movement through blocks spectator check?
2025-03-12 15:27:32 -04:00
Owen1212055 f3f2c8155f Chunk Related Patches
We will need to look into what to do with the identifiers, as previously tickets held onto that but that is gone now.

But overall I inlined the behavior to be identical to FORCED tickets, as that is what it was trying to replicate before.

I kinda just ignore the identifiers for now, as someone else who is more knowledgeable with this can take over.

I also added a diff to chunkmap very intentionally, for whoever gets that patch needs to make sure that method parameter is transfered. (reducedRange equivalent)
2025-03-12 15:27:32 -04:00
Owen1212055 ac68fdc170 Block package 2025-03-12 15:27:32 -04:00
Lulu13022002 c0718848eb container / enchantment menu 2025-03-12 20:28:34 +01:00
Bjarne Koll a6cff5b519 LavaFluid 2025-03-12 20:17:58 +01:00
Noah van der Aa 27bd1fa0b7 random stuff 2025-03-12 20:17:31 +01:00
Noah van der Aa 3ca4f21b90 command fun 2025-03-12 20:01:43 +01:00
Noah van der Aa 5ace1ec0f4 Some work 2025-03-12 19:46:17 +01:00
Warrior 667fa29f93 Fix itemstack diff 2025-03-12 19:23:31 +01:00
Warrior e69d1e6bb4 A few effect/item patches 2025-03-12 19:21:43 +01:00
Bjarne Koll b4322626d2 Piglin 2025-03-12 19:08:36 +01:00
Bjarne Koll 2d58b75357 Some more work 2025-03-12 19:08:36 +01:00
Warrior f875b15d7e Apply OozingMobEffect 2025-03-12 18:34:20 +01:00
Warrior 637a82d779 Apply ArmorStandItem 2025-03-12 18:26:47 +01:00
Bjarne Koll 0f34603c5c Missed furnace block entity diff 2025-03-12 18:25:09 +01:00
Bjarne Koll 8ea09b9d47 Some more work 2025-03-12 18:23:57 +01:00
Bjarne Koll 3ec2262294 Some more work 2025-03-12 17:48:19 +01:00
Bjarne Koll fd4d92e604 Some work to test tooling flow myself 2025-03-12 17:32:53 +01:00
Tamion 6f87d74cf5 Hoglin patch 2025-03-12 15:11:16 +01:00
Owen1212055 1b15719bc8 entity package 2025-03-12 01:26:06 -04:00
Owen1212055 20dee726d0 Some patches 2025-03-11 23:31:19 -04:00
Owen1212055 2ce46092d6 Some patches 2025-03-11 17:11:07 -04:00
Owen1212055 ff9bebb2f1 YIPPEE first patch 2025-03-11 17:00:22 -04:00
Bjarne Koll 208e1ee139 Update resource patches 2025-03-11 21:19:32 +01:00
Bjarne Koll 02e693f159 Move back to diff patches 2025-03-11 18:44:30 +01:00
Bjarne Koll 5e6bcf1412 Rebuild and reject patches 2025-03-11 18:43:40 +01:00
Bjarne Koll 3281c4fdce Bump version 2025-03-11 18:40:33 +01:00
Bjarne Koll ffd7272128 Convert patches to git 2025-03-11 17:41:15 +01:00
Bjarne Koll b7f4c58eab Change to unreleased paperweight version 2025-03-11 17:34:14 +01:00
468 changed files with 5628 additions and 6253 deletions

No files matched your search

-1
View File
@@ -5,4 +5,3 @@ gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
.gitea/CODEOWNERS linguist-detectable=false
-3
View File
@@ -1,3 +0,0 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
+1
View File
@@ -122,6 +122,7 @@ public net.minecraft.tags.TagEntry id
public net.minecraft.tags.TagEntry required
public net.minecraft.tags.TagEntry tag
public net.minecraft.util.datafix.fixes.BlockStateData register(ILjava/lang/String;[Ljava/lang/String;)V
public net.minecraft.util.datafix.fixes.EntityCustomNameToComponentFix fixCustomName(Lcom/mojang/serialization/DynamicOps;Ljava/lang/String;Ljava/lang/String;)Lcom/mojang/serialization/Dynamic;
public net.minecraft.util.datafix.fixes.ItemIdFix ITEM_NAMES
public net.minecraft.util.datafix.fixes.ItemSpawnEggFix ID_TO_ENTITY
public net.minecraft.world.BossEvent color
+1 -1
View File
@@ -12,7 +12,7 @@ import java.nio.file.Path
import kotlin.random.Random
plugins {
id("io.papermc.paperweight.core") version "2.0.0-beta.14" apply false
id("io.papermc.paperweight.core") version "2.0.0-beta.15" apply false
}
subprojects {
+3 -3
View File
@@ -1,9 +1,9 @@
group=io.papermc.paper
version=1.21.4-R0.1-SNAPSHOT
mcVersion=1.21.4
version=1.21.5-R0.1-SNAPSHOT
mcVersion=1.21.5-pre1
# Set to true while updating Minecraft version
updatingMinecraft=false
updatingMinecraft=true
updateTaskListIssue=https://github.com/PaperMC/Paper/issues/11736
org.gradle.configuration-cache=true
@@ -83,12 +83,14 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
* @see #NamespacedKey(Plugin, String)
*/
public NamespacedKey(@NotNull String namespace, @NotNull String key) {
Preconditions.checkArgument(namespace != null, "Namespace cannot be null");
Preconditions.checkArgument(key != null, "Key cannot be null");
Preconditions.checkArgument(namespace != null && isValidNamespace(namespace), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
Preconditions.checkArgument(key != null && isValidKey(key), "Invalid key. Must be [a-z0-9/._-]: %s", key);
this.namespace = namespace;
this.key = key;
this.validate();
String string = toString();
Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation
}
/**
@@ -106,17 +108,16 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
public NamespacedKey(@NotNull Plugin plugin, @NotNull String key) {
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
Preconditions.checkArgument(key != null, "Key cannot be null");
this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
this.key = key.toLowerCase(Locale.ROOT);
// Check validity after normalization
this.validate();
}
private void validate() {
Preconditions.checkArgument(this.namespace.length() + 1 + this.key.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters");
Preconditions.checkArgument(isValidNamespace(this.namespace), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
Preconditions.checkArgument(isValidKey(this.key), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
String string = toString();
Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation
}
@NotNull
@@ -64,7 +64,7 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
@SuppressWarnings("removal")
@Deprecated(forRemoval = true, since = "1.21.4")
private static <A extends Keyed> Registry<A> legacyRegistryFor(final Class<A> clazz) {
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), () -> "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
}
/**
@@ -57,7 +57,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
*/
@org.jetbrains.annotations.Contract(value = "_, _ -> new", pure = true)
public static @NotNull ItemStack of(final @NotNull Material type, final int amount) {
Preconditions.checkArgument(type.asItemType() != null, "%s isn't an item", type);
Preconditions.checkArgument(type.asItemType() != null, type + " isn't an item");
Preconditions.checkArgument(amount > 0, "amount must be greater than 0");
return java.util.Objects.requireNonNull(type.asItemType(), type + " is not an item").createItemStack(amount); // Paper - delegate
}
+6 -3
View File
@@ -11,15 +11,18 @@ plugins {
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
dependencies {
mache("io.papermc:mache:1.21.4+build.7")
mache("io.papermc:mache:1.21.5-pre1+build.1")
paperclip("io.papermc:paperclip:3.0.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
paperweight {
minecraftVersion = providers.gradleProperty("mcVersion")
// macheOldPath = file("F:\\Projects\\PaperTooling\\mache\\versions\\1.21.4\\src\\main\\java")
// gitFilePatches = true
gitFilePatches = false
updatingMinecraft {
oldPaperCommit = "f4f275519f7c1fbe9db173b7144a4fe81440e365"
}
spigot {
buildDataRef = "3edaf46ec1eed4115ce1b18d2846cded42577e42"
@@ -23751,7 +23751,7 @@ index 841a41485af62470d833aba578069b19a0bd1e8d..409c1134327bfcc338c3ac5e658a83cc
// CraftBukkit start
public boolean isDebugging() {
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index ac7bc193f7ea63cbbba73df49f54a17ef7cdec40..d2db6e3a4af13984b0a790fb38e83c253914a973 100644
index f8c81d795b19e73d56d6e0196c75e441ab4c2bef..97a294d2f5c1ddf0af7ffec3e1425eb329c5751b 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -433,7 +433,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -26735,7 +26735,7 @@ index da793ad12565c36fffb26eb771ff68c76632caf7..db06f966077928419bfe469260f04d7d
if (!passengers.equals(this.lastPassengers)) {
this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index d1f235ebd835f58cf0c703c3a64d29825d98e183..080091efc19bc768bb9a660f366c42e831225505 100644
index 400b56657414177cd76a7b94c426dc7c886aa957..a275b17d0852d9d9bc850614713244e580ae81f1 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -170,7 +170,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
@@ -27976,10 +27976,10 @@ index 4eb040006f5d41b47e5ac9df5d9f19c4315d6343..7fa41dea184b01891f45d8e404bc1cba
this.generatingStep = generatingStep;
this.cache = cache;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 7eebb494e38b57e81b4f92f0a96d3a4c610d86df..065f4c810439dde464529b54ae300ecfcb1c2c31 100644
index 5d88b2790710a885957ffcffc02fb99c917123c5..7d1d4abfb04829d8c4722e326c6c6b8fb2ab91f4 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1317,7 +1317,7 @@ public abstract class PlayerList {
@@ -1312,7 +1312,7 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance;
@@ -27988,7 +27988,7 @@ index 7eebb494e38b57e81b4f92f0a96d3a4c610d86df..065f4c810439dde464529b54ae300ecf
for (ServerLevel serverLevel : this.server.getAllLevels()) {
if (serverLevel != null) {
@@ -1328,7 +1328,7 @@ public abstract class PlayerList {
@@ -1323,7 +1323,7 @@ public abstract class PlayerList {
public void setSimulationDistance(int simulationDistance) {
this.simulationDistance = simulationDistance;
@@ -28372,7 +28372,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 9b3b770f6986dd132da78fdc3626d334166ec52a..b2b61203438bb1fad1ee807729781718d2467155 100644
index 994791a83ca6712db3e74ca9aba4bfcd95a0ec6d..1b54cf07616a10d93e9336dbd299ba5f09678a28 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 4894d2bdb354d191fd062202cbcc0bdabfed9209..e54b5a165ad4dc4d2158dab34c5008512e5f7885 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -174,11 +_,13 @@
@@ -174,11 +174,13 @@ import net.minecraft.world.phys.Vec3;
import org.slf4j.Logger;
public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource {
@@ -15,7 +23,7 @@
private static final int OVERLOADED_TICKS_THRESHOLD = 20;
private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND;
private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100;
@@ -218,6 +_,7 @@
@@ -218,6 +220,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private Map<ResourceKey<Level>, ServerLevel> levels = Maps.newLinkedHashMap();
private PlayerList playerList;
private volatile boolean running = true;
@@ -23,7 +31,7 @@
private boolean stopped;
private int tickCount;
private int ticksUntilAutosave = 6000;
@@ -226,11 +_,15 @@
@@ -226,11 +229,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private boolean preventProxyConnections;
private boolean pvp;
private boolean allowFlight;
@@ -41,7 +49,7 @@
@Nullable
private KeyPair keyPair;
@Nullable
@@ -271,10 +_,37 @@
@@ -271,10 +278,37 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private final SuppressedExceptionCollector suppressedExceptions = new SuppressedExceptionCollector();
private final DiscontinuousFrame tickFrame;
@@ -80,7 +88,7 @@
if (Runtime.getRuntime().availableProcessors() > 4) {
thread.setPriority(8);
}
@@ -286,6 +_,10 @@
@@ -286,6 +320,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
public MinecraftServer(
@@ -91,7 +99,7 @@
Thread serverThread,
LevelStorageSource.LevelStorageAccess storageSource,
PackRepository packRepository,
@@ -296,9 +_,10 @@
@@ -296,9 +334,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
ChunkProgressListenerFactory progressListenerFactory
) {
super("Server");
@@ -103,7 +111,7 @@
throw new IllegalStateException("Missing Overworld dimension data");
} else {
this.proxy = proxy;
@@ -309,7 +_,7 @@
@@ -309,7 +348,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
services.profileCache().setExecutor(this);
}
@@ -112,7 +120,7 @@
this.tickRateManager = new ServerTickRateManager(this);
this.progressListenerFactory = progressListenerFactory;
this.storageSource = storageSource;
@@ -328,6 +_,38 @@
@@ -328,6 +367,38 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures());
this.tickFrame = TracyClient.createDiscontinuousFrame("Server Tick");
}
@@ -151,7 +159,7 @@
}
private void readScoreboard(DimensionDataStorage dataStorage) {
@@ -336,18 +_,13 @@
@@ -336,18 +407,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
protected abstract boolean initServer() throws IOException;
@@ -172,7 +180,7 @@
if (profiledDuration != null) {
profiledDuration.finish(true);
}
@@ -364,25 +_,265 @@
@@ -364,25 +430,265 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
protected void forceDifficulty() {
}
@@ -457,7 +465,7 @@
if (!serverLevelData.isInitialized()) {
try {
setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld);
@@ -403,47 +_,30 @@
@@ -403,47 +709,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevelData.setInitialized(true);
}
@@ -522,7 +530,7 @@
int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level);
if (spawnHeight < level.getMinY()) {
BlockPos worldPosition = chunkPos.getWorldPosition();
@@ -495,26 +_,31 @@
@@ -495,26 +784,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevelData.setGameType(GameType.SPECTATOR);
}
@@ -562,7 +570,7 @@
ForcedChunksSavedData forcedChunksSavedData = serverLevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks");
if (forcedChunksSavedData != null) {
LongIterator longIterator = forcedChunksSavedData.getChunks().iterator();
@@ -527,10 +_,17 @@
@@ -527,10 +821,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -583,7 +591,7 @@
}
public GameType getDefaultGameType() {
@@ -559,11 +_,14 @@
@@ -559,11 +860,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
flag = true;
}
@@ -598,7 +606,7 @@
if (flush) {
for (ServerLevel serverLevel2 : this.getAllLevels()) {
LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName());
@@ -593,18 +_,48 @@
@@ -593,18 +897,48 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.stopServer();
}
@@ -648,7 +656,7 @@
}
LOGGER.info("Saving worlds");
@@ -646,6 +_,25 @@
@@ -646,6 +980,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} catch (IOException var4) {
LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4);
}
@@ -674,7 +682,7 @@
}
public String getLocalIp() {
@@ -661,6 +_,14 @@
@@ -661,6 +1014,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
public void halt(boolean waitForServer) {
@@ -689,7 +697,7 @@
this.running = false;
if (waitForServer) {
try {
@@ -671,6 +_,57 @@
@@ -671,6 +1032,57 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -747,7 +755,7 @@
protected void runServer() {
try {
if (!this.initServer()) {
@@ -681,6 +_,35 @@
@@ -681,6 +1093,35 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.statusIcon = this.loadStatusIcon().orElse(null);
this.status = this.buildServerStatus();
@@ -783,7 +791,7 @@
while (this.running) {
long l;
if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) {
@@ -693,11 +_,30 @@
@@ -693,11 +1134,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l
&& this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) {
long l2 = l1 / l;
@@ -814,7 +822,7 @@
boolean flag = l == 0L;
if (this.debugCommandProfilerDelayStart) {
@@ -705,6 +_,8 @@
@@ -705,6 +1165,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
@@ -823,7 +831,7 @@
this.nextTickTimeNanos += l;
try (Profiler.Scope scope = Profiler.use(this.createProfiler())) {
@@ -755,7 +_,7 @@
@@ -755,7 +1217,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.services.profileCache().clearExecutor();
}
@@ -832,7 +840,7 @@
}
}
}
@@ -807,7 +_,14 @@
@@ -807,7 +1269,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
private boolean haveTime() {
@@ -848,7 +856,7 @@
}
public static boolean throwIfFatalException() {
@@ -852,6 +_,12 @@
@@ -852,6 +1321,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public TickTask wrapRunnable(Runnable runnable) {
@@ -861,7 +869,7 @@
return new TickTask(this.tickCount, runnable);
}
@@ -871,15 +_,16 @@
@@ -871,15 +1346,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (super.pollTask()) {
return true;
} else {
@@ -880,7 +888,7 @@
}
}
@@ -927,26 +_,44 @@
@@ -927,26 +1403,44 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
public void tickServer(BooleanSupplier hasTimeLeft) {
@@ -926,7 +934,7 @@
this.tickCount++;
this.tickRateManager.tick();
this.tickChildren(hasTimeLeft);
@@ -956,11 +_,19 @@
@@ -956,11 +1450,19 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
this.ticksUntilAutosave--;
@@ -947,7 +955,7 @@
profilerFiller.push("tallying");
long l = Util.getNanos() - nanos;
int i1 = this.tickCount % 100;
@@ -968,12 +_,17 @@
@@ -968,12 +1470,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.aggregatedTickTimesNanos += l;
this.tickTimesNanos[i1] = l;
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float)l / (float)TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
@@ -966,7 +974,7 @@
LOGGER.debug("Autosave started");
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("save");
@@ -1015,7 +_,7 @@
@@ -1015,7 +1522,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private ServerStatus buildServerStatus() {
ServerStatus.Players players = this.buildPlayerStatus();
return new ServerStatus(
@@ -975,7 +983,7 @@
Optional.of(players),
Optional.of(ServerStatus.Version.current()),
Optional.ofNullable(this.statusIcon),
@@ -1029,7 +_,7 @@
@@ -1029,7 +1536,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
} else {
@@ -984,7 +992,7 @@
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
@@ -1046,17 +_,66 @@
@@ -1046,17 +1553,66 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
protected void tickChildren(BooleanSupplier hasTimeLeft) {
ProfilerFiller profilerFiller = Profiler.get();
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
@@ -1051,7 +1059,7 @@
profilerFiller.push("tick");
@@ -1070,7 +_,9 @@
@@ -1070,7 +1626,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
profilerFiller.pop();
profilerFiller.pop();
@@ -1061,7 +1069,7 @@
profilerFiller.popPush("connection");
this.tickConnection();
@@ -1148,6 +_,22 @@
@@ -1148,6 +1706,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.levels.get(dimension);
}
@@ -1084,7 +1092,7 @@
public Set<ResourceKey<Level>> levelKeys() {
return this.levels.keySet();
}
@@ -1177,7 +_,7 @@
@@ -1177,7 +1751,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@DontObfuscate
public String getServerModName() {
@@ -1093,7 +1101,7 @@
}
public SystemReport fillSystemReport(SystemReport systemReport) {
@@ -1212,7 +_,7 @@
@@ -1212,7 +1786,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public void sendSystemMessage(Component component) {
@@ -1102,7 +1110,7 @@
}
public KeyPair getKeyPair() {
@@ -1250,11 +_,14 @@
@@ -1250,11 +1824,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -1122,7 +1130,7 @@
}
}
@@ -1264,7 +_,7 @@
@@ -1264,7 +1841,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private void updateMobSpawningFlags() {
for (ServerLevel serverLevel : this.getAllLevels()) {
@@ -1131,7 +1139,7 @@
}
}
@@ -1340,10 +_,20 @@
@@ -1340,10 +1917,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public String getMotd() {
@@ -1153,7 +1161,7 @@
this.motd = motd;
}
@@ -1366,7 +_,7 @@
@@ -1366,7 +1953,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
public ServerConnectionListener getConnection() {
@@ -1162,7 +1170,7 @@
}
public boolean isReady() {
@@ -1452,7 +_,7 @@
@@ -1452,7 +2039,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public void executeIfPossible(Runnable task) {
if (this.isStopped()) {
@@ -1171,7 +1179,7 @@
} else {
super.executeIfPossible(task);
}
@@ -1491,7 +_,13 @@
@@ -1491,7 +2078,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.functionManager;
}
@@ -1185,7 +1193,7 @@
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
() -> selectedIds.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()),
this
@@ -1499,7 +_,7 @@
@@ -1499,7 +2092,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
.thenCompose(
list -> {
CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, list);
@@ -1194,7 +1202,7 @@
return ReloadableServerResources.loadResources(
closeableResourceManager,
this.registries,
@@ -1520,20 +_,39 @@
@@ -1520,20 +2113,39 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
)
.thenAcceptAsync(
reloadableResources -> {
@@ -1236,7 +1244,7 @@
},
this
);
@@ -1550,7 +_,7 @@
@@ -1550,7 +2162,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
FeatureFlagSet featureFlagSet = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
FeatureFlagSet featureFlagSet1 = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
@@ -1245,7 +1253,7 @@
if (safeMode) {
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), featureFlagSet, false);
} else {
@@ -1605,7 +_,7 @@
@@ -1605,7 +2217,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private static WorldDataConfiguration configureRepositoryWithSelection(
PackRepository packRepository, Collection<String> selectedPacks, FeatureFlagSet enabledFeatures, boolean safeMode
) {
@@ -1254,7 +1262,7 @@
enableForcedFeaturePacks(packRepository, enabledFeatures);
DataPackConfig selectedPacks1 = getSelectedPacks(packRepository, safeMode);
FeatureFlagSet featureFlagSet = packRepository.getRequestedFeatureFlags().join(enabledFeatures);
@@ -1637,7 +_,7 @@
@@ -1637,7 +2249,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -1263,7 +1271,7 @@
}
}
@@ -1651,11 +_,12 @@
@@ -1651,11 +2263,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void kickUnlistedPlayers(CommandSourceStack commandSource) {
if (this.isEnforceWhitelist()) {
PlayerList playerList = commandSource.getServer().getPlayerList();
@@ -1278,7 +1286,7 @@
}
}
}
@@ -1859,6 +_,22 @@
@@ -1859,6 +2472,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -1301,7 +1309,7 @@
private ProfilerFiller createProfiler() {
if (this.willStartRecordingMetrics) {
this.metricsRecorder = ActiveMetricsRecorder.createStarted(
@@ -1980,16 +_,22 @@
@@ -1980,16 +2609,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) {
@@ -1317,18 +1325,18 @@
+ // Paper end
}
}
+
+ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool(
+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper
+ public final ChatDecorator improvedChatDecorator = new io.papermc.paper.adventure.ImprovedChatDecorator(this); // Paper - adventure
+
public ChatDecorator getChatDecorator() {
- return ChatDecorator.PLAIN;
+ return this.improvedChatDecorator; // Paper - support async chat decoration events
}
public boolean logIPs() {
@@ -2122,4 +_,53 @@
@@ -2122,4 +2757,53 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
};
}
}
@@ -0,0 +1,374 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 146b11ebb315efb4aea1d1183bd08f9db7c350e0..d95413af04121fe91ca0f3b0c70025b9808acef9 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -145,6 +145,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public int serverViewDistance;
private final WorldGenContext worldGenContext;
+ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
+ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
+ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
+
+ private final java.util.Queue<Runnable> queue = new java.util.ArrayDeque<>();
+
+ @Override
+ public void execute(Runnable runnable) {
+ this.queue.add(runnable);
+ }
+
+ @Override
+ public void run() {
+ Runnable task;
+ while ((task = this.queue.poll()) != null) {
+ task.run();
+ }
+ }
+ };
+ // CraftBukkit end
+
+ // Paper start
+ public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
+ return this.pendingUnloads.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ }
+ // Paper end
+
public ChunkMap(
ServerLevel level,
LevelStorageSource.LevelStorageAccess levelStorageAccess,
@@ -171,13 +198,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.level = level;
RegistryAccess registryAccess = level.registryAccess();
long seed = level.getSeed();
- if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
+ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random.
+ ChunkGenerator randomGenerator = generator;
+ if (randomGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator customChunkGenerator) {
+ randomGenerator = customChunkGenerator.getDelegate();
+ }
+ if (randomGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
+ // CraftBukkit end
this.randomState = RandomState.create(noiseBasedChunkGenerator.generatorSettings().value(), registryAccess.lookupOrThrow(Registries.NOISE), seed);
} else {
this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), registryAccess.lookupOrThrow(Registries.NOISE), seed);
}
- this.chunkGeneratorState = generator.createState(registryAccess.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, seed);
+ this.chunkGeneratorState = generator.createState(registryAccess.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, seed, level.spigotConfig); // Spigot
this.mainThreadExecutor = mainThreadExecutor;
ConsecutiveExecutor consecutiveExecutor = new ConsecutiveExecutor(dispatcher, "worldgen");
this.progressListener = progressListener;
@@ -207,6 +240,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.chunksToEagerlySave.add(chunkPos.toLong());
}
+ // Paper start
+ public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
+ return -1;
+ }
+ // Paper end
+
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
}
@@ -354,9 +393,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
);
stringBuilder.append("Updating:").append(System.lineSeparator());
- this.updatingChunkMap.values().forEach(consumer);
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().getUpdatingChunkHolders(this.level).forEach(consumer); // Paper
stringBuilder.append("Visible:").append(System.lineSeparator());
- this.visibleChunkMap.values().forEach(consumer);
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level).forEach(consumer); // Paper
CrashReport crashReport = CrashReport.forThrowable(exception, "Chunk loading");
CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk loading");
crashReportCategory.setDetail("Details", details);
@@ -392,6 +431,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
holder.setTicketLevel(newLevel);
} else {
holder = new ChunkHolder(new ChunkPos(chunkPos), newLevel, this.level, this.lightEngine, this::onLevelChange, this);
+ // Paper start
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder);
+ // Paper end
}
this.updatingChunkMap.put(chunkPos, holder);
@@ -420,8 +462,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
protected void saveAllChunks(boolean flush) {
if (flush) {
- List<ChunkHolder> list = this.visibleChunkMap
- .values()
+ List<ChunkHolder> list = ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level) // Paper - moonrise
+ //.values() // Paper - moonrise
.stream()
.filter(ChunkHolder::wasAccessibleSinceLastSave)
.peek(ChunkHolder::refreshAccessibility)
@@ -447,7 +489,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.nextChunkSaveTime.clear();
long millis = Util.getMillis();
- for (ChunkHolder chunkHolder : this.visibleChunkMap.values()) {
+ for (ChunkHolder chunkHolder : ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level)) { // Paper
this.saveChunkIfNeeded(chunkHolder, millis);
}
}
@@ -468,6 +510,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public boolean hasWork() {
return this.lightEngine.hasLightWork()
|| !this.pendingUnloads.isEmpty()
+ || ca.spottedleaf.moonrise.common.PlatformHooks.get().hasAnyChunkHolders(this.level) // Paper - moonrise
|| !this.updatingChunkMap.isEmpty()
|| this.poiManager.hasWork()
|| !this.toDrop.isEmpty()
@@ -526,7 +569,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.scheduleUnload(chunkPos, chunkHolder);
} else {
ChunkAccess latestChunk = chunkHolder.getLatestChunk();
- if (this.pendingUnloads.remove(chunkPos, chunkHolder) && latestChunk != null) {
+ // Paper start
+ boolean removed;
+ if ((removed = this.pendingUnloads.remove(chunkPos, chunkHolder)) && latestChunk != null) {
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderDelete(this.level, chunkHolder);
+ // Paper end
if (latestChunk instanceof LevelChunk levelChunk) {
levelChunk.setLoaded(false);
}
@@ -540,7 +587,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.lightEngine.tryScheduleUpdate();
this.progressListener.onStatusChange(latestChunk.getPos(), null);
this.nextChunkSaveTime.remove(latestChunk.getPos().toLong());
- }
+ } else if (removed) { // Paper start
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderDelete(this.level, chunkHolder);
+ } // Paper end
}
}, this.unloadQueue::add).whenComplete((_void, error) -> {
if (error != null) {
@@ -856,7 +905,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public int size() {
- return this.visibleChunkMap.size();
+ return ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolderCount(this.level); // Paper
}
public net.minecraft.server.level.DistanceManager getDistanceManager() {
@@ -864,7 +913,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
protected Iterable<ChunkHolder> getChunks() {
- return Iterables.unmodifiableIterable(this.visibleChunkMap.values());
+ return Iterables.unmodifiableIterable(ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level)); // Paper
}
void dumpChunks(Writer writer) throws IOException {
@@ -888,10 +937,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
.build(writer);
TickingTracker tickingTracker = this.distanceManager.tickingTracker();
- for (Entry<ChunkHolder> entry : this.visibleChunkMap.long2ObjectEntrySet()) {
- long longKey = entry.getLongKey();
+ for (ChunkHolder entry : ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level)) { // Paper - Moonrise
+ long longKey = entry.pos.toLong(); // Paper - Moonrise
ChunkPos chunkPos = new ChunkPos(longKey);
- ChunkHolder chunkHolder = entry.getValue();
+ ChunkHolder chunkHolder = entry; // Paper - Moonrise
Optional<ChunkAccess> optional = Optional.ofNullable(chunkHolder.getLatestChunk());
Optional<LevelChunk> optional1 = optional.flatMap(chunk -> chunk instanceof LevelChunk ? Optional.of((LevelChunk)chunk) : Optional.empty());
csvOutput.writeRow(
@@ -931,11 +980,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
- return this.read(pos).thenApplyAsync(optional -> optional.map(this::upgradeChunkTag), Util.backgroundExecutor().forName("upgradeChunk"));
+ return this.read(pos).thenApplyAsync(optional -> optional.map(tag -> upgradeChunkTag(tag, pos)), Util.backgroundExecutor().forName("upgradeChunk")); // CraftBukkit
}
- private CompoundTag upgradeChunkTag(CompoundTag tag) {
- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, tag, this.generator().getTypeNameForDataFixer());
+ // CraftBukkit start
+ private CompoundTag upgradeChunkTag(CompoundTag tag, ChunkPos pos) {
+ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, tag, this.generator().getTypeNameForDataFixer(), pos, this.level);
+ // CraftBukkit end
}
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> action) {
@@ -951,12 +1002,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) {
- return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos);
+ // Spigot start
+ return this.anyPlayerCloseEnoughForSpawning(chunkPos, false);
+ }
+
+ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos, boolean reducedRange) {
+ return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange);
+ // Spigot end
}
private boolean anyPlayerCloseEnoughForSpawningInternal(ChunkPos chunkPos) {
+ // Spigot start
+ return this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, false);
+ }
+
+ private boolean anyPlayerCloseEnoughForSpawningInternal(ChunkPos chunkPos, boolean reducedRange) {
+ double blockRange; // Paper - use from event
+ // Spigot end
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
- if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos)) {
+ // Paper start - PlayerNaturallySpawnCreaturesEvent
+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event;
+ blockRange = 16384.0D;
+ if (reducedRange) {
+ event = serverPlayer.playerNaturallySpawnedEvent;
+ if (event == null || event.isCancelled()) continue;
+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
+ }
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, blockRange)) {
return true;
}
}
@@ -972,7 +1045,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
Builder<ServerPlayer> builder = ImmutableList.builder();
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
- if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos)) {
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, 16384.0D)) { // Spigot
builder.add(serverPlayer);
}
}
@@ -981,12 +1054,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
}
- private boolean playerIsCloseEnoughForSpawning(ServerPlayer player, ChunkPos chunkPos) {
+ private boolean playerIsCloseEnoughForSpawning(ServerPlayer player, ChunkPos chunkPos, double range) { // Spigot
if (player.isSpectator()) {
return false;
} else {
double d = euclideanDistanceSquared(chunkPos, player);
- return d < 16384.0;
+ return d < range; // Spigot
}
}
@@ -1100,9 +1173,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void addEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server
+ if (!entity.valid || entity.level() != this.level || this.entityMap.containsKey(entity.getId())) {
+ LOGGER.error("Illegal ChunkMap::addEntity for world " + this.level.getWorld().getName()
+ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
+ return;
+ }
+ // Paper end - ignore and warn about illegal addEntity calls instead of crashing server
+ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Paper - Fire PlayerJoinEvent when Player is actually ready; Delay adding to tracker until after list packets
if (!(entity instanceof EnderDragonPart)) {
EntityType<?> type = entity.getType();
int i = type.clientTrackingRange() * 16;
+ i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i); // Spigot
if (i != 0) {
int updateInterval = type.updateInterval();
if (this.entityMap.containsKey(entity.getId())) {
@@ -1126,6 +1209,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
protected void removeEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity untrack"); // Spigot
if (entity instanceof ServerPlayer serverPlayer) {
this.updatePlayerStatus(serverPlayer, false);
@@ -1230,7 +1314,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
});
}
- class DistanceManager extends net.minecraft.server.level.DistanceManager {
+ public class DistanceManager extends net.minecraft.server.level.DistanceManager { // Paper - public
protected DistanceManager(final Executor dispatcher, final Executor mainThreadExecutor) {
super(dispatcher, mainThreadExecutor);
}
@@ -1258,10 +1342,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
final Entity entity;
private final int range;
SectionPos lastSectionPos;
- public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast);
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this.seenBy); // CraftBukkit
this.entity = entity;
this.range = range;
this.lastSectionPos = SectionPos.of(entity);
@@ -1297,24 +1381,47 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void removePlayer(ServerPlayer player) {
+ org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot
if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
}
}
public void updatePlayer(ServerPlayer player) {
+ org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
if (player != this.entity) {
- Vec3 vec3 = player.position().subtract(this.entity.position());
+ // Paper start - remove allocation of Vec3D here
+ // Vec3 vec3 = player.position().subtract(this.entity.position());
+ double vec3_dx = player.getX() - this.entity.getX();
+ double vec3_dz = player.getZ() - this.entity.getZ();
+ // Paper end - remove allocation of Vec3D here
int playerViewDistance = ChunkMap.this.getPlayerViewDistance(player);
double d = Math.min(this.getEffectiveRange(), playerViewDistance * 16);
- double d1 = vec3.x * vec3.x + vec3.z * vec3.z;
+ double d1 = vec3_dx * vec3_dx + vec3_dz * vec3_dz; // Paper
double d2 = d * d;
- boolean flag = d1 <= d2
- && this.entity.broadcastToPlayer(player)
- && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+ // Paper start - Configurable entity tracking range by Y
+ boolean flag = d1 <= d2;
+ if (flag && level.paperConfig().entities.trackingRangeY.enabled) {
+ double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
+ if (rangeY != -1) {
+ double vec3_dy = player.getY() - this.entity.getY();
+ flag = vec3_dy * vec3_dy <= rangeY * rangeY;
+ }
+ }
+ flag = flag && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+ // Paper end - Configurable entity tracking range by Y
+ // CraftBukkit start - respect vanish API
+ if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
+ flag = false;
+ }
+ // CraftBukkit end
if (flag) {
if (this.seenBy.add(player.connection)) {
+ // Paper start - entity tracking events
+ if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) {
this.serverEntity.addPairing(player);
+ }
+ // Paper end - entity tracking events
}
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
@@ -1331,6 +1438,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
for (Entity entity : this.entity.getIndirectPassengers()) {
int i1 = entity.getType().clientTrackingRange() * 16;
+ i1 = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i1); // Paper
if (i1 > i) {
i = i1;
}
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 969ed16b60e4a4e3b656f44823bceee7fe215890..f45fb8ddb08d82ce76018b5a5c4fce5b3b319559 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -182,7 +_,7 @@
@@ -182,7 +182,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
final List<ServerPlayer> players = Lists.newArrayList();
public final ServerChunkCache chunkSource;
private final MinecraftServer server;
@@ -9,7 +17,7 @@
private int lastSpawnChunkRadius;
final EntityTickList entityTickList = new EntityTickList();
public final PersistentEntitySectionManager<Entity> entityManager;
@@ -209,11 +_,132 @@
@@ -209,11 +209,132 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private final boolean tickTime;
private final RandomSequences randomSequences;
@@ -143,7 +151,7 @@
ResourceKey<Level> dimension,
LevelStem levelStem,
ChunkProgressListener progressListener,
@@ -221,14 +_,38 @@
@@ -221,14 +342,38 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
long biomeZoomSeed,
List<CustomSpawner> customSpawners,
boolean tickTime,
@@ -184,7 +192,7 @@
boolean flag = server.forceSynchronousWrites();
DataFixer fixerUpper = server.getFixerUpper();
EntityPersistentStorage<Entity> entityPersistentStorage = new EntityStorage(
@@ -250,8 +_,8 @@
@@ -250,8 +395,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
server.getStructureManager(),
dispatcher,
chunkGenerator,
@@ -195,7 +203,7 @@
flag,
progressListener,
this.entityManager::updateChunkStatus,
@@ -272,7 +_,7 @@
@@ -272,7 +417,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.chunkSource.chunkScanner(),
this.registryAccess(),
server.getStructureManager(),
@@ -204,7 +212,7 @@
chunkGenerator,
this.chunkSource.randomState(),
this,
@@ -280,9 +_,9 @@
@@ -280,9 +425,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
seed,
fixerUpper
);
@@ -217,11 +225,10 @@
} else {
this.dragonFight = null;
}
@@ -292,7 +_,15 @@
@@ -292,7 +437,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.randomSequences = Objects.requireNonNullElseGet(
randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(seed), "random_sequences")
);
- }
+ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
+ }
+
@@ -229,12 +236,12 @@
+ @Override
+ public boolean hasChunk(int chunkX, int chunkZ) {
+ return this.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ) != null;
+ }
}
+ // Paper end
@Deprecated
@VisibleForTesting
@@ -304,8 +_,8 @@
@@ -304,8 +457,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.serverLevelData.setClearWeatherTime(clearTime);
this.serverLevelData.setRainTime(weatherTime);
this.serverLevelData.setThunderTime(weatherTime);
@@ -245,7 +252,7 @@
}
@Override
@@ -332,12 +_,25 @@
@@ -332,12 +485,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) {
@@ -274,7 +281,7 @@
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) {
this.resetWeatherCycle();
}
@@ -352,9 +_,9 @@
@@ -352,9 +518,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (!this.isDebug() && runsNormally) {
long l = this.getGameTime();
profilerFiller.push("blockTicks");
@@ -286,7 +293,7 @@
profilerFiller.pop();
}
@@ -372,7 +_,7 @@
@@ -372,7 +538,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.handlingTick = false;
profilerFiller.pop();
@@ -295,7 +302,7 @@
if (flag) {
this.resetEmptyTime();
}
@@ -461,12 +_,12 @@
@@ -461,12 +627,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
int minBlockZ = pos.getMinBlockZ();
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("thunder");
@@ -310,7 +317,7 @@
&& !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD);
if (flag) {
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
@@ -474,7 +_,7 @@
@@ -474,7 +640,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
skeletonHorse.setTrap(true);
skeletonHorse.setAge(0);
skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
@@ -319,7 +326,7 @@
}
}
@@ -482,18 +_,20 @@
@@ -482,18 +648,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (lightningBolt != null) {
lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos));
lightningBolt.setVisualOnly(flag);
@@ -341,7 +348,7 @@
profilerFiller.popPush("tickBlocks");
if (randomTickSpeed > 0) {
@@ -535,7 +_,7 @@
@@ -535,7 +703,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
BlockPos blockPos1 = heightmapPos.below();
Biome biome = this.getBiome(heightmapPos).value();
if (biome.shouldFreeze(this, blockPos1)) {
@@ -350,7 +357,7 @@
}
if (this.isRaining()) {
@@ -547,10 +_,10 @@
@@ -547,10 +715,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (layersValue < Math.min(_int, 8)) {
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, Integer.valueOf(layersValue + 1));
Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos);
@@ -363,7 +370,7 @@
}
}
@@ -575,6 +_,11 @@
@@ -575,6 +743,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
protected BlockPos findLightningTargetAround(BlockPos pos) {
@@ -375,7 +382,7 @@
BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
Optional<BlockPos> optional = this.findLightningRod(heightmapPos);
if (optional.isPresent()) {
@@ -582,11 +_,12 @@
@@ -582,11 +755,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
} else {
AABB aabb = AABB.encapsulatingFullBlocks(heightmapPos, heightmapPos.atY(this.getMaxY() + 1)).inflate(3.0);
List<LivingEntity> entitiesOfClass = this.getEntitiesOfClass(
@@ -389,7 +396,7 @@
if (heightmapPos.getY() == this.getMinY() - 1) {
heightmapPos = heightmapPos.above(2);
}
@@ -673,8 +_,8 @@
@@ -673,8 +847,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.serverLevelData.setThunderTime(thunderTime);
this.serverLevelData.setRainTime(rainTime);
this.serverLevelData.setClearWeatherTime(clearWeatherTime);
@@ -400,7 +407,7 @@
}
this.oThunderLevel = this.thunderLevel;
@@ -695,6 +_,7 @@
@@ -695,6 +869,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F);
}
@@ -408,7 +415,7 @@
if (this.oRainLevel != this.rainLevel) {
this.server
.getPlayerList()
@@ -717,14 +_,47 @@
@@ -717,14 +892,47 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel));
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
}
@@ -460,7 +467,7 @@
}
public void resetEmptyTime() {
@@ -746,18 +_,46 @@
@@ -746,18 +954,46 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
}
@@ -507,7 +514,7 @@
}
private void tickPassenger(Entity ridingEntity, Entity passengerEntity) {
@@ -766,10 +_,12 @@
@@ -766,10 +1002,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
passengerEntity.setOldPosAndRot();
passengerEntity.tickCount++;
@@ -520,7 +527,7 @@
profilerFiller.pop();
for (Entity entity : passengerEntity.getPassengers()) {
@@ -786,6 +_,7 @@
@@ -786,6 +1024,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) {
ServerChunkCache chunkSource = this.getChunkSource();
if (!skipSave) {
@@ -528,7 +535,7 @@
if (progress != null) {
progress.progressStartNoAbort(Component.translatable("menu.savingLevel"));
}
@@ -802,11 +_,19 @@
@@ -802,11 +1041,19 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.entityManager.autoSave();
}
}
@@ -549,7 +556,7 @@
}
DimensionDataStorage dataStorage = this.getChunkSource().getDataStorage();
@@ -871,18 +_,40 @@
@@ -871,18 +1118,40 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public boolean addFreshEntity(Entity entity) {
@@ -593,7 +600,7 @@
}
}
@@ -905,40 +_,119 @@
@@ -905,40 +1174,119 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.entityManager.addNewEntity(player);
}
@@ -667,7 +674,6 @@
public void removePlayerImmediately(ServerPlayer player, Entity.RemovalReason reason) {
- player.remove(reason);
- }
+ player.remove(reason, null); // CraftBukkit - add Bukkit remove cause
+ }
+
@@ -684,7 +690,7 @@
+ }
+
+ return this.addFreshEntity(entitylightning);
+ }
}
+ // CraftBukkit end
@Override
@@ -718,7 +724,7 @@
if (d * d + d1 * d1 + d2 * d2 < 1024.0) {
serverPlayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress));
}
@@ -1000,7 +_,7 @@
@@ -1000,7 +1348,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {
this.server
.getPlayerList()
@@ -727,7 +733,7 @@
}
public int getLogicalHeight() {
@@ -1009,6 +_,11 @@
@@ -1009,6 +1357,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public void gameEvent(Holder<GameEvent> gameEvent, Vec3 pos, GameEvent.Context context) {
@@ -739,7 +745,7 @@
this.gameEventDispatcher.post(gameEvent, pos, context);
}
@@ -1021,17 +_,28 @@
@@ -1021,17 +1374,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.getChunkSource().blockChanged(pos);
this.pathTypesByPosCache.invalidate(pos);
@@ -768,7 +774,7 @@
try {
this.isUpdatingNavigations = true;
@@ -1043,15 +_,18 @@
@@ -1043,15 +1407,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.isUpdatingNavigations = false;
}
}
@@ -787,7 +793,7 @@
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, null, orientation);
}
@@ -1100,6 +_,42 @@
@@ -1100,6 +1467,42 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
ParticleOptions largeExplosionParticles,
Holder<SoundEvent> explosionSound
) {
@@ -830,7 +836,7 @@
Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) {
case NONE -> Explosion.BlockInteraction.KEEP;
case BLOCK -> this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY);
@@ -1108,10 +_,17 @@
@@ -1108,10 +1511,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
: Explosion.BlockInteraction.KEEP;
case TNT -> this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY);
case TRIGGER -> Explosion.BlockInteraction.TRIGGER_BLOCK;
@@ -848,7 +854,7 @@
ParticleOptions particleOptions = serverExplosion.isSmall() ? smallExplosionParticles : largeExplosionParticles;
for (ServerPlayer serverPlayer : this.players) {
@@ -1120,6 +_,8 @@
@@ -1120,6 +1530,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
serverPlayer.connection.send(new ClientboundExplodePacket(vec3, optional, particleOptions, explosionSound));
}
}
@@ -857,7 +863,7 @@
}
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayGameRule) {
@@ -1190,7 +_,7 @@
@@ -1190,7 +1602,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public <T extends ParticleOptions> int sendParticles(
T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed
) {
@@ -866,7 +872,7 @@
}
public <T extends ParticleOptions> int sendParticles(
@@ -1206,13 +_,49 @@
@@ -1206,13 +1618,49 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
double zOffset,
double speed
) {
@@ -918,7 +924,7 @@
if (this.sendParticles(serverPlayer, overrideLimiter, posX, posY, posZ, clientboundLevelParticlesPacket)) {
i++;
}
@@ -1280,7 +_,7 @@
@@ -1280,7 +1728,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Nullable
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipExistingChunks) {
@@ -927,7 +933,7 @@
return null;
} else {
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
@@ -1327,11 +_,38 @@
@@ -1327,11 +1775,38 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Nullable
@Override
public MapItemSavedData getMapData(MapId mapId) {
@@ -967,7 +973,7 @@
this.getServer().overworld().getDataStorage().set(mapId.key(), mapData);
}
@@ -1344,17 +_,27 @@
@@ -1344,17 +1819,27 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
BlockPos spawnPos = this.levelData.getSpawnPos();
float spawnAngle = this.levelData.getSpawnAngle();
if (!spawnPos.equals(pos) || spawnAngle != angle) {
@@ -997,7 +1003,7 @@
}
this.lastSpawnChunkRadius = i;
@@ -1403,6 +_,11 @@
@@ -1403,6 +1888,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
DebugPackets.sendPoiRemovedPacket(this, blockPos);
}));
optional1.ifPresent(poiType -> this.getServer().execute(() -> {
@@ -1009,7 +1015,7 @@
this.getPoiManager().add(blockPos, (Holder<PoiType>)poiType);
DebugPackets.sendPoiAddedPacket(this, blockPos);
}));
@@ -1543,6 +_,11 @@
@@ -1543,6 +2033,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public void blockUpdated(BlockPos pos, Block block) {
if (!this.isDebug()) {
@@ -1021,7 +1027,7 @@
this.updateNeighborsAt(pos, block);
}
}
@@ -1562,12 +_,12 @@
@@ -1562,12 +2057,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
public boolean isFlat() {
@@ -1036,7 +1042,7 @@
}
@Nullable
@@ -1618,6 +_,7 @@
@@ -1618,6 +2113,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public LevelEntityGetter<Entity> getEntities() {
@@ -1044,7 +1050,7 @@
return this.entityManager.getEntityGetter();
}
@@ -1699,6 +_,27 @@
@@ -1699,6 +2195,27 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return this.serverLevelData.getGameRules();
}
@@ -1072,7 +1078,7 @@
@Override
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
@@ -1714,6 +_,7 @@
@@ -1714,6 +2231,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
final class EntityCallbacks implements LevelCallback<Entity> {
@Override
public void onCreated(Entity entity) {
@@ -1080,7 +1086,7 @@
}
@Override
@@ -1723,24 +_,32 @@
@@ -1723,24 +2241,32 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public void onTickingStart(Entity entity) {
@@ -1115,7 +1121,7 @@
String string = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde(
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
@@ -1757,10 +_,52 @@
@@ -1757,10 +2283,52 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
@@ -1168,7 +1174,7 @@
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
@@ -1768,7 +_,7 @@
@@ -1768,7 +2336,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
if (entity instanceof Mob mob) {
@@ -1177,7 +1183,7 @@
String string = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde(
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
@@ -1785,6 +_,15 @@
@@ -1785,6 +2353,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
@@ -1193,7 +1199,7 @@
}
@Override
@@ -1792,4 +_,24 @@
@@ -1792,4 +2369,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index ae499e8589f51d910976c614f6c11ff19f7b69ff..f054ea710108e5017bc48fdda5f180a04f5b55e2 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -223,7 +_,8 @@
@@ -223,7 +223,8 @@ public class ServerPlayer extends Player {
private int levitationStartTime;
private boolean disconnected;
private int requestedViewDistance = 2;
@@ -10,7 +18,7 @@
@Nullable
private Vec3 startingToFallPosition;
@Nullable
@@ -258,6 +_,20 @@
@@ -258,6 +259,13 @@ public class ServerPlayer extends Player {
}
}
@@ -20,18 +28,11 @@
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
+ }
+ // Paper end - Sync offhand slot in menus
+
+ // Paper start - add flag to simplify remote matching logic
+ @Override
+ public ServerPlayer player() {
+ return ServerPlayer.this;
+ }
+ // Paper end - add flag to simplify remote matching logic
+
@Override
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack));
@@ -288,6 +_,32 @@
@@ -288,6 +296,32 @@ public class ServerPlayer extends Player {
}
}
@@ -64,7 +65,7 @@
@Override
public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {
}
@@ -316,9 +_,43 @@
@@ -316,9 +350,43 @@ public class ServerPlayer extends Player {
public void sendSystemMessage(Component component) {
ServerPlayer.this.sendSystemMessage(component);
}
@@ -108,7 +109,7 @@
public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) {
super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile);
@@ -328,16 +_,22 @@
@@ -328,16 +396,22 @@ public class ServerPlayer extends Player {
this.server = server;
this.stats = server.getPlayerList().getPlayerStats(this);
this.advancements = server.getPlayerList().getPlayerAdvancements(this);
@@ -134,7 +135,7 @@
int max = Math.max(0, this.server.getSpawnRadius(level));
int floor = Mth.floor(level.getWorldBorder().getDistanceToBorder(pos.getX(), pos.getZ()));
if (floor < max) {
@@ -420,11 +_,20 @@
@@ -420,11 +494,20 @@ public class ServerPlayer extends Player {
if (compound.contains("recipeBook", 10)) {
this.recipeBook.fromNbt(compound.getCompound("recipeBook"), key -> this.server.getRecipeManager().byKey(key).isPresent());
}
@@ -155,7 +156,7 @@
if (compound.contains("SpawnX", 99) && compound.contains("SpawnY", 99) && compound.contains("SpawnZ", 99)) {
this.respawnPosition = new BlockPos(compound.getInt("SpawnX"), compound.getInt("SpawnY"), compound.getInt("SpawnZ"));
this.respawnForced = compound.getBoolean("SpawnForced");
@@ -475,6 +_,7 @@
@@ -475,6 +558,7 @@ public class ServerPlayer extends Player {
.resultOrPartial(LOGGER::error)
.ifPresent(spawnDimension -> compound.put("SpawnDimension", spawnDimension));
}
@@ -163,7 +164,7 @@
compound.putBoolean("spawn_extra_particles_on_fall", this.spawnExtraParticlesOnFall);
if (this.raidOmenPosition != null) {
@@ -490,7 +_,18 @@
@@ -490,7 +574,18 @@ public class ServerPlayer extends Player {
private void saveParentVehicle(CompoundTag tag) {
Entity rootVehicle = this.getRootVehicle();
Entity vehicle = this.getVehicle();
@@ -183,7 +184,7 @@
CompoundTag compoundTag = new CompoundTag();
CompoundTag compoundTag1 = new CompoundTag();
rootVehicle.save(compoundTag1);
@@ -504,7 +_,7 @@
@@ -504,7 +599,7 @@ public class ServerPlayer extends Player {
if (tag.isPresent() && tag.get().contains("RootVehicle", 10) && this.level() instanceof ServerLevel serverLevel) {
CompoundTag compound = tag.get().getCompound("RootVehicle");
Entity entity = EntityType.loadEntityRecursive(
@@ -192,7 +193,7 @@
);
if (entity == null) {
return;
@@ -530,10 +_,10 @@
@@ -530,10 +625,10 @@ public class ServerPlayer extends Player {
if (!this.isPassenger()) {
LOGGER.warn("Couldn't reattach entity to player");
@@ -205,7 +206,7 @@
}
}
}
@@ -544,6 +_,7 @@
@@ -544,6 +639,7 @@ public class ServerPlayer extends Player {
ListTag listTag = new ListTag();
for (ThrownEnderpearl thrownEnderpearl : this.enderPearls) {
@@ -213,7 +214,7 @@
if (thrownEnderpearl.isRemoved()) {
LOGGER.warn("Trying to save removed ender pearl, skipping");
} else {
@@ -593,6 +_,16 @@
@@ -593,6 +689,16 @@ public class ServerPlayer extends Player {
}
}
@@ -230,7 +231,7 @@
public void setExperiencePoints(int experiencePoints) {
float f = this.getXpNeededForNextLevel();
float f1 = (f - 1.0F) / f;
@@ -650,6 +_,11 @@
@@ -650,6 +756,11 @@ public class ServerPlayer extends Player {
@Override
public void tick() {
@@ -242,7 +243,7 @@
this.tickClientLoadTimeout();
this.gameMode.tick();
this.wardenSpawnTracker.tick();
@@ -657,9 +_,14 @@
@@ -657,9 +768,14 @@ public class ServerPlayer extends Player {
this.invulnerableTime--;
}
@@ -260,7 +261,7 @@
this.containerMenu = this.inventoryMenu;
}
@@ -709,7 +_,7 @@
@@ -709,7 +825,7 @@ public class ServerPlayer extends Player {
public void doTick() {
try {
@@ -269,7 +270,7 @@
super.tick();
}
@@ -723,7 +_,7 @@
@@ -723,7 +839,7 @@ public class ServerPlayer extends Player {
if (this.getHealth() != this.lastSentHealth
|| this.lastSentFood != this.foodData.getFoodLevel()
|| this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) {
@@ -278,7 +279,7 @@
this.lastSentHealth = this.getHealth();
this.lastSentFood = this.foodData.getFoodLevel();
this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F;
@@ -754,6 +_,12 @@
@@ -754,6 +870,12 @@ public class ServerPlayer extends Player {
this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float)this.lastRecordedExperience));
}
@@ -291,7 +292,7 @@
if (this.experienceLevel != this.lastRecordedLevel) {
this.lastRecordedLevel = this.experienceLevel;
this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float)this.lastRecordedLevel));
@@ -767,6 +_,21 @@
@@ -767,6 +889,21 @@ public class ServerPlayer extends Player {
if (this.tickCount % 20 == 0) {
CriteriaTriggers.LOCATION.trigger(this);
}
@@ -313,7 +314,7 @@
} catch (Throwable var4) {
CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player");
CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked");
@@ -791,7 +_,7 @@
@@ -791,7 +928,7 @@ public class ServerPlayer extends Player {
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
if (this.tickCount % 20 == 0) {
if (this.getHealth() < this.getMaxHealth()) {
@@ -322,15 +323,14 @@
}
float saturationLevel = this.foodData.getSaturationLevel();
@@ -840,15 +_,100 @@
@@ -840,15 +977,100 @@ public class ServerPlayer extends Player {
}
private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) {
- this.getScoreboard().forAllObjectives(criteria, this, scoreAccess -> scoreAccess.set(points));
- }
+ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, scoreAccess -> scoreAccess.set(points)); // CraftBukkit - Use our scores instead
+ }
+
}
+ // Paper start - PlayerDeathEvent#getItemsToKeep
+ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList<ItemStack> inv) {
+ List<org.bukkit.inventory.ItemStack> itemsToKeep = event.getItemsToKeep();
@@ -370,7 +370,7 @@
+ }
+ }
+ // Paper end - PlayerDeathEvent#getItemsToKeep
+
@Override
public void die(DamageSource cause) {
- this.gameEvent(GameEvent.ENTITY_DIE);
@@ -429,7 +429,7 @@
this.connection
.send(
new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage),
@@ -882,11 +_,22 @@
@@ -882,11 +1104,22 @@ public class ServerPlayer extends Player {
this.tellNeutralMobsThatIDied();
}
@@ -455,7 +455,7 @@
LivingEntity killCredit = this.getKillCredit();
if (killCredit != null) {
this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType()));
@@ -919,10 +_,10 @@
@@ -919,10 +1152,10 @@ public class ServerPlayer extends Player {
public void awardKillScore(Entity entity, DamageSource damageSource) {
if (entity != this) {
super.awardKillScore(entity, damageSource);
@@ -468,7 +468,7 @@
} else {
this.awardStat(Stats.MOB_KILLS);
}
@@ -938,7 +_,7 @@
@@ -938,7 +1171,7 @@ public class ServerPlayer extends Player {
if (playersTeam != null) {
int id = playersTeam.getColor().getId();
if (id >= 0 && id < crtieria.length) {
@@ -477,7 +477,7 @@
}
}
}
@@ -949,9 +_,20 @@
@@ -949,9 +1182,20 @@ public class ServerPlayer extends Player {
return false;
} else {
Entity entity = damageSource.getEntity();
@@ -500,7 +500,7 @@
}
}
@@ -961,10 +_,15 @@
@@ -961,10 +1205,15 @@ public class ServerPlayer extends Player {
}
private boolean isPvpAllowed() {
@@ -518,7 +518,7 @@
BlockPos respawnPosition = this.getRespawnPosition();
float respawnAngle = this.getRespawnAngle();
boolean isRespawnForced = this.isRespawnForced();
@@ -973,13 +_,66 @@
@@ -973,13 +1222,66 @@ public class ServerPlayer extends Player {
Optional<ServerPlayer.RespawnPosAngle> optional = findRespawnAndUseSpawnBlock(level, respawnPosition, respawnAngle, isRespawnForced, useCharge);
if (optional.isPresent()) {
ServerPlayer.RespawnPosAngle respawnPosAngle = optional.get();
@@ -534,13 +534,12 @@
}
} else {
- return new TeleportTransition(this.server.overworld(), this, postTeleportTransition);
- }
+ teleportTransition = new TeleportTransition(this.server.overworld(), this, postTeleportTransition); // CraftBukkit
+ }
+ // CraftBukkit start
+ if (respawnReason == null) {
+ return teleportTransition;
+ }
}
+
+ org.bukkit.entity.Player respawnPlayer = this.getBukkitEntity();
+ org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(
@@ -589,7 +588,7 @@
}
public static Optional<ServerPlayer.RespawnPosAngle> findRespawnAndUseSpawnBlock(
@@ -993,10 +_,10 @@
@@ -993,10 +1295,10 @@ public class ServerPlayer extends Player {
level.setBlock(pos, blockState.setValue(RespawnAnchorBlock.CHARGE, Integer.valueOf(blockState.getValue(RespawnAnchorBlock.CHARGE) - 1)), 3);
}
@@ -602,7 +601,7 @@
} else if (!forced) {
return Optional.empty();
} else {
@@ -1004,7 +_,7 @@
@@ -1004,7 +1306,7 @@ public class ServerPlayer extends Player {
BlockState blockState1 = level.getBlockState(pos.above());
boolean isPossibleToRespawnInThis1 = blockState1.getBlock().isPossibleToRespawnInThis(blockState1);
return isPossibleToRespawnInThis && isPossibleToRespawnInThis1
@@ -611,7 +610,7 @@
: Optional.empty();
}
}
@@ -1022,6 +_,7 @@
@@ -1022,6 +1324,7 @@ public class ServerPlayer extends Player {
@Nullable
@Override
public ServerPlayer teleport(TeleportTransition teleportTransition) {
@@ -619,7 +618,7 @@
if (this.isRemoved()) {
return null;
} else {
@@ -1031,17 +_,52 @@
@@ -1031,17 +1334,52 @@ public class ServerPlayer extends Player {
ServerLevel level = teleportTransition.newLevel();
ServerLevel serverLevel = this.serverLevel();
@@ -675,7 +674,7 @@
this.isChangingDimension = true;
LevelData levelData = level.getLevelData();
this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(level), (byte)3));
@@ -1050,16 +_,30 @@
@@ -1050,16 +1388,30 @@ public class ServerPlayer extends Player {
playerList.sendPlayerPermissionLevel(this);
serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
this.unsetRemoved();
@@ -708,7 +707,7 @@
this.connection.resetPosition();
level.addDuringTeleport(this);
profilerFiller.pop();
@@ -1073,10 +_,40 @@
@@ -1073,11 +1425,41 @@ public class ServerPlayer extends Player {
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@@ -727,7 +726,7 @@
}
}
}
+
+ // CraftBukkit start
+ @Override
+ public org.bukkit.craftbukkit.event.CraftPortalEvent callPortalEvent(
@@ -746,10 +745,11 @@
+ return new org.bukkit.craftbukkit.event.CraftPortalEvent(event);
+ }
+ // CraftBukkit end
+
@Override
public void forceSetRotation(float yRot, float xRot) {
@@ -1086,12 +_,26 @@
this.connection.send(new ClientboundPlayerRotationPacket(yRot, xRot));
@@ -1086,12 +1468,26 @@ public class ServerPlayer extends Player {
public void triggerDimensionChangeTriggers(ServerLevel level) {
ResourceKey<Level> resourceKey = level.dimension();
ResourceKey<Level> resourceKey1 = this.level().dimension();
@@ -779,7 +779,7 @@
this.enteredNetherPosition = null;
}
}
@@ -1107,19 +_,18 @@
@@ -1107,19 +1503,18 @@ public class ServerPlayer extends Player {
this.containerMenu.broadcastChanges();
}
@@ -803,7 +803,7 @@
if (this.level().isDay()) {
return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW);
} else {
@@ -1138,7 +_,34 @@
@@ -1138,7 +1533,34 @@ public class ServerPlayer extends Player {
}
}
@@ -839,7 +839,7 @@
this.awardStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
});
@@ -1174,13 +_,31 @@
@@ -1174,13 +1596,31 @@ public class ServerPlayer extends Player {
@Override
public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) {
@@ -872,7 +872,7 @@
}
}
@@ -1192,9 +_,9 @@
@@ -1192,9 +1632,9 @@ public class ServerPlayer extends Player {
@Override
public boolean isInvulnerableTo(ServerLevel level, DamageSource damageSource) {
@@ -884,7 +884,7 @@
}
@Override
@@ -1237,8 +_,9 @@
@@ -1237,8 +1677,9 @@ public class ServerPlayer extends Player {
this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText));
}
@@ -895,7 +895,7 @@
}
@Override
@@ -1246,12 +_,43 @@
@@ -1246,12 +1687,43 @@ public class ServerPlayer extends Player {
if (menu == null) {
return OptionalInt.empty();
} else {
@@ -939,7 +939,7 @@
if (abstractContainerMenu == null) {
if (this.isSpectator()) {
this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true);
@@ -1259,10 +_,14 @@
@@ -1259,10 +1731,14 @@ public class ServerPlayer extends Player {
return OptionalInt.empty();
} else {
@@ -956,7 +956,7 @@
return OptionalInt.of(this.containerCounter);
}
}
@@ -1275,14 +_,25 @@
@@ -1275,14 +1751,25 @@ public class ServerPlayer extends Player {
@Override
public void openHorseInventory(AbstractHorse horse, Container inventory) {
@@ -985,7 +985,7 @@
this.initMenu(this.containerMenu);
}
@@ -1304,9 +_,28 @@
@@ -1304,9 +1791,28 @@ public class ServerPlayer extends Player {
@Override
public void closeContainer() {
@@ -1014,7 +1014,7 @@
@Override
public void doCloseContainer() {
@@ -1330,19 +_,19 @@
@@ -1330,19 +1836,19 @@ public class ServerPlayer extends Player {
int rounded = Math.round((float)Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F);
if (rounded > 0) {
this.awardStat(Stats.SWIM_ONE_CM, rounded);
@@ -1037,7 +1037,7 @@
}
} else if (this.onClimbable()) {
if (dy > 0.0) {
@@ -1353,13 +_,13 @@
@@ -1353,13 +1859,13 @@ public class ServerPlayer extends Player {
if (rounded > 0) {
if (this.isSprinting()) {
this.awardStat(Stats.SPRINT_ONE_CM, rounded);
@@ -1054,7 +1054,7 @@
}
}
} else if (this.isFallFlying()) {
@@ -1399,13 +_,13 @@
@@ -1399,13 +1905,13 @@ public class ServerPlayer extends Player {
@Override
public void awardStat(Stat<?> stat, int amount) {
this.stats.increment(this, stat, amount);
@@ -1070,7 +1070,7 @@
}
@Override
@@ -1436,9 +_,9 @@
@@ -1436,9 +1942,9 @@ public class ServerPlayer extends Player {
super.jumpFromGround();
this.awardStat(Stats.JUMP);
if (this.isSprinting()) {
@@ -1082,7 +1082,7 @@
}
}
@@ -1451,6 +_,13 @@
@@ -1451,6 +1957,13 @@ public class ServerPlayer extends Player {
public void disconnect() {
this.disconnected = true;
this.ejectPassengers();
@@ -1096,7 +1096,7 @@
if (this.isSleeping()) {
this.stopSleepInBed(true, false);
}
@@ -1462,6 +_,7 @@
@@ -1462,6 +1975,7 @@ public class ServerPlayer extends Player {
public void resetSentInfo() {
this.lastSentHealth = -1.0E8F;
@@ -1104,7 +1104,7 @@
}
@Override
@@ -1496,12 +_,12 @@
@@ -1496,12 +2010,12 @@ public class ServerPlayer extends Player {
this.onUpdateAbilities();
if (keepEverything) {
this.getAttributes().assignBaseValues(that.getAttributes());
@@ -1119,7 +1119,7 @@
}
this.getInventory().replaceWith(that.getInventory());
@@ -1512,7 +_,7 @@
@@ -1512,7 +2026,7 @@ public class ServerPlayer extends Player {
this.portalProcess = that.portalProcess;
} else {
this.getAttributes().assignBaseValues(that.getAttributes());
@@ -1128,7 +1128,7 @@
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || that.isSpectator()) {
this.getInventory().replaceWith(that.getInventory());
this.experienceLevel = that.experienceLevel;
@@ -1528,7 +_,7 @@
@@ -1528,7 +2042,7 @@ public class ServerPlayer extends Player {
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@@ -1137,7 +1137,7 @@
this.seenCredits = that.seenCredits;
this.enteredNetherPosition = that.enteredNetherPosition;
this.chunkTrackingView = that.chunkTrackingView;
@@ -1581,7 +_,7 @@
@@ -1581,7 +2095,7 @@ public class ServerPlayer extends Player {
}
@Override
@@ -1146,7 +1146,7 @@
if (this.isSleeping()) {
this.stopSleepInBed(true, true);
}
@@ -1590,7 +_,7 @@
@@ -1590,7 +2104,7 @@ public class ServerPlayer extends Player {
this.setCamera(this);
}
@@ -1155,7 +1155,7 @@
if (flag) {
this.setYHeadRot(relativeMovements.contains(Relative.Y_ROT) ? this.getYHeadRot() + yaw : yaw);
}
@@ -1627,9 +_,17 @@
@@ -1627,9 +2141,17 @@ public class ServerPlayer extends Player {
}
public boolean setGameMode(GameType gameMode) {
@@ -1175,7 +1175,7 @@
} else {
this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, gameMode.getId()));
if (gameMode == GameType.SPECTATOR) {
@@ -1645,7 +_,7 @@
@@ -1645,7 +2167,7 @@ public class ServerPlayer extends Player {
this.onUpdateAbilities();
this.updateEffectVisibility();
@@ -1184,7 +1184,7 @@
}
}
@@ -1705,8 +_,13 @@
@@ -1705,8 +2227,13 @@ public class ServerPlayer extends Player {
}
public void sendChatMessage(OutgoingChatMessage message, boolean filtered, ChatType.Bound boundType) {
@@ -1199,7 +1199,7 @@
}
}
@@ -1717,7 +_,42 @@
@@ -1717,7 +2244,42 @@ public class ServerPlayer extends Player {
}
public void updateOptions(ClientInformation clientInformation) {
@@ -1242,7 +1242,7 @@
this.requestedViewDistance = clientInformation.viewDistance();
this.chatVisibility = clientInformation.chatVisibility();
this.canChatColor = clientInformation.chatColors();
@@ -1803,8 +_,23 @@
@@ -1803,8 +2365,23 @@ public class ServerPlayer extends Player {
Entity camera = this.getCamera();
this.camera = (Entity)(entityToSpectate == null ? this : entityToSpectate);
if (camera != this.camera) {
@@ -1267,7 +1267,7 @@
}
if (entityToSpectate != null) {
@@ -1838,11 +_,11 @@
@@ -1838,11 +2415,11 @@ public class ServerPlayer extends Player {
@Nullable
public Component getTabListDisplayName() {
@@ -1281,7 +1281,7 @@
}
@Override
@@ -1884,11 +_,56 @@
@@ -1884,11 +2461,56 @@ public class ServerPlayer extends Player {
this.setRespawnPosition(player.getRespawnDimension(), player.getRespawnPosition(), player.getRespawnAngle(), player.isRespawnForced(), false);
}
@@ -1340,7 +1340,7 @@
}
this.respawnPosition = position;
@@ -1901,6 +_,8 @@
@@ -1901,6 +2523,8 @@ public class ServerPlayer extends Player {
this.respawnAngle = 0.0F;
this.respawnForced = false;
}
@@ -1349,7 +1349,7 @@
}
public SectionPos getLastSectionPos() {
@@ -1930,21 +_,55 @@
@@ -1930,21 +2554,55 @@ public class ServerPlayer extends Player {
}
@Override
@@ -1407,7 +1407,7 @@
return itemEntity;
}
}
@@ -1955,6 +_,11 @@
@@ -1955,6 +2613,11 @@ public class ServerPlayer extends Player {
return null;
} else {
double d = this.getEyeY() - 0.3F;
@@ -1419,7 +1419,7 @@
ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), d, this.getZ(), droppedItem);
itemEntity.setPickUpDelay(40);
if (includeThrowerName) {
@@ -2008,6 +_,16 @@
@@ -2008,6 +2671,16 @@ public class ServerPlayer extends Player {
}
public void loadGameTypes(@Nullable CompoundTag tag) {
@@ -1436,7 +1436,7 @@
this.gameMode
.setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(tag, "playerGameType")), readPlayerMode(tag, "previousPlayerGameType"));
}
@@ -2108,8 +_,14 @@
@@ -2108,8 +2781,14 @@ public class ServerPlayer extends Player {
@Override
public void stopRiding() {
@@ -1452,7 +1452,7 @@
if (vehicle instanceof LivingEntity livingEntity) {
for (MobEffectInstance mobEffectInstance : livingEntity.getActiveEffects()) {
this.connection.send(new ClientboundRemoveMobEffectPacket(vehicle.getId(), mobEffectInstance.getEffect()));
@@ -2204,13 +_,15 @@
@@ -2204,13 +2883,15 @@ public class ServerPlayer extends Player {
}
public static long placeEnderPearlTicket(ServerLevel level, ChunkPos pos) {
@@ -1472,7 +1472,7 @@
}
private static float calculateLookAtYaw(Vec3 position, BlockPos towardsPos) {
@@ -2218,4 +_,147 @@
@@ -2218,4 +2899,147 @@ public class ServerPlayer extends Player {
return (float)Mth.wrapDegrees(Mth.atan2(vec3.z, vec3.x) * 180.0F / (float)Math.PI - 90.0);
}
}
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index e64f6f68bc29f680f6f78db07e77445534e10592..47ed3ad5c0b4753f58e0bafff5e5e70b2f0bb40b 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -41,28 +_,49 @@
@@ -41,28 +41,49 @@ public class ServerPlayerGameMode {
private BlockPos delayedDestroyPos = BlockPos.ZERO;
private int delayedTickStart;
private int lastSentState = -1;
@@ -54,7 +62,7 @@
}
}
@@ -90,10 +_,11 @@
@@ -90,10 +111,11 @@ public class ServerPlayerGameMode {
}
public void tick() {
@@ -69,7 +77,7 @@
this.hasDelayedDestroy = false;
} else {
float f = this.incrementDestroyProgress(blockState, this.delayedDestroyPos, this.delayedTickStart);
@@ -103,7 +_,13 @@
@@ -103,7 +125,13 @@ public class ServerPlayerGameMode {
}
}
} else if (this.isDestroyingBlock) {
@@ -84,7 +92,7 @@
if (blockState.isAir()) {
this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
this.lastSentState = -1;
@@ -131,6 +_,7 @@
@@ -131,6 +159,7 @@ public class ServerPlayerGameMode {
public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.Action action, Direction face, int maxBuildHeight, int sequence) {
if (!this.player.canInteractWithBlock(pos, 1.0)) {
@@ -92,7 +100,7 @@
this.debugLogging(pos, false, sequence, "too far");
} else if (pos.getY() > maxBuildHeight) {
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
@@ -138,16 +_,39 @@
@@ -138,16 +167,39 @@ public class ServerPlayerGameMode {
} else {
if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) {
if (!this.level.mayInteract(this.player, pos)) {
@@ -100,14 +108,12 @@
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
this.debugLogging(pos, false, sequence, "may not interact");
- return;
- }
+ // Update any tile entity data for this block
+ this.capturedBlockEntity = true; // Paper - Send block entities after destroy prediction
+ // CraftBukkit end
+ return;
+ }
+
return;
}
+ // CraftBukkit start
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
+ if (event.isCancelled()) {
@@ -118,7 +124,7 @@
+ return;
+ }
+ // CraftBukkit end
+
if (this.isCreative()) {
this.destroyAndAck(pos, sequence, "creative destroy");
return;
@@ -134,7 +140,7 @@
if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) {
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
this.debugLogging(pos, false, sequence, "block action restricted");
@@ -157,7 +_,7 @@
@@ -157,7 +209,7 @@ public class ServerPlayerGameMode {
this.destroyProgressStart = this.gameTicks;
float f = 1.0F;
BlockState blockState = this.level.getBlockState(pos);
@@ -143,7 +149,7 @@
EnchantmentHelper.onHitBlock(
this.level,
this.player.getMainHandItem(),
@@ -172,6 +_,23 @@
@@ -172,6 +224,23 @@ public class ServerPlayerGameMode {
f = blockState.getDestroyProgress(this.player, this.player.level(), pos);
}
@@ -167,7 +173,7 @@
if (!blockState.isAir() && f >= 1.0F) {
this.destroyAndAck(pos, sequence, "insta mine");
} else {
@@ -212,14 +_,22 @@
@@ -212,14 +281,22 @@ public class ServerPlayerGameMode {
this.debugLogging(pos, true, sequence, "stopped destroying");
} else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
this.isDestroyingBlock = false;
@@ -192,7 +198,7 @@
}
}
}
@@ -235,36 +_,108 @@
@@ -235,36 +312,108 @@ public class ServerPlayerGameMode {
public boolean destroyBlock(BlockPos pos) {
BlockState blockState = this.level.getBlockState(pos);
@@ -276,14 +282,11 @@
mainHandItem.mineBlock(this.level, blockState1, pos, this.player);
- if (flag && hasCorrectToolForDrops) {
- block.playerDestroy(this.level, this.player, pos, blockState1, blockEntity, itemStack);
- }
-
- return true;
- }
+ if (flag && hasCorrectToolForDrops) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion
+ block.playerDestroy(this.level, this.player, pos, blockState1, blockEntity, itemStack, event.isDropItems(), false); // Paper - fix drops not preventing stats/food exhaustion
+ }
+
}
- return true;
+ // return true; // CraftBukkit
+ }
+ // CraftBukkit start
@@ -291,7 +294,7 @@
+ this.level.captureDrops = null; // Paper - capture all item additions to the world; Remove this earlier so that we can actually drop stuff
+ if (event.isDropItems()) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world
+ }
}
+
+ // Drop event experience
+ if (flag) {
@@ -310,7 +313,7 @@
}
}
}
@@ -307,15 +_,47 @@
@@ -307,15 +456,47 @@ public class ServerPlayerGameMode {
}
}
@@ -360,7 +363,7 @@
return InteractionResult.CONSUME;
} else {
return InteractionResult.PASS;
@@ -340,7 +_,7 @@
@@ -340,7 +521,7 @@ public class ServerPlayerGameMode {
}
}
@@ -369,7 +372,7 @@
UseOnContext useOnContext = new UseOnContext(player, hand, hitResult);
InteractionResult interactionResult1;
if (this.isCreative()) {
@@ -357,6 +_,11 @@
@@ -357,6 +538,11 @@ public class ServerPlayerGameMode {
return interactionResult1;
} else {
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/item/enchantment/ItemEnchantments.java b/net/minecraft/world/item/enchantment/ItemEnchantments.java
index 7f2568b40b5f8858d85e41732df84187d48db586..cc87a5026a65192ae1f97b2bd03a918b75df0698 100644
--- a/net/minecraft/world/item/enchantment/ItemEnchantments.java
+++ b/net/minecraft/world/item/enchantment/ItemEnchantments.java
@@ -28,10 +_,19 @@
@@ -28,10 +28,19 @@ import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.TooltipProvider;
public class ItemEnchantments implements TooltipProvider {
@@ -23,7 +31,7 @@
private static final Codec<ItemEnchantments> FULL_CODEC = RecordCodecBuilder.create(
instance -> instance.group(
LEVELS_CODEC.fieldOf("levels").forGetter(itemEnchantments -> itemEnchantments.enchantments),
@@ -41,16 +_,16 @@
@@ -41,16 +50,16 @@ public class ItemEnchantments implements TooltipProvider {
);
public static final Codec<ItemEnchantments> CODEC = Codec.withAlternative(FULL_CODEC, LEVELS_CODEC, map -> new ItemEnchantments(map, true));
public static final StreamCodec<RegistryFriendlyByteBuf, ItemEnchantments> STREAM_CODEC = StreamCodec.composite(
@@ -43,7 +51,7 @@
this.enchantments = enchantments;
this.showInTooltip = showInTooltip;
@@ -139,7 +_,7 @@
@@ -139,7 +148,7 @@ public class ItemEnchantments implements TooltipProvider {
}
public static class Mutable {
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index fc3e691ebd28365ef6c13d576cb4122c1576b6ff..ce781ba2c8b3f9f051201d3809a9cb041036f93a 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -76,7 +_,7 @@
@@ -76,7 +76,7 @@ public class LevelChunk extends ChunkAccess {
};
private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel = Maps.newHashMap();
public boolean loaded;
@@ -9,7 +17,7 @@
@Nullable
private Supplier<FullChunkStatus> fullStatus;
@Nullable
@@ -85,6 +_,14 @@
@@ -85,6 +85,14 @@ public class LevelChunk extends ChunkAccess {
private final LevelChunkTicks<Block> blockTicks;
private final LevelChunkTicks<Fluid> fluidTicks;
private LevelChunk.UnsavedListener unsavedListener = chunkPos -> {};
@@ -24,7 +32,7 @@
public LevelChunk(Level level, ChunkPos pos) {
this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, null, null, null);
@@ -102,7 +_,7 @@
@@ -102,7 +110,7 @@ public class LevelChunk extends ChunkAccess {
@Nullable BlendingData blendingData
) {
super(pos, data, level, level.registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData);
@@ -33,7 +41,7 @@
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
for (Heightmap.Types types : Heightmap.Types.values()) {
@@ -154,6 +_,10 @@
@@ -154,6 +162,10 @@ public class LevelChunk extends ChunkAccess {
this.skyLightSources = chunk.skyLightSources;
this.setLightCorrect(chunk.isLightCorrect());
this.markUnsaved();
@@ -44,7 +52,7 @@
}
public void setUnsavedListener(LevelChunk.UnsavedListener unsavedListener) {
@@ -162,6 +_,12 @@
@@ -162,6 +174,12 @@ public class LevelChunk extends ChunkAccess {
unsavedListener.setUnsaved(this.chunkPos);
}
}
@@ -57,7 +65,7 @@
@Override
public void markUnsaved() {
@@ -195,8 +_,25 @@
@@ -195,8 +213,25 @@ public class LevelChunk extends ChunkAccess {
: super.getListenerRegistry(sectionY);
}
@@ -83,7 +91,7 @@
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
@@ -231,33 +_,54 @@
@@ -231,33 +266,54 @@ public class LevelChunk extends ChunkAccess {
}
}
@@ -140,7 +148,7 @@
int y = pos.getY();
LevelChunkSection section = this.getSection(this.getSectionIndex(y));
boolean hasOnlyAir = section.hasOnlyAir();
@@ -292,7 +_,7 @@
@@ -292,7 +348,7 @@ public class LevelChunk extends ChunkAccess {
}
boolean hasBlockEntity = blockState.hasBlockEntity();
@@ -149,7 +157,7 @@
blockState.onRemove(this.level, pos, state, isMoving);
} else if (!blockState.is(block) && hasBlockEntity) {
this.removeBlockEntity(pos);
@@ -301,7 +_,7 @@
@@ -301,7 +357,7 @@ public class LevelChunk extends ChunkAccess {
if (!section.getBlockState(i, i1, i2).is(block)) {
return null;
} else {
@@ -158,7 +166,7 @@
state.onPlace(this.level, pos, blockState, isMoving);
}
@@ -355,7 +_,12 @@
@@ -355,7 +411,12 @@ public class LevelChunk extends ChunkAccess {
@Nullable
public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) {
@@ -172,7 +180,7 @@
if (blockEntity == null) {
CompoundTag compoundTag = this.pendingBlockEntities.remove(pos);
if (compoundTag != null) {
@@ -409,7 +_,13 @@
@@ -409,7 +470,13 @@ public class LevelChunk extends ChunkAccess {
BlockPos blockPos = blockEntity.getBlockPos();
BlockState blockState = this.getBlockState(blockPos);
if (!blockState.hasBlockEntity()) {
@@ -187,7 +195,7 @@
} else {
BlockState blockState1 = blockEntity.getBlockState();
if (blockState != blockState1) {
@@ -457,6 +_,11 @@
@@ -457,6 +524,11 @@ public class LevelChunk extends ChunkAccess {
public void removeBlockEntity(BlockPos pos) {
if (this.isInLevel()) {
BlockEntity blockEntity = this.blockEntities.remove(pos);
@@ -199,7 +207,7 @@
if (blockEntity != null) {
if (this.level instanceof ServerLevel serverLevel) {
this.removeGameEventListener(blockEntity, serverLevel);
@@ -499,6 +_,65 @@
@@ -499,6 +571,65 @@ public class LevelChunk extends ChunkAccess {
}
}
@@ -265,7 +273,7 @@
public boolean isEmpty() {
return false;
}
@@ -711,23 +_,24 @@
@@ -711,23 +842,24 @@ public class LevelChunk extends ChunkAccess {
if (this.blockEntity.getType().isValid(blockState)) {
this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockState, this.blockEntity);
this.loggedInvalidBlockState = false;
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index d84090814956f36cacb4e1ed1e3dbad1fc8a2ab0..c7c87bc8df86ceeef3e15a8f23fc252d4cee1984 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -91,6 +_,7 @@
@@ -91,6 +91,7 @@ public record SerializableChunkData(
List<CompoundTag> entities,
List<CompoundTag> blockEntities,
CompoundTag structureData
@@ -8,7 +16,7 @@
) {
public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(
Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()
@@ -107,12 +_,39 @@
@@ -107,12 +108,39 @@ public record SerializableChunkData(
public static final String BLOCK_LIGHT_TAG = "BlockLight";
public static final String SKY_LIGHT_TAG = "SkyLight";
@@ -49,7 +57,7 @@
long _long = tag.getLong("LastUpdate");
long _long1 = tag.getLong("InhabitedTime");
ChunkStatus chunkStatus = ChunkStatus.byName(tag.getString("Status"));
@@ -181,7 +_,7 @@
@@ -181,7 +209,7 @@ public record SerializableChunkData(
ListTag list7 = tag.getList("sections", 10);
List<SerializableChunkData.SectionData> list8 = new ArrayList<>(list7.size());
Registry<Biome> registry = registries.lookupOrThrow(Registries.BIOME);
@@ -58,7 +66,7 @@
for (int i2 = 0; i2 < list7.size(); i2++) {
CompoundTag compound2 = list7.getCompound(i2);
@@ -199,7 +_,7 @@
@@ -199,7 +227,7 @@ public record SerializableChunkData(
);
}
@@ -67,7 +75,7 @@
if (compound2.contains("biomes", 10)) {
palettedContainerRo = codec.parse(NbtOps.INSTANCE, compound2.getCompound("biomes"))
.promotePartial(string -> logErrors(chunkPos, _byte, string))
@@ -239,6 +_,7 @@
@@ -239,6 +267,7 @@ public record SerializableChunkData(
list5,
list6,
compound1
@@ -75,7 +83,7 @@
);
}
}
@@ -316,6 +_,12 @@
@@ -316,6 +345,12 @@ public record SerializableChunkData(
}
}
@@ -88,7 +96,7 @@
chunkAccess.setLightCorrect(this.lightCorrect);
EnumSet<Heightmap.Types> set = EnumSet.noneOf(Heightmap.Types.class);
@@ -346,6 +_,13 @@
@@ -346,6 +381,13 @@ public record SerializableChunkData(
}
for (CompoundTag compoundTag : this.blockEntities) {
@@ -102,7 +110,7 @@
protoChunk1.setBlockEntityNbt(compoundTag);
}
@@ -370,6 +_,12 @@
@@ -370,6 +412,12 @@ public record SerializableChunkData(
);
}
@@ -115,7 +123,7 @@
public static SerializableChunkData copyOf(ServerLevel level, ChunkAccess chunk) {
if (!chunk.canBeSerialized()) {
throw new IllegalArgumentException("Chunk can't be serialized: " + chunk);
@@ -428,6 +_,12 @@
@@ -428,6 +476,12 @@ public record SerializableChunkData(
CompoundTag compoundTag = packStructureData(
StructurePieceSerializationContext.fromLevel(level), pos, chunk.getAllStarts(), chunk.getAllReferences()
);
@@ -128,7 +136,7 @@
return new SerializableChunkData(
level.registryAccess().lookupOrThrow(Registries.BIOME),
pos,
@@ -447,6 +_,7 @@
@@ -447,6 +501,7 @@ public record SerializableChunkData(
list2,
list1,
compoundTag
@@ -136,7 +144,7 @@
);
}
}
@@ -525,6 +_,11 @@
@@ -525,6 +580,11 @@ public record SerializableChunkData(
this.heightmaps.forEach((types, longs) -> compoundTag2.put(types.getSerializationKey(), new LongArrayTag(longs)));
compoundTag.put("Heightmaps", compoundTag2);
compoundTag.put("structures", this.structureData);
@@ -148,7 +156,7 @@
return compoundTag;
}
@@ -562,6 +_,13 @@
@@ -562,6 +622,13 @@ public record SerializableChunkData(
chunk.setBlockEntityNbt(compoundTag);
} else {
BlockPos posFromTag = BlockEntity.getPosFromTag(compoundTag);
@@ -162,7 +170,7 @@
BlockEntity blockEntity = BlockEntity.loadStatic(posFromTag, chunk.getBlockState(posFromTag), compoundTag, level.registryAccess());
if (blockEntity != null) {
chunk.setBlockEntity(blockEntity);
@@ -610,6 +_,12 @@
@@ -610,6 +677,12 @@ public record SerializableChunkData(
} else {
StructureStart structureStart = StructureStart.loadStaticStart(context, compound.getCompound(string), seed);
if (structureStart != null) {
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index 3bfdc4df0db8944db6c671f53499cf07f3a3e7be..3c1c89aade5ff092b880ba1bf1de83f54d3d62cc 100644
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -61,6 +_,7 @@
@@ -61,6 +61,7 @@ public class MapItemSavedData extends SavedData {
public byte scale;
public byte[] colors = new byte[16384];
public boolean locked;
@@ -8,7 +16,7 @@
public final List<MapItemSavedData.HoldingPlayer> carriedBy = Lists.newArrayList();
public final Map<Player, MapItemSavedData.HoldingPlayer> carriedByPlayers = Maps.newHashMap();
private final Map<String, MapBanner> bannerMarkers = Maps.newHashMap();
@@ -68,6 +_,13 @@
@@ -68,6 +69,13 @@ public class MapItemSavedData extends SavedData {
private final Map<String, MapFrame> frameMarkers = Maps.newHashMap();
private int trackedDecorationCount;
@@ -22,7 +30,7 @@
public static SavedData.Factory<MapItemSavedData> factory() {
return new SavedData.Factory<>(() -> {
throw new IllegalStateException("Should never create an empty map saved data");
@@ -82,6 +_,11 @@
@@ -82,6 +90,11 @@ public class MapItemSavedData extends SavedData {
this.trackingPosition = trackingPosition;
this.unlimitedTracking = unlimitedTracking;
this.locked = locked;
@@ -34,7 +42,7 @@
}
public static MapItemSavedData createFresh(
@@ -100,9 +_,47 @@
@@ -100,9 +113,47 @@ public class MapItemSavedData extends SavedData {
}
public static MapItemSavedData load(CompoundTag tag, HolderLookup.Provider levelRegistry) {
@@ -85,7 +93,7 @@
int _int = tag.getInt("xCenter");
int _int1 = tag.getInt("zCenter");
byte b = (byte)Mth.clamp(tag.getByte("scale"), 0, 4);
@@ -114,6 +_,7 @@
@@ -114,6 +165,7 @@ public class MapItemSavedData extends SavedData {
if (byteArray.length == 16384) {
mapItemSavedData.colors = byteArray;
}
@@ -93,7 +101,7 @@
RegistryOps<Tag> registryOps = levelRegistry.createSerializationContext(NbtOps.INSTANCE);
@@ -154,6 +_,25 @@
@@ -154,6 +206,25 @@ public class MapItemSavedData extends SavedData {
.encodeStart(NbtOps.INSTANCE, this.dimension.location())
.resultOrPartial(LOGGER::error)
.ifPresent(dimension -> tag.put("dimension", dimension));
@@ -119,7 +127,7 @@
tag.putInt("xCenter", this.centerX);
tag.putInt("zCenter", this.centerZ);
tag.putByte("scale", this.scale);
@@ -233,10 +_,12 @@
@@ -233,10 +304,12 @@ public class MapItemSavedData extends SavedData {
}
MapFrame mapFrame1 = new MapFrame(pos, frame.getDirection().get2DDataValue() * 90, frame.getId());
@@ -132,7 +140,7 @@
}
MapDecorations mapDecorations = mapStack.getOrDefault(DataComponents.MAP_DECORATIONS, MapDecorations.EMPTY);
@@ -267,7 +_,7 @@
@@ -267,7 +340,7 @@ public class MapItemSavedData extends SavedData {
this.trackedDecorationCount--;
}
@@ -141,7 +149,7 @@
}
public static void addTargetDecoration(ItemStack stack, BlockPos pos, String type, Holder<MapDecorationType> mapDecorationType) {
@@ -421,7 +_,7 @@
@@ -421,7 +494,7 @@ public class MapItemSavedData extends SavedData {
return true;
}
@@ -150,7 +158,7 @@
this.bannerMarkers.put(mapBanner.getId(), mapBanner);
this.addDecoration(mapBanner.getDecoration(), accessor, mapBanner.getId(), d, d1, 180.0, mapBanner.name().orElse(null));
return true;
@@ -521,7 +_,7 @@
@@ -521,7 +594,7 @@ public class MapItemSavedData extends SavedData {
this.player = player;
}
@@ -159,7 +167,7 @@
int i = this.minDirtyX;
int i1 = this.minDirtyY;
int i2 = this.maxDirtyX + 1 - this.minDirtyX;
@@ -530,7 +_,7 @@
@@ -530,7 +603,7 @@ public class MapItemSavedData extends SavedData {
for (int i4 = 0; i4 < i2; i4++) {
for (int i5 = 0; i5 < i3; i5++) {
@@ -168,7 +176,7 @@
}
}
@@ -540,17 +_,38 @@
@@ -540,17 +613,38 @@ public class MapItemSavedData extends SavedData {
@Nullable
Packet<?> nextUpdatePacket(MapId mapId) {
MapItemSavedData.MapPatch mapPatch;
@@ -210,7 +218,7 @@
} else {
collection = null;
}
@@ -578,6 +_,23 @@
@@ -578,6 +672,23 @@ public class MapItemSavedData extends SavedData {
private void markDecorationsDirty() {
this.dirtyDecorations = true;
}
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/level/storage/DimensionDataStorage.java b/net/minecraft/world/level/storage/DimensionDataStorage.java
index 693edd43b9ff2a9f93889eb321c3c7b943b98708..d9a3b5a2e6495b7e22c114506c2bd1e406f58f8f 100644
--- a/net/minecraft/world/level/storage/DimensionDataStorage.java
+++ b/net/minecraft/world/level/storage/DimensionDataStorage.java
@@ -139,7 +_,7 @@
@@ -139,7 +139,7 @@ public class DimensionDataStorage implements AutoCloseable {
} else {
int i = Util.maxAllowedExecutorThreads();
int size = map.size();
@@ -9,7 +17,7 @@
this.pendingWriteFuture = this.pendingWriteFuture.thenCompose(object -> {
List<CompletableFuture<?>> list = new ArrayList<>(i);
int i1 = Mth.positiveCeilDiv(size, i);
@@ -160,7 +_,7 @@
@@ -160,7 +160,7 @@ public class DimensionDataStorage implements AutoCloseable {
object -> CompletableFuture.allOf(
map.entrySet()
.stream()
@@ -1,6 +1,14 @@
From 3aeeaf31b7a7f888f54e47826e8ec0ddbe65c4bf Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 14:37:42 +0100
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/level/storage/PrimaryLevelData.java b/net/minecraft/world/level/storage/PrimaryLevelData.java
index 385d424ed08a6f3202c263cc8acedbc32cdeae7c..2f4922a2035cc7d628dd2c979137163feb90e19f 100644
--- a/net/minecraft/world/level/storage/PrimaryLevelData.java
+++ b/net/minecraft/world/level/storage/PrimaryLevelData.java
@@ -74,6 +_,21 @@
@@ -74,6 +74,21 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
private final Set<String> removedFeatureFlags;
private final TimerQueue<MinecraftServer> scheduledEvents;
@@ -22,7 +30,7 @@
private PrimaryLevelData(
@Nullable CompoundTag loadedPlayerTag,
boolean wasModded,
@@ -237,7 +_,7 @@
@@ -237,7 +252,7 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
nbt.put("Version", compoundTag);
NbtUtils.addCurrentDataVersion(nbt);
DynamicOps<Tag> dynamicOps = registry.createSerializationContext(NbtOps.INSTANCE);
@@ -31,7 +39,7 @@
.resultOrPartial(Util.prefix("WorldGenSettings: ", LOGGER::error))
.ifPresent(worldOptionsTag -> nbt.put("WorldGenSettings", worldOptionsTag));
nbt.putInt("GameType", this.settings.gameType().getId());
@@ -281,6 +_,8 @@
@@ -281,6 +296,8 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
if (this.wanderingTraderId != null) {
nbt.putUUID("WanderingTraderId", this.wanderingTraderId);
}
@@ -40,7 +48,7 @@
}
private static ListTag stringCollectionToTag(Set<String> stringCollection) {
@@ -358,6 +_,25 @@
@@ -358,6 +375,25 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
@Override
public void setThundering(boolean thundering) {
@@ -66,7 +74,7 @@
this.thundering = thundering;
}
@@ -378,6 +_,26 @@
@@ -378,6 +414,26 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
@Override
public void setRaining(boolean isRaining) {
@@ -93,7 +101,7 @@
this.raining = isRaining;
}
@@ -444,6 +_,12 @@
@@ -444,6 +500,12 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
@Override
public void setDifficulty(Difficulty difficulty) {
this.settings = this.settings.withDifficulty(difficulty);
@@ -106,11 +114,10 @@
}
@Override
@@ -579,6 +_,14 @@
public LevelSettings getLevelSettings() {
@@ -580,6 +642,14 @@ public class PrimaryLevelData implements ServerLevelData, WorldData {
return this.settings.copy();
}
+
+ // CraftBukkit start - Check if the name stored in NBT is the correct one
+ public void checkName(String name) {
+ if (!this.settings.levelName.equals(name)) {
@@ -118,6 +125,7 @@
+ }
+ }
+ // CraftBukkit end
+
@Deprecated
public static enum SpecialWorldProperty {
NONE,
@@ -1,6 +1,6 @@
--- a/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
+++ b/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
@@ -44,6 +_,7 @@
@@ -47,6 +_,7 @@
.collect(Collectors.toSet());
final int page = 0;
@@ -8,7 +8,7 @@
for (final List<String> request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) {
final List<String> normalizedRequest = request.stream().map(YggdrasilGameProfileRepository::normalizeName).toList();
@@ -75,6 +_,12 @@
@@ -78,6 +_,12 @@
LOGGER.debug("Couldn't find profile {}", name);
callback.onProfileLookupFailed(name, new ProfileNotFoundException("Server did not find the requested profile"));
}
@@ -1,28 +1,29 @@
--- a/com/mojang/math/OctahedralGroup.java
+++ b/com/mojang/math/OctahedralGroup.java
@@ -111,6 +_,7 @@
this.permutation = permutation;
this.transformation = new Matrix3f().scaling(invertX ? -1.0F : 1.0F, invertY ? -1.0F : 1.0F, invertZ ? -1.0F : 1.0F);
this.transformation.mul(permutation.transformation());
@@ -132,6 +_,7 @@
Matrix3f matrix3f = new Matrix3f().scaling(invertX ? -1.0F : 1.0F, invertY ? -1.0F : 1.0F, invertZ ? -1.0F : 1.0F);
matrix3f.mul(permutation.transformation());
this.transformation = matrix3f;
+ this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
}
private BooleanList packInversions() {
@@ -139,7 +_,7 @@
@@ -160,7 +_,7 @@
return this.name;
}
- public Direction rotate(Direction direction) {
+ public void initializeRotationDirections() { // Paper - Avoid Lazy Initialization for Enum Fields
if (this.rotatedDirections == null) {
this.rotatedDirections = Maps.newEnumMap(Direction.class);
Direction.Axis[] axiss = Direction.Axis.values();
@@ -154,6 +_,10 @@
}
this.rotatedDirections = Util.makeEnumMap(Direction.class, direction1 -> {
Direction.Axis axis = direction1.getAxis();
@@ -171,6 +_,11 @@
});
}
+ // Paper start - Avoid Lazy Initialization for Enum Fields
+ }
+
+ public Direction rotate(Direction direction) {
+ // Paper end - Avoid Lazy Initialization for Enum Fields
return this.rotatedDirections.get(direction);
@@ -1,6 +1,6 @@
--- a/net/minecraft/ChatFormatting.java
+++ b/net/minecraft/ChatFormatting.java
@@ -112,6 +_,19 @@
@@ -118,6 +_,19 @@
return friendlyName == null ? null : FORMATTING_BY_NAME.get(cleanName(friendlyName));
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/Util.java
+++ b/net/minecraft/Util.java
@@ -92,9 +_,26 @@
@@ -93,9 +_,26 @@
private static final int DEFAULT_MAX_THREADS = 255;
private static final int DEFAULT_SAFE_FILE_OPERATION_RETRIES = 10;
private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads";
@@ -28,7 +28,7 @@
private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT);
public static final int LINEAR_LOOKUP_THRESHOLD = 8;
private static final Set<String> ALLOWED_UNTRUSTED_LINK_PROTOCOLS = Set.of("http", "https");
@@ -113,6 +_,7 @@
@@ -114,6 +_,7 @@
.findFirst()
.orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
private static Consumer<String> thePauser = string -> {};
@@ -36,7 +36,7 @@
public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
return Collectors.toMap(Entry::getKey, Entry::getValue);
@@ -135,7 +_,7 @@
@@ -136,7 +_,7 @@
}
public static long getNanos() {
@@ -45,7 +45,7 @@
}
public static long getEpochMillis() {
@@ -146,9 +_,10 @@
@@ -147,9 +_,10 @@
return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now());
}
@@ -58,7 +58,7 @@
if (i <= 0) {
directExecutorService = MoreExecutors.newDirectExecutorService();
} else {
@@ -173,16 +_,30 @@
@@ -174,16 +_,30 @@
super.onTermination(throwOnTermination);
}
};
@@ -91,7 +91,7 @@
}
private static int getMaxThreads() {
@@ -233,6 +_,21 @@
@@ -234,6 +_,21 @@
}));
}
@@ -113,7 +113,7 @@
public static void throwAsRuntime(Throwable throwable) {
throw throwable instanceof RuntimeException ? (RuntimeException)throwable : new RuntimeException(throwable);
}
@@ -1075,16 +_,7 @@
@@ -1088,16 +_,7 @@
}
public void openUri(URI uri) {
@@ -94,7 +94,7 @@
public Vec3 getPosition() {
return this.worldPosition;
}
@@ -499,20 +_,25 @@
@@ -498,20 +_,25 @@
Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC);
if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) {
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@@ -123,7 +123,7 @@
}
}
@@ -523,7 +_,7 @@
@@ -522,7 +_,7 @@
@Override
public Collection<String> getOnlinePlayerNames() {
@@ -132,7 +132,7 @@
}
@Override
@@ -598,4 +_,16 @@
@@ -597,4 +_,16 @@
public boolean isSilent() {
return this.silent;
}
@@ -127,7 +127,7 @@
StackTraceElement[] stackTrace = var12.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
@@ -309,18 +_,22 @@
@@ -308,18 +_,22 @@
}
@Nullable
@@ -148,12 +148,12 @@
int min = Math.min(var7.getInput().length(), var7.getCursor());
MutableComponent mutableComponent = Component.empty()
.withStyle(ChatFormatting.GRAY)
- .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command)));
+ .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + label))); // CraftBukkit // Paper
- .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + command)));
+ .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + label))); // CraftBukkit // Paper
if (min > 10) {
mutableComponent.append(CommonComponents.ELLIPSIS);
}
@@ -332,7 +_,17 @@
@@ -331,7 +_,17 @@
}
mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
@@ -172,7 +172,7 @@
}
return null;
@@ -360,26 +_,120 @@
@@ -359,26 +_,120 @@
}
public void sendCommands(ServerPlayer player) {
@@ -297,9 +297,9 @@
+ // we want the exact command instance to be used for equality checks
+ // when assigning serialization ids to each command node
if (argumentBuilder instanceof RequiredArgumentBuilder) {
RequiredArgumentBuilder<SharedSuggestionProvider, ?> requiredArgumentBuilder = (RequiredArgumentBuilder<SharedSuggestionProvider, ?>)argumentBuilder;
@@ -396,7 +_,7 @@
if (argumentBuilder instanceof RequiredArgumentBuilder requiredArgumentBuilder
&& requiredArgumentBuilder.getSuggestionsProvider() != null) {
@@ -393,7 +_,7 @@
commandNodeToSuggestionNode.put(commandNode, commandNode1);
rootSuggestion.addChild(commandNode1);
if (!commandNode.getChildren().isEmpty()) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/core/Direction.java
+++ b/net/minecraft/core/Direction.java
@@ -57,6 +_,12 @@
@@ -62,6 +_,12 @@
.sorted(Comparator.comparingInt(direction -> direction.data2d))
.toArray(Direction[]::new);
@@ -13,10 +13,10 @@
private Direction(
final int data3d,
final int oppositeIndex,
@@ -74,6 +_,11 @@
this.axisDirection = axisDirection;
@@ -80,6 +_,11 @@
this.normal = normal;
this.normalVec3 = Vec3.atLowerCornerOf(normal);
this.normalVec3f = new Vector3f(normal.getX(), normal.getY(), normal.getZ());
+ // Paper start - Perf: Inline shift direction fields
+ this.adjX = normal.getX();
+ this.adjY = normal.getY();
@@ -25,7 +25,7 @@
}
public static Direction[] orderedByNearest(Entity entity) {
@@ -247,15 +_,15 @@
@@ -252,15 +_,15 @@
}
public int getStepX() {
@@ -1,6 +1,6 @@
--- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java
@@ -33,17 +_,18 @@
@@ -32,17 +_,18 @@
public class MappedRegistry<T> implements WritableRegistry<T> {
private final ResourceKey<? extends Registry<T>> key;
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
@@ -24,7 +24,7 @@
@Override
public Stream<HolderSet.Named<T>> listTags() {
@@ -114,6 +_,7 @@
@@ -113,6 +_,7 @@
this.toId.put(value, size);
this.registrationInfos.put(key, registrationInfo);
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
@@ -32,7 +32,7 @@
return reference;
}
}
@@ -275,6 +_,7 @@
@@ -274,6 +_,7 @@
return this;
} else {
this.frozen = true;
@@ -40,7 +40,7 @@
this.byValue.forEach((object, reference) -> reference.bindValue((T)object));
List<ResourceLocation> list = this.byKey
.entrySet()
@@ -509,4 +_,13 @@
@@ -508,4 +_,13 @@
Stream<HolderSet.Named<T>> getTags();
}
@@ -1,21 +1,25 @@
--- a/net/minecraft/core/Rotations.java
+++ b/net/minecraft/core/Rotations.java
@@ -34,6 +_,18 @@
this(tag.getFloat(0), tag.getFloat(1), tag.getFloat(2));
}
+ // Paper start - faster alternative constructor
+ private Rotations(float x, float y, float z, Void dummy_var) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
@@ -26,11 +_,22 @@
buffer.writeFloat(value.z);
}
};
+ // Paper start - add internal method for skipping validation for plugins
+ private static boolean SKIP_VALIDATION = false;
+ public static Rotations createWithoutValidityChecks(float x, float y, float z) {
+ return new Rotations(x, y, z, null);
+ SKIP_VALIDATION = true;
+ Rotations rotations = new Rotations(x, y, z);
+ SKIP_VALIDATION = false;
+ return rotations;
+ }
+ // Paper end - faster alternative constructor
+
public ListTag save() {
ListTag listTag = new ListTag();
listTag.add(FloatTag.valueOf(this.x));
+ // Paper end - add internal method for skipping validation for plugins
public Rotations(float x, float y, float z) {
+ if (SKIP_VALIDATION) { // Paper - add internal method for skipping validation for plugins
x = !Float.isInfinite(x) && !Float.isNaN(x) ? x % 360.0F : 0.0F;
y = !Float.isInfinite(y) && !Float.isNaN(y) ? y % 360.0F : 0.0F;
z = !Float.isInfinite(z) && !Float.isNaN(z) ? z % 360.0F : 0.0F;
+ } // Paper - add internal method for skipping validation for plugins
this.x = x;
this.y = y;
this.z = z;
@@ -1,8 +1,8 @@
--- a/net/minecraft/core/Vec3i.java
+++ b/net/minecraft/core/Vec3i.java
@@ -16,9 +_,9 @@
vec3i -> IntStream.of(vec3i.getX(), vec3i.getY(), vec3i.getZ())
);
@@ -22,9 +_,9 @@
ByteBufCodecs.VAR_INT, Vec3i::getX, ByteBufCodecs.VAR_INT, Vec3i::getY, ByteBufCodecs.VAR_INT, Vec3i::getZ, Vec3i::new
);
public static final Vec3i ZERO = new Vec3i(0, 0, 0);
- private int x;
- private int y;
@@ -13,7 +13,7 @@
public static Codec<Vec3i> offsetCodec(int maxOffset) {
return CODEC.validate(
@@ -35,12 +_,12 @@
@@ -41,12 +_,12 @@
}
@Override
@@ -28,7 +28,7 @@
return (this.getY() + this.getZ() * 31) * 31 + this.getX();
}
@@ -53,15 +_,15 @@
@@ -59,15 +_,15 @@
}
}
@@ -47,7 +47,7 @@
return this.z;
}
@@ -235,4 +_,10 @@
@@ -241,4 +_,10 @@
public String toShortString() {
return this.getX() + ", " + this.getY() + ", " + this.getZ();
}
@@ -122,13 +122,14 @@
)
);
addDefaultInteractions(map3);
@@ -202,15 +_,34 @@
@@ -202,15 +_,35 @@
Predicate<BlockState> statePredicate,
SoundEvent fillSound
) {
+ // Paper start - add hitDirection
+ return fillBucket(state, level, pos, player, hand, emptyStack, filledStack, statePredicate, fillSound, null); // Paper - add hitDirection
+ }
+
+ static InteractionResult fillBucket(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack emptyStack, ItemStack filledStack, Predicate<BlockState> statePredicate, SoundEvent fillSound, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
+ // Paper end - add hitDirection
if (!statePredicate.test(state)) {
@@ -137,7 +138,7 @@
if (!level.isClientSide) {
+ // Paper start - fire PlayerBucketFillEvent
+ if (hitDirection != null) {
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((net.minecraft.server.level.ServerLevel) level, player, pos, pos, hitDirection, emptyStack, filledStack.getItem(), hand);
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(level, player, pos, pos, hitDirection, emptyStack, filledStack.getItem(), hand);
+ if (event.isCancelled()) {
+ return InteractionResult.PASS;
+ }
@@ -158,20 +159,21 @@
level.playSound(null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PICKUP, pos);
}
@@ -222,12 +_,32 @@
@@ -222,12 +_,33 @@
static InteractionResult emptyBucket(
Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound
) {
+ // Paper start - add hitDirection
+ return emptyBucket(level, pos, player, hand, filledStackl, state, emptySound, null);
+ }
+
+ static InteractionResult emptyBucket(Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
+ // Paper end - add hitDirection
if (!level.isClientSide) {
+ // Paper start - fire PlayerBucketEmptyEvent
+ ItemStack output = new ItemStack(Items.BUCKET);
+ if (hitDirection != null) {
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent((net.minecraft.server.level.ServerLevel) level, player, pos, pos, hitDirection, filledStackl, hand);
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent(level, player, pos, pos, hitDirection, filledStackl, hand);
+ if (event.isCancelled()) {
+ return InteractionResult.PASS;
+ }
@@ -193,7 +195,7 @@
level.playSound(null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
}
@@ -236,7 +_,7 @@
@@ -236,23 +_,23 @@
}
private static InteractionResult fillWaterInteraction(
@@ -201,13 +203,8 @@
+ BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack, final net.minecraft.core.Direction hitDirection // Paper - add hitDirection
) {
return emptyBucket(
level,
@@ -245,20 +_,20 @@
hand,
filledStack,
Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)),
- SoundEvents.BUCKET_EMPTY
+ SoundEvents.BUCKET_EMPTY, hitDirection // Paper - add hitDirection
- level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY
+ level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY, hitDirection // Paper - add hitDirection
);
}
@@ -227,10 +224,10 @@
) {
return (InteractionResult)(isUnderWater(level, pos)
? InteractionResult.CONSUME
@@ -269,53 +_,68 @@
@@ -263,53 +_,68 @@
hand,
filledStack,
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)),
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3),
- SoundEvents.BUCKET_EMPTY_POWDER_SNOW
+ SoundEvents.BUCKET_EMPTY_POWDER_SNOW, hitDirection // Paper - add hitDirection
));
@@ -1,50 +1,50 @@
--- a/net/minecraft/core/component/DataComponentPatch.java
+++ b/net/minecraft/core/component/DataComponentPatch.java
@@ -86,6 +_,11 @@
buffer.writeVarInt(0);
buffer.writeVarInt(0);
} else {
+ // Paper start - data sanitization for items
+ final io.papermc.paper.util.ItemObfuscationSession itemObfuscationSession = value.map.isEmpty()
+ ? null // Avoid thread local lookup of current session if it won't be needed anyway.
+ : io.papermc.paper.util.ItemObfuscationSession.currentSession();
+ // Paper end - data sanitization for items
int i = 0;
int i1 = 0;
@@ -106,6 +_,11 @@
buffer.writeVarInt(0);
buffer.writeVarInt(0);
} else {
+ // Paper start - data sanitization for items
+ final io.papermc.paper.util.ItemObfuscationSession itemObfuscationSession = value.map.isEmpty()
+ ? null // Avoid thread local lookup of current session if it won't be needed anyway.
+ : io.papermc.paper.util.ItemObfuscationSession.currentSession();
+ // Paper end - data sanitization for items
int i = 0;
int i1 = 0;
@@ -93,7 +_,7 @@
value.map
)) {
if (entry.getValue().isPresent()) {
- i++;
+ if (!io.papermc.paper.util.ItemComponentSanitizer.shouldDrop(itemObfuscationSession, entry.getKey())) i++; // Paper - data sanitization for items
} else {
i1++;
}
@@ -106,6 +_,7 @@
value.map
)) {
Optional<?> optional = entryx.getValue();
+ optional = io.papermc.paper.util.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
if (optional.isPresent()) {
DataComponentType<?> dataComponentType = entryx.getKey();
DataComponentType.STREAM_CODEC.encode(buffer, dataComponentType);
@@ -125,7 +_,13 @@
}
@@ -113,7 +_,7 @@
value.map
)) {
if (entry.getValue().isPresent()) {
- i++;
+ if (!io.papermc.paper.util.ItemComponentSanitizer.shouldDrop(itemObfuscationSession, entry.getKey())) i++; // Paper - data sanitization for items
} else {
i1++;
}
@@ -126,6 +_,7 @@
value.map
)) {
Optional<?> optional = entryx.getValue();
+ optional = io.papermc.paper.util.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
if (optional.isPresent()) {
DataComponentType<?> dataComponentType = entryx.getKey();
DataComponentType.STREAM_CODEC.encode(buffer, dataComponentType);
@@ -145,7 +_,13 @@
}
private static <T> void encodeComponent(RegistryFriendlyByteBuf buffer, DataComponentType<T> component, Object value) {
- component.streamCodec().encode(buffer, (T)value);
+ // Paper start - codec errors of random anonymous classes are useless
+ try {
+ component.streamCodec().encode(buffer, (T)value);
+ } catch (final Exception e) {
+ throw new RuntimeException("Error encoding component " + component, e);
+ }
+ // Paper end - codec errors of random anonymous classes are useless
}
};
private static final String REMOVED_PREFIX = "!";
@@ -230,6 +_,42 @@
private <T> void encodeComponent(RegistryFriendlyByteBuf registryFriendlyByteBuf, DataComponentType<T> dataComponentType, Object object) {
- codecGetter.apply(dataComponentType).encode(registryFriendlyByteBuf, (T)object);
+ // Paper start - codec errors of random anonymous classes are useless
+ try {
+ codecGetter.apply(dataComponentType).encode(registryFriendlyByteBuf, (T)object);
+ } catch (final Exception e) {
+ throw new RuntimeException("Error encoding component " + dataComponentType, e);
+ }
+ // Paper end - codec errors of random anonymous classes are useless
}
};
}
@@ -249,6 +_,42 @@
Builder() {
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/core/component/DataComponents.java
+++ b/net/minecraft/core/component/DataComponents.java
@@ -180,10 +_,10 @@
@@ -203,10 +_,10 @@
"map_post_processing", builder -> builder.networkSynchronized(MapPostProcessing.STREAM_CODEC)
);
public static final DataComponentType<ChargedProjectiles> CHARGED_PROJECTILES = register(
@@ -13,7 +13,7 @@
);
public static final DataComponentType<PotionContents> POTION_CONTENTS = register(
"potion_contents", builder -> builder.persistent(PotionContents.CODEC).networkSynchronized(PotionContents.STREAM_CODEC).cacheEncoding()
@@ -250,7 +_,7 @@
@@ -286,7 +_,7 @@
"pot_decorations", builder -> builder.persistent(PotDecorations.CODEC).networkSynchronized(PotDecorations.STREAM_CODEC).cacheEncoding()
);
public static final DataComponentType<ItemContainerContents> CONTAINER = register(
@@ -1,6 +1,6 @@
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -82,16 +_,48 @@
@@ -83,16 +_,48 @@
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
EntityType<?> type = ((SpawnEggItem)item.getItem()).getType(blockSource.level().registryAccess(), item);
@@ -51,7 +51,7 @@
blockSource.level().gameEvent(null, GameEvent.ENTITY_PLACE, blockSource.pos());
return item;
}
@@ -109,12 +_,40 @@
@@ -110,12 +_,40 @@
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
BlockPos blockPos = blockSource.pos().relative(direction);
ServerLevel serverLevel = blockSource.level();
@@ -94,45 +94,7 @@
}
return item;
@@ -134,7 +_,36 @@
livingEntity -> livingEntity instanceof Saddleable saddleable && !saddleable.isSaddled() && saddleable.isSaddleable()
);
if (!entitiesOfClass.isEmpty()) {
- ((Saddleable)entitiesOfClass.get(0)).equipSaddle(item.split(1), SoundSource.BLOCKS);
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
+ ServerLevel world = blockSource.level();
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
+ if (!DispenserBlock.eventFired) {
+ world.getCraftServer().getPluginManager().callEvent(event);
+ }
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+ ((Saddleable) entitiesOfClass.get(0)).equipSaddle(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event
+ // CraftBukkit end
+ if (shrink) item.shrink(1); // Paper - actually handle here
this.setSuccess(true);
return item;
} else {
@@ -156,8 +_,36 @@
@@ -135,8 +_,36 @@
new AABB(blockPos),
abstractChestedHorse1 -> abstractChestedHorse1.isAlive() && !abstractChestedHorse1.hasChest()
)) {
@@ -171,7 +133,7 @@
this.setSuccess(true);
return item;
}
@@ -195,8 +_,50 @@
@@ -174,8 +_,50 @@
DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)item.getItem();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
Level level = blockSource.level();
@@ -223,7 +185,7 @@
return this.consumeWithRemainder(blockSource, item, new ItemStack(Items.BUCKET));
} else {
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
@@ -219,12 +_,37 @@
@@ -198,12 +_,37 @@
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
BlockState blockState = levelAccessor.getBlockState(blockPos);
if (blockState.getBlock() instanceof BucketPickup bucketPickup) {
@@ -262,7 +224,7 @@
return this.consumeWithRemainder(blockSource, item, new ItemStack(item1));
}
} else {
@@ -236,17 +_,44 @@
@@ -215,18 +_,45 @@
@Override
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
ServerLevel serverLevel = blockSource.level();
@@ -303,14 +265,15 @@
+ }
+ // CraftBukkit end
} else if (CampfireBlock.canLight(blockState) || CandleBlock.canLight(blockState) || CandleCakeBlock.canLight(blockState)) {
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)));
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, true));
serverLevel.gameEvent(null, GameEvent.BLOCK_CHANGE, blockPos);
- } else if (blockState.getBlock() instanceof TntBlock) {
+ } else if (blockState.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos())) { // CraftBukkit - TNTPrimeEvent
TntBlock.explode(serverLevel, blockPos);
serverLevel.removeBlock(blockPos, false);
} else {
@@ -266,11 +_,62 @@
} else if (blockState.getBlock() instanceof TntBlock) {
- if (TntBlock.prime(serverLevel, blockPos)) {
+ if (TntBlock.prime(serverLevel, blockPos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos()))) { // CraftBukkit - TNTPrimeEvent
serverLevel.removeBlock(blockPos, false);
} else {
this.setSuccess(false);
@@ -248,11 +_,62 @@
this.setSuccess(true);
Level level = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
@@ -373,49 +336,50 @@
return item;
}
@@ -280,11 +_,39 @@
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
Level level = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
- PrimedTnt primedTnt = new PrimedTnt(level, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
@@ -265,12 +_,39 @@
this.setSuccess(false);
return item;
} else {
- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
- PrimedTnt primedTnt = new PrimedTnt(serverLevel, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ }
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+ }
+
+ PrimedTnt primedTnt = new PrimedTnt(level, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
+ // CraftBukkit end
level.addFreshEntity(primedTnt);
level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
- item.shrink(1);
+ if (shrink) item.shrink(1); // Paper - actually handle here
return item;
}
});
@@ -296,6 +_,29 @@
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+
+ PrimedTnt primedTnt = new PrimedTnt(serverLevel, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
+ // CraftBukkit end
serverLevel.addFreshEntity(primedTnt);
serverLevel.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
serverLevel.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
- item.shrink(1);
+ if (shrink) item.shrink(1); // Paper - actually handle here;
this.setSuccess(true);
return item;
}
@@ -284,6 +_,29 @@
Level level = blockSource.level();
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
BlockPos blockPos = blockSource.pos().relative(direction);
@@ -445,7 +409,7 @@
if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, item)) {
level.setBlock(
blockPos,
@@ -313,7 +_,7 @@
@@ -299,7 +_,7 @@
item.shrink(1);
this.setSuccess(true);
} else {
@@ -454,7 +418,7 @@
}
return item;
@@ -326,6 +_,29 @@
@@ -312,6 +_,29 @@
Level level = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN;
@@ -484,7 +448,7 @@
if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) {
if (!level.isClientSide) {
level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3);
@@ -335,7 +_,7 @@
@@ -321,7 +_,7 @@
item.shrink(1);
this.setSuccess(true);
} else {
@@ -493,7 +457,7 @@
}
return item;
@@ -361,6 +_,29 @@
@@ -347,6 +_,29 @@
ServerLevel serverLevel = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
BlockState blockState = serverLevel.getBlockState(blockPos);
@@ -523,7 +487,7 @@
if (blockState.is(
BlockTags.BEEHIVES,
blockStateBase -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockStateBase.getBlock() instanceof BeehiveBlock
@@ -389,6 +_,13 @@
@@ -375,6 +_,13 @@
this.setSuccess(true);
if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
if (blockState.getValue(RespawnAnchorBlock.CHARGE) != 4) {
@@ -537,7 +501,7 @@
RespawnAnchorBlock.charge(null, level, blockPos, blockState);
item.shrink(1);
} else {
@@ -412,6 +_,29 @@
@@ -398,6 +_,29 @@
this.setSuccess(false);
return item;
} else {
@@ -567,7 +531,7 @@
for (Armadillo armadillo : entitiesOfClass) {
if (armadillo.brushOffScute()) {
item.hurtAndBreak(16, serverLevel, null, item1 -> {});
@@ -432,6 +_,13 @@
@@ -418,6 +_,13 @@
BlockState blockState = level.getBlockState(blockPos);
Optional<BlockState> waxed = HoneycombItem.getWaxed(blockState);
if (waxed.isPresent()) {
@@ -581,7 +545,7 @@
level.setBlockAndUpdate(blockPos, waxed.get());
level.levelEvent(3003, blockPos, 0);
item.shrink(1);
@@ -459,6 +_,12 @@
@@ -445,6 +_,12 @@
if (!serverLevel.getBlockState(blockPos1).is(BlockTags.CONVERTABLE_TO_MUD)) {
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
} else {
@@ -55,7 +55,7 @@
+ livingEntity.setItemSlot(equipmentSlotForItem, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
+ // CraftBukkit end
if (livingEntity instanceof Mob mob) {
mob.setDropChance(equipmentSlotForItem, 2.0F);
mob.setGuaranteedDrop(equipmentSlotForItem);
mob.setPersistenceRequired();
}
@@ -1,8 +1,8 @@
--- a/net/minecraft/core/registries/BuiltInRegistries.java
+++ b/net/minecraft/core/registries/BuiltInRegistries.java
@@ -296,6 +_,17 @@
public static final Registry<SlotDisplay.Type<?>> SLOT_DISPLAY = registerSimple(Registries.SLOT_DISPLAY, SlotDisplays::bootstrap);
public static final Registry<RecipeBookCategory> RECIPE_BOOK_CATEGORY = registerSimple(Registries.RECIPE_BOOK_CATEGORY, RecipeBookCategories::bootstrap);
@@ -311,6 +_,17 @@
);
public static final Registry<Consumer<GameTestHelper>> TEST_FUNCTION = registerSimple(Registries.TEST_FUNCTION, BuiltinTestFunctions::bootstrap);
public static final Registry<? extends Registry<?>> REGISTRY = WRITABLE_REGISTRY;
+ // Paper start - add built-in registry conversions
+ public static final io.papermc.paper.registry.data.util.Conversions BUILT_IN_CONVERSIONS = new io.papermc.paper.registry.data.util.Conversions(new net.minecraft.resources.RegistryOps.RegistryInfoLookup() {
@@ -18,7 +18,7 @@
private static <T> Registry<T> registerSimple(ResourceKey<? extends Registry<T>> key, BuiltInRegistries.RegistryBootstrap<T> bootstrap) {
return internalRegister(key, new MappedRegistry<>(key, Lifecycle.stable(), false), bootstrap);
@@ -321,6 +_,7 @@
@@ -336,6 +_,7 @@
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> bootstrap
) {
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
@@ -26,7 +26,7 @@
ResourceLocation resourceLocation = key.location();
LOADERS.put(resourceLocation, () -> bootstrap.run(registry));
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN);
@@ -328,16 +_,34 @@
@@ -343,16 +_,34 @@
}
public static void bootStrap() {
@@ -61,7 +61,7 @@
});
}
@@ -346,6 +_,7 @@
@@ -361,6 +_,7 @@
for (Registry<?> registry : REGISTRY) {
bindBootstrappedTagsToEmpty(registry);
@@ -1,6 +1,6 @@
--- a/net/minecraft/data/loot/packs/VanillaChestLoot.java
+++ b/net/minecraft/data/loot/packs/VanillaChestLoot.java
@@ -946,7 +_,6 @@
@@ -1000,7 +_,6 @@
.add(
LootItem.lootTableItem(Items.COMPASS)
.apply(SetItemCountFunction.setCount(ConstantValue.exactly(1.0F)))
@@ -1,6 +1,6 @@
--- a/net/minecraft/gametest/framework/GameTestInfo.java
+++ b/net/minecraft/gametest/framework/GameTestInfo.java
@@ -241,7 +_,7 @@
@@ -247,7 +_,7 @@
AABB structureBounds = this.getStructureBounds();
List<Entity> entitiesOfClass = this.getLevel()
.getEntitiesOfClass(Entity.class, structureBounds.inflate(1.0), entity -> !(entity instanceof Player));
@@ -1,7 +1,7 @@
--- a/net/minecraft/gametest/framework/GameTestServer.java
+++ b/net/minecraft/gametest/framework/GameTestServer.java
@@ -139,6 +_,8 @@
BlockPos spawnPos
@@ -133,6 +_,8 @@
boolean verify
) {
super(
+ null, // Paper
@@ -9,7 +9,7 @@
serverThread,
storageSource,
packRepository,
@@ -154,8 +_,15 @@
@@ -148,8 +_,15 @@
@Override
public boolean initServer() {
@@ -25,9 +25,9 @@
+ this.loadLevel("blah");
+ // Paper end
ServerLevel serverLevel = this.overworld();
this.testBatches = Lists.newArrayList(GameTestBatchFactory.fromTestFunction(this.testFunctions, serverLevel));
serverLevel.setDefaultSpawnPos(this.spawnPos, 0.0F);
@@ -303,6 +_,13 @@
this.testBatches = this.evaluateTestsToRun(serverLevel);
LOGGER.info("Started game test server");
@@ -338,6 +_,13 @@
public boolean shouldInformAdmins() {
return false;
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/gametest/framework/StructureUtils.java
+++ b/net/minecraft/gametest/framework/StructureUtils.java
@@ -187,7 +_,7 @@
@@ -86,7 +_,7 @@
level.clearBlockEvents(boundingBox1);
AABB aabb = AABB.of(boundingBox1);
List<Entity> entitiesOfClass = level.getEntitiesOfClass(Entity.class, aabb, entity -> !(entity instanceof Player));
@@ -1,11 +0,0 @@
--- a/net/minecraft/gametest/framework/TestCommand.java
+++ b/net/minecraft/gametest/framework/TestCommand.java
@@ -278,7 +_,7 @@
}
private static int resetGameTestInfo(GameTestInfo gameTestInfo) {
- gameTestInfo.getLevel().getEntities(null, gameTestInfo.getStructureBounds()).stream().forEach(entity -> entity.remove(Entity.RemovalReason.DISCARDED));
+ gameTestInfo.getLevel().getEntities(null, gameTestInfo.getStructureBounds()).stream().forEach(entity -> entity.remove(Entity.RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD)); // Paper
gameTestInfo.getStructureBlockEntity().placeStructure(gameTestInfo.getLevel());
StructureUtils.removeBarriers(gameTestInfo.getStructureBounds(), gameTestInfo.getLevel());
say(gameTestInfo.getLevel(), "Reset succeded for: " + gameTestInfo.getTestName(), ChatFormatting.GREEN);
@@ -1,6 +1,6 @@
--- a/net/minecraft/nbt/CompoundTag.java
+++ b/net/minecraft/nbt/CompoundTag.java
@@ -49,7 +_,7 @@
@@ -54,7 +_,7 @@
private static CompoundTag loadCompound(DataInput input, NbtAccounter nbtAccounter) throws IOException {
nbtAccounter.accountBytes(48L);
@@ -9,55 +9,21 @@
byte b;
while ((b = input.readByte()) != 0) {
@@ -166,7 +_,7 @@
@@ -171,7 +_,7 @@
}
public CompoundTag() {
- this(Maps.newHashMap());
- this(new HashMap<>());
+ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - Reduce memory footprint of CompoundTag
}
@Override
@@ -232,14 +_,34 @@
}
public void putUUID(String key, UUID value) {
+ // Paper start - Support old UUID format
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ this.tags.remove(key + "Most");
+ this.tags.remove(key + "Least");
+ }
+ // Paper end - Support old UUID format
this.tags.put(key, NbtUtils.createUUID(value));
}
+
+ /**
+ * You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
+ */
public UUID getUUID(String key) {
+ // Paper start - Support old UUID format
+ if (!contains(key, 11) && this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least"));
+ }
+ // Paper end - Support old UUID format
return NbtUtils.loadUUID(this.get(key));
}
public boolean hasUUID(String key) {
+ // Paper start - Support old UUID format
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ return true;
+ }
+ // Paper end - Support old UUID format
Tag tag = this.get(key);
return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
}
@@ -477,8 +_,16 @@
@@ -402,9 +_,16 @@
@Override
public CompoundTag copy() {
- Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
- HashMap<String, Tag> map = new HashMap<>();
- this.tags.forEach((string, tag) -> map.put(string, tag.copy()));
- return new CompoundTag(map);
+ // Paper start - Reduce memory footprint of CompoundTag
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);
@@ -72,3 +38,55 @@
}
@Override
@@ -525,22 +_,47 @@
this.merge((CompoundTag)mapCodec.encoder().encodeStart(ops, data).getOrThrow());
}
- public <T> Optional<T> read(String key, Codec<T> codec) {
+ public <T> Optional<T> read(String key, Codec<T> codec) { // Paper - option to read via codec without logging errors - diff on change
return this.read(key, codec, NbtOps.INSTANCE);
}
- public <T> Optional<T> read(String key, Codec<T> codec, DynamicOps<Tag> ops) {
+ public <T> Optional<T> read(String key, Codec<T> codec, DynamicOps<Tag> ops) { // Paper - option to read via codec without logging errors - diff on change
Tag tag = this.get(key);
return tag == null
? Optional.empty()
: codec.parse(ops, tag).resultOrPartial(string -> LOGGER.error("Failed to read field ({}={}): {}", key, tag, string));
}
- public <T> Optional<T> read(MapCodec<T> mapCodec) {
+ public <T> Optional<T> read(MapCodec<T> mapCodec) { // Paper - option to read via codec without logging errors - diff on change
return this.read(mapCodec, NbtOps.INSTANCE);
}
- public <T> Optional<T> read(MapCodec<T> mapCodec, DynamicOps<Tag> ops) {
+ public <T> Optional<T> read(MapCodec<T> mapCodec, DynamicOps<Tag> ops) { // Paper - option to read via codec without logging errors - diff on change
return mapCodec.decode(ops, ops.getMap(this).getOrThrow()).resultOrPartial(string -> LOGGER.error("Failed to read value ({}): {}", this, string));
}
+
+ // Paper start - option to read via codec without logging errors
+ // The below methods are 1 to 1 copies of the above-defined read methods without the logging part.
+ // Copying was chosen over overloading the read methods as a boolean parameter to mark a method as quiet
+ // is not intuitive and would require even more overloads.
+ // Not a lot of diff in these methods is expected
+ public <T> Optional<T> readQuiet(String key, Codec<T> codec) {
+ return this.readQuiet(key, codec, NbtOps.INSTANCE);
+ }
+
+ public <T> Optional<T> readQuiet(String key, Codec<T> codec, DynamicOps<Tag> ops) {
+ Tag tag = this.get(key);
+ return tag == null
+ ? Optional.empty()
+ : codec.parse(ops, tag).resultOrPartial();
+ }
+
+ public <T> Optional<T> readQuiet(MapCodec<T> mapCodec) {
+ return this.readQuiet(mapCodec, NbtOps.INSTANCE);
+ }
+
+ public <T> Optional<T> readQuiet(MapCodec<T> mapCodec, DynamicOps<Tag> ops) {
+ return mapCodec.decode(ops, ops.getMap(this).getOrThrow()).resultOrPartial();
+ }
+ // Paper end - option to read via codec without logging errors
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/nbt/NbtIo.java
+++ b/net/minecraft/nbt/NbtIo.java
@@ -118,6 +_,11 @@
@@ -119,6 +_,11 @@
}
public static CompoundTag read(DataInput input, NbtAccounter accounter) throws IOException {
@@ -1,15 +0,0 @@
--- a/net/minecraft/nbt/NbtUtils.java
+++ b/net/minecraft/nbt/NbtUtils.java
@@ -143,8 +_,10 @@
if (!tag.contains("Name", 8)) {
return Blocks.AIR.defaultBlockState();
} else {
- ResourceLocation resourceLocation = ResourceLocation.parse(tag.getString("Name"));
- Optional<? extends Holder<Block>> optional = blockGetter.get(ResourceKey.create(Registries.BLOCK, resourceLocation));
+ // Paper start - Validate resource location
+ ResourceLocation resourceLocation = ResourceLocation.tryParse(tag.getString("Name"));
+ Optional<? extends Holder<Block>> optional = resourceLocation != null ? blockGetter.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty();
+ // Paper end - Validate resource location
if (optional.isEmpty()) {
return Blocks.AIR.defaultBlockState();
} else {
@@ -0,0 +1,21 @@
--- a/net/minecraft/nbt/SnbtGrammar.java
+++ b/net/minecraft/nbt/SnbtGrammar.java
@@ -591,7 +_,7 @@
Atom<List<Entry<String, T>>> atom30 = Atom.of("map_entries");
dictionary.put(atom30, Term.repeatedWithTrailingSeparator(namedRule3, atom30, StringReaderTerms.character(',')), scope -> scope.getOrThrow(atom30));
Atom<T> atom31 = Atom.of("map_literal");
- dictionary.put(atom31, Term.sequence(StringReaderTerms.character('{'), dictionary.named(atom30), StringReaderTerms.character('}')), scope -> {
+ dictionary.put(atom31, Term.sequence(StringReaderTerms.character('{'), Scope.increaseDepth(), dictionary.named(atom30), Scope.decreaseDepth(), StringReaderTerms.character('}')), scope -> { // Paper - track depth
List<Entry<String, T>> list = scope.getOrThrow(atom30);
if (list.isEmpty()) {
return object2;
@@ -626,7 +_,9 @@
atom35,
Term.sequence(
StringReaderTerms.character('['),
+ Scope.increaseDepth(), // Paper - track depth
Term.alternative(Term.sequence(dictionary.named(atom33), StringReaderTerms.character(';'), dictionary.named(atom34)), dictionary.named(atom32)),
+ Scope.decreaseDepth(), // Paper - track depth
StringReaderTerms.character(']')
),
parseState -> {
@@ -1,54 +0,0 @@
--- a/net/minecraft/nbt/TagParser.java
+++ b/net/minecraft/nbt/TagParser.java
@@ -49,6 +_,7 @@
}, CompoundTag::toString);
public static final Codec<CompoundTag> LENIENT_CODEC = Codec.withAlternative(AS_CODEC, CompoundTag.CODEC);
private final StringReader reader;
+ private int depth; // Paper
public static CompoundTag parseTag(String text) throws CommandSyntaxException {
return new TagParser(new StringReader(text)).readSingleStruct();
@@ -159,6 +_,7 @@
public CompoundTag readStruct() throws CommandSyntaxException {
this.expect('{');
+ this.increaseDepth(); // Paper
CompoundTag compoundTag = new CompoundTag();
this.reader.skipWhitespace();
@@ -182,6 +_,7 @@
}
this.expect('}');
+ this.depth--; // Paper
return compoundTag;
}
@@ -191,6 +_,7 @@
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
} else {
+ this.increaseDepth(); // Paper
ListTag listTag = new ListTag();
TagType<?> tagType = null;
@@ -216,6 +_,7 @@
}
this.expect(']');
+ this.depth--; // Paper
return listTag;
}
}
@@ -287,5 +_,11 @@
private void expect(char expected) throws CommandSyntaxException {
this.reader.skipWhitespace();
this.reader.expect(expected);
+ }
+ private void increaseDepth() throws CommandSyntaxException {
+ this.depth++;
+ if (this.depth > 512) {
+ throw new io.papermc.paper.brigadier.TagParseCommandSyntaxException("NBT tag is too complex, depth > 512");
+ }
}
}
@@ -36,7 +36,7 @@
}
public static <T> IntFunction<T> limitValue(IntFunction<T> function, int limit) {
@@ -527,7 +_,7 @@
@@ -539,7 +_,7 @@
try {
NbtIo.writeAnyTag(nbt, new ByteBufOutputStream(buffer));
@@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/ComponentSerialization.java
+++ b/net/minecraft/network/chat/ComponentSerialization.java
@@ -37,9 +_,31 @@
@@ -35,9 +_,31 @@
public class ComponentSerialization {
public static final Codec<Component> CODEC = Codec.recursive("Component", ComponentSerialization::createCodec);
@@ -34,7 +34,7 @@
public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply(
ByteBufCodecs::optional
);
@@ -102,7 +_,25 @@
@@ -94,7 +_,25 @@
return ExtraCodecs.orCompressed(mapCodec2, mapCodec1);
}
@@ -60,7 +60,7 @@
ComponentContents.Type<?>[] types = new ComponentContents.Type[]{
PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE
};
@@ -115,6 +_,34 @@
@@ -107,6 +_,34 @@
)
.apply(instance, MutableComponent::new)
);
@@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/PlayerChatMessage.java
+++ b/net/minecraft/network/chat/PlayerChatMessage.java
@@ -17,6 +_,43 @@
@@ -18,6 +_,43 @@
public record PlayerChatMessage(
SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask
) {
@@ -44,7 +44,7 @@
public static final MapCodec<PlayerChatMessage> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link),
@@ -47,7 +_,14 @@
@@ -48,7 +_,14 @@
}
public PlayerChatMessage withUnsignedContent(Component message) {
@@ -1,20 +1,20 @@
--- a/net/minecraft/network/chat/contents/NbtContents.java
+++ b/net/minecraft/network/chat/contents/NbtContents.java
@@ -115,7 +_,7 @@
}).map(Tag::getAsString);
@@ -119,7 +_,7 @@
if (this.interpreting) {
RegistryOps<Tag> registryOps = nbtPathPattern.registryAccess().createSerializationContext(NbtOps.INSTANCE);
Component component = DataFixUtils.orElse(
- ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR
+ ComponentUtils.updateSeparatorForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR // Paper - validate separator
);
return stream.flatMap(text -> {
return stream.flatMap(tag -> {
try {
@@ -127,7 +_,7 @@
}
@@ -132,7 +_,7 @@
}).reduce((mutableComponent, component1) -> mutableComponent.append(component).append(component1)).orElseGet(Component::empty);
} else {
Stream<String> stream1 = stream.map(NbtContents::asString);
- return ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth)
+ return ComponentUtils.updateSeparatorForEntity(nbtPathPattern, this.separator, entity, recursionDepth) // Paper - validate separator
.map(
mutableComponent -> stream.map(Component::literal)
mutableComponent -> stream1.map(Component::literal)
.reduce((mutableComponent1, otherMutableComponent) -> mutableComponent1.append(mutableComponent).append(otherMutableComponent))
@@ -1,6 +1,6 @@
--- a/net/minecraft/network/codec/ByteBufCodecs.java
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
@@ -378,6 +_,48 @@
@@ -390,6 +_,48 @@
};
}
@@ -1,9 +1,9 @@
--- a/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
+++ b/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
@@ -35,6 +_,20 @@
this.items = ItemStack.OPTIONAL_LIST_STREAM_CODEC.decode(buffer);
this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
}
@@ -22,6 +_,21 @@
ClientboundContainerSetContentPacket::new
);
+ // Paper start - Handle large packets disconnecting client
+ @Override
+ public boolean hasLargePacketFallback() {
@@ -18,6 +18,7 @@
+ return true;
+ }
+ // Paper end - Handle large packets disconnecting client
private void write(RegistryFriendlyByteBuf buffer) {
buffer.writeContainerId(this.containerId);
+
@Override
public PacketType<ClientboundContainerSetContentPacket> type() {
return GamePacketTypes.CLIENTBOUND_CONTAINER_SET_CONTENT;
@@ -1,15 +1,15 @@
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -52,7 +_,7 @@
throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
@@ -50,7 +_,7 @@
public ClientboundLevelChunkPacketData(RegistryFriendlyByteBuf buffer, int x, int z) {
this.heightmaps = HEIGHTMAPS_STREAM_CODEC.decode(buffer);
int varInt = buffer.readVarInt();
- if (varInt > 2097152) {
+ if (varInt > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
int varInt = buffer.readVarInt();
- if (varInt > 2097152) {
+ if (varInt > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
this.buffer = new byte[varInt];
@@ -154,6 +_,7 @@
this.buffer = new byte[varInt];
@@ -151,6 +_,7 @@
CompoundTag updateTag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
BlockPos blockPos = blockEntity.getBlockPos();
int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());
@@ -1,6 +1,6 @@
--- a/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
+++ b/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
@@ -30,6 +_,11 @@
@@ -31,6 +_,11 @@
private final Collection<String> players;
private final Optional<ClientboundSetPlayerTeamPacket.Parameters> parameters;
@@ -12,12 +12,12 @@
private ClientboundSetPlayerTeamPacket(String name, int method, Optional<ClientboundSetPlayerTeamPacket.Parameters> parameters, Collection<String> players) {
this.name = name;
this.method = method;
@@ -198,7 +_,7 @@
@@ -199,7 +_,7 @@
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.displayName);
buffer.writeByte(this.options);
buffer.writeUtf(this.nametagVisibility);
- buffer.writeUtf(this.collisionRule);
+ buffer.writeUtf(!io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? PlayerTeam.CollisionRule.NEVER.name : this.collisionRule); // Paper - Configurable player collision
Team.Visibility.STREAM_CODEC.encode(buffer, this.nametagVisibility);
- Team.CollisionRule.STREAM_CODEC.encode(buffer, this.collisionRule);
+ Team.CollisionRule.STREAM_CODEC.encode(buffer, !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? PlayerTeam.CollisionRule.NEVER : this.collisionRule); // Paper - Configurable player collision
buffer.writeEnum(this.color);
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.playerPrefix);
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.playerSuffix);
@@ -1,20 +0,0 @@
--- a/net/minecraft/network/protocol/game/ServerboundContainerClickPacket.java
+++ b/net/minecraft/network/protocol/game/ServerboundContainerClickPacket.java
@@ -17,7 +_,7 @@
);
private static final int MAX_SLOT_COUNT = 128;
private static final StreamCodec<RegistryFriendlyByteBuf, Int2ObjectMap<ItemStack>> SLOTS_STREAM_CODEC = ByteBufCodecs.map(
- Int2ObjectOpenHashMap::new, ByteBufCodecs.SHORT.map(Short::intValue, Integer::shortValue), ItemStack.OPTIONAL_STREAM_CODEC, 128
+ Int2ObjectOpenHashMap::new, ByteBufCodecs.SHORT.map(Short::intValue, Integer::shortValue), ItemStack.OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs::trackDepth), 128 // Paper - Track codec depth
);
private final int containerId;
private final int stateId;
@@ -46,7 +_,7 @@
this.buttonNum = buffer.readByte();
this.clickType = buffer.readEnum(ClickType.class);
this.changedSlots = Int2ObjectMaps.unmodifiable(SLOTS_STREAM_CODEC.decode(buffer));
- this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
+ this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs::trackDepth).decode(buffer); // Paper - Track codec depth
}
private void write(RegistryFriendlyByteBuf buffer) {
@@ -4,8 +4,8 @@
public static final StreamCodec<RegistryFriendlyByteBuf, ServerboundSetCreativeModeSlotPacket> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.SHORT,
ServerboundSetCreativeModeSlotPacket::slotNum,
- ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_STREAM_CODEC),
+ ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_STREAM_CODEC).apply(ByteBufCodecs::trackDepth), // Paper - Track codec depth
- ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC),
+ ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC).apply(ByteBufCodecs::trackDepth), // Paper - Track codec depth
ServerboundSetCreativeModeSlotPacket::itemStack,
ServerboundSetCreativeModeSlotPacket::new
);
@@ -1,6 +1,6 @@
--- a/net/minecraft/resources/RegistryDataLoader.java
+++ b/net/minecraft/resources/RegistryDataLoader.java
@@ -247,13 +_,14 @@
@@ -271,13 +_,14 @@
RegistryOps<JsonElement> ops,
ResourceKey<E> resourceKey,
Resource resource,
@@ -17,7 +17,7 @@
}
}
@@ -267,6 +_,7 @@
@@ -291,6 +_,7 @@
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
@@ -25,7 +25,7 @@
for (Entry<ResourceLocation, Resource> entry : fileToIdConverter.listMatchingResources(resourceManager).entrySet()) {
ResourceLocation resourceLocation = entry.getKey();
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), fileToIdConverter.fileToId(resourceLocation));
@@ -274,7 +_,7 @@
@@ -298,7 +_,7 @@
RegistrationInfo registrationInfo = REGISTRATION_INFO_CACHE.apply(resource.knownPackInfo());
try {
@@ -34,7 +34,7 @@
} catch (Exception var14) {
loadingErrors.put(
resourceKey,
@@ -283,7 +_,9 @@
@@ -307,7 +_,9 @@
}
}
@@ -45,7 +45,7 @@
}
static <E> void loadContentsFromNetwork(
@@ -300,6 +_,7 @@
@@ -324,6 +_,7 @@
RegistryOps<JsonElement> registryOps1 = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
@@ -53,7 +53,7 @@
for (RegistrySynchronization.PackedRegistryEntry packedRegistryEntry : networkedRegistryData.elements) {
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), packedRegistryEntry.id());
Optional<Tag> optional = packedRegistryEntry.data();
@@ -318,7 +_,7 @@
@@ -342,7 +_,7 @@
try {
Resource resourceOrThrow = resourceProvider.getResourceOrThrow(resourceLocation);
@@ -62,7 +62,7 @@
} catch (Exception var17) {
loadingErrors.put(resourceKey, new IllegalStateException("Failed to parse local data", var17));
}
@@ -360,6 +_,7 @@
@@ -384,6 +_,7 @@
RegistryDataLoader.Loader<T> create(Lifecycle registryLifecycle, Map<ResourceKey<?>, Exception> loadingErrors) {
WritableRegistry<T> writableRegistry = new MappedRegistry<>(this.key, registryLifecycle);
@@ -1,6 +1,6 @@
--- a/net/minecraft/resources/ResourceLocation.java
+++ b/net/minecraft/resources/ResourceLocation.java
@@ -32,6 +_,7 @@
@@ -23,6 +_,7 @@
public static final char NAMESPACE_SEPARATOR = ':';
public static final String DEFAULT_NAMESPACE = "minecraft";
public static final String REALMS_NAMESPACE = "realms";
@@ -8,7 +8,7 @@
private final String namespace;
private final String path;
@@ -40,6 +_,13 @@
@@ -31,6 +_,13 @@
assert isValidPath(path);
@@ -22,7 +22,7 @@
this.namespace = namespace;
this.path = path;
}
@@ -252,7 +_,7 @@
@@ -243,7 +_,7 @@
private static String assertValidNamespace(String namespace, String path) {
if (!isValidNamespace(namespace)) {
@@ -31,7 +31,7 @@
} else {
return namespace;
}
@@ -277,7 +_,7 @@
@@ -268,7 +_,7 @@
private static String assertValidPath(String namespace, String path) {
if (!isValidPath(path)) {
@@ -180,11 +180,11 @@
+ /*
RegistryAccess.Frozen frozen = worldStem.registries().compositeAccess();
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
if (optionSet.has(optionSpec4) || hasOptionSpec1) {
@@ -245,9 +_,13 @@
WorldData worldData = worldStem.worldData();
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
@@ -245,9 +_,13 @@
}
levelStorageAccess.saveDataTag(frozen, worldData);
+ */
final DedicatedServer dedicatedServer = MinecraftServer.spin(
@@ -241,12 +241,12 @@
} catch (Exception var42) {
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var42);
}
@@ -316,7 +_,7 @@
@@ -317,7 +_,7 @@
RegistryAccess registryAccess,
boolean recreateRegionFiles
) {
- LOGGER.info("Forcing world upgrade!");
+ LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit
try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, registryAccess, eraseCache, recreateRegionFiles)) {
try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, worldData, registryAccess, eraseCache, recreateRegionFiles)) {
Component component = null;
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/ServerScoreboard.java
+++ b/net/minecraft/server/ServerScoreboard.java
@@ -39,9 +_,7 @@
@@ -43,9 +_,7 @@
protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) {
super.onScoreChanged(scoreHolder, objective, score);
if (this.trackedObjectives.contains(objective)) {
@@ -11,7 +11,7 @@
new ClientboundSetScorePacket(
scoreHolder.getScoreboardName(),
objective.getName(),
@@ -64,7 +_,7 @@
@@ -68,7 +_,7 @@
@Override
public void onPlayerRemoved(ScoreHolder scoreHolder) {
super.onPlayerRemoved(scoreHolder);
@@ -20,7 +20,7 @@
this.setDirty();
}
@@ -72,7 +_,7 @@
@@ -76,7 +_,7 @@
public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) {
super.onPlayerScoreRemoved(scoreHolder, objective);
if (this.trackedObjectives.contains(objective)) {
@@ -29,7 +29,7 @@
}
this.setDirty();
@@ -84,7 +_,7 @@
@@ -88,7 +_,7 @@
super.setDisplayObjective(slot, objective);
if (displayObjective != objective && displayObjective != null) {
if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) {
@@ -38,7 +38,7 @@
} else {
this.stopTrackingObjective(displayObjective);
}
@@ -92,7 +_,7 @@
@@ -96,7 +_,7 @@
if (objective != null) {
if (this.trackedObjectives.contains(objective)) {
@@ -47,7 +47,7 @@
} else {
this.startTrackingObjective(objective);
}
@@ -104,24 +_,50 @@
@@ -108,24 +_,50 @@
@Override
public boolean addPlayerToTeam(String playerName, PlayerTeam team) {
if (super.addPlayerToTeam(playerName, team)) {
@@ -112,7 +112,7 @@
@Override
public void onObjectiveAdded(Objective objective) {
@@ -133,7 +_,7 @@
@@ -137,7 +_,7 @@
public void onObjectiveChanged(Objective objective) {
super.onObjectiveChanged(objective);
if (this.trackedObjectives.contains(objective)) {
@@ -121,7 +121,7 @@
}
this.setDirty();
@@ -152,21 +_,21 @@
@@ -156,21 +_,21 @@
@Override
public void onTeamAdded(PlayerTeam playerTeam) {
super.onTeamAdded(playerTeam);
@@ -146,7 +146,7 @@
this.setDirty();
}
@@ -209,6 +_,7 @@
@@ -213,6 +_,7 @@
List<Packet<?>> startTrackingPackets = this.getStartTrackingPackets(objective);
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@@ -154,7 +154,7 @@
for (Packet<?> packet : startTrackingPackets) {
serverPlayer.connection.send(packet);
}
@@ -234,6 +_,7 @@
@@ -238,6 +_,7 @@
List<Packet<?>> stopTrackingPackets = this.getStopTrackingPackets(objective);
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@@ -162,9 +162,9 @@
for (Packet<?> packet : stopTrackingPackets) {
serverPlayer.connection.send(packet);
}
@@ -267,6 +_,16 @@
private ScoreboardSaveData createData(CompoundTag tag, HolderLookup.Provider registries) {
return this.createData().load(tag, registries);
@@ -269,6 +_,16 @@
scoreboardSaveData.loadFrom(data);
return scoreboardSaveData;
}
+
+ // CraftBukkit start - Send to players
@@ -1,11 +0,0 @@
--- a/net/minecraft/server/commands/OpCommand.java
+++ b/net/minecraft/server/commands/OpCommand.java
@@ -46,7 +_,7 @@
if (!playerList.isOp(gameProfile)) {
playerList.op(gameProfile);
i++;
- source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfiles.iterator().next().getName()), true);
+ source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfile.getName()), true); // Paper - fixes MC-253721
}
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/PlaceCommand.java
+++ b/net/minecraft/server/commands/PlaceCommand.java
@@ -280,6 +_,7 @@
@@ -301,6 +_,7 @@
if (!structureStart.isValid()) {
throw ERROR_STRUCTURE_FAILED.create();
} else {
@@ -6,7 +6,7 @@
+ final Collection<ServerPlayer> actualTargets = new java.util.ArrayList<>(); // Paper - Add PlayerSetSpawnEvent
for (ServerPlayer serverPlayer : targets) {
- serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false);
- serverPlayer.setRespawnPosition(new ServerPlayer.RespawnConfig(resourceKey, pos, angle, true), false);
- }
+ // Paper start - Add PlayerSetSpawnEvent
+ if (serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
@@ -3,7 +3,7 @@
@@ -82,6 +_,7 @@
ServerLevel level = source.getLevel();
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, EntitySpawnReason.COMMAND, entity1 -> {
entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot());
entity1.snapTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot());
+ entity1.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND; // Paper - Entity#getEntitySpawnReason
return entity1;
});
@@ -1,366 +1,20 @@
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -145,6 +_,33 @@
public int serverViewDistance;
private final WorldGenContext worldGenContext;
+ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
+ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
+ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
+
+ private final java.util.Queue<Runnable> queue = new java.util.ArrayDeque<>();
+
+ @Override
+ public void execute(Runnable runnable) {
+ this.queue.add(runnable);
+ }
+
+ @Override
+ public void run() {
+ Runnable task;
+ while ((task = this.queue.poll()) != null) {
+ task.run();
+ }
+ }
+ };
+ // CraftBukkit end
+
+ // Paper start
+ public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
+ return this.pendingUnloads.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ }
+ // Paper end
+
public ChunkMap(
ServerLevel level,
LevelStorageSource.LevelStorageAccess levelStorageAccess,
@@ -171,13 +_,19 @@
this.level = level;
RegistryAccess registryAccess = level.registryAccess();
long seed = level.getSeed();
- if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
+ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random.
+ ChunkGenerator randomGenerator = generator;
+ if (randomGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator customChunkGenerator) {
+ randomGenerator = customChunkGenerator.getDelegate();
+ }
+ if (randomGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
+ // CraftBukkit end
this.randomState = RandomState.create(noiseBasedChunkGenerator.generatorSettings().value(), registryAccess.lookupOrThrow(Registries.NOISE), seed);
} else {
this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), registryAccess.lookupOrThrow(Registries.NOISE), seed);
}
- this.chunkGeneratorState = generator.createState(registryAccess.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, seed);
+ this.chunkGeneratorState = generator.createState(registryAccess.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, seed, level.spigotConfig); // Spigot
this.mainThreadExecutor = mainThreadExecutor;
ConsecutiveExecutor consecutiveExecutor = new ConsecutiveExecutor(dispatcher, "worldgen");
this.progressListener = progressListener;
@@ -207,6 +_,12 @@
this.chunksToEagerlySave.add(chunkPos.toLong());
}
+ // Paper start
+ public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
+ return -1;
+ }
+ // Paper end
+
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
}
@@ -354,9 +_,9 @@
}
);
stringBuilder.append("Updating:").append(System.lineSeparator());
- this.updatingChunkMap.values().forEach(consumer);
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().getUpdatingChunkHolders(this.level).forEach(consumer); // Paper
stringBuilder.append("Visible:").append(System.lineSeparator());
- this.visibleChunkMap.values().forEach(consumer);
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level).forEach(consumer); // Paper
CrashReport crashReport = CrashReport.forThrowable(exception, "Chunk loading");
CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk loading");
crashReportCategory.setDetail("Details", details);
@@ -392,6 +_,9 @@
holder.setTicketLevel(newLevel);
} else {
holder = new ChunkHolder(new ChunkPos(chunkPos), newLevel, this.level, this.lightEngine, this::onLevelChange, this);
+ // Paper start
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder);
+ // Paper end
}
this.updatingChunkMap.put(chunkPos, holder);
@@ -420,8 +_,8 @@
protected void saveAllChunks(boolean flush) {
if (flush) {
- List<ChunkHolder> list = this.visibleChunkMap
- .values()
+ List<ChunkHolder> list = ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level) // Paper - moonrise
+ //.values() // Paper - moonrise
.stream()
.filter(ChunkHolder::wasAccessibleSinceLastSave)
.peek(ChunkHolder::refreshAccessibility)
@@ -447,7 +_,7 @@
this.nextChunkSaveTime.clear();
long millis = Util.getMillis();
- for (ChunkHolder chunkHolder : this.visibleChunkMap.values()) {
+ for (ChunkHolder chunkHolder : ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level)) { // Paper
this.saveChunkIfNeeded(chunkHolder, millis);
}
}
@@ -468,6 +_,7 @@
public boolean hasWork() {
return this.lightEngine.hasLightWork()
|| !this.pendingUnloads.isEmpty()
+ || ca.spottedleaf.moonrise.common.PlatformHooks.get().hasAnyChunkHolders(this.level) // Paper - moonrise
|| !this.updatingChunkMap.isEmpty()
|| this.poiManager.hasWork()
|| !this.toDrop.isEmpty()
@@ -526,7 +_,11 @@
this.scheduleUnload(chunkPos, chunkHolder);
} else {
ChunkAccess latestChunk = chunkHolder.getLatestChunk();
- if (this.pendingUnloads.remove(chunkPos, chunkHolder) && latestChunk != null) {
+ // Paper start
+ boolean removed;
+ if ((removed = this.pendingUnloads.remove(chunkPos, chunkHolder)) && latestChunk != null) {
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderDelete(this.level, chunkHolder);
+ // Paper end
if (latestChunk instanceof LevelChunk levelChunk) {
levelChunk.setLoaded(false);
}
@@ -540,7 +_,9 @@
this.lightEngine.tryScheduleUpdate();
this.progressListener.onStatusChange(latestChunk.getPos(), null);
this.nextChunkSaveTime.remove(latestChunk.getPos().toLong());
- }
+ } else if (removed) { // Paper start
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderDelete(this.level, chunkHolder);
+ } // Paper end
}
}, this.unloadQueue::add).whenComplete((_void, error) -> {
if (error != null) {
@@ -856,7 +_,7 @@
}
public int size() {
- return this.visibleChunkMap.size();
+ return ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolderCount(this.level); // Paper
}
public net.minecraft.server.level.DistanceManager getDistanceManager() {
@@ -864,7 +_,7 @@
}
protected Iterable<ChunkHolder> getChunks() {
- return Iterables.unmodifiableIterable(this.visibleChunkMap.values());
+ return Iterables.unmodifiableIterable(ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level)); // Paper
}
void dumpChunks(Writer writer) throws IOException {
@@ -888,10 +_,10 @@
.build(writer);
TickingTracker tickingTracker = this.distanceManager.tickingTracker();
- for (Entry<ChunkHolder> entry : this.visibleChunkMap.long2ObjectEntrySet()) {
- long longKey = entry.getLongKey();
+ for (ChunkHolder entry : ca.spottedleaf.moonrise.common.PlatformHooks.get().getVisibleChunkHolders(this.level)) { // Paper - Moonrise
+ long longKey = entry.pos.toLong(); // Paper - Moonrise
ChunkPos chunkPos = new ChunkPos(longKey);
- ChunkHolder chunkHolder = entry.getValue();
+ ChunkHolder chunkHolder = entry; // Paper - Moonrise
Optional<ChunkAccess> optional = Optional.ofNullable(chunkHolder.getLatestChunk());
Optional<LevelChunk> optional1 = optional.flatMap(chunk -> chunk instanceof LevelChunk ? Optional.of((LevelChunk)chunk) : Optional.empty());
csvOutput.writeRow(
@@ -931,11 +_,13 @@
}
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
- return this.read(pos).thenApplyAsync(optional -> optional.map(this::upgradeChunkTag), Util.backgroundExecutor().forName("upgradeChunk"));
+ return this.read(pos).thenApplyAsync(optional -> optional.map(tag -> upgradeChunkTag(tag, pos)), Util.backgroundExecutor().forName("upgradeChunk")); // CraftBukkit
}
- private CompoundTag upgradeChunkTag(CompoundTag tag) {
- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, tag, this.generator().getTypeNameForDataFixer());
+ // CraftBukkit start
+ private CompoundTag upgradeChunkTag(CompoundTag tag, ChunkPos pos) {
+ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, tag, this.generator().getTypeNameForDataFixer(), pos, this.level);
+ // CraftBukkit end
}
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> action) {
@@ -951,12 +_,34 @@
}
public boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) {
- return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos);
+ // Spigot start
+ return this.anyPlayerCloseEnoughForSpawning(chunkPos, false);
+ }
+
+ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos, boolean reducedRange) {
+ return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange);
+ // Spigot end
}
private boolean anyPlayerCloseEnoughForSpawningInternal(ChunkPos chunkPos) {
+ // Spigot start
+ return this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, false);
+ }
+
+ private boolean anyPlayerCloseEnoughForSpawningInternal(ChunkPos chunkPos, boolean reducedRange) {
+ double blockRange; // Paper - use from event
+ // Spigot end
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
- if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos)) {
+ // Paper start - PlayerNaturallySpawnCreaturesEvent
+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event;
+ blockRange = 16384.0D;
+ if (reducedRange) {
+ event = serverPlayer.playerNaturallySpawnedEvent;
+ if (event == null || event.isCancelled()) continue;
+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
+ }
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, blockRange)) {
return true;
}
}
@@ -972,7 +_,7 @@
Builder<ServerPlayer> builder = ImmutableList.builder();
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
- if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos)) {
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, 16384.0D)) { // Spigot
builder.add(serverPlayer);
@@ -939,7 +_,7 @@
ChunkHolder chunkHolder = this.visibleChunkMap.get(spawnCandidateChunks.nextLong());
if (chunkHolder != null) {
LevelChunk tickingChunk = chunkHolder.getTickingChunk();
- if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos())) {
+ if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos(), true)) { // Spigot
output.add(tickingChunk);
}
}
@@ -981,12 +_,12 @@
}
}
- private boolean playerIsCloseEnoughForSpawning(ServerPlayer player, ChunkPos chunkPos) {
+ private boolean playerIsCloseEnoughForSpawning(ServerPlayer player, ChunkPos chunkPos, double range) { // Spigot
if (player.isSpectator()) {
return false;
} else {
double d = euclideanDistanceSquared(chunkPos, player);
- return d < 16384.0;
+ return d < range; // Spigot
}
}
@@ -1100,9 +_,19 @@
}
public void addEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server
+ if (!entity.valid || entity.level() != this.level || this.entityMap.containsKey(entity.getId())) {
+ LOGGER.error("Illegal ChunkMap::addEntity for world " + this.level.getWorld().getName()
+ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
+ return;
+ }
+ // Paper end - ignore and warn about illegal addEntity calls instead of crashing server
+ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Paper - Fire PlayerJoinEvent when Player is actually ready; Delay adding to tracker until after list packets
if (!(entity instanceof EnderDragonPart)) {
EntityType<?> type = entity.getType();
int i = type.clientTrackingRange() * 16;
+ i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i); // Spigot
if (i != 0) {
int updateInterval = type.updateInterval();
if (this.entityMap.containsKey(entity.getId())) {
@@ -1126,6 +_,7 @@
}
protected void removeEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity untrack"); // Spigot
if (entity instanceof ServerPlayer serverPlayer) {
this.updatePlayerStatus(serverPlayer, false);
@@ -1230,7 +_,7 @@
});
}
- class DistanceManager extends net.minecraft.server.level.DistanceManager {
+ public class DistanceManager extends net.minecraft.server.level.DistanceManager { // Paper - public
protected DistanceManager(final Executor dispatcher, final Executor mainThreadExecutor) {
super(dispatcher, mainThreadExecutor);
}
@@ -1258,10 +_,10 @@
final Entity entity;
private final int range;
SectionPos lastSectionPos;
- public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
@@ -1278,7 +_,7 @@
public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast);
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this.seenBy); // CraftBukkit
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers);
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers, this.seenBy); // Paper
this.entity = entity;
this.range = range;
this.lastSectionPos = SectionPos.of(entity);
@@ -1297,24 +_,47 @@
}
public void removePlayer(ServerPlayer player) {
+ org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot
if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
}
}
public void updatePlayer(ServerPlayer player) {
+ org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
if (player != this.entity) {
- Vec3 vec3 = player.position().subtract(this.entity.position());
+ // Paper start - remove allocation of Vec3D here
+ // Vec3 vec3 = player.position().subtract(this.entity.position());
+ double vec3_dx = player.getX() - this.entity.getX();
+ double vec3_dz = player.getZ() - this.entity.getZ();
+ // Paper end - remove allocation of Vec3D here
int playerViewDistance = ChunkMap.this.getPlayerViewDistance(player);
double d = Math.min(this.getEffectiveRange(), playerViewDistance * 16);
- double d1 = vec3.x * vec3.x + vec3.z * vec3.z;
+ double d1 = vec3_dx * vec3_dx + vec3_dz * vec3_dz; // Paper
double d2 = d * d;
- boolean flag = d1 <= d2
- && this.entity.broadcastToPlayer(player)
- && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+ // Paper start - Configurable entity tracking range by Y
+ boolean flag = d1 <= d2;
+ if (flag && level.paperConfig().entities.trackingRangeY.enabled) {
+ double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
+ if (rangeY != -1) {
+ double vec3_dy = player.getY() - this.entity.getY();
+ flag = vec3_dy * vec3_dy <= rangeY * rangeY;
+ }
+ }
+ flag = flag && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+ // Paper end - Configurable entity tracking range by Y
+ // CraftBukkit start - respect vanish API
+ if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
+ flag = false;
+ }
+ // CraftBukkit end
if (flag) {
if (this.seenBy.add(player.connection)) {
+ // Paper start - entity tracking events
+ if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) {
this.serverEntity.addPairing(player);
+ }
+ // Paper end - entity tracking events
}
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
@@ -1331,6 +_,7 @@
for (Entity entity : this.entity.getIndirectPassengers()) {
int i1 = entity.getType().clientTrackingRange() * 16;
+ i1 = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i1); // Paper
if (i1 > i) {
i = i1;
}
@@ -1,6 +1,15 @@
--- a/net/minecraft/server/level/DistanceManager.java
+++ b/net/minecraft/server/level/DistanceManager.java
@@ -107,6 +_,12 @@
@@ -36,7 +_,7 @@
final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap<>();
private final LoadingChunkTracker loadingChunkTracker;
private final SimulationChunkTracker simulationChunkTracker;
- final TicketStorage ticketStorage;
+ public final TicketStorage ticketStorage; // Paper - TODO: AT
private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8);
private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(32);
protected final Set<ChunkHolder> chunksToUpdateFutures = new ReferenceOpenHashSet<>();
@@ -72,6 +_,12 @@
}
if (!this.chunksToUpdateFutures.isEmpty()) {
@@ -13,51 +22,7 @@
for (ChunkHolder chunkHolder : this.chunksToUpdateFutures) {
chunkHolder.updateHighestAllowedStatus(chunkMap);
}
@@ -177,16 +_,42 @@
public <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
long packedChunkPos = pos.toLong();
- this.addTicket(packedChunkPos, ticket);
+ this.addTicket(packedChunkPos, ticket); // Paper - diff on change above
this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
}
public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
long packedChunkPos = pos.toLong();
+ this.removeTicket(packedChunkPos, ticket); // Paper - diff on change above
+ this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
+ }
+
+ // Paper start
+ public boolean addPluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
+ final long packedChunkPos = pos.toLong();
+ final Set<Ticket<?>> tickets = this.getTickets(packedChunkPos);
+ if (tickets.contains(ticket)) {
+ return false;
+ }
+ this.addTicket(packedChunkPos, ticket);
+ this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
+ return true;
+ }
+
+ public boolean removePluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
+ final long packedChunkPos = pos.toLong();
+ final Set<Ticket<?>> tickets = this.tickets.get(packedChunkPos); // Don't use getTickets, we don't want to create a new set
+ if (tickets == null || !tickets.contains(ticket)) {
+ return false;
+ }
this.removeTicket(packedChunkPos, ticket);
this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
+ return true;
}
+ // Paper end
private SortedArraySet<Ticket<?>> getTickets(long chunkPos) {
return this.tickets.computeIfAbsent(chunkPos, l -> SortedArraySet.create(4));
@@ -217,8 +_,10 @@
@@ -121,8 +_,10 @@
ChunkPos chunkPos = sectionPos.chunk();
long packedChunkPos = chunkPos.toLong();
ObjectSet<ServerPlayer> set = this.playersPerChunk.get(packedChunkPos);
@@ -70,39 +35,3 @@
this.playersPerChunk.remove(packedChunkPos);
this.naturalSpawnChunkCounter.update(packedChunkPos, Integer.MAX_VALUE, false);
this.playerTicketManager.update(packedChunkPos, Integer.MAX_VALUE, false);
@@ -299,7 +_,7 @@
}
public void removeTicketsOnClosing() {
- ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN);
+ ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.FUTURE_AWAIT); // Paper - add additional tickets to preserve
ObjectIterator<Entry<SortedArraySet<Ticket<?>>>> objectIterator = this.tickets.long2ObjectEntrySet().fastIterator();
while (objectIterator.hasNext()) {
@@ -329,6 +_,26 @@
public boolean hasTickets() {
return !this.tickets.isEmpty();
}
+
+ // CraftBukkit start
+ public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
+ Ticket<T> target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier);
+
+ for (java.util.Iterator<Entry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ Entry<SortedArraySet<Ticket<?>>> entry = iterator.next();
+ SortedArraySet<Ticket<?>> tickets = entry.getValue();
+ if (tickets.remove(target)) {
+ // copied from removeTicket
+ this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt(tickets), false);
+
+ // can't use entry after it's removed
+ if (tickets.isEmpty()) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+ // CraftBukkit end
class ChunkTicketTracker extends ChunkTracker {
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -73,6 +_,13 @@
@@ -77,6 +_,13 @@
@Nullable
@VisibleForDebug
private NaturalSpawner.SpawnState lastSpawnState;
@@ -14,7 +14,7 @@
public ServerChunkCache(
ServerLevel level,
@@ -121,6 +_,64 @@
@@ -127,6 +_,64 @@
this.clearCache();
}
@@ -46,12 +46,12 @@
+ return holder.getLatestChunk();
+ }
+
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
+ public <T> void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.ticketStorage.addTicketWithRadius(ticketType, chunkPos, ticketLevel);
+ }
+
+ public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
+ public <T> void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.ticketStorage.removeTicketWithRadius(ticketType, chunkPos, ticketLevel);
+ }
+
+ // "real" get chunk if loaded
@@ -79,7 +79,7 @@
@Override
public ThreadedLevelLightEngine getLightEngine() {
return this.lightEngine;
@@ -160,7 +_,7 @@
@@ -166,7 +_,7 @@
for (int i = 0; i < 4; i++) {
if (packedChunkPos == this.lastChunkPos[i] && chunkStatus == this.lastChunkStatus[i]) {
ChunkAccess chunkAccess = this.lastChunk[i];
@@ -88,7 +88,7 @@
return chunkAccess;
}
}
@@ -169,6 +_,7 @@
@@ -175,6 +_,7 @@
profilerFiller.incrementCounter("getChunkCacheMiss");
CompletableFuture<ChunkResult<ChunkAccess>> chunkFutureMainThread = this.getChunkFutureMainThread(x, z, chunkStatus, requireChunk);
this.mainThreadProcessor.managedBlock(chunkFutureMainThread::isDone);
@@ -96,7 +96,7 @@
ChunkResult<ChunkAccess> chunkResult = chunkFutureMainThread.join();
ChunkAccess chunkAccess1 = chunkResult.orElse(null);
if (chunkAccess1 == null && requireChunk) {
@@ -240,7 +_,15 @@
@@ -246,7 +_,15 @@
long packedChunkPos = chunkPos.toLong();
int i = ChunkLevel.byStatus(chunkStatus);
ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(packedChunkPos);
@@ -109,11 +109,11 @@
+ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL));
+ }
+ if (requireChunk && !currentlyUnloading) {
+ // CraftBukkit end
this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, i, chunkPos);
+ // CraftBukkit end
this.addTicket(new Ticket(TicketType.UNKNOWN, i), chunkPos);
if (this.chunkAbsent(visibleChunkIfPresent, i)) {
ProfilerFiller profilerFiller = Profiler.get();
@@ -260,7 +_,7 @@
@@ -266,7 +_,7 @@
}
private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) {
@@ -122,7 +122,7 @@
}
@Override
@@ -287,7 +_,7 @@
@@ -293,7 +_,7 @@
return this.mainThreadProcessor.pollTask();
}
@@ -131,7 +131,7 @@
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
boolean flag1 = this.chunkMap.promoteChunkMap();
this.chunkMap.runGenerationTasks();
@@ -315,17 +_,39 @@
@@ -321,17 +_,39 @@
@Override
public void close() throws IOException {
@@ -155,7 +155,7 @@
+ ProfilerFiller gameprofilerfiller = Profiler.get();
+
+ gameprofilerfiller.push("purge");
+ this.distanceManager.purgeStaleTickets();
+ this.ticketStorage.purgeStaleTickets();
+ this.runDistanceManagerUpdates();
+ gameprofilerfiller.popPush("unload");
+ this.chunkMap.tick(() -> true);
@@ -170,10 +170,10 @@
profilerFiller.push("purge");
- if (this.level.tickRateManager().runsNormally() || !tickChunks) {
+ if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
this.distanceManager.purgeStaleTickets();
this.ticketStorage.purgeStaleTickets();
}
@@ -400,12 +_,20 @@
@@ -388,12 +_,20 @@
);
this.lastSpawnState = spawnState;
profiler.popPush("spawnAndTick");
@@ -197,16 +197,7 @@
} else {
filteredSpawningCategories = List.of();
}
@@ -413,7 +_,7 @@
for (LevelChunk levelChunk : chunks) {
ChunkPos pos = levelChunk.getPos();
levelChunk.incrementInhabitedTime(timeInhabited);
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos)) {
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, filteredSpawningCategories);
}
@@ -526,8 +_,13 @@
@@ -544,8 +_,13 @@
@Override
public void setSpawnSettings(boolean spawnSettings) {
@@ -221,7 +212,7 @@
}
public String getChunkDebugData(ChunkPos chunkPos) {
@@ -603,12 +_,18 @@
@@ -618,12 +_,18 @@
@Override
public boolean pollTask() {
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -65,13 +_,17 @@
@@ -69,11 +_,12 @@
private Vec3 lastSentMovement;
private int tickCount;
private int teleportDelay;
@@ -10,26 +10,25 @@
private boolean wasOnGround;
@Nullable
private List<SynchedEntityData.DataValue<?>> trackedDataValues;
+ private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers; // Paper
- public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer<Packet<?>> broadcast) {
+ // CraftBukkit start
+ private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers;
+ public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer<Packet<?>> broadcast, final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers) {
+ this.trackedPlayers = trackedPlayers;
+ // CraftBukkit end
public ServerEntity(
ServerLevel level,
@@ -81,8 +_,12 @@
int updateInterval,
boolean trackDelta,
Consumer<Packet<?>> broadcast,
- BiConsumer<Packet<?>, List<UUID>> broadcastWithIgnore
+ // Paper start
+ BiConsumer<Packet<?>, List<UUID>> broadcastWithIgnore,
+ final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers
+ // Paper end
) {
+ this.trackedPlayers = trackedPlayers; // Paper
this.level = level;
this.broadcast = broadcast;
this.entity = entity;
@@ -89,7 +_,7 @@
public void sendChanges() {
List<Entity> passengers = this.entity.getPassengers();
if (!passengers.equals(this.lastPassengers)) {
- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity));
+ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
removedPassengers(passengers, this.lastPassengers)
.forEach(
removedPassenger -> {
@@ -102,13 +_,14 @@
@@ -106,13 +_,14 @@
this.lastPassengers = passengers;
}
@@ -48,7 +47,7 @@
savedData.tickCarriedBy(serverPlayer, item);
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
if (updatePacket != null) {
@@ -141,7 +_,13 @@
@@ -145,7 +_,13 @@
} else {
this.teleportDelay++;
Vec3 vec3 = this.entity.trackingPosition();
@@ -63,7 +62,7 @@
Packet<?> packet = null;
boolean flag2 = flag1 || this.tickCount % 60 == 0;
boolean flag3 = false;
@@ -219,6 +_,25 @@
@@ -223,6 +_,25 @@
this.tickCount++;
if (this.entity.hurtMarked) {
@@ -89,7 +88,7 @@
this.entity.hurtMarked = false;
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
}
@@ -273,7 +_,10 @@
@@ -280,7 +_,10 @@
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> consumer) {
if (this.entity.isRemoved()) {
@@ -101,7 +100,7 @@
}
Packet<ClientGamePacketListener> addEntityPacket = this.entity.getAddEntityPacket(this);
@@ -285,6 +_,12 @@
@@ -292,6 +_,12 @@
boolean flag = this.trackDelta;
if (this.entity instanceof LivingEntity) {
Collection<AttributeInstance> syncableAttributes = ((LivingEntity)this.entity).getAttributes().getSyncableAttributes();
@@ -114,7 +113,7 @@
if (!syncableAttributes.isEmpty()) {
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), syncableAttributes));
}
@@ -309,8 +_,9 @@
@@ -316,8 +_,9 @@
}
if (!list.isEmpty()) {
@@ -125,7 +124,7 @@
}
if (!this.entity.getPassengers().isEmpty()) {
@@ -357,6 +_,11 @@
@@ -364,6 +_,11 @@
if (this.entity instanceof LivingEntity) {
Set<AttributeInstance> attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
if (!attributesToSync.isEmpty()) {
@@ -1,20 +1,21 @@
--- a/net/minecraft/server/level/TicketType.java
+++ b/net/minecraft/server/level/TicketType.java
@@ -7,6 +_,7 @@
import net.minecraft.world.level.ChunkPos;
@@ -2,6 +_,7 @@
public class TicketType<T> {
+ public static final TicketType<Long> FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper
private final String name;
private final Comparator<T> comparator;
public long timeout;
@@ -17,6 +_,9 @@
public static final TicketType<BlockPos> PORTAL = create("portal", Vec3i::compareTo, 300);
public static final TicketType<ChunkPos> ENDER_PEARL = create("ender_pearl", Comparator.comparingLong(ChunkPos::toLong), 40);
public static final TicketType<ChunkPos> UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1);
+ public static final TicketType<Unit> PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit
+ public static final TicketType<org.bukkit.plugin.Plugin> PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit
+ public static final TicketType<Integer> POST_TELEPORT = TicketType.create("post_teleport", Integer::compare, 5); // Paper - post teleport ticket type
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.util.Unit;
public static <T> TicketType<T> create(String name, Comparator<T> comparator) {
return new TicketType<>(name, comparator, 0L);
public record TicketType(long timeout, boolean persist, TicketType.TicketUse use) {
public static final long NO_TIMEOUT = 0L;
@@ -13,6 +_,10 @@
public static final TicketType PORTAL = register("portal", 300L, true, TicketType.TicketUse.LOADING_AND_SIMULATION);
public static final TicketType ENDER_PEARL = register("ender_pearl", 40L, false, TicketType.TicketUse.LOADING_AND_SIMULATION);
public static final TicketType UNKNOWN = register("unknown", 1L, false, TicketType.TicketUse.LOADING);
+ public static final TicketType PLUGIN = register("plugin", 0L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // CraftBukkit
+ public static final TicketType POST_TELEPORT = register("post_teleport", 5L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
+ public static final TicketType PLUGIN_TICKET = register("plugin_ticket", 0L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
+ public static final TicketType FUTURE_AWAIT = register("future_await", 0L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
private static TicketType register(String name, long timeout, boolean persist, TicketType.TicketUse use) {
return Registry.register(BuiltInRegistries.TICKET_TYPE, name, new TicketType(timeout, persist, use));
@@ -71,10 +71,10 @@
return false;
} else {
ChunkAccess chunk = this.getChunk(pos);
- BlockState blockState = chunk.setBlockState(pos, state, false);
+ BlockState blockState = chunk.setBlockState(pos, state, false); final BlockState previousBlockState = blockState; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
- BlockState blockState = chunk.setBlockState(pos, state, flags);
+ BlockState blockState = chunk.setBlockState(pos, state, flags); final BlockState previousBlockState = blockState; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
if (blockState != null) {
this.level.onBlockStateChange(pos, blockState, state);
this.level.updatePOIOnBlockStateChange(pos, blockState, state);
}
@@ -294,6 +_,17 @@
chunk.removeBlockEntity(pos);
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/players/GameProfileCache.java
+++ b/net/minecraft/server/players/GameProfileCache.java
@@ -56,6 +_,10 @@
@@ -54,6 +_,10 @@
private final AtomicLong operationCount = new AtomicLong();
@Nullable
private Executor executor;
@@ -11,7 +11,7 @@
public GameProfileCache(GameProfileRepository profileRepository, File file) {
this.profileRepository = profileRepository;
@@ -64,10 +_,12 @@
@@ -62,17 +_,21 @@
}
private void safeAdd(GameProfileCache.GameProfileInfo profile) {
@@ -24,16 +24,17 @@
}
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository profileRepo, String name) {
@@ -86,6 +_,8 @@
atomicReference.set(null);
}
};
+ if (!org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - Add setting for proxy online mode status
profileRepo.findProfilesByNames(new String[]{name}, profileLookupCallback);
GameProfile gameProfile = atomicReference.get();
return gameProfile != null ? Optional.of(gameProfile) : createUnknownProfile(name);
@@ -101,7 +_,7 @@
if (!StringUtil.isValidPlayerName(name)) {
return createUnknownProfile(name);
} else {
- Optional<GameProfile> optional = profileRepo.findProfileByName(name);
+ final boolean shouldLookup = !org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode(); // Paper - Add setting for proxy online mode status
+ Optional<GameProfile> optional = shouldLookup ? profileRepo.findProfileByName(name) : Optional.empty(); // Paper - Don't lookup a profile with a blank name
return optional.isEmpty() ? createUnknownProfile(name) : optional;
}
}
@@ -86,7 +_,7 @@
}
private static boolean usesAuthentication() {
@@ -42,7 +43,7 @@
}
public void add(GameProfile gameProfile) {
@@ -111,15 +_,29 @@
@@ -96,15 +_,29 @@
Date time = instance.getTime();
GameProfileCache.GameProfileInfo gameProfileInfo = new GameProfileCache.GameProfileInfo(gameProfile, time);
this.safeAdd(gameProfileInfo);
@@ -73,7 +74,7 @@
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
boolean flag = false;
if (gameProfileInfo != null && new Date().getTime() >= gameProfileInfo.expirationDate.getTime()) {
@@ -133,19 +_,24 @@
@@ -118,19 +_,24 @@
if (gameProfileInfo != null) {
gameProfileInfo.setLastAccess(this.getNextOperation());
optional = Optional.of(gameProfileInfo.getProfile());
@@ -101,7 +102,7 @@
}
public CompletableFuture<Optional<GameProfile>> getAsync(String name) {
@@ -157,7 +_,7 @@
@@ -142,7 +_,7 @@
return completableFuture;
} else {
CompletableFuture<Optional<GameProfile>> completableFuture1 = CompletableFuture.<Optional<GameProfile>>supplyAsync(
@@ -110,7 +111,7 @@
)
.whenCompleteAsync((gameProfile, exception) -> this.requests.remove(name), this.executor);
this.requests.put(name, completableFuture1);
@@ -167,6 +_,7 @@
@@ -152,6 +_,7 @@
}
public Optional<GameProfile> get(UUID uuid) {
@@ -118,7 +119,7 @@
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByUUID.get(uuid);
if (gameProfileInfo == null) {
return Optional.empty();
@@ -174,6 +_,7 @@
@@ -159,6 +_,7 @@
gameProfileInfo.setLastAccess(this.getNextOperation());
return Optional.of(gameProfileInfo.getProfile());
}
@@ -126,7 +127,7 @@
}
public void setExecutor(Executor exectutor) {
@@ -206,6 +_,11 @@
@@ -191,6 +_,11 @@
return (List<GameProfileCache.GameProfileInfo>)var9;
} catch (FileNotFoundException var7) {
@@ -138,7 +139,7 @@
} catch (JsonParseException | IOException var8) {
LOGGER.warn("Failed to load profile cache {}", this.file, var8);
}
@@ -213,24 +_,45 @@
@@ -198,24 +_,45 @@
return list;
}
@@ -47,7 +47,7 @@
GameProfile gameProfile = player.getGameProfile();
GameProfileCache profileCache = this.server.getProfileCache();
String string;
@@ -150,30 +_,93 @@
@@ -150,30 +_,94 @@
}
Optional<CompoundTag> optional = this.load(player);
@@ -55,11 +55,7 @@
- compoundTag -> DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension"))).resultOrPartial(LOGGER::error)
+ // CraftBukkit start - Better rename detection
+ if (optional.isPresent()) {
+ CompoundTag nbttagcompound = optional.get();
+ if (nbttagcompound.contains("bukkit")) {
+ CompoundTag bukkit = nbttagcompound.getCompound("bukkit");
+ string = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : string;
+ }
+ string = optional.flatMap(t -> t.getCompound("bukkit")).flatMap(t -> t.getString("lastKnownName")).orElse(string);
+ }
+ // CraftBukkit end
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
@@ -68,10 +64,15 @@
+ bukkitData: if (optional.isPresent()) {
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
+ final org.bukkit.World bWorld;
+ if (optional.get().contains("WorldUUIDMost") && optional.get().contains("WorldUUIDLeast")) {
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(optional.get().getLong("WorldUUIDMost"), optional.get().getLong("WorldUUIDLeast")));
+ } else if (optional.get().contains("world", net.minecraft.nbt.Tag.TAG_STRING)) { // Paper - legacy bukkit world name
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(optional.get().getString("world"));
+ final CompoundTag playerData = optional.get();
+ // TODO maybe convert this to a codec and use compoundTag#read, we need silent variants of that method first.
+ final Optional<Long> worldUUIDMost = playerData.getLong("WorldUUIDMost");
+ final Optional<Long> worldUUIDLeast = playerData.getLong("WorldUUIDLeast");
+ final java.util.Optional<String> worldName = playerData.getString("world");
+ if (worldUUIDMost.isPresent() && worldUUIDLeast.isPresent()) {
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(worldUUIDMost.get(), worldUUIDLeast.get()));
+ } else if (worldName.isPresent()) { // Paper - legacy bukkit world name
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(worldName.get());
+ } else {
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
+ }
@@ -113,7 +114,7 @@
+ }
+ if (optional.isEmpty() || invalidPlayerWorld[0]) {
+ // Paper end - reset to main world spawn if first spawn or invalid world
+ player.moveTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
+ player.snapTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
+ }
+ // Paper end - Entity#getEntitySpawnReason
player.setServerLevel(serverLevel);
@@ -153,7 +154,7 @@
LevelData levelData = serverLevel.getLevelData();
player.loadGameTypes(optional.orElse(null));
ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl(this.server, connection, player, cookie);
@@ -190,8 +_,8 @@
@@ -191,8 +_,8 @@
levelData.isHardcore(),
this.server.levelKeys(),
this.getMaxPlayers(),
@@ -164,15 +165,15 @@
_boolean1,
!_boolean,
_boolean2,
@@ -199,6 +_,7 @@
@@ -200,6 +_,7 @@
this.server.enforceSecureProfile()
)
);
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
@@ -218,24 +_,117 @@
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
@@ -219,26 +_,119 @@
mutableComponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), string);
}
@@ -201,8 +202,10 @@
- this.sendActivePlayerEffects(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below serverLevel.addPlayerJoin(player);
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
player.loadAndSpawnEnderpearls(optional);
player.loadAndSpawnParentVehicle(optional);
optional.ifPresent(compoundTag -> {
player.loadAndSpawnEnderPearls(compoundTag);
player.loadAndSpawnParentVehicle(compoundTag);
});
+ // CraftBukkit start
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
+
@@ -296,7 +299,7 @@
}
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
@@ -258,30 +_,31 @@
@@ -261,30 +_,31 @@
}
public void addWorldborderListener(ServerLevel level) {
@@ -333,7 +336,7 @@
}
@Override
@@ -309,56 +_,162 @@
@@ -312,56 +_,162 @@
}
protected void save(ServerPlayer player) {
@@ -510,7 +513,7 @@
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned.reason", userBanListEntry.getReason());
if (userBanListEntry.getExpires() != null) {
mutableComponent.append(
@@ -366,10 +_,12 @@
@@ -369,10 +_,12 @@
);
}
@@ -527,7 +530,7 @@
IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress);
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason());
if (ipBanListEntry.getExpires() != null) {
@@ -378,69 +_,129 @@
@@ -381,69 +_,129 @@
);
}
@@ -677,9 +680,9 @@
+ serverPlayer.unsetRemoved();
+ serverPlayer.setShiftKeyDown(false);
Vec3 vec3 = teleportTransition.position();
- serverPlayer.moveTo(vec3.x, vec3.y, vec3.z, teleportTransition.yRot(), teleportTransition.xRot());
- serverPlayer.snapTo(vec3.x, vec3.y, vec3.z, teleportTransition.yRot(), teleportTransition.xRot());
+ serverPlayer.forceSetPositionRotation(vec3.x, vec3.y, vec3.z, teleportTransition.yRot(), teleportTransition.xRot());
+ level.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(vec3.x()) >> 4, net.minecraft.util.Mth.floor(vec3.z()) >> 4), 1, player.getId()); // Paper - post teleport ticket type
+ level.getChunkSource().addTicketWithRadius(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(vec3.x()) >> 4, net.minecraft.util.Mth.floor(vec3.z()) >> 4), 1); // Paper - post teleport ticket type
+ // CraftBukkit end
if (teleportTransition.missingRespawnBlock()) {
serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
@@ -698,7 +701,7 @@
serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
serverPlayer.connection
@@ -448,10 +_,13 @@
@@ -451,10 +_,13 @@
this.sendActivePlayerEffects(serverPlayer);
this.sendLevelInfo(serverPlayer, level);
this.sendPlayerPermissionLevel(serverPlayer);
@@ -714,19 +717,19 @@
+ }
+ // serverPlayer.initInventoryMenu();
serverPlayer.setHealth(serverPlayer.getHealth());
BlockPos respawnPosition = serverPlayer.getRespawnPosition();
ServerLevel level1 = this.server.getLevel(serverPlayer.getRespawnDimension());
@@ -472,7 +_,40 @@
)
);
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
if (!keepInventory && respawnConfig != null) {
@@ -477,8 +_,41 @@
)
);
}
+ // Paper start - Add PlayerPostRespawnEvent
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) {
+ isBedSpawn = true;
+ }
+ // Paper end - Add PlayerPostRespawnEvent
}
- }
+ // Paper start - Add PlayerPostRespawnEvent
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) {
+ isBedSpawn = true;
+ }
+ // Paper end - Add PlayerPostRespawnEvent
+ }
}
+ // Added from changeDimension
+ this.sendAllPlayerInfo(player); // Update health, etc...
+ player.onUpdateAbilities();
@@ -758,7 +761,7 @@
return serverPlayer;
}
@@ -482,24 +_,60 @@
@@ -488,24 +_,60 @@
}
public void sendActiveEffects(LivingEntity entity, ServerGamePacketListenerImpl connection) {
@@ -822,7 +825,7 @@
public void broadcastAll(Packet<?> packet) {
for (ServerPlayer serverPlayer : this.players) {
serverPlayer.connection.send(packet);
@@ -575,6 +_,11 @@
@@ -581,6 +_,11 @@
}
private void sendPlayerPermissionLevel(ServerPlayer player, int permLevel) {
@@ -834,7 +837,7 @@
if (player.connection != null) {
byte b;
if (permLevel <= 0) {
@@ -588,11 +_,32 @@
@@ -594,11 +_,32 @@
player.connection.send(new ClientboundEntityEventPacket(player, b));
}
@@ -868,7 +871,7 @@
}
public boolean isOp(GameProfile profile) {
@@ -603,21 +_,17 @@
@@ -609,21 +_,17 @@
@Nullable
public ServerPlayer getPlayerByName(String username) {
@@ -896,7 +899,7 @@
if (serverPlayer != except && serverPlayer.level().dimension() == dimension) {
double d = x - serverPlayer.getX();
double d1 = y - serverPlayer.getY();
@@ -630,9 +_,11 @@
@@ -636,9 +_,11 @@
}
public void saveAll() {
@@ -908,7 +911,7 @@
}
public UserWhiteList getWhiteList() {
@@ -655,14 +_,18 @@
@@ -661,14 +_,18 @@
}
public void sendLevelInfo(ServerPlayer player, ServerLevel level) {
@@ -931,20 +934,15 @@
}
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
@@ -671,8 +_,21 @@
@@ -677,8 +_,16 @@
public void sendAllPlayerInfo(ServerPlayer player) {
player.inventoryMenu.sendAllDataToRemote();
- player.resetSentInfo();
+ // entityplayer.resetSentInfo();
+ // Paper start - send all attributes
+ // needs to be done because the ServerPlayer instance is being reused on respawn instead of getting replaced like on vanilla
+ java.util.Collection<net.minecraft.world.entity.ai.attributes.AttributeInstance> syncableAttributes = player.getAttributes().getSyncableAttributes();
+ player.getBukkitEntity().injectScaledMaxHealth(syncableAttributes, true);
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket(player.getId(), syncableAttributes));
+ // Paper end - send all attributes
+ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange
+ player.refreshEntityData(player); // CraftBukkit - SPIGOT-7218: sync metadata
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
+ // CraftBukkit start - from GameRules
+ int i = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
+ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i));
@@ -954,7 +952,7 @@
}
public int getPlayerCount() {
@@ -688,6 +_,7 @@
@@ -694,6 +_,7 @@
}
public void setUsingWhiteList(boolean whitelistEnabled) {
@@ -962,7 +960,7 @@
this.doWhiteList = whitelistEnabled;
}
@@ -725,10 +_,35 @@
@@ -731,10 +_,35 @@
}
public void removeAll() {
@@ -1002,7 +1000,7 @@
public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) {
this.broadcastSystemMessage(message, serverPlayer -> message, bypassHiddenChat);
@@ -750,20 +_,39 @@
@@ -756,20 +_,39 @@
}
public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound boundChatType) {
@@ -1045,7 +1043,7 @@
flag1 |= flag2 && message.isFullyFiltered();
}
@@ -772,18 +_,25 @@
@@ -778,18 +_,25 @@
}
}
@@ -1076,7 +1074,7 @@
Path path = file2.toPath();
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
file2.renameTo(file1);
@@ -791,7 +_,7 @@
@@ -797,7 +_,7 @@
}
serverStatsCounter = new ServerStatsCounter(this.server, file1);
@@ -1085,7 +1083,7 @@
}
return serverStatsCounter;
@@ -799,11 +_,11 @@
@@ -805,11 +_,11 @@
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
UUID uuid = player.getUUID();
@@ -1099,7 +1097,7 @@
}
playerAdvancements.setPlayer(player);
@@ -846,11 +_,34 @@
@@ -852,11 +_,34 @@
}
public void reloadResources() {
@@ -1118,7 +1116,7 @@
+ // }
+ for (ServerPlayer player : this.players) {
+ player.getAdvancements().reload(this.server.getAdvancements());
+ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements
+ player.getAdvancements().flushDirty(player, false); // CraftBukkit - trigger immediate flush of advancements
}
+ // CraftBukkit end
@@ -1,6 +1,6 @@
--- a/net/minecraft/stats/ServerRecipeBook.java
+++ b/net/minecraft/stats/ServerRecipeBook.java
@@ -67,7 +_,7 @@
@@ -66,7 +_,7 @@
for (RecipeHolder<?> recipeHolder : recipes) {
ResourceKey<Recipe<?>> resourceKey = recipeHolder.id();
@@ -9,7 +9,7 @@
this.add(resourceKey);
this.addHighlight(resourceKey);
this.displayResolver
@@ -78,7 +_,7 @@
@@ -77,7 +_,7 @@
}
}
@@ -18,7 +18,7 @@
player.connection.send(new ClientboundRecipeBookAddPacket(list, false));
}
@@ -96,7 +_,7 @@
@@ -95,7 +_,7 @@
}
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/stats/ServerStatsCounter.java
+++ b/net/minecraft/stats/ServerStatsCounter.java
@@ -51,9 +_,21 @@
@@ -70,9 +_,21 @@
LOGGER.error("Couldn't parse statistics file {}", file, var5);
}
}
@@ -22,7 +22,7 @@
try {
FileUtils.writeStringToFile(this.file, this.toJson());
} catch (IOException var2) {
@@ -63,6 +_,8 @@
@@ -82,6 +_,8 @@
@Override
public void setValue(Player player, Stat<?> stat, int i) {
@@ -1,21 +1,21 @@
--- a/net/minecraft/util/datafix/DataFixers.java
+++ b/net/minecraft/util/datafix/DataFixers.java
@@ -505,6 +_,18 @@
@@ -541,6 +_,18 @@
Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED);
builder.addFixer(new EntityItemFrameDirectionFix(schema44, false));
Schema schema45 = builder.addSchema(1458, SAME_NAMESPACED);
Schema schema45 = builder.addSchema(1458, V1458::new);
+ // CraftBukkit start
+ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) {
+ @Override
+ protected com.mojang.datafixers.TypeRewriteRule makeRule() {
+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), (typed) -> {
+ return typed.update(DSL.remainderFinder(), (dynamic) -> {
+ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic);
+ return EntityCustomNameToComponentFix.fixCustomName(dynamic.getOps(), dynamic.get("CustomName").asString(""), "minecraft:player");
+ });
+ });
+ }
+ });
+ // CraftBukkit end
builder.addFixer(new EntityCustomNameToComponentFix(schema45, false));
builder.addFixer(new ItemCustomNameToComponentFix(schema45, false));
builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false));
builder.addFixer(new EntityCustomNameToComponentFix(schema45));
builder.addFixer(new ItemCustomNameToComponentFix(schema45));
builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45));
@@ -0,0 +1,39 @@
--- a/net/minecraft/util/parsing/packrat/Scope.java
+++ b/net/minecraft/util/parsing/packrat/Scope.java
@@ -281,4 +_,36 @@
return true;
}
+
+ // Paper start - track depth
+ private int depth;
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static <S> Term<S> increaseDepth() {
+ class IncreasingDepthTerm<W> implements Term<W> {
+ public static final IncreasingDepthTerm INSTANCE = new IncreasingDepthTerm();
+ @Override
+ public boolean parse(final ParseState<W> parseState, final Scope scope, final Control control) {
+ if (++scope.depth > 512) {
+ parseState.errorCollector().store(parseState.mark(), new IllegalStateException("Too deep"));
+ return false;
+ }
+ return true;
+ }
+ }
+ return (Term<S>) IncreasingDepthTerm.INSTANCE;
+ }
+
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static <S> Term<S> decreaseDepth() {
+ class DecreasingDepthTerm<W> implements Term<W> {
+ public static final DecreasingDepthTerm INSTANCE = new DecreasingDepthTerm();
+ @Override
+ public boolean parse(final ParseState<W> parseState, final Scope scope, final Control control) {
+ scope.depth--;
+ return true;
+ }
+ }
+ return (Term<S>) DecreasingDepthTerm.INSTANCE;
+ }
+ // Paper end - track depth
}
@@ -0,0 +1,28 @@
--- a/net/minecraft/util/random/WeightedList.java
+++ b/net/minecraft/util/random/WeightedList.java
@@ -13,14 +_,14 @@
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.RandomSource;
-public final class WeightedList<E> {
+public class WeightedList<E> { // Paper - non-final
private static final int FLAT_THRESHOLD = 64;
private final int totalWeight;
private final List<Weighted<E>> items;
@Nullable
private final WeightedList.Selector<E> selector;
- WeightedList(List<? extends Weighted<E>> items) {
+ protected WeightedList(List<? extends Weighted<E>> items) { // Paper - protected
this.items = List.copyOf(items);
this.totalWeight = WeightedRandom.getTotalWeight(items, Weighted::weight);
if (this.totalWeight == 0) {
@@ -122,7 +_,7 @@
}
public static class Builder<E> {
- private final ImmutableList.Builder<Weighted<E>> result = ImmutableList.builder();
+ protected final ImmutableList.Builder<Weighted<E>> result = ImmutableList.builder();
public WeightedList.Builder<E> add(E element) {
return this.add(element, 1);
@@ -1,7 +1,7 @@
--- a/net/minecraft/util/worldupdate/WorldUpgrader.java
+++ b/net/minecraft/util/worldupdate/WorldUpgrader.java
@@ -79,7 +_,7 @@
LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, RegistryAccess registryAccess, boolean eraseCache, boolean recreateRegionFiles
@@ -87,7 +_,7 @@
boolean recreateRegionFiles
) {
this.dimensions = registryAccess.lookupOrThrow(Registries.LEVEL_STEM);
- this.levels = this.dimensions.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet());
@@ -9,12 +9,12 @@
this.eraseCache = eraseCache;
this.dataFixer = dataFixer;
this.levelStorage = levelStorage;
@@ -358,7 +_,7 @@
@@ -369,7 +_,7 @@
int version = ChunkStorage.getVersion(compoundTag);
ChunkGenerator chunkGenerator = WorldUpgrader.this.dimensions.getValueOrThrow(Registries.levelToLevelStem(dimension)).generator();
CompoundTag compoundTag1 = chunkStorage.upgradeChunkTag(
- dimension, () -> WorldUpgrader.this.overworldDataStorage, compoundTag, chunkGenerator.getTypeNameForDataFixer()
+ Registries.levelToLevelStem(dimension), () -> WorldUpgrader.this.overworldDataStorage, compoundTag, chunkGenerator.getTypeNameForDataFixer(), chunkPos, null // CraftBukkit
);
ChunkPos chunkPos1 = new ChunkPos(compoundTag1.getInt("xPos"), compoundTag1.getInt("zPos"));
ChunkPos chunkPos1 = new ChunkPos(compoundTag1.getIntOr("xPos", 0), compoundTag1.getIntOr("zPos", 0));
if (!chunkPos1.equals(chunkPos)) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/BossEvent.java
+++ b/net/minecraft/world/BossEvent.java
@@ -13,6 +_,7 @@
@@ -15,6 +_,7 @@
protected boolean darkenScreen;
protected boolean playBossMusic;
protected boolean createWorldFog;
@@ -8,7 +8,7 @@
public BossEvent(UUID id, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay overlay) {
this.id = id;
@@ -27,61 +_,75 @@
@@ -29,61 +_,75 @@
}
public Component getName() {
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/Container.java
+++ b/net/minecraft/world/Container.java
@@ -24,9 +_,7 @@
@@ -26,9 +_,7 @@
void setItem(int slot, ItemStack stack);
@@ -11,9 +11,9 @@
default int getMaxStackSize(ItemStack stack) {
return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
@@ -87,4 +_,22 @@
BlockPos blockPos = blockEntity.getBlockPos();
return level != null && level.getBlockEntity(blockPos) == blockEntity && player.canInteractWithBlock(blockPos, distance);
@@ -117,4 +_,22 @@
}
}
}
+
+ // CraftBukkit start
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/RandomizableContainer.java
+++ b/net/minecraft/world/RandomizableContainer.java
@@ -28,7 +_,7 @@
@@ -26,7 +_,7 @@
void setLootTable(@Nullable ResourceKey<LootTable> lootTable);
@@ -9,30 +9,21 @@
this.setLootTable(lootTable);
this.setLootTableSeed(seed);
}
@@ -50,15 +_,17 @@
@@ -49,8 +_,9 @@
default boolean tryLoadLootTable(CompoundTag tag) {
if (tag.contains("LootTable", 8)) {
- this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(tag.getString("LootTable"))));
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(tag.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
+ if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(tag); // Paper - LootTable API
if (tag.contains("LootTableSeed", 4)) {
this.setLootTableSeed(tag.getLong("LootTableSeed"));
} else {
this.setLootTableSeed(0L);
}
- return true;
+ return this.lootableData() == null; // Paper - only track the loot table if there is chance for replenish
} else {
+ setLootTable(null); // Paper - Fix removing loottable from nbt not updating block entity, MC-279196
return false;
}
ResourceKey<LootTable> resourceKey = tag.read("LootTable", LootTable.KEY_CODEC).orElse(null);
this.setLootTable(resourceKey);
+ if (this.lootableData() != null && resourceKey != null) this.lootableData().loadNbt(tag); // Paper - LootTable API
this.setLootTableSeed(tag.getLongOr("LootTableSeed", 0L));
- return resourceKey != null;
+ return resourceKey != null && this.lootableData() == null; // Paper - only track the loot table if there is chance for replenish
}
@@ -69,26 +_,42 @@
default boolean trySaveLootTable(CompoundTag tag) {
@@ -59,26 +_,42 @@
return false;
} else {
tag.putString("LootTable", lootTable.location().toString());
tag.store("LootTable", LootTable.KEY_CODEC, lootTable);
+ if (this.lootableData() != null) this.lootableData().saveNbt(tag); // Paper - LootTable API
long lootTableSeed = this.getLootTableSeed();
if (lootTableSeed != 0L) {
@@ -74,7 +65,7 @@
LootParams.Builder builder = new LootParams.Builder((ServerLevel)level).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockPos));
if (player != null) {
builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
@@ -97,4 +_,17 @@
@@ -87,4 +_,17 @@
lootTable1.fill(this, builder.create(LootContextParamSets.CHEST), this.getLootTableSeed());
}
}
@@ -2,7 +2,7 @@
+++ b/net/minecraft/world/effect/InfestedMobEffect.java
@@ -44,7 +_,11 @@
Vector3f vector3f = entity.getLookAngle().toVector3f().mul(0.3F).mul(1.0F, 1.5F, 1.0F).rotateY(f1);
silverfish.moveTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
silverfish.snapTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
silverfish.setDeltaMovement(new Vec3(vector3f));
- level.addFreshEntity(silverfish);
+ // CraftBukkit start
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/effect/MobEffect.java
+++ b/net/minecraft/world/effect/MobEffect.java
@@ -76,6 +_,7 @@
@@ -86,6 +_,7 @@
public void applyInstantenousEffect(
ServerLevel level, @Nullable Entity source, @Nullable Entity indirectSource, LivingEntity entity, int amplifier, double health
) {
@@ -1,14 +1,15 @@
--- a/net/minecraft/world/effect/MobEffectInstance.java
+++ b/net/minecraft/world/effect/MobEffectInstance.java
@@ -216,6 +_,7 @@
@@ -219,7 +_,7 @@
return false;
} else {
int i = this.isInfiniteDuration() ? entity.tickCount : this.duration;
if (entity.level() instanceof ServerLevel serverLevel
&& this.effect.value().shouldApplyEffectTickThisTick(i, this.amplifier)
+ && new io.papermc.paper.event.entity.EntityEffectTickEvent(entity.getBukkitLivingEntity(), org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftHolderToBukkit(this.effect), this.amplifier).callEvent() // Paper - Add EntityEffectTickEvent
&& !this.effect.value().applyEffectTick(serverLevel, entity, this.amplifier)) {
entity.removeEffect(this.effect);
}
@@ -408,7 +_,7 @@
- if (this.effect.value().shouldApplyEffectTickThisTick(i, this.amplifier) && !this.effect.value().applyEffectTick(level, entity, this.amplifier)) {
+ if (this.effect.value().shouldApplyEffectTickThisTick(i, this.amplifier) && new io.papermc.paper.event.entity.EntityEffectTickEvent(entity.getBukkitLivingEntity(), org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftHolderToBukkit(this.effect), this.amplifier).callEvent() && !this.effect.value().applyEffectTick(level, entity, this.amplifier)) { // Paper - Add EntityEffectTickEvent
return false;
} else {
this.tickDownDuration();
@@ -415,7 +_,7 @@
.apply(instance, MobEffectInstance.Details::create)
)
);
@@ -17,7 +18,7 @@
codec -> StreamCodec.composite(
ByteBufCodecs.VAR_INT,
MobEffectInstance.Details::amplifier,
@@ -420,7 +_,7 @@
@@ -427,7 +_,7 @@
MobEffectInstance.Details::showParticles,
ByteBufCodecs.BOOL,
MobEffectInstance.Details::showIcon,
@@ -3,7 +3,7 @@
@@ -49,7 +_,7 @@
if (slime != null) {
slime.setSize(2, true);
slime.moveTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
slime.snapTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
- level.addFreshEntity(slime);
+ level.addFreshEntity(slime, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.POTION_EFFECT); // CraftBukkit
}
@@ -1,14 +1,14 @@
--- a/net/minecraft/world/entity/AgeableMob.java
+++ b/net/minecraft/world/entity/AgeableMob.java
@@ -20,6 +_,7 @@
protected int age;
protected int forcedAge;
@@ -22,6 +_,7 @@
protected int age = 0;
protected int forcedAge = 0;
protected int forcedAgeTimer;
+ public boolean ageLocked; // CraftBukkit
protected AgeableMob(EntityType<? extends AgeableMob> entityType, Level level) {
super(entityType, level);
@@ -66,6 +_,7 @@
@@ -68,6 +_,7 @@
}
public void ageUp(int amount, boolean forced) {
@@ -16,7 +16,7 @@
int age = this.getAge();
age += amount * 20;
if (age > 0) {
@@ -104,6 +_,7 @@
@@ -106,6 +_,7 @@
super.addAdditionalSaveData(compound);
compound.putInt("Age", this.getAge());
compound.putInt("ForcedAge", this.forcedAge);
@@ -24,15 +24,15 @@
}
@Override
@@ -111,6 +_,7 @@
@@ -113,6 +_,7 @@
super.readAdditionalSaveData(compound);
this.setAge(compound.getInt("Age"));
this.forcedAge = compound.getInt("ForcedAge");
+ this.ageLocked = compound.getBoolean("AgeLocked"); // CraftBukkit
this.setAge(compound.getIntOr("Age", 0));
this.forcedAge = compound.getIntOr("ForcedAge", 0);
+ this.ageLocked = compound.getBooleanOr("AgeLocked", false); // CraftBukkit
}
@Override
@@ -125,7 +_,7 @@
@@ -127,7 +_,7 @@
@Override
public void aiStep() {
super.aiStep();
@@ -1,24 +1,24 @@
--- a/net/minecraft/world/entity/AreaEffectCloud.java
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
@@ -47,7 +_,7 @@
public float radiusOnUse;
public float radiusPerTick;
@@ -59,7 +_,7 @@
public float radiusOnUse = 0.0F;
public float radiusPerTick = 0.0F;
@Nullable
- private LivingEntity owner;
+ private net.minecraft.world.entity.LivingEntity owner;
@Nullable
public UUID ownerUUID;
@@ -177,7 +_,7 @@
@@ -193,7 +_,7 @@
private void serverTick(ServerLevel level) {
if (this.tickCount >= this.waitTime + this.duration) {
if (this.duration != -1 && this.tickCount >= this.waitTime + this.duration) {
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
boolean isWaiting = this.isWaiting();
boolean flag = this.tickCount < this.waitTime;
@@ -190,7 +_,7 @@
@@ -206,7 +_,7 @@
if (this.radiusPerTick != 0.0F) {
radius += this.radiusPerTick;
if (radius < 0.5F) {
@@ -27,15 +27,15 @@
return;
}
@@ -220,6 +_,7 @@
list.addAll(this.potionContents.customEffects());
@@ -222,6 +_,7 @@
this.potionContents.forEachEffect(list::add, this.potionDurationScale);
List<LivingEntity> entitiesOfClass = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox());
if (!entitiesOfClass.isEmpty()) {
+ List<org.bukkit.entity.LivingEntity> entities = new java.util.ArrayList<>(); // CraftBukkit
for (LivingEntity livingEntity : entitiesOfClass) {
if (!this.victims.containsKey(livingEntity)
&& livingEntity.isAffectedByPotions()
@@ -228,6 +_,17 @@
@@ -230,6 +_,17 @@
double d1 = livingEntity.getZ() - this.getZ();
double d2 = d * d + d1 * d1;
if (d2 <= radius * radius) {
@@ -52,13 +52,13 @@
+ // CraftBukkit end
this.victims.put(livingEntity, this.tickCount + this.reapplicationDelay);
for (MobEffectInstance mobEffectInstance1 : list) {
@@ -236,14 +_,14 @@
for (MobEffectInstance mobEffectInstance : list) {
@@ -238,14 +_,14 @@
.value()
.applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance1.getAmplifier(), 0.5);
.applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), 0.5);
} else {
- livingEntity.addEffect(new MobEffectInstance(mobEffectInstance1), this);
+ livingEntity.addEffect(new MobEffectInstance(mobEffectInstance1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit
- livingEntity.addEffect(new MobEffectInstance(mobEffectInstance), this);
+ livingEntity.addEffect(new MobEffectInstance(mobEffectInstance), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit
}
}
@@ -70,8 +70,8 @@
return;
}
@@ -253,7 +_,7 @@
if (this.durationOnUse != 0) {
@@ -255,7 +_,7 @@
if (this.durationOnUse != 0 && this.duration != -1) {
this.duration = this.duration + this.durationOnUse;
if (this.duration <= 0) {
- this.discard();
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/entity/Display.java
+++ b/net/minecraft/world/entity/Display.java
@@ -213,7 +_,7 @@
if (tag.contains("transformation")) {
Transformation.EXTENDED_CODEC
.decode(NbtOps.INSTANCE, tag.get("transformation"))
- .resultOrPartial(Util.prefix("Display entity", LOGGER::error))
+ .result() // Paper - Hide text display error on spawn
.ifPresent(pair -> this.setTransformation(pair.getFirst()));
}
@@ -1,15 +1,15 @@
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -136,6 +_,108 @@
import org.slf4j.Logger;
@@ -141,6 +_,107 @@
import org.jetbrains.annotations.Contract;
public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder {
+
public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter {
+ // CraftBukkit start
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger();
+ private static final int CURRENT_LEVEL = 2;
+ public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first setPositionRotation
+ static boolean isLevelAtLeast(CompoundTag tag, int level) {
+ return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
+ return tag.getIntOr("Bukkit.updateLevel", CURRENT_LEVEL) >= level;
+ }
+
+ // Paper start - Share random for entities to make them more random
@@ -84,7 +84,7 @@
+ }
+ }
+ // Paper end - Share random for entities to make them more random
+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
+ public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
+
+ private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
+
@@ -105,20 +105,19 @@
+ return this.bukkitEntity;
+ }
+ // Paper end
+
private static final Logger LOGGER = LogUtils.getLogger();
public static final String ID_TAG = "id";
public static final String PASSENGERS_TAG = "Passengers";
@@ -196,7 +_,7 @@
private static final String DATA_TAG = "data";
@@ -203,7 +_,7 @@
public double yOld;
public double zOld;
public boolean noPhysics;
private boolean wasOnFire;
- public final RandomSource random = RandomSource.create();
+ public final RandomSource random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
public int tickCount;
private int remainingFireTicks = -this.getFireImmuneTicks();
public boolean wasTouchingWater;
@@ -233,7 +_,7 @@
@@ -240,7 +_,7 @@
protected UUID uuid = Mth.createInsecureUUID(this.random);
protected String stringUUID = this.uuid.toString();
private boolean hasGlowingTag;
@@ -127,10 +126,10 @@
private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0};
private long pistonDeltasGameTime;
private EntityDimensions dimensions;
@@ -250,6 +_,60 @@
private final List<Entity.Movement> movementThisTick = new ArrayList<>();
private final Set<BlockState> blocksInside = new ReferenceArraySet<>();
@@ -259,6 +_,60 @@
private final LongSet visitedBlocks = new LongOpenHashSet();
private final InsideBlockEffectApplier.StepBasedCollector insideEffectCollector = new InsideBlockEffectApplier.StepBasedCollector();
private CustomData customData = CustomData.EMPTY;
+ // CraftBukkit start
+ public boolean forceDrops;
+ public boolean persist = true;
@@ -188,7 +187,7 @@
public Entity(EntityType<?> entityType, Level level) {
this.type = entityType;
@@ -271,6 +_,7 @@
@@ -280,6 +_,7 @@
this.entityData = builder.build();
this.setPos(0.0, 0.0, 0.0);
this.eyeHeight = this.dimensions.eyeHeight();
@@ -196,7 +195,7 @@
}
public boolean isColliding(BlockPos pos, BlockState state) {
@@ -284,6 +_,12 @@
@@ -292,6 +_,12 @@
return team != null && team.getColor().getColor() != null ? team.getColor().getColor() : 16777215;
}
@@ -209,7 +208,7 @@
public boolean isSpectator() {
return false;
}
@@ -324,7 +_,7 @@
@@ -332,7 +_,7 @@
}
public boolean addTag(String tag) {
@@ -218,7 +217,7 @@
}
public boolean removeTag(String tag) {
@@ -332,12 +_,18 @@
@@ -340,12 +_,18 @@
}
public void kill(ServerLevel level) {
@@ -239,7 +238,7 @@
}
protected abstract void defineSynchedData(SynchedEntityData.Builder builder);
@@ -346,6 +_,48 @@
@@ -354,6 +_,48 @@
return this.entityData;
}
@@ -288,7 +287,7 @@
@Override
public boolean equals(Object object) {
return object instanceof Entity && ((Entity)object).id == this.id;
@@ -357,7 +_,13 @@
@@ -365,7 +_,13 @@
}
public void remove(Entity.RemovalReason reason) {
@@ -303,7 +302,7 @@
}
public void onClientRemoval() {
@@ -367,6 +_,17 @@
@@ -375,6 +_,17 @@
}
public void setPose(Pose pose) {
@@ -321,7 +320,7 @@
this.entityData.set(DATA_POSE, pose);
}
@@ -390,6 +_,32 @@
@@ -398,6 +_,32 @@
}
public void setRot(float yRot, float xRot) {
@@ -354,7 +353,7 @@
this.setYRot(yRot % 360.0F);
this.setXRot(xRot % 360.0F);
}
@@ -399,8 +_,8 @@
@@ -407,8 +_,8 @@
}
public void setPos(double x, double y, double z) {
@@ -365,7 +364,7 @@
}
protected final AABB makeBoundingBox() {
@@ -430,12 +_,28 @@
@@ -438,12 +_,28 @@
}
public void tick() {
@@ -394,7 +393,7 @@
this.inBlockState = null;
if (this.isPassenger() && this.getVehicle().isRemoved()) {
this.stopRiding();
@@ -445,7 +_,7 @@
@@ -453,7 +_,7 @@
this.boardingCooldown--;
}
@@ -403,19 +402,10 @@
if (this.canSpawnSprintParticle()) {
this.spawnSprintParticle();
}
@@ -470,7 +_,7 @@
this.setRemainingFireTicks(this.remainingFireTicks - 1);
}
@@ -484,6 +_,10 @@
- if (this.getTicksFrozen() > 0) {
+ if (this.getTicksFrozen() > 0 && !this.freezeLocked) { // Paper - Freeze Tick Lock API
this.setTicksFrozen(0);
this.level().levelEvent(null, 1009, this.blockPosition, 1);
}
@@ -482,6 +_,10 @@
if (this.isInLava()) {
this.lavaHurt();
this.fallDistance *= 0.5F;
this.fallDistance *= 0.5;
+ // CraftBukkit start
+ } else {
+ this.lastLavaContact = null;
@@ -423,7 +413,7 @@
}
this.checkBelowWorld();
@@ -502,7 +_,12 @@
@@ -504,7 +_,12 @@
}
public void checkBelowWorld() {
@@ -437,9 +427,9 @@
this.onBelowWorld();
}
}
@@ -531,9 +_,24 @@
@@ -533,14 +_,35 @@
public void lavaHurt() {
public void lavaIgnite() {
if (!this.fireImmune()) {
- this.igniteForSeconds(15.0F);
+ // CraftBukkit start - Fallen in lava TODO: this event spams!
@@ -458,13 +448,24 @@
+ this.igniteForSeconds(15.0F, false);
+ }
+ // CraftBukkit end
}
}
public void lavaHurt() {
+ // Paper start - track lava contact
+ this.lavaHurt(this.lastLavaContact); // fallback for minecarts if defined
+ }
+
+ public void lavaHurt(BlockPos pos) {
+ // Paper end - track lava contact
if (!this.fireImmune()) {
if (this.level() instanceof ServerLevel serverLevel
- && this.hurtServer(serverLevel, this.damageSources().lava(), 4.0F)
+ && this.hurtServer(serverLevel, this.damageSources().lava().eventBlockDamager(this.level, this.lastLavaContact), 4.0F) // CraftBukkit - we also don't throw an event unless the object in lava is living, to save on some event calls
+ && this.hurtServer(serverLevel, this.damageSources().lava().eventBlockDamager(this.level, pos), 4.0F) // CraftBukkit - we also don't throw an event unless the object in lava is living, to save on some event calls
&& this.shouldPlayLavaHurtSound()
&& !this.isSilent()) {
serverLevel.playSound(
@@ -548,7 +_,23 @@
@@ -555,7 +_,23 @@
}
public final void igniteForSeconds(float seconds) {
@@ -489,7 +490,7 @@
}
public void igniteForTicks(int ticks) {
@@ -570,7 +_,7 @@
@@ -579,7 +_,7 @@
}
protected void onBelowWorld() {
@@ -498,7 +499,7 @@
}
public boolean isFree(double x, double y, double z) {
@@ -626,7 +_,43 @@
@@ -635,7 +_,43 @@
return this.onGround;
}
@@ -542,10 +543,10 @@
if (this.noPhysics) {
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
@@ -701,6 +_,28 @@
@@ -721,6 +_,27 @@
block.updateEntityMovementAfterFallOn(this.level(), this);
}
}
+ // CraftBukkit start
+ if (this.horizontalCollision && this.getBukkitEntity() instanceof org.bukkit.entity.Vehicle) {
+ org.bukkit.entity.Vehicle vehicle = (org.bukkit.entity.Vehicle) this.getBukkitEntity();
@@ -567,11 +568,10 @@
+ }
+ }
+ // CraftBukkit end
+
if (!this.level().isClientSide() || this.isControlledByLocalInstance()) {
if (!this.level().isClientSide() || this.isLocalInstanceAuthoritative()) {
Entity.MovementEmission movementEmission = this.getMovementEmission();
if (movementEmission.emitsAnything() && !this.isPassenger()) {
@@ -713,6 +_,13 @@
@@ -734,6 +_,13 @@
profilerFiller.pop();
}
}
@@ -585,7 +585,7 @@
}
private void applyMovementEmissionAndPlaySound(Entity.MovementEmission movementEmission, Vec3 movement, BlockPos pos, BlockState state) {
@@ -850,7 +_,7 @@
@@ -898,7 +_,7 @@
}
protected BlockPos getOnPos(float yOffset) {
@@ -594,10 +594,10 @@
BlockPos blockPos = this.mainSupportingBlockPos.get();
if (!(yOffset > 1.0E-5F)) {
return blockPos;
@@ -1049,6 +_,20 @@
@@ -1081,6 +_,19 @@
protected SoundEvent getSwimHighSpeedSplashSound() {
return SoundEvents.GENERIC_SPLASH;
}
+ // CraftBukkit start - Add delegate methods
+ public SoundEvent getSwimSound0() {
+ return this.getSwimSound();
@@ -611,32 +611,31 @@
+ return this.getSwimHighSpeedSplashSound();
+ }
+ // CraftBukkit end
+
public void recordMovementThroughBlocks(Vec3 oldPosition, Vec3 position) {
this.movementThisTick.add(new Entity.Movement(oldPosition, position));
}
@@ -1485,6 +_,7 @@
private void checkInsideBlocks(List<Entity.Movement> movements, InsideBlockEffectApplier.StepBasedCollector stepBasedCollector) {
if (this.isAffectedByBlocks()) {
@@ -1519,6 +_,7 @@
this.setXRot(Mth.clamp(xRot, -90.0F, 90.0F) % 360.0F);
this.yRotO = this.getYRot();
this.xRotO = this.getXRot();
+ this.setYHeadRot(yRot); // Paper - Update head rotation
}
public void absMoveTo(double x, double y, double z) {
@@ -1494,6 +_,7 @@
public void absSnapTo(double x, double y, double z) {
@@ -1528,6 +_,7 @@
this.yo = y;
this.zo = d1;
this.setPos(d, y, d1);
+ if (this.valid) this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit
}
public void moveTo(Vec3 vec) {
@@ -1513,11 +_,19 @@
public void snapTo(Vec3 pos) {
@@ -1547,11 +_,19 @@
}
public void moveTo(double x, double y, double z, float yRot, float xRot) {
public void snapTo(double x, double y, double z, float yRot, float xRot) {
+ // Paper start - Fix Entity Teleportation and cancel velocity if teleported
+ if (!preserveMotion) {
+ if (!this.preserveMotion) {
+ this.deltaMovement = Vec3.ZERO;
+ } else {
+ this.preserveMotion = false;
@@ -651,7 +650,7 @@
}
public final void setOldPosAndRot() {
@@ -1584,6 +_,7 @@
@@ -1618,6 +_,7 @@
public void push(Entity entity) {
if (!this.isPassengerOfSameVehicle(entity)) {
if (!entity.noPhysics && !this.noPhysics) {
@@ -659,7 +658,7 @@
double d = entity.getX() - this.getX();
double d1 = entity.getZ() - this.getZ();
double max = Mth.absMax(d, d1);
@@ -1617,7 +_,21 @@
@@ -1651,7 +_,21 @@
}
public void push(double x, double y, double z) {
@@ -682,7 +681,7 @@
this.hasImpulse = true;
}
@@ -1724,8 +_,20 @@
@@ -1758,8 +_,20 @@
}
public boolean isPushable() {
@@ -703,7 +702,7 @@
public void awardKillScore(Entity entity, DamageSource damageSource) {
if (entity instanceof ServerPlayer) {
@@ -1752,15 +_,22 @@
@@ -1786,15 +_,22 @@
}
public boolean saveAsPassenger(CompoundTag compound) {
@@ -730,7 +729,7 @@
return true;
}
}
@@ -1771,15 +_,37 @@
@@ -1805,14 +_,36 @@
}
public CompoundTag saveWithoutId(CompoundTag compound) {
@@ -743,23 +742,17 @@
+ // Paper end - Raw entity serialization API
+ // CraftBukkit end
try {
- if (this.vehicle != null) {
- compound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ()));
- } else {
- compound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ()));
- }
+ // CraftBukkit start - selectively save position
+ if (includeAll) {
+ if (this.vehicle != null) {
+ compound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ()));
+ } else {
+ compound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ()));
+ }
+ }
if (this.vehicle != null) {
compound.store("Pos", Vec3.CODEC, new Vec3(this.vehicle.getX(), this.getY(), this.vehicle.getZ()));
} else {
compound.store("Pos", Vec3.CODEC, this.position());
}
+ }
+ // CraftBukkit end
Vec3 deltaMovement = this.getDeltaMovement();
compound.put("Motion", this.newDoubleList(deltaMovement.x, deltaMovement.y, deltaMovement.z));
compound.store("Motion", Vec3.CODEC, this.getDeltaMovement());
+ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero
+ // TODO: make sure this is the best way to address this.
+ if (Float.isNaN(this.yRot)) {
@@ -770,17 +763,17 @@
+ this.xRot = 0;
+ }
+ // CraftBukkit end
compound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot()));
compound.putFloat("FallDistance", this.fallDistance);
compound.store("Rotation", Vec2.CODEC, new Vec2(this.getYRot(), this.getXRot()));
compound.putDouble("fall_distance", this.fallDistance);
compound.putShort("Fire", (short)this.remainingFireTicks);
@@ -1787,7 +_,29 @@
@@ -1820,7 +_,29 @@
compound.putBoolean("OnGround", this.onGround());
compound.putBoolean("Invulnerable", this.invulnerable);
compound.putInt("PortalCooldown", this.portalCooldown);
- compound.putUUID("UUID", this.getUUID());
- compound.store("UUID", UUIDUtil.CODEC, this.getUUID());
+ // CraftBukkit start - selectively save uuid and world
+ if (includeAll) {
+ compound.putUUID("UUID", this.getUUID());
+ compound.store("UUID", UUIDUtil.CODEC, this.getUUID());
+ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast
+ compound.putLong("WorldUUIDLeast", this.level.getWorld().getUID().getLeastSignificantBits());
+ compound.putLong("WorldUUIDMost", this.level.getWorld().getUID().getMostSignificantBits());
@@ -803,9 +796,9 @@
+ // CraftBukkit end
Component customName = this.getCustomName();
if (customName != null) {
compound.putString("CustomName", Component.Serializer.toJson(customName, this.registryAccess()));
@@ -1828,13 +_,13 @@
compound.put("Tags", listTag);
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
@@ -1860,13 +_,13 @@
compound.store("data", CustomData.CODEC, this.customData);
}
- this.addAdditionalSaveData(compound);
@@ -820,7 +813,7 @@
listTag.add(compoundTag);
}
}
@@ -1844,6 +_,33 @@
@@ -1876,6 +_,33 @@
}
}
@@ -833,9 +826,9 @@
+ if (this.origin != null) {
+ UUID originWorld = this.originWorld != null ? this.originWorld : this.level != null ? this.level.getWorld().getUID() : null;
+ if (originWorld != null) {
+ compound.putUUID("Paper.OriginWorld", originWorld);
+ compound.store("Paper.OriginWorld", UUIDUtil.CODEC, originWorld);
+ }
+ compound.put("Paper.Origin", this.newDoubleList(this.origin.getX(), this.origin.getY(), this.origin.getZ()));
+ compound.store("Paper.Origin", Vec3.CODEC, new Vec3(this.origin.getX(), this.origin.getY(), this.origin.getZ()));
+ }
+ if (this.spawnReason != null) {
+ compound.putString("Paper.SpawnReason", this.spawnReason.name());
@@ -852,53 +845,51 @@
+ }
+ // Paper end
return compound;
} catch (Throwable var9) {
CrashReport crashReport = CrashReport.forThrowable(var9, "Saving entity NBT");
@@ -1930,6 +_,69 @@
} catch (Throwable var8) {
CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT");
@@ -1932,6 +_,67 @@
} else {
throw new IllegalStateException("Entity has invalid rotation");
}
+ // CraftBukkit start
+ // Spigot start
+ if (this instanceof net.minecraft.world.entity.LivingEntity) {
+ this.totalEntityAge = compound.getInt("Spigot.ticksLived"); // Paper
+ this.totalEntityAge = compound.getIntOr("Spigot.ticksLived", 0); // Paper
+ }
+ // Spigot end
+ this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist");
+ this.visibleByDefault = !compound.contains("Bukkit.visibleByDefault") || compound.getBoolean("Bukkit.visibleByDefault");
+ this.persist = compound.getBooleanOr("Bukkit.persist", true);
+ this.visibleByDefault = compound.getBooleanOr("Bukkit.visibleByDefault", true);
+ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
+ if (compound.contains("Bukkit.MaxAirSupply")) {
+ this.maxAirTicks = compound.getInt("Bukkit.MaxAirSupply");
+ }
+ this.maxAirTicks = compound.getIntOr("Bukkit.MaxAirSupply",this.maxAirTicks);
+ // CraftBukkit end
+
+ // CraftBukkit start
+ // Paper - move world parsing/loading to PlayerList#placeNewPlayer
+ this.getBukkitEntity().readBukkitValues(compound);
+ if (compound.contains("Bukkit.invisible")) {
+ boolean bukkitInvisible = compound.getBoolean("Bukkit.invisible");
+ boolean bukkitInvisible = compound.getBooleanOr("Bukkit.invisible", false);
+ this.setInvisible(bukkitInvisible);
+ this.persistentInvisibility = bukkitInvisible;
+ }
+ // CraftBukkit end
+
+ // Paper start
+ ListTag originTag = compound.getList("Paper.Origin", net.minecraft.nbt.Tag.TAG_DOUBLE);
+ if (!originTag.isEmpty()) {
+ Optional<Vec3> originTag = compound.read("Paper.Origin", Vec3.CODEC);
+ if (originTag.isPresent()) {
+ UUID originWorld = null;
+ if (compound.contains("Paper.OriginWorld")) {
+ originWorld = compound.getUUID("Paper.OriginWorld");
+ originWorld = compound.read("Paper.OriginWorld", UUIDUtil.CODEC).orElse(null);
+ } else if (this.level != null) {
+ originWorld = this.level.getWorld().getUID();
+ }
+ this.originWorld = originWorld;
+ origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2));
+ origin = new org.bukkit.util.Vector(originTag.get().x, originTag.get().y, originTag.get().z);
+ }
+
+ spawnedViaMobSpawner = compound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
+ fromNetherPortal = compound.getBoolean("Paper.FromNetherPortal");
+ spawnedViaMobSpawner = compound.getBooleanOr("Paper.FromMobSpawner", false); // Restore entity's from mob spawner status
+ fromNetherPortal = compound.getBooleanOr("Paper.FromNetherPortal", false);
+ if (compound.contains("Paper.SpawnReason")) {
+ String spawnReasonName = compound.getString("Paper.SpawnReason");
+ String spawnReasonName = compound.getString("Paper.SpawnReason").orElse(null);
+ try {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName);
+ } catch (Exception ignored) {
@@ -909,7 +900,7 @@
+ if (spawnedViaMobSpawner) {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER;
+ } else if (this instanceof Mob && (this instanceof net.minecraft.world.entity.animal.Animal || this instanceof net.minecraft.world.entity.animal.AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) {
+ if (!compound.getBoolean("PersistenceRequired")) {
+ if (!compound.getBooleanOr("PersistenceRequired", false)) {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL;
+ }
+ }
@@ -918,13 +909,13 @@
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT;
+ }
+ if (compound.contains("Paper.FreezeLock")) {
+ freezeLocked = compound.getBoolean("Paper.FreezeLock");
+ freezeLocked = compound.getBooleanOr("Paper.FreezeLock", false);
+ }
+ // Paper end
} catch (Throwable var17) {
CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT");
} catch (Throwable var8) {
CrashReport crashReport = CrashReport.forThrowable(var8, "Loading entity NBT");
CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded");
@@ -1944,10 +_,21 @@
@@ -1946,10 +_,21 @@
@Nullable
public final String getEncodeId() {
@@ -948,7 +939,7 @@
protected abstract void readAdditionalSaveData(CompoundTag tag);
@@ -1990,11 +_,61 @@
@@ -1972,11 +_,61 @@
@Nullable
public ItemEntity spawnAtLocation(ServerLevel level, ItemStack stack, float yOffset) {
@@ -1011,7 +1002,7 @@
level.addFreshEntity(itemEntity);
return itemEntity;
}
@@ -2028,7 +_,16 @@
@@ -2008,7 +_,16 @@
if (this.isAlive() && this instanceof Leashable leashable) {
if (leashable.getLeashHolder() == player) {
if (!this.level().isClientSide()) {
@@ -1029,7 +1020,7 @@
leashable.removeLeash();
} else {
leashable.dropLeash();
@@ -2043,6 +_,13 @@
@@ -2023,6 +_,13 @@
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.LEAD) && leashable.canHaveALeashAttachedToIt()) {
if (!this.level().isClientSide()) {
@@ -1043,7 +1034,7 @@
leashable.setLeashedTo(player, true);
}
@@ -2116,11 +_,11 @@
@@ -2096,11 +_,11 @@
}
public boolean startRiding(Entity vehicle, boolean force) {
@@ -1057,7 +1048,7 @@
return false;
} else {
for (Entity entity = vehicle; entity.vehicle != null; entity = entity.vehicle) {
@@ -2130,6 +_,27 @@
@@ -2110,6 +_,27 @@
}
if (force || this.canRide(vehicle) && vehicle.canAddPassenger(this)) {
@@ -1085,7 +1076,7 @@
if (this.isPassenger()) {
this.stopRiding();
}
@@ -2158,15 +_,26 @@
@@ -2138,15 +_,26 @@
}
public void removeVehicle() {
@@ -1114,7 +1105,7 @@
}
protected void addPassenger(Entity passenger) {
@@ -2190,10 +_,43 @@
@@ -2170,10 +_,43 @@
}
}
@@ -1159,7 +1150,7 @@
if (this.passengers.size() == 1 && this.passengers.get(0) == passenger) {
this.passengers = ImmutableList.of();
} else {
@@ -2203,6 +_,7 @@
@@ -2183,6 +_,7 @@
passenger.boardingCooldown = 60;
this.gameEvent(GameEvent.ENTITY_DISMOUNT, passenger);
}
@@ -1167,7 +1158,7 @@
}
protected boolean canAddPassenger(Entity passenger) {
@@ -2295,8 +_,8 @@
@@ -2266,8 +_,8 @@
TeleportTransition portalDestination = this.portalProcess.getPortalDestination(serverLevel, this);
if (portalDestination != null) {
ServerLevel level = portalDestination.newLevel();
@@ -1178,7 +1169,7 @@
this.teleport(portalDestination);
}
}
@@ -2377,7 +_,7 @@
@@ -2348,7 +_,7 @@
}
public boolean isCrouching() {
@@ -1187,7 +1178,7 @@
}
public boolean isSprinting() {
@@ -2393,7 +_,7 @@
@@ -2364,7 +_,7 @@
}
public boolean isVisuallySwimming() {
@@ -1196,7 +1187,7 @@
}
public boolean isVisuallyCrawling() {
@@ -2401,6 +_,13 @@
@@ -2372,6 +_,13 @@
}
public void setSwimming(boolean swimming) {
@@ -1210,7 +1201,7 @@
this.setSharedFlag(4, swimming);
}
@@ -2439,6 +_,7 @@
@@ -2410,6 +_,7 @@
@Nullable
public PlayerTeam getTeam() {
@@ -1218,7 +1209,7 @@
return this.level().getScoreboard().getPlayersTeam(this.getScoreboardName());
}
@@ -2455,7 +_,11 @@
@@ -2426,7 +_,11 @@
}
public void setInvisible(boolean invisible) {
@@ -1231,7 +1222,7 @@
}
public boolean getSharedFlag(int flag) {
@@ -2472,7 +_,7 @@
@@ -2443,7 +_,7 @@
}
public int getMaxAirSupply() {
@@ -1240,7 +1231,7 @@
}
public int getAirSupply() {
@@ -2480,7 +_,18 @@
@@ -2451,10 +_,22 @@
}
public void setAirSupply(int air) {
@@ -1259,8 +1250,12 @@
+ // CraftBukkit end
}
public int getTicksFrozen() {
@@ -2506,11 +_,43 @@
public void clearFreeze() {
+ if (this.freezeLocked) return; // Paper - Freeze Tick Lock API
this.setTicksFrozen(0);
}
@@ -2481,11 +_,43 @@
public void thunderHit(ServerLevel level, LightningBolt lightning) {
this.setRemainingFireTicks(this.remainingFireTicks + 1);
@@ -1307,8 +1302,8 @@
+ // CraftBukkit end
}
public void onAboveBubbleCol(boolean downwards) {
@@ -2636,26 +_,30 @@
public void onAboveBubbleColumn(boolean downwards, BlockPos pos) {
@@ -2641,26 +_,30 @@
return this.removalReason != null
? String.format(
Locale.ROOT,
@@ -1342,7 +1337,7 @@
);
}
@@ -2679,6 +_,13 @@
@@ -2684,6 +_,13 @@
}
public void restoreFrom(Entity entity) {
@@ -1356,7 +1351,7 @@
CompoundTag compoundTag = entity.saveWithoutId(new CompoundTag());
compoundTag.remove("Dimension");
this.load(compoundTag);
@@ -2688,7 +_,56 @@
@@ -2693,7 +_,56 @@
@Nullable
public Entity teleport(TeleportTransition teleportTransition) {
@@ -1413,7 +1408,7 @@
ServerLevel level = teleportTransition.newLevel();
boolean flag = level.dimension() != serverLevel.dimension();
if (!teleportTransition.asPassenger()) {
@@ -2737,10 +_,19 @@
@@ -2742,10 +_,19 @@
profilerFiller.pop();
return null;
} else {
@@ -1434,7 +1429,7 @@
for (Entity entity2 : list) {
entity2.startRiding(entityx, true);
@@ -2814,9 +_,17 @@
@@ -2818,9 +_,17 @@
}
protected void removeAfterChangingDimensions() {
@@ -1455,7 +1450,7 @@
}
}
@@ -2824,11 +_,34 @@
@@ -2828,11 +_,34 @@
return PortalShape.getRelativePosition(portal, axis, this.position(), this.getDimensions(this.getPose()));
}
@@ -1490,24 +1485,23 @@
if (fromLevel.dimension() == Level.END && toLevel.dimension() == Level.OVERWORLD) {
for (Entity entity : this.getPassengers()) {
if (entity instanceof ServerPlayer serverPlayer && !serverPlayer.seenCredits) {
@@ -2936,9 +_,14 @@
@@ -2940,8 +_,13 @@
return this.entityData.get(DATA_CUSTOM_NAME_VISIBLE);
}
- public boolean teleportTo(ServerLevel level, double x, double y, double z, Set<Relative> relativeMovements, float yaw, float pitch, boolean setCamera) {
- Entity entity = this.teleport(new TeleportTransition(level, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relativeMovements, TeleportTransition.DO_NOTHING));
+ // CraftBukkit start
+ public final boolean teleportTo(ServerLevel level, double x, double y, double z, Set<Relative> relativeMovements, float yaw, float pitch, boolean setCamera) {
+ return this.teleportTo(level, x, y, z, relativeMovements, yaw, pitch, setCamera, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ }
+ public boolean teleportTo(ServerLevel level, double x, double y, double z, Set<Relative> relativeMovements, float yaw, float pitch, boolean setCamera, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) {
+ // CraftBukkit end
float f = Mth.clamp(pitch, -90.0F, 90.0F);
- Entity entity = this.teleport(new TeleportTransition(level, new Vec3(x, y, z), Vec3.ZERO, yaw, f, relativeMovements, TeleportTransition.DO_NOTHING));
+ Entity entity = this.teleport(new TeleportTransition(level, new Vec3(x, y, z), Vec3.ZERO, yaw, f, relativeMovements, TeleportTransition.DO_NOTHING, cause)); // CraftBukkit
+ Entity entity = this.teleport(new TeleportTransition(level, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relativeMovements, TeleportTransition.DO_NOTHING, cause)); // CraftBukkit
return entity != null;
}
@@ -3052,7 +_,26 @@
@@ -3055,7 +_,26 @@
}
public final void setBoundingBox(AABB bb) {
@@ -1535,7 +1529,7 @@
}
public final float getEyeHeight(Pose pose) {
@@ -3096,6 +_,12 @@
@@ -3099,6 +_,12 @@
}
public void stopSeenByPlayer(ServerPlayer serverPlayer) {
@@ -1548,7 +1542,7 @@
}
public float rotate(Rotation transformRotation) {
@@ -3129,7 +_,7 @@
@@ -3132,7 +_,7 @@
}
@Nullable
@@ -1557,7 +1551,7 @@
return null;
}
@@ -3161,21 +_,32 @@
@@ -3164,21 +_,32 @@
}
private Stream<Entity> getIndirectPassengersStream() {
@@ -1591,7 +1585,7 @@
}
public int countPlayerPassengers() {
@@ -3183,6 +_,7 @@
@@ -3186,6 +_,7 @@
}
public boolean hasExactlyOnePlayerPassenger() {
@@ -1599,7 +1593,7 @@
return this.countPlayerPassengers() == 1;
}
@@ -3260,9 +_,38 @@
@@ -3268,9 +_,38 @@
return 1;
}
@@ -1639,7 +1633,7 @@
);
}
@@ -3320,6 +_,11 @@
@@ -3328,6 +_,11 @@
vec3 = vec3.add(flow);
i++;
}
@@ -1651,7 +1645,7 @@
}
}
}
@@ -3417,7 +_,9 @@
@@ -3425,7 +_,9 @@
}
public void setDeltaMovement(Vec3 deltaMovement) {
@@ -1661,7 +1655,7 @@
}
public void addDeltaMovement(Vec3 addend) {
@@ -3480,9 +_,43 @@
@@ -3488,9 +_,43 @@
return this.getZ((2.0 * this.random.nextDouble() - 1.0) * scale);
}
@@ -1705,7 +1699,7 @@
int floor = Mth.floor(x);
int floor1 = Mth.floor(y);
int floor2 = Mth.floor(z);
@@ -3496,6 +_,12 @@
@@ -3504,6 +_,12 @@
this.levelCallback.onMove();
}
@@ -1718,7 +1712,7 @@
}
public void checkDespawn() {
@@ -3583,6 +_,15 @@
@@ -3594,6 +_,15 @@
@Override
public final void setRemoved(Entity.RemovalReason removalReason) {
@@ -1734,7 +1728,7 @@
if (this.removalReason == null) {
this.removalReason = removalReason;
}
@@ -3594,12 +_,28 @@
@@ -3605,12 +_,28 @@
this.getPassengers().forEach(Entity::stopRiding);
this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason);
@@ -1763,7 +1757,7 @@
@Override
public void setLevelCallback(EntityInLevelCallback levelCallback) {
this.levelCallback = levelCallback;
@@ -3723,4 +_,14 @@
@@ -3780,4 +_,14 @@
return this.save;
}
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/EntitySelector.java
+++ b/net/minecraft/world/entity/EntitySelector.java
@@ -16,6 +_,23 @@
@@ -17,6 +_,23 @@
public static final Predicate<Entity> NO_SPECTATORS = entity -> !entity.isSpectator();
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = NO_SPECTATORS.and(Entity::canBeCollidedWith);
public static final Predicate<Entity> CAN_BE_PICKED = NO_SPECTATORS.and(Entity::isPickable);
@@ -24,7 +24,7 @@
private EntitySelector() {
}
@@ -26,29 +_,34 @@
@@ -27,18 +_,23 @@
}
public static Predicate<Entity> pushableBy(Entity entity) {
@@ -38,38 +38,15 @@
return (Predicate<Entity>)(collisionRule == Team.CollisionRule.NEVER
? Predicates.alwaysFalse()
: NO_SPECTATORS.and(
- pushedEntity -> {
pushedEntity -> {
- if (!pushedEntity.isPushable()) {
+ pushedEntity -> {
+ if (!pushedEntity.isCollidable(ignoreClimbing) || !pushedEntity.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(pushedEntity)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
+ return false;
+ } else if (!entity.level().isClientSide || pushedEntity instanceof Player && ((Player)pushedEntity).isLocalPlayer()) {
+ Team team1 = pushedEntity.getTeam();
+ Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
+ if (collisionRule1 == Team.CollisionRule.NEVER || (pushedEntity instanceof Player && !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions)) { // Paper - Configurable player collision
+ if (!pushedEntity.isCollidable(ignoreClimbing) || !pushedEntity.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(pushedEntity)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
return false;
- } else if (!entity.level().isClientSide || pushedEntity instanceof Player && ((Player)pushedEntity).isLocalPlayer()) {
- Team team1 = pushedEntity.getTeam();
- Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
} else if (!entity.level().isClientSide || pushedEntity instanceof Player player && player.isLocalPlayer()) {
Team team1 = pushedEntity.getTeam();
Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
- if (collisionRule1 == Team.CollisionRule.NEVER) {
- return false;
- } else {
- boolean flag = team != null && team.isAlliedTo(team1);
- return (collisionRule != Team.CollisionRule.PUSH_OWN_TEAM && collisionRule1 != Team.CollisionRule.PUSH_OWN_TEAM || !flag)
- && (collisionRule != Team.CollisionRule.PUSH_OTHER_TEAMS && collisionRule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag);
- }
} else {
- return false;
+ boolean flag = team != null && team.isAlliedTo(team1);
+ return (collisionRule != Team.CollisionRule.PUSH_OWN_TEAM && collisionRule1 != Team.CollisionRule.PUSH_OWN_TEAM || !flag)
+ && (collisionRule != Team.CollisionRule.PUSH_OTHER_TEAMS && collisionRule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag);
}
+ } else {
+ return false;
}
- ));
+ }
+ ));
}
public static Predicate<Entity> notRiding(Entity entity) {
+ if (collisionRule1 == Team.CollisionRule.NEVER || (pushedEntity instanceof Player && !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions)) { // Paper - Configurable player collision
return false;
} else {
boolean flag = team != null && team.isAlliedTo(team1);
@@ -1,14 +1,6 @@
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -176,6 +_,7 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.entity.CreatureSpawnEvent;
import org.slf4j.Logger;
public class EntityType<T extends Entity> implements FeatureElement, EntityTypeTest<Entity, T> {
@@ -215,7 +_,7 @@
@@ -216,7 +_,7 @@
.fireImmune()
.sized(6.0F, 0.5F)
.clientTrackingRange(10)
@@ -17,7 +9,7 @@
);
public static final EntityType<Armadillo> ARMADILLO = register(
"armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10)
@@ -1132,6 +_,22 @@
@@ -1145,6 +_,22 @@
boolean shouldOffsetY,
boolean shouldOffsetYMore
) {
@@ -39,8 +31,8 @@
+ // CraftBukkit end
Consumer<T> consumer;
if (spawnedFrom != null) {
consumer = createDefaultStackConfig(level, spawnedFrom, player);
@@ -1139,7 +_,7 @@
consumer = createDefaultStackConfig(level, spawnedFrom, owner);
@@ -1152,7 +_,7 @@
consumer = entity -> {};
}
@@ -48,16 +40,16 @@
+ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, createSpawnReason); // CraftBukkit
}
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack spawnedFrom, @Nullable Player player) {
@@ -1159,19 +_,54 @@
Consumer<T> consumer, Level level, ItemStack spawnedFrom, @Nullable Player player
) {
CustomData customData = spawnedFrom.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
- return !customData.isEmpty() ? consumer.andThen(entity -> updateCustomEntityTag(level, player, entity, customData)) : consumer;
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack stack, @Nullable LivingEntity owner) {
@@ -1169,19 +_,54 @@
public static <T extends Entity> Consumer<T> appendCustomEntityStackConfig(Consumer<T> consumer, Level level, ItemStack stack, @Nullable LivingEntity owner) {
CustomData customData = stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
- return !customData.isEmpty() ? consumer.andThen(entity -> updateCustomEntityTag(level, owner, entity, customData)) : consumer;
+ // CraftBukkit start - SPIGOT-5665
+ return !customData.isEmpty() ? consumer.andThen(entity -> {
+ try {
+ updateCustomEntityTag(level, player, entity, customData);
+ updateCustomEntityTag(level, owner, entity, customData);
+ } catch (Throwable t) {
+ EntityType.LOGGER.warn("Error loading spawn egg NBT", t);
+ }
@@ -107,12 +99,12 @@
if (entity instanceof Mob mob) {
mob.playAmbientSound();
}
@@ -1225,6 +_,15 @@
EntityType<?> entityType = customData.parseEntityType(server.registryAccess(), Registries.ENTITY_TYPE);
if (entity.getType() == entityType) {
if (level.isClientSide || !entity.getType().onlyOpCanSetNbt() || player != null && server.getPlayerList().isOp(player.getGameProfile())) {
@@ -1237,6 +_,15 @@
if (level.isClientSide
|| !entity.getType().onlyOpCanSetNbt()
|| owner instanceof Player player && server.getPlayerList().isOp(player.getGameProfile())) {
+ // Paper start - filter out protected tags
+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
+ if (owner == null || !owner.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
+ customData = customData.update((compound) -> {
+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : level.paperConfig().entities.spawning.filteredEntityTagNbtPaths) {
+ tag.remove(compound);
@@ -123,7 +115,7 @@
customData.loadInto(entity);
}
}
@@ -1296,9 +_,19 @@
@@ -1308,9 +_,19 @@
}
public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason) {
@@ -135,21 +127,12 @@
return Util.ifElse(
by(tag).map(entityType -> entityType.create(level, spawnReason)),
- entity -> entity.load(tag),
+ // Paper start - Don't fire sync event during generation
+ entity -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
+ entity.load(tag);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id"))
+ // Paper start - Don't fire sync event during generation
+ entity -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
+ entity.load(tag);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", tag.getStringOr("id", "[invalid]"))
);
}
@@ -1325,7 +_,7 @@
}
public static Optional<EntityType<?>> by(CompoundTag tag) {
- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(tag.getString("id")));
+ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(tag.getString("id"))); // Paper - Validate ResourceLocation
}
@Nullable
@@ -13,12 +13,12 @@
+// CraftBukkit end
+
public class ExperienceOrb extends Entity {
protected static final EntityDataAccessor<Integer> DATA_VALUE = SynchedEntityData.defineId(ExperienceOrb.class, EntityDataSerializers.INT);
private static final int LIFETIME = 6000;
private static final int ENTITY_SCAN_PERIOD = 20;
@@ -35,9 +_,63 @@
public int value;
public int count = 1;
@@ -41,9 +_,63 @@
@Nullable
private Player followingPlayer;
private final InterpolationHandler interpolation = new InterpolationHandler(this);
-
+ // Paper start
+ @javax.annotation.Nullable
@@ -78,18 +78,25 @@
+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+ // Paper end
this.setPos(x, y, z);
this.setYRot((float)(this.random.nextDouble() * 360.0));
this.setDeltaMovement(
@@ -67,6 +_,7 @@
@Override
public void tick() {
super.tick();
if (!this.level().isClientSide) {
this.setYRot((float)(this.random.nextDouble() * 360.0));
@@ -119,12 +_,13 @@
this.age++;
if (this.age >= 6000) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
}
private void followNearbyPlayer() {
+ Player prevTarget = this.followingPlayer;// CraftBukkit - store old target
this.xo = this.getX();
this.yo = this.getY();
this.zo = this.getZ();
@@ -92,7 +_,22 @@
this.followingPlayer = null;
if (this.followingPlayer == null || this.followingPlayer.distanceToSqr(this) > 64.0) {
Player nearestPlayer = this.level().getNearestPlayer(this, 8.0);
if (nearestPlayer != null && !nearestPlayer.isSpectator() && !nearestPlayer.isDeadOrDying()) {
@@ -134,7 +_,22 @@
}
}
- if (this.followingPlayer != null) {
@@ -112,16 +119,7 @@
Vec3 vec3 = new Vec3(
this.followingPlayer.getX() - this.getX(),
this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(),
@@ -120,7 +_,7 @@
this.age++;
if (this.age >= 6000) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
@@ -143,16 +_,25 @@
@@ -161,16 +_,25 @@
}
public static void award(ServerLevel level, Vec3 pos, int amount) {
@@ -148,7 +146,7 @@
AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0);
int randomInt = level.getRandom().nextInt(40);
List<ExperienceOrb> entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount));
@@ -175,9 +_,14 @@
@@ -193,9 +_,14 @@
}
private void merge(ExperienceOrb orb) {
@@ -164,7 +162,7 @@
}
private void setUnderwaterMovement() {
@@ -202,7 +_,7 @@
@@ -220,7 +_,7 @@
this.markHurt();
this.health = (int)(this.health - amount);
if (this.health <= 0) {
@@ -173,23 +171,23 @@
}
return true;
@@ -213,32 +_,34 @@
@@ -231,32 +_,34 @@
public void addAdditionalSaveData(CompoundTag compound) {
compound.putShort("Health", (short)this.health);
compound.putShort("Age", (short)this.age);
- compound.putShort("Value", (short)this.value);
+ compound.putInt("Value", this.value); // Paper - save as Integer
- compound.putShort("Value", (short)this.getValue());
+ compound.putInt("Value", this.getValue()); // Paper - save as Integer
compound.putInt("Count", this.count);
+ this.savePaperNBT(compound); // Paper
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
this.health = compound.getShort("Health");
this.age = compound.getShort("Age");
- this.value = compound.getShort("Value");
+ this.value = compound.getInt("Value"); // Paper - load as Integer
this.count = Math.max(compound.getInt("Count"), 1);
this.health = compound.getShortOr("Health", (short)5);
this.age = compound.getShortOr("Age", (short)0);
- this.setValue(compound.getShortOr("Value", (short)0));
+ this.setValue(compound.getIntOr("Value", 0)); // Paper - load as Integer
this.count = compound.read("Count", ExtraCodecs.POSITIVE_INT).orElse(1);
+ this.loadPaperNBT(compound); // Paper
}
@@ -201,7 +199,7 @@
+ if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent
+ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
entity.take(this, 1);
int i = this.repairPlayerItems(serverPlayer, this.value);
int i = this.repairPlayerItems(serverPlayer, this.getValue());
if (i > 0) {
- entity.giveExperiencePoints(i);
+ entity.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entity, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object
@@ -214,7 +212,7 @@
}
}
}
@@ -252,10 +_,21 @@
@@ -270,10 +_,21 @@
ItemStack itemStack = randomItemWith.get().itemStack();
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemStack, value);
int min = Math.min(i, itemStack.getDamageValue());
@@ -237,7 +235,7 @@
return this.repairPlayerItems(player, i1);
}
}
@@ -295,6 +_,24 @@
@@ -318,6 +_,24 @@
}
public static int getExperienceValue(int expValue) {
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/InsideBlockEffectType.java
+++ b/net/minecraft/world/entity/InsideBlockEffectType.java
@@ -6,7 +_,7 @@
public enum InsideBlockEffectType {
FREEZE(entity -> {
entity.setIsInPowderSnow(true);
- if (entity.canFreeze()) {
+ if (entity.canFreeze() && !entity.freezeLocked) { // Paper - Freeze Tick Lock API
entity.setTicksFrozen(Math.min(entity.getTicksRequiredToFreeze(), entity.getTicksFrozen() + 1));
}
}),
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/Interaction.java
+++ b/net/minecraft/world/entity/Interaction.java
@@ -130,9 +_,16 @@
@@ -100,9 +_,16 @@
@Override
public boolean skipAttackInteraction(Entity entity) {
if (entity instanceof Player player) {
@@ -1,9 +1,9 @@
--- a/net/minecraft/world/entity/ItemBasedSteering.java
+++ b/net/minecraft/world/entity/ItemBasedSteering.java
@@ -51,6 +_,14 @@
@@ -47,4 +_,11 @@
public int boostTimeTotal() {
return this.entityData.get(this.boostTimeAccessor);
}
+ // CraftBukkit add setBoostTicks(int)
+ public void setBoostTicks(int ticks) {
+ this.boosting = true;
@@ -11,7 +11,4 @@
+ this.entityData.set(this.boostTimeAccessor, ticks);
+ }
+ // CraftBukkit end
+
public void addAdditionalSaveData(CompoundTag nbt) {
nbt.putBoolean("Saddle", this.hasSaddle());
}
}
@@ -1,33 +1,18 @@
--- a/net/minecraft/world/entity/Leashable.java
+++ b/net/minecraft/world/entity/Leashable.java
@@ -56,7 +_,13 @@
@Nullable
private static Leashable.LeashData readLeashDataInternal(CompoundTag tag) {
if (tag.contains("leash", 10)) {
- return new Leashable.LeashData(Either.left(tag.getCompound("leash").getUUID("UUID")));
+ // Paper start
+ final CompoundTag leashTag = tag.getCompound("leash");
+ if (!leashTag.hasUUID("UUID")) {
+ return null;
+ }
+ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID")));
+ // Paper end
} else {
if (tag.contains("leash", 11)) {
Either<UUID, BlockPos> either = NbtUtils.readBlockPos(tag, "leash").<Either<UUID, BlockPos>>map(Either::right).orElse(null);
@@ -72,6 +_,11 @@
@@ -56,6 +_,11 @@
}
default void writeLeashData(CompoundTag tag, @Nullable Leashable.LeashData leashData) {
if (leashData != null) {
Either<UUID, BlockPos> either = leashData.delayedLeashInfo;
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
+ if (leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) {
+ return;
+ }
+ // CraftBukkit end
if (leashData.leashHolder instanceof LeashFenceKnotEntity leashFenceKnotEntity) {
either = Either.right(leashFenceKnotEntity.getPos());
} else if (leashData.leashHolder != null) {
@@ -104,7 +_,9 @@
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
+ if (leashData != null && leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) {
+ return;
+ }
+ // CraftBukkit end
tag.storeNullable("leash", Leashable.LeashData.CODEC, leashData);
}
@@ -75,7 +_,9 @@
}
if (entity.tickCount > 100) {
@@ -37,7 +22,7 @@
entity.setLeashData(null);
}
}
@@ -128,7 +_,9 @@
@@ -99,7 +_,9 @@
entity.onLeashRemoved();
if (entity.level() instanceof ServerLevel serverLevel) {
if (dropItem) {
@@ -47,7 +32,7 @@
}
if (broadcastPacket) {
@@ -146,7 +_,15 @@
@@ -117,7 +_,15 @@
if (leashData != null && leashData.leashHolder != null) {
if (!entity.isAlive() || !leashData.leashHolder.isAlive()) {
@@ -64,7 +49,7 @@
entity.dropLeash();
} else {
entity.removeLeash();
@@ -160,7 +_,7 @@
@@ -131,7 +_,7 @@
return;
}
@@ -73,7 +58,7 @@
entity.leashTooFarBehaviour();
} else if (f > 6.0) {
entity.elasticRangeLeashBehaviour(leashHolder, f);
@@ -177,7 +_,21 @@
@@ -148,7 +_,21 @@
}
default void leashTooFarBehaviour() {
File diff suppressed because it is too large. Load diff
@@ -1,8 +1,8 @@
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -84,6 +_,18 @@
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
@@ -83,6 +_,18 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.ticks.ContainerSingleItem;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
@@ -27,7 +27,7 @@
public GoalSelector targetSelector;
@Nullable
private LivingEntity target;
@@ -131,6 +_,7 @@
@@ -126,6 +_,7 @@
private Leashable.LeashData leashData;
private BlockPos restrictCenter = BlockPos.ZERO;
private float restrictRadius = -1.0F;
@@ -35,7 +35,7 @@
protected Mob(EntityType<? extends Mob> entityType, Level level) {
super(entityType, level);
@@ -150,6 +_,12 @@
@@ -142,6 +_,12 @@
}
}
@@ -48,7 +48,7 @@
protected void registerGoals() {
}
@@ -230,7 +_,40 @@
@@ -222,7 +_,40 @@
}
public void setTarget(@Nullable LivingEntity target) {
@@ -89,7 +89,7 @@
}
@Override
@@ -354,6 +_,12 @@
@@ -338,6 +_,12 @@
return null;
}
@@ -102,7 +102,7 @@
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
@@ -413,13 +_,25 @@
@@ -358,13 +_,22 @@
if (this.isNoAi()) {
compound.putBoolean("NoAI", this.isNoAi());
}
@@ -112,45 +112,30 @@
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
- this.setCanPickUpLoot(compound.getBoolean("CanPickUpLoot"));
- this.persistenceRequired = compound.getBoolean("PersistenceRequired");
- this.setCanPickUpLoot(compound.getBooleanOr("CanPickUpLoot", false));
- this.persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
+ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
+ if (compound.contains("CanPickUpLoot", 99)) {
+ boolean data = compound.getBoolean("CanPickUpLoot");
+ if (isLevelAtLeast(compound, 1) || data) {
+ this.setCanPickUpLoot(data);
+ }
+ boolean canPickUpLoot = compound.getBooleanOr("CanPickUpLoot", false);
+ if (isLevelAtLeast(compound, 1) || canPickUpLoot) {
+ this.setCanPickUpLoot(canPickUpLoot);
+ }
+
+ boolean data = compound.getBoolean("PersistenceRequired");
+ if (isLevelAtLeast(compound, 1) || data) {
+ this.persistenceRequired = data;
+ boolean persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
+ if (isLevelAtLeast(compound, 1) || persistenceRequired) {
+ this.persistenceRequired = persistenceRequired;
+ }
+ // CraftBukkit end
if (compound.contains("ArmorItems", 9)) {
ListTag list = compound.getList("ArmorItems", 10);
@@ -472,13 +_,18 @@
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
this.dropChances = compound.read("drop_chances", DropChances.CODEC, registryOps).orElse(DropChances.DEFAULT);
this.readLeashData(compound);
this.setLeftHanded(compound.getBoolean("LeftHanded"));
if (compound.contains("DeathLootTable", 8)) {
- this.lootTable = Optional.of(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(compound.getString("DeathLootTable"))));
+ this.lootTable = Optional.ofNullable(ResourceLocation.tryParse(compound.getString("DeathLootTable"))).map((rs) -> ResourceKey.create(Registries.LOOT_TABLE, rs)); // Paper - Validate ResourceLocation
} else {
this.lootTable = Optional.empty();
}
this.lootTableSeed = compound.getLong("DeathLootTableSeed");
this.setNoAi(compound.getBoolean("NoAI"));
+ // CraftBukkit start
+ if (compound.contains("Bukkit.Aware")) {
+ this.aware = compound.getBoolean("Bukkit.Aware");
+ }
+ // CraftBukkit end
@@ -372,6 +_,7 @@
this.lootTable = compound.read("DeathLootTable", LootTable.KEY_CODEC);
this.lootTableSeed = compound.getLongOr("DeathLootTableSeed", 0L);
this.setNoAi(compound.getBooleanOr("NoAI", false));
+ this.aware = compound.getBooleanOr("Bukkit.Aware", true); // CraftBukkit
}
@Override
@@ -540,6 +_,11 @@
@@ -433,6 +_,11 @@
&& !itemEntity.getItem().isEmpty()
&& !itemEntity.hasPickUpDelay()
&& this.wantsToPickUp(serverLevel, itemEntity.getItem())) {
@@ -162,7 +147,7 @@
this.pickUpItem(serverLevel, itemEntity);
}
}
@@ -554,18 +_,24 @@
@@ -447,18 +_,24 @@
protected void pickUpItem(ServerLevel level, ItemEntity entity) {
ItemStack item = entity.getItem();
@@ -184,32 +169,32 @@
+ return this.equipItemIfPossible(level, stack, null);
+ }
+
+ public ItemStack equipItemIfPossible(ServerLevel level, ItemStack stack, ItemEntity entity) {
+ public ItemStack equipItemIfPossible(ServerLevel level, ItemStack stack, @Nullable ItemEntity entity) {
+ // CraftBukkit end
EquipmentSlot equipmentSlotForItem = this.getEquipmentSlotForItem(stack);
ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem);
boolean canReplaceCurrentItem = this.canReplaceCurrentItem(stack, itemBySlot, equipmentSlotForItem);
@@ -575,10 +_,18 @@
canReplaceCurrentItem = itemBySlot.isEmpty();
}
- if (canReplaceCurrentItem && this.canHoldItem(stack)) {
+ // CraftBukkit start
+ boolean canPickup = canReplaceCurrentItem && this.canHoldItem(stack);
+ if (entity != null) {
+ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, !canPickup).isCancelled();
+ }
+ if (canPickup) {
+ // CraftBukkit end
double d = this.getEquipmentDropChance(equipmentSlotForItem);
if (!itemBySlot.isEmpty() && Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) {
+ this.forceDrops = true; // CraftBukkit
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // CraftBukkit
if (!this.isEquippableInSlot(stack, equipmentSlotForItem)) {
return ItemStack.EMPTY;
@@ -471,10 +_,18 @@
canReplaceCurrentItem = itemBySlot.isEmpty();
}
ItemStack itemStack = equipmentSlotForItem.limit(stack);
@@ -703,22 +_,29 @@
- if (canReplaceCurrentItem && this.canHoldItem(stack)) {
+ // CraftBukkit start
+ boolean canPickup = canReplaceCurrentItem && this.canHoldItem(stack);
+ if (entity != null) {
+ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, !canPickup).isCancelled();
+ }
+ if (canPickup) {
+ // CraftBukkit end
double d = this.dropChances.byEquipment(equipmentSlotForItem);
if (!itemBySlot.isEmpty() && Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) {
+ this.forceDrops = true; // CraftBukkit
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // CraftBukkit
}
ItemStack itemStack = equipmentSlotForItem.limit(stack);
@@ -591,22 +_,29 @@
@Override
public void checkDespawn() {
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
@@ -229,9 +214,9 @@
+ final io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DespawnRangePair despawnRangePair = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory());
+ final io.papermc.paper.configuration.type.DespawnRange.Shape shape = this.level().paperConfig().entities.spawning.despawnRangeShape;
+ final double dy = Math.abs(nearestPlayer.getY() - this.getY());
+ final double dySqr = Math.pow(dy, 2);
+ final double dxSqr = Math.pow(nearestPlayer.getX() - this.getX(), 2);
+ final double dzSqr = Math.pow(nearestPlayer.getZ() - this.getZ(), 2);
+ final double dySqr = Mth.square(dy);
+ final double dxSqr = Mth.square(nearestPlayer.getX() - this.getX());
+ final double dzSqr = Mth.square(nearestPlayer.getZ() - this.getZ());
+ final double distanceSquared = dxSqr + dzSqr + dySqr;
+ // Despawn if hard/soft limit is exceeded
+ if (despawnRangePair.hard().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy) && this.removeWhenFarAway(distanceSquared)) {
@@ -252,7 +237,7 @@
this.noActionTime = 0;
}
}
@@ -730,6 +_,15 @@
@@ -618,6 +_,15 @@
@Override
protected final void serverAiStep() {
this.noActionTime++;
@@ -268,41 +253,16 @@
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("sensing");
this.sensing.tick();
@@ -908,26 +_,40 @@
@Override
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
+ // Paper start - Fix silent equipment change
+ setItemSlot(slot, stack, false);
+ }
+
+ @Override
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
+ // Paper end - Fix silent equipment change
this.verifyEquippedItem(stack);
switch (slot.getType()) {
case HAND:
- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
break;
case HUMANOID_ARMOR:
- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
break;
case ANIMAL_ARMOR:
ItemStack itemStack = this.bodyArmorItem;
this.bodyArmorItem = stack;
- this.onEquipItem(slot, itemStack, stack);
+ this.onEquipItem(slot, itemStack, stack, silent); // Paper - Fix silent equipment change
}
@@ -796,11 +_,18 @@
};
}
+
+ // Paper start
+ protected boolean shouldSkipLoot(EquipmentSlot slot) { // method to avoid to fallback into the global mob loot logic (i.e fox)
+ return false;
+ }
+ // Paper end
+
@Override
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
super.dropCustomDeathLoot(level, damageSource, recentlyHit);
@@ -310,9 +270,9 @@
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ if (this.shouldSkipLoot(equipmentSlot)) continue; // Paper
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
float equipmentDropChance = this.getEquipmentDropChance(equipmentSlot);
if (equipmentDropChance != 0.0F) {
@@ -951,7 +_,13 @@
float f = this.dropChances.byEquipment(equipmentSlot);
if (f != 0.0F) {
@@ -820,7 +_,13 @@
}
this.spawnAtLocation(level, itemBySlot);
@@ -326,17 +286,17 @@
}
}
}
@@ -981,7 +_,9 @@
double d = this.getEquipmentDropChance(equipmentSlot);
if (d > 1.0) {
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
}
@@ -844,7 +_,9 @@
set.add(equipmentSlot);
} else if (this.dropChances.isPreserved(equipmentSlot)) {
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
this.spawnAtLocation(level, itemBySlot);
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
}
}
@@ -1269,6 +_,22 @@
}
@@ -1122,6 +_,22 @@
public <T extends Mob> T convertTo(
EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion
) {
@@ -359,7 +319,7 @@
if (this.isRemoved()) {
return null;
} else {
@@ -1277,13 +_,23 @@
@@ -1130,13 +_,23 @@
return null;
} else {
conversionParams.type().convert(this, mob, conversionParams);
@@ -386,7 +346,7 @@
}
return mob;
@@ -1293,7 +_,20 @@
@@ -1146,7 +_,20 @@
@Nullable
public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.AfterConversion<T> afterConversion) {
@@ -408,7 +368,7 @@
}
@Nullable
@@ -1329,7 +_,17 @@
@@ -1182,7 +_,17 @@
public boolean startRiding(Entity entity, boolean force) {
boolean flag = super.startRiding(entity, force);
if (flag && this.isLeashed()) {
@@ -427,7 +387,7 @@
}
return flag;
@@ -1412,7 +_,7 @@
@@ -1270,7 +_,7 @@
float knockback = this.getKnockback(source, damageSource);
if (knockback > 0.0F && source instanceof LivingEntity livingEntity) {
livingEntity.knockback(
Loaded 100 of 468 files, more files were not shown because too many files have changed in this diff. Show more