ExperienceOrb award methods were consolidated to avoid this large of a
conflict in future versions for what is a single override.
Callers are expected to now pass null to the 3rd overload param as well.
This commit is contained in:
Bjarne Koll
2025-05-29 17:46:55 +02:00
parent 0795cbed25
commit ca8da0e3ca
12 changed files with 356 additions and 449 deletions

View File

@@ -1,19 +0,0 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
index c5419fd9ca690fc65c2ffc6a4e0a4bbf747afcf4..514f8fbdeb776087608665c35de95294aadf5cf0 100644
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -105,7 +105,7 @@ public class EntitySelector {
}
private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException {
- if (this.usesSelector && !source.hasPermission(2)) {
+ if (!source.bypassSelectorPermissions && (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector"))) { // CraftBukkit // Paper - add bypass for selector perms
throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create();
}
}

View File

@@ -10,7 +10,7 @@
private final RedirectModifier<S> modifier;
private final boolean forks;
private Command<S> command;
+ public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API
+ public CommandNode<S> clientNode; // Paper - Brigadier API
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> wrappedCached = null; // Paper - Brigadier Command API
+ public io.papermc.paper.command.brigadier.APICommandMeta apiCommandMeta; // Paper - Brigadier Command API

View File

@@ -1,23 +1,15 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
index 5b51e130f440273f03396a53938e0c771cde2c75..cb63e4c264a31788cd1405428af70f7a018910e9 100644
--- a/net/minecraft/commands/CommandSourceStack.java
+++ b/net/minecraft/commands/CommandSourceStack.java
@@ -45,7 +45,7 @@ import net.minecraft.world.level.dimension.DimensionType;
@@ -47,7 +_,7 @@
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
-public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, SharedSuggestionProvider {
+public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, SharedSuggestionProvider, io.papermc.paper.command.brigadier.PaperCommandSourceStack { // Paper - Brigadier API
-public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, PermissionSource, SharedSuggestionProvider {
+public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, PermissionSource, SharedSuggestionProvider, io.papermc.paper.command.brigadier.PaperCommandSourceStack { // Paper - Brigadier API
public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(Component.translatable("permissions.requires.player"));
public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(Component.translatable("permissions.requires.entity"));
public final CommandSource source;
@@ -63,6 +63,8 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -65,6 +_,8 @@
private final Vec2 rotation;
private final CommandSigningContext signingContext;
private final TaskChainer chatMessageChainer;
@@ -26,7 +18,7 @@ index 5b51e130f440273f03396a53938e0c771cde2c75..cb63e4c264a31788cd1405428af70f7a
public CommandSourceStack(
CommandSource source,
@@ -188,6 +190,30 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -190,6 +_,30 @@
);
}
@@ -57,7 +49,7 @@ index 5b51e130f440273f03396a53938e0c771cde2c75..cb63e4c264a31788cd1405428af70f7a
public CommandSourceStack withRotation(Vec2 rotation) {
return this.rotation.equals(rotation)
? this
@@ -391,9 +417,44 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -393,9 +_,44 @@
@Override
public boolean hasPermission(int level) {
@@ -102,7 +94,7 @@ index 5b51e130f440273f03396a53938e0c771cde2c75..cb63e4c264a31788cd1405428af70f7a
public Vec3 getPosition() {
return this.worldPosition;
}
@@ -498,20 +559,25 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -500,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()) {
@@ -131,7 +123,7 @@ index 5b51e130f440273f03396a53938e0c771cde2c75..cb63e4c264a31788cd1405428af70f7a
}
}
@@ -522,7 +588,7 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -524,7 +_,7 @@
@Override
public Collection<String> getOnlinePlayerNames() {
@@ -140,7 +132,7 @@ index 5b51e130f440273f03396a53938e0c771cde2c75..cb63e4c264a31788cd1405428af70f7a
}
@Override
@@ -597,4 +663,16 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -604,4 +_,16 @@
public boolean isSilent() {
return this.silent;
}

View File

@@ -1,14 +1,6 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535e853d127 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -150,6 +150,11 @@ public class Commands {
@@ -176,6 +_,11 @@
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
@@ -20,7 +12,7 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
AdvancementCommands.register(this.dispatcher);
AttributeCommand.register(this.dispatcher, context);
ExecuteCommand.register(this.dispatcher, context);
@@ -251,6 +256,40 @@ public class Commands {
@@ -280,6 +_,40 @@
PublishCommand.register(this.dispatcher);
}
@@ -61,7 +53,7 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
}
@@ -260,15 +299,58 @@ public class Commands {
@@ -289,9 +_,41 @@
return new ParseResults<>(commandContextBuilder, parseResults.getReader(), parseResults.getExceptions());
}
@@ -97,12 +89,16 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
+ }
+
+ public void performPrefixedCommand(CommandSourceStack source, String command, String label) {
command = command.startsWith("/") ? command.substring(1) : command;
command = trimOptionalPrefix(command);
- this.performCommand(this.dispatcher.parse(command, source), command);
+ this.performCommand(this.dispatcher.parse(command, source), command, label);
+ // CraftBukkit end
}
public static String trimOptionalPrefix(String command) {
@@ -299,9 +_,20 @@
}
public void performCommand(ParseResults<CommandSourceStack> parseResults, String command) {
+ // CraftBukkit start
+ this.performCommand(parseResults, command, command);
@@ -122,7 +118,7 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
try {
if (contextChain != null) {
@@ -280,9 +362,10 @@ public class Commands {
@@ -313,9 +_,10 @@
);
}
} catch (Exception var12) {
@@ -135,7 +131,7 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
StackTraceElement[] stackTrace = var12.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
@@ -308,18 +391,22 @@ public class Commands {
@@ -341,18 +_,22 @@
}
@Nullable
@@ -161,7 +157,7 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
if (min > 10) {
mutableComponent.append(CommonComponents.ELLIPSIS);
}
@@ -331,7 +418,17 @@ public class Commands {
@@ -364,7 +_,17 @@
}
mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
@@ -180,13 +176,13 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
}
return null;
@@ -359,26 +456,121 @@ public class Commands {
@@ -392,17 +_,111 @@
}
public void sendCommands(ServerPlayer player) {
+ // Paper start - Send empty commands if tab completion is disabled
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {
+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>()));
+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>(), COMMAND_NODE_INSPECTOR));
+ return;
+ }
+ // Paper end - Send empty commands if tab completion is disabled
@@ -211,11 +207,11 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
+
+ private void sendAsync(ServerPlayer player, java.util.Collection<CommandNode<CommandSourceStack>> dispatcherRootChildren) {
+ // Paper end - Perf: Async command map building
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newHashMap();
RootCommandNode<SharedSuggestionProvider> rootCommandNode = new RootCommandNode<>();
Map<CommandNode<CommandSourceStack>, CommandNode<CommandSourceStack>> map = new HashMap<>();
RootCommandNode<CommandSourceStack> rootCommandNode = new RootCommandNode<>();
map.put(this.dispatcher.getRoot(), rootCommandNode);
- this.fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
+ this.fillUsableCommands(dispatcherRootChildren, rootCommandNode, player.createCommandSourceStack(), map); // Paper - Perf: Async command map building; pass copy of children
- fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
+ fillUsableCommands(dispatcherRootChildren, rootCommandNode, player.createCommandSourceStack(), map); // Paper - Perf: Async command map building; pass copy of children
+
+ java.util.Collection<String> bukkit = new java.util.LinkedHashSet<>();
+ for (CommandNode node : rootCommandNode.getChildren()) {
@@ -224,11 +220,11 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
+ // Paper start - Perf: Async command map building
+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) rootCommandNode, false).callEvent(); // Paper - Brigadier API
+ net.minecraft.server.MinecraftServer.getServer().execute(() -> {
+ runSync(player, bukkit, rootCommandNode);
+ runSync(player, bukkit, rootCommandNode);
+ });
+ }
+
+ private void runSync(ServerPlayer player, java.util.Collection<String> bukkit, RootCommandNode<SharedSuggestionProvider> rootCommandNode) {
+ private void runSync(ServerPlayer player, java.util.Collection<String> bukkit, RootCommandNode<CommandSourceStack> rootCommandNode) {
+ // Paper end - Perf: Async command map building
+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) rootCommandNode, true).callEvent(); // Paper - Brigadier API
+ org.bukkit.event.player.PlayerCommandSendEvent event = new org.bukkit.event.player.PlayerCommandSendEvent(player.getBukkitEntity(), new java.util.LinkedHashSet<>(bukkit));
@@ -241,19 +237,13 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
+ }
+ }
+ // CraftBukkit end
+
player.connection.send(new ClientboundCommandsPacket(rootCommandNode));
player.connection.send(new ClientboundCommandsPacket(rootCommandNode, COMMAND_NODE_INSPECTOR));
}
private void fillUsableCommands(
- CommandNode<CommandSourceStack> rootCommandSource,
+ java.util.Collection<CommandNode<CommandSourceStack>> children, // Paper - Perf: Async command map building; pass copy of children
CommandNode<SharedSuggestionProvider> rootSuggestion,
CommandSourceStack source,
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode
) {
- for (CommandNode<CommandSourceStack> commandNode : rootCommandSource.getChildren()) {
+ for (CommandNode<CommandSourceStack> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
- private static <S> void fillUsableCommands(CommandNode<S> root, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) {
- for (CommandNode<S> commandNode : root.getChildren()) {
+ private static <S> void fillUsableCommands(java.util.Collection<CommandNode<S>> children, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) { // Paper - Perf: Async command map building; pass copy of children
+ for (CommandNode<S> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
+ // Paper start - Brigadier API
+ if (commandNode.clientNode != null) {
+ commandNode = commandNode.clientNode;
@@ -262,10 +252,7 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot
+ if (commandNode.wrappedCached != null && commandNode.wrappedCached.apiCommandMeta != null && commandNode.wrappedCached.apiCommandMeta.serverSideOnly()) continue; // Paper
if (commandNode.canUse(source)) {
ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder();
- argumentBuilder.requires(suggestions -> true);
- if (argumentBuilder.getCommand() != null) {
- argumentBuilder.executes(commandContext -> 0);
ArgumentBuilder<S, ?> argumentBuilder = commandNode.createBuilder();
+ // Paper start
+ /*
+ Because of how commands can be yeeted right left and center due to bad bukkit practices
@@ -282,38 +269,34 @@ index fe4da263cd7c62805239fff40fd2b51655f829d5..1927163db5d44383b69f41e4b9855535
+ - Do this :)
+ */
+ // Is there an invalid command redirect?
+ if (argumentBuilder.getRedirect() != null && commandNodeToSuggestionNode.get(argumentBuilder.getRedirect()) == null) {
+ if (argumentBuilder.getRedirect() != null && output.get(argumentBuilder.getRedirect()) == null) {
+ // Create the argument builder with the same values as the specified node, but with a different literal and populated children
+
+ final CommandNode<SharedSuggestionProvider> redirect = argumentBuilder.getRedirect();
+ final CommandNode<S> redirect = argumentBuilder.getRedirect();
+ // Diff copied from LiteralCommand#createBuilder
+ final com.mojang.brigadier.builder.LiteralArgumentBuilder<SharedSuggestionProvider> builder = com.mojang.brigadier.builder.LiteralArgumentBuilder.literal(commandNode.getName());
+ final com.mojang.brigadier.builder.LiteralArgumentBuilder<S> builder = com.mojang.brigadier.builder.LiteralArgumentBuilder.literal(commandNode.getName());
+ builder.requires(redirect.getRequirement());
+ // builder.forward(redirect.getRedirect(), redirect.getRedirectModifier(), redirect.isFork()); We don't want to migrate the forward, since it's invalid.
+ if (redirect.getCommand() != null) {
+ builder.executes(redirect.getCommand());
+ }
+ // Diff copied from LiteralCommand#createBuilder
+ for (final CommandNode<SharedSuggestionProvider> child : redirect.getChildren()) {
+ for (final CommandNode<S> child : redirect.getChildren()) {
+ builder.then(child);
+ }
+
+ argumentBuilder = builder;
}
+ }
+ // Paper end
+ argumentBuilder.requires(suggestions -> true);
+ // Paper - don't replace Command instance on suggestion node
+ // 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
&& requiredArgumentBuilder.getSuggestionsProvider() != null) {
@@ -393,7 +585,7 @@ public class Commands {
commandNodeToSuggestionNode.put(commandNode, commandNode1);
rootSuggestion.addChild(commandNode1);
if (argumentBuilder.getRedirect() != null) {
argumentBuilder.redirect(output.get(argumentBuilder.getRedirect()));
}
@@ -411,7 +_,7 @@
output.put(commandNode, commandNode1);
current.addChild(commandNode1);
if (!commandNode.getChildren().isEmpty()) {
- this.fillUsableCommands(commandNode, commandNode1, source, commandNodeToSuggestionNode);
+ this.fillUsableCommands(commandNode.getChildren(), commandNode1, source, commandNodeToSuggestionNode); // Paper - Perf: Async command map building; pass copy of children
- fillUsableCommands(commandNode, commandNode1, source, output);
+ fillUsableCommands(commandNode.getChildren(), commandNode1, source, output); // Paper - Perf: Async command map building; pass copy of children
}
}
}

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -105,7 +_,7 @@
}
private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException {
- if (this.usesSelector && !source.allowsSelectors()) {
+ if (!source.bypassSelectorPermissions && (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector"))) { // CraftBukkit // Paper - add bypass for selector perms
throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create();
}
}

View File

@@ -1,14 +1,6 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
index 343381f8190061e6f42131e36c256fff6fbc85a6..a6f232747df631f6afe440606bea94c588f1a0dd 100644
--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
@@ -122,6 +122,11 @@ public class EntitySelectorParser {
@@ -122,6 +_,11 @@
}
public static <S> boolean allowSelectors(S suggestionProvider) {
@@ -17,10 +9,10 @@ index 343381f8190061e6f42131e36c256fff6fbc85a6..a6f232747df631f6afe440606bea94c5
+ return stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector");
+ }
+ // Paper end - Fix EntityArgument permissions
return suggestionProvider instanceof SharedSuggestionProvider sharedSuggestionProvider && sharedSuggestionProvider.hasPermission(2);
return suggestionProvider instanceof PermissionSource permissionSource && permissionSource.allowsSelectors();
}
@@ -198,8 +203,10 @@ public class EntitySelectorParser {
@@ -198,8 +_,10 @@
};
}
@@ -33,7 +25,7 @@ index 343381f8190061e6f42131e36c256fff6fbc85a6..a6f232747df631f6afe440606bea94c5
this.suggestions = this::suggestSelector;
if (!this.reader.canRead()) {
throw ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader);
@@ -467,6 +474,12 @@ public class EntitySelectorParser {
@@ -467,6 +_,12 @@
}
public EntitySelector parse() throws CommandSyntaxException {
@@ -46,7 +38,7 @@ index 343381f8190061e6f42131e36c256fff6fbc85a6..a6f232747df631f6afe440606bea94c5
this.startPosition = this.reader.getCursor();
this.suggestions = this::suggestNameOrSelector;
if (this.reader.canRead() && this.reader.peek() == '@') {
@@ -475,7 +488,7 @@ public class EntitySelectorParser {
@@ -475,7 +_,7 @@
}
this.reader.skip();

View File

@@ -1,14 +1,6 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 3993b90daeff2a5a72816e9cc76dacc830d6af77..4c57990c94721dd0973477669e1dadfab5f16404 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -216,7 +216,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -217,7 +_,7 @@
.fireImmune()
.sized(6.0F, 0.5F)
.clientTrackingRange(10)
@@ -17,7 +9,7 @@ index 3993b90daeff2a5a72816e9cc76dacc830d6af77..4c57990c94721dd0973477669e1dadfa
);
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)
@@ -1145,6 +1145,22 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1155,6 +_,22 @@
boolean shouldOffsetY,
boolean shouldOffsetYMore
) {
@@ -40,7 +32,7 @@ index 3993b90daeff2a5a72816e9cc76dacc830d6af77..4c57990c94721dd0973477669e1dadfa
Consumer<T> consumer;
if (spawnedFrom != null) {
consumer = createDefaultStackConfig(level, spawnedFrom, owner);
@@ -1152,7 +1168,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1162,7 +_,7 @@
consumer = entity -> {};
}
@@ -49,7 +41,7 @@ index 3993b90daeff2a5a72816e9cc76dacc830d6af77..4c57990c94721dd0973477669e1dadfa
}
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack stack, @Nullable LivingEntity owner) {
@@ -1169,19 +1185,56 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1179,19 +_,56 @@
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);
@@ -109,7 +101,7 @@ index 3993b90daeff2a5a72816e9cc76dacc830d6af77..4c57990c94721dd0973477669e1dadfa
if (entity instanceof Mob mob) {
mob.playAmbientSound();
}
@@ -1237,6 +1290,15 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1247,6 +_,15 @@
if (level.isClientSide
|| !entity.getType().onlyOpCanSetNbt()
|| owner instanceof Player player && server.getPlayerList().isOp(player.getGameProfile())) {
@@ -125,25 +117,25 @@ index 3993b90daeff2a5a72816e9cc76dacc830d6af77..4c57990c94721dd0973477669e1dadfa
customData.loadInto(entity);
}
}
@@ -1308,9 +1370,20 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1318,9 +_,20 @@
}
public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason) {
public static Optional<Entity> create(ValueInput input, Level level, EntitySpawnReason spawnReason) {
+ // Paper start - Don't fire sync event during generation
+ return create(tag, level, spawnReason, false);
+ return create(input, level, spawnReason, false);
+ }
+
+ public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason, boolean generation) {
+ public static Optional<Entity> create(ValueInput input, Level level, EntitySpawnReason spawnReason, boolean generation) {
+ // Paper end - Don't fire sync event during generation
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.getStringOr("id", "[invalid]"))
by(input).map(entityType -> entityType.create(level, spawnReason)),
- entity -> entity.load(input),
+ // 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(input);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", input.getStringOr("id", "[invalid]"))
);
}

View File

@@ -1,14 +1,6 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java
index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715775f5393 100644
--- a/net/minecraft/world/entity/ExperienceOrb.java
+++ b/net/minecraft/world/entity/ExperienceOrb.java
@@ -41,9 +41,54 @@ public class ExperienceOrb extends Entity {
@@ -44,13 +_,54 @@
@Nullable
private Player followingPlayer;
private final InterpolationHandler interpolation = new InterpolationHandler(this);
@@ -18,52 +10,52 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
+ @Nullable
+ public java.util.UUID triggerEntityId;
+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+
+ private void loadPaperNBT(CompoundTag tag) {
+ CompoundTag expData = tag.getCompoundOrEmpty("Paper.ExpData");
+ if (expData.isEmpty()) {
+ return;
+ }
+ this.sourceEntityId = expData.read("source", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ this.triggerEntityId = expData.read("trigger", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ expData.getString("reason").ifPresent(reason -> {
+ try {
+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
+ } catch (Exception e) {
+ this.level().getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
+ }
+ private void loadPaperNBT(ValueInput valueInput) {
+ valueInput.read("Paper.ExpData", net.minecraft.nbt.CompoundTag.CODEC).ifPresent(expData -> {
+ this.sourceEntityId = expData.read("source", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ this.triggerEntityId = expData.read("trigger", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ expData.getString("reason").ifPresent(reason -> {
+ try {
+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
+ } catch (Exception e) {
+ this.level().getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
+ }
+ });
+ });
+ }
+ private void savePaperNBT(CompoundTag tag) {
+ CompoundTag expData = new CompoundTag();
+ private void savePaperNBT(ValueOutput tag) {
+ net.minecraft.nbt.CompoundTag expData = new net.minecraft.nbt.CompoundTag();
+ expData.storeNullable("source", net.minecraft.core.UUIDUtil.CODEC, this.sourceEntityId);
+ expData.storeNullable("trigger", net.minecraft.core.UUIDUtil.CODEC, this.triggerEntityId);
+ if (this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
+ expData.putString("reason", this.spawnReason.name());
+ }
+ tag.put("Paper.ExpData", expData);
+ tag.store("Paper.ExpData", net.minecraft.nbt.CompoundTag.CODEC, expData);
+ }
+
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
+ // Paper end
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - overload ctor
public ExperienceOrb(Level level, double x, double y, double z, int value) {
+ this(level, x, y, z, value, null, null);
this(level, new Vec3(x, y, z), Vec3.ZERO, value);
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - overload ctor
public ExperienceOrb(Level level, Vec3 pos, Vec3 direction, int value) {
+ // Paper start - add reasons for orbs
+ this(level, pos, direction, value, null, null, null);
+ }
+
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId) {
+ this(level, x, y, z, value, reason, triggerId, null);
+ }
+
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ public ExperienceOrb(Level level, Vec3 pos, Vec3 direction, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reasons for orbs
this(EntityType.EXPERIENCE_ORB, level);
+ // Paper start - add reasons for orbs
+ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null;
+ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null;
+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+ // Paper end
this.setPos(x, y, z);
if (!this.level().isClientSide) {
this.setYRot((float)(this.random.nextDouble() * 360.0));
@@ -119,12 +164,13 @@ public class ExperienceOrb extends Entity {
+ // Paper end - add reasons for orbs
this.setPos(pos);
if (!level.isClientSide) {
this.setYRot(this.random.nextFloat() * 360.0F);
@@ -147,12 +_,13 @@
this.age++;
if (this.age >= 6000) {
@@ -78,7 +70,7 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
if (this.followingPlayer == null || this.followingPlayer.isSpectator() || this.followingPlayer.distanceToSqr(this) > 64.0) {
Player nearestPlayer = this.level().getNearestPlayer(this, 8.0);
if (nearestPlayer != null && !nearestPlayer.isSpectator() && !nearestPlayer.isDeadOrDying()) {
@@ -134,7 +180,24 @@ public class ExperienceOrb extends Entity {
@@ -162,7 +_,24 @@
}
}
@@ -104,26 +96,21 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
Vec3 vec3 = new Vec3(
this.followingPlayer.getX() - this.getX(),
this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(),
@@ -161,18 +224,29 @@ public class ExperienceOrb extends Entity {
@@ -193,18 +_,24 @@
}
public static void award(ServerLevel level, Vec3 pos, int amount) {
+ // Paper start - add reasons for orbs
+ award(level, pos, amount, null, null, null);
public static void awardWithDirection(ServerLevel level, Vec3 pos, Vec3 direction, int amount) {
+ // Paper start - add reason to orbs
+ awardWithDirection(level, pos, direction, amount, null, null, null);
+ }
+
+ public static void award(ServerLevel level, Vec3 pos, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId) {
+ award(level, pos, amount, reason, triggerId, null);
+ }
+
+ public static void award(ServerLevel level, Vec3 pos, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reasons for orbs
+ public static void awardWithDirection(ServerLevel level, Vec3 pos, Vec3 direction, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reason to orbs
while (amount > 0) {
int experienceValue = getExperienceValue(amount);
amount -= experienceValue;
if (!tryMergeToExisting(level, pos, experienceValue)) {
- level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), experienceValue));
+ level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), experienceValue, reason, triggerId, sourceId)); // Paper - add reason
- level.addFreshEntity(new ExperienceOrb(level, pos, direction, experienceValue));
+ level.addFreshEntity(new ExperienceOrb(level, pos, direction, experienceValue, reason, triggerId, sourceId)); // Paper - add reason to orbs
}
}
}
@@ -133,10 +120,10 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0);
- int randomInt = level.getRandom().nextInt(40);
+ int randomInt = level.getRandom().nextInt(io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA)); // Paper - Configure how many orb groups per area
List<ExperienceOrb> entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount));
if (!entities.isEmpty()) {
ExperienceOrb experienceOrb = entities.get(0);
@@ -189,13 +263,18 @@ public class ExperienceOrb extends Entity {
List<ExperienceOrb> entities = level.getEntities(
EntityTypeTest.forClass(ExperienceOrb.class), aabb, experienceOrb1 -> canMerge(experienceOrb1, randomInt, amount)
);
@@ -223,13 +_,18 @@
}
private static boolean canMerge(ExperienceOrb orb, int amount, int other) {
@@ -157,7 +144,7 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
}
private void setUnderwaterMovement() {
@@ -220,7 +299,7 @@ public class ExperienceOrb extends Entity {
@@ -254,7 +_,7 @@
this.markHurt();
this.health = (int)(this.health - amount);
if (this.health <= 0) {
@@ -166,24 +153,24 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
}
return true;
@@ -231,32 +310,34 @@ public class ExperienceOrb extends Entity {
public void addAdditionalSaveData(CompoundTag compound) {
compound.putShort("Health", (short)this.health);
compound.putShort("Age", (short)this.age);
- compound.putShort("Value", (short)this.getValue());
+ compound.putInt("Value", this.getValue()); // Paper - save as Integer
compound.putInt("Count", this.count);
+ this.savePaperNBT(compound); // Paper
@@ -265,32 +_,34 @@
protected void addAdditionalSaveData(ValueOutput output) {
output.putShort("Health", (short)this.health);
output.putShort("Age", (short)this.age);
- output.putShort("Value", (short)this.getValue());
+ output.putInt("Value", this.getValue()); // Paper - save as Integer
output.putInt("Count", this.count);
+ this.savePaperNBT(output); // Paper
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
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
protected void readAdditionalSaveData(ValueInput input) {
this.health = input.getShortOr("Health", (short)5);
this.age = input.getShortOr("Age", (short)0);
- this.setValue(input.getShortOr("Value", (short)0));
+ this.setValue(input.getIntOr("Value", 0)); // Paper - load as Integer
this.count = input.read("Count", ExtraCodecs.POSITIVE_INT).orElse(1);
+ this.loadPaperNBT(input); // Paper
}
@Override
@@ -207,9 +194,9 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
}
}
}
@@ -270,9 +351,19 @@ public class ExperienceOrb extends Entity {
@@ -304,9 +_,19 @@
ItemStack itemStack = randomItemWith.get().itemStack();
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemStack, value);
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.level(), itemStack, value);
int min = Math.min(i, itemStack.getDamageValue());
+ // CraftBukkit start
+ // Paper start - mending event
@@ -228,7 +215,7 @@ index 8f5d415aeed587c8477f0a0839104fdbd4be9724..c97a0e500e889b406cb2d679a3870715
if (i1 > 0) {
return this.repairPlayerItems(player, i1);
}
@@ -318,6 +409,24 @@ public class ExperienceOrb extends Entity {
@@ -352,6 +_,24 @@
}
public static int getExperienceValue(int expValue) {

View File

@@ -1,26 +1,18 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/entity/Leashable.java b/net/minecraft/world/entity/Leashable.java
index d658dfeb7d1e154f0153621ff6779b6e2bb1cc4d..24b663e48a88345bb366cc4c9afbabac22c9df85 100644
--- a/net/minecraft/world/entity/Leashable.java
+++ b/net/minecraft/world/entity/Leashable.java
@@ -56,6 +56,11 @@ public interface Leashable {
@@ -80,6 +_,11 @@
}
default void writeLeashData(CompoundTag tag, @Nullable Leashable.LeashData leashData) {
default void writeLeashData(ValueOutput output, @Nullable Leashable.LeashData leashData) {
+ // 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);
output.storeNullable("leash", Leashable.LeashData.CODEC, leashData);
}
@@ -75,7 +80,9 @@ public interface Leashable {
@@ -99,7 +_,9 @@
}
if (entity.tickCount > 100) {
@@ -30,7 +22,7 @@ index d658dfeb7d1e154f0153621ff6779b6e2bb1cc4d..24b663e48a88345bb366cc4c9afbabac
entity.setLeashData(null);
}
}
@@ -99,7 +106,9 @@ public interface Leashable {
@@ -123,7 +_,9 @@
entity.onLeashRemoved();
if (entity.level() instanceof ServerLevel serverLevel) {
if (dropItem) {
@@ -40,7 +32,7 @@ index d658dfeb7d1e154f0153621ff6779b6e2bb1cc4d..24b663e48a88345bb366cc4c9afbabac
}
if (broadcastPacket) {
@@ -117,7 +126,15 @@ public interface Leashable {
@@ -143,7 +_,15 @@
if (leashData != null && leashData.leashHolder != null) {
if (!entity.isAlive() || !leashData.leashHolder.isAlive()) {
@@ -57,16 +49,29 @@ index d658dfeb7d1e154f0153621ff6779b6e2bb1cc4d..24b663e48a88345bb366cc4c9afbabac
entity.dropLeash();
} else {
entity.removeLeash();
@@ -131,7 +148,7 @@ public interface Leashable {
return;
}
- if (f > 10.0) {
+ if (f > entity.level().paperConfig().misc.maxLeashDistance.or(LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
@@ -154,7 +_,7 @@
if (leashHolder != null && leashHolder.level() == entity.level()) {
double d = entity.leashDistanceTo(leashHolder);
entity.whenLeashedTo(leashHolder);
- if (d > entity.leashSnapDistance()) {
+ if (d > entity.leashSnapDistanceOrConfig()) { // Paper - Configurable max leash distance
level.playSound(null, leashHolder, SoundEvents.LEAD_BREAK, SoundSource.NEUTRAL, 1.0F, 1.0F);
entity.leashTooFarBehaviour();
} else if (f > 6.0) {
entity.elasticRangeLeashBehaviour(leashHolder, f);
@@ -148,7 +165,21 @@ public interface Leashable {
} else if (d > entity.leashElasticDistance() - leashHolder.getBbWidth() - entity.getBbWidth()
@@ -175,6 +_,12 @@
entity.checkFallDistanceAccumulation();
}
+ // Paper start - Configurable max leash distance
+ default double leashSnapDistanceOrConfig() {
+ if (!(this instanceof final Entity entity)) return leashSnapDistance();
+ return entity.level().paperConfig().misc.maxLeashDistance.or(leashSnapDistance());
+ }
+ // Paper end - Configurable max leash distance
default double leashSnapDistance() {
return 12.0;
}
@@ -196,7 +_,21 @@
}
default void leashTooFarBehaviour() {

View File

@@ -1,14 +1,6 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc64d673165 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -135,6 +135,17 @@ import net.minecraft.world.scores.Scoreboard;
@@ -138,6 +_,17 @@
import org.jetbrains.annotations.Contract;
import org.slf4j.Logger;
@@ -23,13 +15,13 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+import org.bukkit.event.entity.EntityResurrectEvent;
+// CraftBukkit end
+
public abstract class LivingEntity extends Entity implements Attackable {
public abstract class LivingEntity extends Entity implements Attackable, WaypointTransmitter {
private static final Logger LOGGER = LogUtils.getLogger();
private static final String TAG_ACTIVE_EFFECTS = "active_effects";
@@ -251,11 +262,25 @@ public abstract class LivingEntity extends Entity implements Attackable {
EquipmentSlot.class
@@ -264,11 +_,25 @@
);
protected final EntityEquipment equipment;
private Waypoint.Icon locatorBarIcon = new Waypoint.Icon();
+ // CraftBukkit start
+ public int expToDrop;
+ public List<DefaultDrop> drops = new java.util.ArrayList<>(); // Paper - Restore vanilla drops behavior
@@ -53,7 +45,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.equipment = this.createEquipment();
this.blocksBuilding = true;
this.reapplyPosition();
@@ -350,7 +375,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -364,7 +_,13 @@
double d1 = Math.min(0.2F + d / 15.0, 2.5);
int i = (int)(150.0 * d1);
@@ -68,7 +60,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
@@ -535,7 +566,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -549,7 +_,7 @@
this.deathTime++;
if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) {
this.level().broadcastEntityEvent(this, (byte)60);
@@ -77,7 +69,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
@@ -640,7 +671,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -654,7 +_,7 @@
}
public boolean shouldDiscardFriction() {
@@ -86,7 +78,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
public void setDiscardFriction(boolean discardFriction) {
@@ -652,10 +683,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -666,10 +_,15 @@
}
public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) {
@@ -103,7 +95,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.level()
.playSeededSound(
null,
@@ -682,12 +718,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -696,12 +_,12 @@
}
@Override
@@ -118,7 +110,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.brain.clearMemories();
}
@@ -696,11 +732,17 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -718,11 +_,17 @@
mobEffectInstance.onMobRemoved(level, this, removalReason);
}
@@ -127,22 +119,23 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
@Override
public void addAdditionalSaveData(CompoundTag compound) {
protected void addAdditionalSaveData(ValueOutput output) {
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ compound.putString("Paper.FrictionState", this.frictionState.toString());
+ output.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end - Friction API
compound.putFloat("Health", this.getHealth());
compound.putShort("HurtTime", (short)this.hurtTime);
compound.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -731,8 +773,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
output.putFloat("Health", this.getHealth());
output.putShort("HurtTime", (short)this.hurtTime);
output.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -756,8 +_,15 @@
}
}
+ // Paper start - Extend dropItem API
@Nullable
- @Nullable
- public ItemEntity drop(ItemStack stack, boolean randomizeMotion, boolean includeThrower) {
+ // Paper start - Extend dropItem API
+ @Nullable
+ public final ItemEntity drop(ItemStack stack, boolean randomizeMotion, boolean includeThrower) {
+ return this.drop(stack, randomizeMotion, includeThrower, true, null);
+ }
@@ -153,7 +146,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (stack.isEmpty()) {
return null;
} else if (this.level().isClientSide) {
@@ -741,6 +790,31 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -766,6 +_,31 @@
} else {
ItemEntity itemEntity = this.createItemStackToDrop(stack, randomizeMotion, includeThrower);
if (itemEntity != null) {
@@ -185,20 +178,20 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.level().addFreshEntity(itemEntity);
}
@@ -750,7 +824,22 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -775,7 +_,22 @@
@Override
public void readAdditionalSaveData(CompoundTag compound) {
- this.internalSetAbsorptionAmount(compound.getFloatOr("AbsorptionAmount", 0.0F));
protected void readAdditionalSaveData(ValueInput input) {
- this.internalSetAbsorptionAmount(input.getFloatOr("AbsorptionAmount", 0.0F));
+ // Paper start - Check for NaN
+ float absorptionAmount = compound.getFloatOr("AbsorptionAmount", 0.0F);
+ float absorptionAmount = input.getFloatOr("AbsorptionAmount", 0.0F);
+ if (Float.isNaN(absorptionAmount)) {
+ absorptionAmount = 0;
+ }
+ this.internalSetAbsorptionAmount(absorptionAmount);
+ // Paper end - Check for NaN
+ // Paper start - Friction API
+ compound.getString("Paper.FrictionState").ifPresent(frictionState -> {
+ input.getString("Paper.FrictionState").ifPresent(frictionState -> {
+ try {
+ this.frictionState = net.kyori.adventure.util.TriState.valueOf(frictionState);
+ } catch (Exception ignored) {
@@ -207,32 +200,32 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+ });
+ // Paper end - Friction API
if (this.level() != null && !this.level().isClientSide) {
compound.getList("attributes").ifPresent(this.getAttributes()::load);
input.read("attributes", AttributeInstance.Packed.LIST_CODEC).ifPresent(this.getAttributes()::apply);
}
@@ -763,6 +852,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -787,6 +_,11 @@
this.activeEffects.put(mobEffectInstance.getEffect(), mobEffectInstance);
}
+ // CraftBukkit start
+ compound.getDouble("Bukkit.MaxHealth").ifPresent(maxHealth -> {
+ input.getDouble("Bukkit.MaxHealth").ifPresent(maxHealth -> {
+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(maxHealth);
+ });
+ // CraftBukkit end
this.setHealth(compound.getFloatOr("Health", this.getMaxHealth()));
this.hurtTime = compound.getShortOr("HurtTime", (short)0);
this.deathTime = compound.getShortOr("DeathTime", (short)0);
@@ -770,6 +864,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
compound.getString("Team").ifPresent(string -> {
this.setHealth(input.getFloatOr("Health", this.getMaxHealth()));
this.hurtTime = input.getShortOr("HurtTime", (short)0);
this.deathTime = input.getShortOr("DeathTime", (short)0);
@@ -794,6 +_,7 @@
input.getString("Team").ifPresent(string -> {
Scoreboard scoreboard = this.level().getScoreboard();
PlayerTeam playerTeam = scoreboard.getPlayerTeam(string);
+ if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { playerTeam = null; } // Paper - Perf: Disable Scoreboards for non players by default
boolean flag = playerTeam != null && scoreboard.addPlayerToTeam(this.getStringUUID(), playerTeam);
if (!flag) {
LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", string);
@@ -777,11 +872,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -801,11 +_,13 @@
});
this.setSharedFlag(7, compound.getBooleanOr("FallFlying", false));
compound.read("sleeping_pos", BlockPos.CODEC).ifPresentOrElse(blockPos -> {
this.setSharedFlag(7, input.getBooleanOr("FallFlying", false));
input.read("sleeping_pos", BlockPos.CODEC).ifPresentOrElse(blockPos -> {
+ if (this.position().distanceToSqr(blockPos.getX(), blockPos.getY(), blockPos.getZ()) < Mth.square(16)) { // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
this.setSleepingPos(blockPos);
this.entityData.set(DATA_POSE, Pose.SLEEPING);
@@ -241,10 +234,10 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
+ } // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
}, this::clearSleepingPos);
compound.getCompound("Brain").ifPresent(compoundTag -> this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, compoundTag)));
this.lastHurtByPlayer = EntityReference.read(compound, "last_hurt_by_player");
@@ -791,15 +888,44 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.equipment.setAll(compound.read("equipment", EntityEquipment.CODEC, registryOps).orElseGet(EntityEquipment::new));
input.read("Brain", Codec.PASSTHROUGH).ifPresent(dynamic -> this.brain = this.makeBrain((Dynamic<?>)dynamic));
this.lastHurtByPlayer = EntityReference.read(input, "last_hurt_by_player");
@@ -816,15 +_,44 @@
this.locatorBarIcon = input.read("locator_bar_icon", Waypoint.Icon.CODEC).orElseGet(Waypoint.Icon::new);
}
+ // CraftBukkit start
@@ -288,7 +281,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
iterator.remove();
this.onEffectsRemoved(List.of(mobEffectInstance));
} else if (mobEffectInstance.getDuration() % 600 == 0) {
@@ -809,6 +935,17 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -834,6 +_,17 @@
} catch (ConcurrentModificationException var6) {
}
@@ -306,7 +299,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (this.effectsDirty) {
this.updateInvisibilityStatus();
this.updateGlowingStatus();
@@ -916,15 +1053,33 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -941,15 +_,33 @@
}
public boolean removeAllEffects() {
@@ -344,7 +337,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
@@ -951,21 +1106,57 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -976,21 +_,57 @@
}
public final boolean addEffect(MobEffectInstance effectInstance) {
@@ -404,7 +397,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.onEffectUpdated(mobEffectInstance, true, entity);
flag = true;
}
@@ -1004,11 +1195,37 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1029,11 +_,37 @@
@Nullable
public final MobEffectInstance removeEffectNoUpdate(Holder<MobEffect> effect) {
@@ -443,7 +436,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (mobEffectInstance != null) {
this.onEffectsRemoved(List.of(mobEffectInstance));
return true;
@@ -1092,17 +1309,62 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1124,17 +_,62 @@
}
public void heal(float healAmount) {
@@ -507,7 +500,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.entityData.set(DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth()));
}
@@ -1114,7 +1376,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1146,7 +_,7 @@
public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
if (this.isInvulnerableTo(level, damageSource)) {
return false;
@@ -516,15 +509,14 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
return false;
} else if (damageSource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
return false;
@@ -1128,35 +1390,59 @@ public abstract class LivingEntity extends Entity implements Attackable {
amount = 0.0F;
@@ -1161,35 +_,58 @@
}
float originAmount = amount;
- float f1 = this.applyItemBlocking(level, damageSource, amount);
- amount -= f1;
+ final float originalAmount = amount; // Paper - revert to vanilla #hurt - OBFHELPER
+ float f1 = this.applyItemBlocking(level, damageSource, amount, true); // Paper
+ // Paper end
+ // amount -= f1; // CraftBukkit - Moved into handleEntityDamage(DamageSource, float) to allow modification
boolean flag = f1 > 0.0F;
- if (damageSource.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) {
+ // CraftBukkit - Moved into handleEntityDamage(DamageSource, float) to get amount
@@ -561,7 +553,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+ if (!this.actuallyHurt(level, damageSource, (float) event.getFinalDamage(), event)) { // Paper - fix invulnerability reduction in EntityDamageEvent - no longer subtract lastHurt, that is part of the damage event calc now
+ return false;
+ }
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originalAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
+ // CraftBukkit end
this.lastHurt = amount;
flag1 = false;
@@ -574,7 +566,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+ if (!this.actuallyHurt(level, damageSource, (float) event.getFinalDamage(), event)) {
+ return false;
+ }
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originalAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
this.lastHurt = amount;
- this.invulnerableTime = 20;
- this.actuallyHurt(level, damageSource, amount);
@@ -584,7 +576,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.hurtDuration = 10;
this.hurtTime = this.hurtDuration;
}
@@ -1171,7 +1457,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1204,7 +_,7 @@
level.broadcastDamageEvent(this, damageSource);
}
@@ -593,7 +585,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.markHurt();
}
@@ -1186,8 +1472,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1219,8 +_,16 @@
d = damageSource.getSourcePosition().x() - this.getX();
d1 = damageSource.getSourcePosition().z() - this.getZ();
}
@@ -611,7 +603,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (!flag) {
this.indicateDamage(d, d1);
}
@@ -1196,19 +1490,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1229,19 +_,19 @@
if (this.isDeadOrDying()) {
if (!this.checkTotemDeathProtection(damageSource)) {
@@ -636,7 +628,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (flag2) {
this.lastDamageSource = damageSource;
this.lastDamageStamp = this.level().getGameTime();
@@ -1234,6 +1528,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1267,6 +_,12 @@
}
public float applyItemBlocking(ServerLevel level, DamageSource damageSource, float damageAmount) {
@@ -649,7 +641,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (damageAmount <= 0.0F) {
return 0.0F;
} else {
@@ -1258,10 +1558,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1291,10 +_,12 @@
}
float f = blocksAttacks.resolveBlockedDamage(damageSource, damageAmount, acos);
@@ -663,7 +655,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
return f;
}
@@ -1272,6 +1574,59 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1305,6 +_,59 @@
}
}
@@ -723,7 +715,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
public void playSecondaryHurtSound(DamageSource damageSource) {
if (damageSource.is(DamageTypes.THORNS)) {
SoundSource soundSource = this instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE;
@@ -1304,12 +1659,24 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1337,12 +_,24 @@
return EntityReference.get(this.lastHurtByPlayer, this.level(), Player.class);
}
@@ -749,7 +741,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
private boolean checkTotemDeathProtection(DamageSource damageSource) {
@@ -1319,18 +1686,39 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1352,18 +_,39 @@
ItemStack itemStack = null;
DeathProtection deathProtection = null;
@@ -763,14 +755,11 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (deathProtection != null) {
+ hand = interactionHand; // CraftBukkit
itemStack = itemInHand.copy();
- itemInHand.shrink(1);
+ // itemInHand.shrink(1); // CraftBukkit
break;
}
}
- if (itemStack != null) {
- if (this instanceof ServerPlayer serverPlayer) {
+ break;
+ }
+ }
+
+ final org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null;
+ final EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot);
+ event.setCancelled(itemStack == null);
@@ -780,7 +769,13 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+ deathProtection = null;
+ } else {
+ if (!itemInHand.isEmpty() && itemStack != null) { // Paper - only reduce item if actual totem was found
+ itemInHand.shrink(1);
itemInHand.shrink(1);
- break;
- }
- }
-
- if (itemStack != null) {
- if (this instanceof ServerPlayer serverPlayer) {
+ }
+ // Paper start - fix NPE when pre-cancelled EntityResurrectEvent is uncancelled
+ // restore the previous behavior in that case by defaulting to vanillas totem of undying effect
@@ -793,7 +788,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
serverPlayer.awardStat(Stats.ITEM_USED.get(itemStack.getItem()));
CriteriaTriggers.USED_TOTEM.trigger(serverPlayer, itemStack);
this.gameEvent(GameEvent.ITEM_INTERACT_FINISH);
@@ -1389,6 +1777,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1422,6 +_,7 @@
if (!this.isRemoved() && !this.dead) {
Entity entity = damageSource.getEntity();
LivingEntity killCredit = this.getKillCredit();
@@ -801,7 +796,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (killCredit != null) {
killCredit.awardKillScore(this, damageSource);
}
@@ -1398,68 +1787,141 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1431,68 +_,141 @@
}
if (!this.level().isClientSide && this.hasCustomName()) {
@@ -940,6 +935,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
|| this.lastHurtByPlayerMemoryTime > 0 && this.shouldDropExperience() && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)
)) {
- ExperienceOrb.award(level, this.position(), this.getExperienceReward(level, entity));
- }
+ return this.getExperienceReward(level, entity); // CraftBukkit
+ }
+ return 0; // CraftBukkit
@@ -950,12 +946,12 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+ if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
+ ExperienceOrb.award(level, this.position(), this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, entity, this); // Paper
+ this.expToDrop = 0;
}
+ }
+ // CraftBukkit end
}
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
@@ -1539,9 +2001,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1572,9 +_,14 @@
}
public void knockback(double strength, double x, double z) {
@@ -972,7 +968,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
Vec3 deltaMovement = this.getDeltaMovement();
while (x * x + z * z < 1.0E-5F) {
@@ -1550,11 +2017,22 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1583,11 +_,22 @@
}
Vec3 vec3 = new Vec3(x, 0.0, z).normalize().scale(strength);
@@ -996,7 +992,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
@@ -1639,7 +2117,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1672,7 +_,7 @@
@Override
public boolean isAlive() {
@@ -1005,7 +1001,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
public boolean isLookingAtMe(LivingEntity entity, double tolerance, boolean scaleByDistance, boolean visual, double... yValues) {
@@ -1673,9 +2151,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1706,9 +_,14 @@
boolean flag = super.causeFallDamage(fallDistance, damageMultiplier, damageSource);
int i = this.calculateFallDamage(fallDistance, damageMultiplier);
if (i > 0) {
@@ -1021,7 +1017,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
return true;
} else {
return flag;
@@ -1740,7 +2223,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1773,7 +_,7 @@
protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) {
if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) {
@@ -1030,7 +1026,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
damageAmount = CombatRules.getDamageAfterAbsorb(
this, damageAmount, damageSource, this.getArmorValue(), (float)this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)
);
@@ -1753,7 +2236,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1786,7 +_,8 @@
if (damageSource.is(DamageTypeTags.BYPASSES_EFFECTS)) {
return damageAmount;
} else {
@@ -1040,7 +1036,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
int i = (this.getEffect(MobEffects.RESISTANCE).getAmplifier() + 1) * 5;
int i1 = 25 - i;
float f = damageAmount * i1;
@@ -1790,24 +2274,201 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1823,24 +_,201 @@
}
}
@@ -1252,7 +1248,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
public CombatTracker getCombatTracker() {
@@ -1836,7 +2497,17 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1869,7 +_,17 @@
}
public final void setArrowCount(int count) {
@@ -1271,7 +1267,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
public final int getStingerCount() {
@@ -1991,7 +2662,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2024,7 +_,7 @@
@Override
protected void onBelowWorld() {
@@ -1280,14 +1276,15 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
protected void updateSwingTime() {
@@ -2087,8 +2758,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2120,8 +_,15 @@
}
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
- this.onEquipItem(slot, this.equipment.set(slot, stack), stack);
- }
+ // Paper start
+ this.setItemSlot(slot, stack, false);
}
+ }
+ // CraftBukkit start
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
+ // Paper end
@@ -1297,7 +1294,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
public float getArmorCoverPercentage() {
int i = 0;
@@ -2180,14 +2858,27 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2213,14 +_,27 @@
return this.hasEffect(MobEffects.JUMP_BOOST) ? 0.1F * (this.getEffect(MobEffects.JUMP_BOOST).getAmplifier() + 1.0F) : 0.0F;
}
@@ -1325,7 +1322,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.addDeltaMovement(new Vec3(-Mth.sin(f) * 0.2, 0.0, Mth.cos(f) * 0.2));
}
@@ -2327,8 +3018,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2380,8 +_,10 @@
}
public void stopFallFlying() {
@@ -1336,7 +1333,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
private Vec3 updateFallFlyingMovement(Vec3 deltaMovement) {
@@ -2454,7 +3147,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2507,7 +_,7 @@
}
protected float getFlyingSpeed() {
@@ -1345,7 +1342,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
public float getSpeed() {
@@ -2538,37 +3231,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2591,37 +_,15 @@
profilerFiller.pop();
profilerFiller.push("rangeChecks");
@@ -1364,19 +1361,15 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
- while (this.yBodyRot - this.yBodyRotO >= 180.0F) {
- this.yBodyRotO += 360.0F;
- }
+ // Paper start - stop large pitch and yaw changes from crashing the server
+ this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F;
-
- while (this.getXRot() - this.xRotO < -180.0F) {
- this.xRotO -= 360.0F;
- }
+ this.yBodyRotO += Math.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F;
-
- while (this.getXRot() - this.xRotO >= 180.0F) {
- this.xRotO += 360.0F;
- }
+ this.xRotO += Math.round((this.getXRot() - this.xRotO) / 360.0F) * 360.0F;
-
- while (this.yHeadRot - this.yHeadRotO < -180.0F) {
- this.yHeadRotO -= 360.0F;
- }
@@ -1384,12 +1377,19 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
- while (this.yHeadRot - this.yHeadRotO >= 180.0F) {
- this.yHeadRotO += 360.0F;
- }
+ // Paper start - stop large pitch and yaw changes from crashing the server
+ this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F;
+
+ this.yBodyRotO += Math.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F;
+
+ this.xRotO += Math.round((this.getXRot() - this.xRotO) / 360.0F) * 360.0F;
+
+ this.yHeadRotO += Math.round((this.yHeadRot - this.yHeadRotO) / 360.0F) * 360.0F;
+ // Paper end - stop large pitch and yaw changes from crashing the server
profilerFiller.pop();
if (this.isFallFlying()) {
@@ -2598,16 +3269,39 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2651,16 +_,39 @@
@Nullable
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
Map<EquipmentSlot, ItemStack> map = null;
@@ -1429,7 +1429,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
AttributeMap attributes = this.getAttributes();
if (!itemStack.isEmpty()) {
this.stopLocationBasedEffects(itemStack, equipmentSlot, attributes);
@@ -2632,6 +3326,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2685,6 +_,8 @@
}
}
}
@@ -1438,7 +1438,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
return map;
@@ -2663,7 +3359,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2716,7 +_,7 @@
list.add(Pair.of(equipmentSlot, itemStack1));
this.lastEquipmentItems.put(equipmentSlot, itemStack1);
});
@@ -1447,7 +1447,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
protected void tickHeadTurn(float yBodyRot) {
@@ -2749,8 +3445,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2802,8 +_,10 @@
if (!flag || this.onGround() && !(fluidHeight > fluidJumpThreshold)) {
if (!this.isInLava() || this.onGround() && !(fluidHeight > fluidJumpThreshold)) {
if ((this.onGround() || flag && fluidHeight <= fluidJumpThreshold) && this.noJumpDelay == 0) {
@@ -1458,7 +1458,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
} else {
this.jumpInLiquid(FluidTags.LAVA);
@@ -2791,7 +3489,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2844,7 +_,7 @@
profilerFiller.pop();
if (this.level() instanceof ServerLevel serverLevel) {
profilerFiller.push("freezing");
@@ -1467,7 +1467,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.setTicksFrozen(Math.max(0, this.getTicksFrozen() - 2));
}
@@ -2812,6 +3510,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2865,6 +_,20 @@
this.pushEntities();
profilerFiller.pop();
@@ -1488,15 +1488,15 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) {
this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F);
}
@@ -2830,6 +3542,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.checkSlowFallDistance();
@@ -2887,6 +_,7 @@
this.checkFallDistanceAccumulation();
if (!this.level().isClientSide) {
if (!this.canGlide()) {
+ if (this.getSharedFlag(7) != false && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit
this.setSharedFlag(7, false);
return;
}
@@ -2869,10 +3582,25 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2926,10 +_,25 @@
}
protected void pushEntities() {
@@ -1523,7 +1523,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (_int > 0 && pushableEntities.size() > _int - 1 && this.random.nextInt(4) == 0) {
int i = 0;
@@ -2888,7 +3616,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2945,7 +_,16 @@
}
}
@@ -1540,7 +1540,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.doPush(entity1);
}
}
@@ -2930,9 +3667,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2987,9 +_,16 @@
@Override
public void stopRiding() {
@@ -1559,7 +1559,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.dismountVehicle(vehicle);
}
}
@@ -2959,7 +3703,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3016,7 +_,7 @@
}
public void onItemPickup(ItemEntity itemEntity) {
@@ -1568,7 +1568,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (owner instanceof ServerPlayer) {
CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer)owner, itemEntity.getItem(), this);
}
@@ -2969,7 +3713,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3026,7 +_,7 @@
if (!entity.isRemoved()
&& !this.level().isClientSide
&& (entity instanceof ItemEntity || entity instanceof AbstractArrow || entity instanceof ExperienceOrb)) {
@@ -1577,7 +1577,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
@@ -2983,7 +3727,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3040,7 +_,8 @@
} else {
Vec3 vec3 = new Vec3(this.getX(), this.getEyeY(), this.getZ());
Vec3 vec31 = new Vec3(entity.getX(), y, entity.getZ());
@@ -1587,7 +1587,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
@@ -3003,14 +3748,28 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3060,13 +_,27 @@
@Override
public boolean isPickable() {
@@ -1599,9 +1599,10 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
@Override
public boolean isPushable() {
- return this.isAlive() && !this.isSpectator() && !this.onClimbable();
- }
+ return this.isCollidable(this.level().paperConfig().collisions.fixClimbingBypassingCrammingRule);
}
+ }
+
+ @Override
+ public boolean isCollidable(boolean ignoreClimbing) {
+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit
@@ -1614,11 +1615,10 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
+ return this.isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID());
+ }
+ // CraftBukkit end
+
@Override
public float getYHeadRot() {
return this.yHeadRot;
@@ -3040,7 +3799,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3097,7 +_,7 @@
}
public final void setAbsorptionAmount(float absorptionAmount) {
@@ -1627,7 +1627,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
protected void internalSetAbsorptionAmount(float absorptionAmount) {
@@ -3067,6 +3826,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3124,6 +_,15 @@
return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
}
@@ -1643,7 +1643,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
private void updatingUsingItem() {
if (this.isUsingItem()) {
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
@@ -3084,6 +3852,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3141,6 +_,11 @@
return null;
} else {
double d = this.getEyeY() - 0.3F;
@@ -1655,7 +1655,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), d, this.getZ(), stack);
itemEntity.setPickUpDelay(40);
if (includeThrower) {
@@ -3115,7 +3888,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3172,7 +_,12 @@
protected void updateUsingItem(ItemStack usingItem) {
usingItem.onUseTick(this.level(), this, this.getUseItemRemainingTicks());
@@ -1669,7 +1669,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.completeUsingItem();
}
}
@@ -3141,10 +3919,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3198,10 +_,19 @@
}
public void startUsingItem(InteractionHand hand) {
@@ -1691,7 +1691,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
if (!this.level().isClientSide) {
this.setLivingEntityFlag(1, true);
this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND);
@@ -3168,7 +3955,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3225,7 +_,10 @@
}
} else if (!this.isUsingItem() && !this.useItem.isEmpty()) {
this.useItem = ItemStack.EMPTY;
@@ -1703,7 +1703,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
}
@@ -3207,12 +3997,49 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3264,12 +_,49 @@
this.releaseUsingItem();
} else {
if (!this.useItem.isEmpty() && this.isUsingItem()) {
@@ -1754,7 +1754,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
}
}
@@ -3237,6 +4064,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3294,6 +_,7 @@
ItemStack itemInHand = this.getItemInHand(this.getUsedItemHand());
if (!this.useItem.isEmpty() && ItemStack.isSameItem(itemInHand, this.useItem)) {
this.useItem = itemInHand;
@@ -1762,7 +1762,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
this.useItem.releaseUsing(this.level(), this, this.getUseItemRemainingTicks());
if (this.useItem.useOnRelease()) {
this.updatingUsingItem();
@@ -3256,7 +4084,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3313,7 +_,10 @@
}
this.useItem = ItemStack.EMPTY;
@@ -1774,7 +1774,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
}
public boolean isBlocking() {
@@ -3280,6 +4111,60 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3337,6 +_,60 @@
}
}
@@ -1835,7 +1835,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
public boolean isSuppressingSlidingDownLadder() {
return this.isShiftKeyDown();
}
@@ -3298,6 +4183,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3355,6 +_,12 @@
}
public boolean randomTeleport(double x, double y, double z, boolean broadcastTeleport) {
@@ -1848,7 +1848,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
double x1 = this.getX();
double y1 = this.getY();
double z1 = this.getZ();
@@ -3320,16 +4211,39 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3377,16 +_,39 @@
}
if (flag1) {
@@ -1891,7 +1891,7 @@ index cf7386c6f44d8c32dfa93e1333eca9fba510fa03..267544f50fafd914566df1c4b2327bc6
} else {
if (broadcastTeleport) {
level.broadcastEntityEvent(this, (byte)46);
@@ -3339,7 +4253,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3396,7 +_,7 @@
pathfinderMob.getNavigation().stop();
}

View File

@@ -1,15 +1,7 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08dbc6a690 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -83,6 +83,14 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.AABB;
@@ -82,6 +_,14 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.ticks.ContainerSingleItem;
+// CraftBukkit start
@@ -23,7 +15,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
public abstract class Mob extends LivingEntity implements EquipmentUser, Leashable, Targeting {
private static final EntityDataAccessor<Byte> DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE);
private static final int MOB_FLAG_NO_AI = 1;
@@ -112,6 +120,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -115,6 +_,7 @@
private final BodyRotationControl bodyRotationControl;
protected PathNavigation navigation;
public GoalSelector goalSelector;
@@ -31,15 +23,15 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
public GoalSelector targetSelector;
@Nullable
private LivingEntity target;
@@ -126,6 +135,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -129,6 +_,7 @@
private Leashable.LeashData leashData;
private BlockPos restrictCenter = BlockPos.ZERO;
private float restrictRadius = -1.0F;
private BlockPos homePosition = BlockPos.ZERO;
private int homeRadius = -1;
+ public boolean aware = true; // CraftBukkit
protected Mob(EntityType<? extends Mob> entityType, Level level) {
super(entityType, level);
@@ -142,6 +152,12 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -145,6 +_,12 @@
}
}
@@ -52,7 +44,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
protected void registerGoals() {
}
@@ -222,7 +238,39 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -225,7 +_,39 @@
}
public void setTarget(@Nullable LivingEntity target) {
@@ -92,40 +84,40 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
@Override
@@ -358,13 +406,22 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -365,13 +_,22 @@
if (this.isNoAi()) {
compound.putBoolean("NoAI", this.isNoAi());
output.putBoolean("NoAI", this.isNoAi());
}
+ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
- this.setCanPickUpLoot(compound.getBooleanOr("CanPickUpLoot", false));
- this.persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
protected void readAdditionalSaveData(ValueInput input) {
super.readAdditionalSaveData(input);
- this.setCanPickUpLoot(input.getBooleanOr("CanPickUpLoot", false));
- this.persistenceRequired = input.getBooleanOr("PersistenceRequired", false);
+ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
+ boolean canPickUpLoot = compound.getBooleanOr("CanPickUpLoot", false);
+ if (isLevelAtLeast(compound, 1) || canPickUpLoot) {
+ boolean canPickUpLoot = input.getBooleanOr("CanPickUpLoot", false);
+ if (isLevelAtLeast(input, 1) || canPickUpLoot) {
+ this.setCanPickUpLoot(canPickUpLoot);
+ }
+ boolean persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
+ if (isLevelAtLeast(compound, 1) || persistenceRequired) {
+ boolean persistenceRequired = input.getBooleanOr("PersistenceRequired", false);
+ if (isLevelAtLeast(input, 1) || persistenceRequired) {
+ this.persistenceRequired = persistenceRequired;
+ }
+ // CraftBukkit end
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
this.dropChances = compound.read("drop_chances", DropChances.CODEC, registryOps).orElse(DropChances.DEFAULT);
this.readLeashData(compound);
@@ -372,6 +429,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
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
this.dropChances = input.read("drop_chances", DropChances.CODEC).orElse(DropChances.DEFAULT);
this.readLeashData(input);
this.homeRadius = input.getIntOr("home_radius", -1);
@@ -383,6 +_,7 @@
this.lootTable = input.read("DeathLootTable", LootTable.KEY_CODEC);
this.lootTableSeed = input.getLongOr("DeathLootTableSeed", 0L);
this.setNoAi(input.getBooleanOr("NoAI", false));
+ this.aware = input.getBooleanOr("Bukkit.Aware", true); // CraftBukkit
}
@Override
@@ -433,6 +491,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -446,6 +_,11 @@
&& !itemEntity.getItem().isEmpty()
&& !itemEntity.hasPickUpDelay()
&& this.wantsToPickUp(serverLevel, itemEntity.getItem())) {
@@ -137,7 +129,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
this.pickUpItem(serverLevel, itemEntity);
}
}
@@ -447,18 +510,24 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -460,18 +_,24 @@
protected void pickUpItem(ServerLevel level, ItemEntity entity) {
ItemStack item = entity.getItem();
@@ -164,7 +156,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
EquipmentSlot equipmentSlotForItem = this.getEquipmentSlotForItem(stack);
if (!this.isEquippableInSlot(stack, equipmentSlotForItem)) {
return ItemStack.EMPTY;
@@ -471,10 +540,18 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -484,10 +_,18 @@
canReplaceCurrentItem = itemBySlot.isEmpty();
}
@@ -184,7 +176,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
ItemStack itemStack = equipmentSlotForItem.limit(stack);
@@ -591,22 +668,29 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -608,22 +_,29 @@
@Override
public void checkDespawn() {
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
@@ -200,12 +192,6 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
- if (d > i && this.removeWhenFarAway(d)) {
- this.discard();
- }
-
- int noDespawnDistance = this.getType().getCategory().getNoDespawnDistance();
- int i1 = noDespawnDistance * noDespawnDistance;
- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d > i1 && this.removeWhenFarAway(d)) {
- this.discard();
- } else if (d < i1) {
+ // Paper start - Configurable despawn distances
+ 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;
@@ -218,7 +204,12 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
+ if (despawnRangePair.hard().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy) && this.removeWhenFarAway(distanceSquared)) {
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
+ }
+
- int noDespawnDistance = this.getType().getCategory().getNoDespawnDistance();
- int i1 = noDespawnDistance * noDespawnDistance;
- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d > i1 && this.removeWhenFarAway(d)) {
- this.discard();
- } else if (d < i1) {
+ if (despawnRangePair.soft().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy)) {
+ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && this.removeWhenFarAway(distanceSquared)) {
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
@@ -228,7 +219,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
this.noActionTime = 0;
}
}
@@ -618,6 +702,15 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -635,6 +_,15 @@
@Override
protected final void serverAiStep() {
this.noActionTime++;
@@ -244,7 +235,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("sensing");
this.sensing.tick();
@@ -793,14 +886,69 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -814,14 +_,69 @@
public boolean stillValid(Player player) {
return player.getVehicle() == Mob.this || player.canInteractWithEntity(Mob.this, 4.0);
}
@@ -314,7 +305,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
float f = this.dropChances.byEquipment(equipmentSlot);
if (f != 0.0F) {
@@ -820,7 +968,13 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -841,7 +_,13 @@
}
this.spawnAtLocation(level, itemBySlot);
@@ -328,7 +319,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
}
}
@@ -844,7 +998,9 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -865,7 +_,9 @@
set.add(equipmentSlot);
} else if (this.dropChances.isPreserved(equipmentSlot)) {
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
@@ -338,7 +329,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
}
}
@@ -1122,6 +1278,21 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -1147,6 +_,21 @@
public <T extends Mob> T convertTo(
EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion
) {
@@ -360,7 +351,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
if (this.isRemoved()) {
return null;
} else {
@@ -1130,13 +1301,23 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -1155,13 +_,23 @@
return null;
} else {
conversionParams.type().convert(this, mob, conversionParams);
@@ -387,7 +378,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
return mob;
@@ -1146,7 +1327,18 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -1171,7 +_,18 @@
@Nullable
public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.AfterConversion<T> afterConversion) {
@@ -407,7 +398,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
@Nullable
@@ -1182,7 +1374,17 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -1213,7 +_,17 @@
public boolean startRiding(Entity entity, boolean force) {
boolean flag = super.startRiding(entity, force);
if (flag && this.isLeashed()) {
@@ -426,7 +417,7 @@ index 5d5d2ad050e47c52eda5aa1a772a72a77bfe1858..8f5c377540f83911c8d245fb00569f08
}
return flag;
@@ -1270,7 +1472,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -1296,7 +_,7 @@
float knockback = this.getKnockback(source, damageSource);
if (knockback > 0.0F && source instanceof LivingEntity livingEntity) {
livingEntity.knockback(

View File

@@ -1,42 +1,15 @@
From 09671551669244ef4f259d8b27547e463d6795d4 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 15:37:42 +0200
Subject: [PATCH] paper File Patches
diff --git a/net/minecraft/world/entity/TamableAnimal.java b/net/minecraft/world/entity/TamableAnimal.java
index 925db6260a57d4a54294ef2d8d9a3c903ee04518..1cdebee93d6c7e08c1923beed426d17310208be8 100644
--- a/net/minecraft/world/entity/TamableAnimal.java
+++ b/net/minecraft/world/entity/TamableAnimal.java
@@ -77,7 +77,7 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
@@ -75,7 +_,7 @@
}
this.orderedToSit = compound.getBooleanOr("Sitting", false);
this.orderedToSit = input.getBooleanOr("Sitting", false);
- this.setInSittingPose(this.orderedToSit);
+ this.setInSittingPose(this.orderedToSit, false); // Paper - Add EntityToggleSitEvent
}
@Override
@@ -88,8 +88,16 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
@Override
public boolean handleLeashAtDistance(Entity leashHolder, float distance) {
if (this.isInSittingPose()) {
- if (distance > 10.0F) {
- this.dropLeash();
+ if (distance > (float) this.level().paperConfig().misc.maxLeashDistance.or(Leashable.LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
+ // Paper start - Expand EntityUnleashEvent
+ org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(this.getBukkitEntity(), org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.DISTANCE, true);
+ if (!event.callEvent()) return false;
+ if (event.isDropLeash()) {
+ this.dropLeash();
+ } else {
+ this.removeLeash();
+ }
+ // Paper end - Expand EntityUnleashEvent
}
return false;
@@ -148,6 +156,13 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
@@ -133,6 +_,13 @@
}
public void setInSittingPose(boolean sitting) {
@@ -50,7 +23,7 @@ index 925db6260a57d4a54294ef2d8d9a3c903ee04518..1cdebee93d6c7e08c1923beed426d173
byte b = this.entityData.get(DATA_FLAGS_ID);
if (sitting) {
this.entityData.set(DATA_FLAGS_ID, (byte)(b | 1));
@@ -230,7 +245,12 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
@@ -215,7 +_,12 @@
if (this.level() instanceof ServerLevel serverLevel
&& serverLevel.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES)
&& this.getOwner() instanceof ServerPlayer serverPlayer) {
@@ -64,7 +37,7 @@ index 925db6260a57d4a54294ef2d8d9a3c903ee04518..1cdebee93d6c7e08c1923beed426d173
}
super.die(cause);
@@ -273,7 +293,14 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
@@ -258,7 +_,14 @@
if (!this.canTeleportTo(new BlockPos(x, y, z))) {
return false;
} else {