More more more more more more more more patches

This commit is contained in:
Nassim Jahnke 2023-03-14 22:10:53 +01:00
parent 1295869b43
commit 18d51375b8
No known key found for this signature in database
GPG key ID: 6BE3B555EBC5982B
98 changed files with 232 additions and 307 deletions

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 15 Apr 2022 17:09:28 -0700
Subject: [PATCH] Fix slime spawners not spawning outside slime chunks
Fixes MC-50647 by just checking if the spawn type is a SPAWNER
and then bypassing the spawn check logic if on slimes if it is.
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
index 3da612821708f10f7f53b1c9e70adc649689529e..87c2e50c6f817d1a77e0cfd64366765b265f9ba0 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
@@ -322,6 +322,11 @@ public class Slime extends Mob implements Enemy {
public static boolean checkSlimeSpawnRules(EntityType<Slime> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (world.getDifficulty() != Difficulty.PEACEFUL) {
+ // Paper start - fix slime spawners; Fixes MC-50647
+ if (spawnReason == MobSpawnType.SPAWNER) {
+ return random.nextInt(10) == 0;
+ }
+ // Paper end
// Paper start - Replace rules for Height in Swamp Biome
final double maxHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.maximum;
final double minHeightSwamp = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.surfaceBiome.minimum;

View file

@ -1,181 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 27 Mar 2022 13:51:09 -0400
Subject: [PATCH] Pass ServerLevel for gamerule callbacks
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 5b46cabf4f2e2a1f7feaad378dd98d64aeef8671..51b3db0b6c2cede95b584268e035c0fb36d38094 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -304,7 +304,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
//DedicatedServer.LOGGER.info("Done ({})! For help, type \"help\"", s); // Paper moved to after init
if (dedicatedserverproperties.announcePlayerAchievements != null) {
- ((GameRules.BooleanValue) this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)).set(dedicatedserverproperties.announcePlayerAchievements, this);
+ ((GameRules.BooleanValue) this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)).set(dedicatedserverproperties.announcePlayerAchievements, null); // Paper
}
if (dedicatedserverproperties.enableQuery) {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 5a9be5839b1e93b18408bb6b29306b8b39b302c9..3d4ad106222d0bc365c3207e5b414539ffc861ec 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2877,7 +2877,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
this.player = this.server.getPlayerList().respawn(this.player, false);
if (this.server.isHardcore()) {
this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper
- ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server);
+ ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.player.getLevel()); // Paper
}
}
break;
diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java
index fa8cd4438c19a262272da47985a57f7e84654f1b..663c1d8c1611af915a1bae733920dd75ad73feb1 100644
--- a/src/main/java/net/minecraft/world/level/GameRules.java
+++ b/src/main/java/net/minecraft/world/level/GameRules.java
@@ -51,7 +51,7 @@ public class GameRules {
public static final GameRules.Key<GameRules.BooleanValue> RULE_SENDCOMMANDFEEDBACK = GameRules.register("sendCommandFeedback", GameRules.Category.CHAT, GameRules.BooleanValue.create(true));
public static final GameRules.Key<GameRules.BooleanValue> RULE_REDUCEDDEBUGINFO = GameRules.register("reducedDebugInfo", GameRules.Category.MISC, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> {
int i = gamerules_gameruleboolean.get() ? 22 : 23;
- Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator();
+ Iterator iterator = minecraftserver.players().iterator(); // Paper
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
@@ -71,7 +71,7 @@ public class GameRules {
public static final GameRules.Key<GameRules.BooleanValue> RULE_DISABLE_RAIDS = GameRules.register("disableRaids", GameRules.Category.MOBS, GameRules.BooleanValue.create(false));
public static final GameRules.Key<GameRules.BooleanValue> RULE_DOINSOMNIA = GameRules.register("doInsomnia", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true));
public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_IMMEDIATE_RESPAWN = GameRules.register("doImmediateRespawn", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> {
- Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator();
+ Iterator iterator = minecraftserver.players().iterator(); // Paper
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
@@ -164,13 +164,13 @@ public class GameRules {
((GameRules.Type<T>) type).callVisitor(consumer, (GameRules.Key<T>) key); // CraftBukkit - decompile error
}
- public void assignFrom(GameRules rules, @Nullable MinecraftServer server) {
+ public void assignFrom(GameRules rules, @Nullable net.minecraft.server.level.ServerLevel server) { // Paper
rules.rules.keySet().forEach((gamerules_gamerulekey) -> {
this.assignCap(gamerules_gamerulekey, rules, server);
});
}
- private <T extends GameRules.Value<T>> void assignCap(GameRules.Key<T> key, GameRules rules, @Nullable MinecraftServer server) {
+ private <T extends GameRules.Value<T>> void assignCap(GameRules.Key<T> key, GameRules rules, @Nullable net.minecraft.server.level.ServerLevel server) { // Paper
T t0 = rules.getRule(key);
this.getRule(key).setFrom(t0, server);
@@ -238,10 +238,10 @@ public class GameRules {
private final Supplier<ArgumentType<?>> argument;
private final Function<GameRules.Type<T>, T> constructor;
- final BiConsumer<MinecraftServer, T> callback;
+ final BiConsumer<net.minecraft.server.level.ServerLevel, T> callback; // Paper
private final GameRules.VisitorCaller<T> visitorCaller;
- Type(Supplier<ArgumentType<?>> argumentType, Function<GameRules.Type<T>, T> ruleFactory, BiConsumer<MinecraftServer, T> changeCallback, GameRules.VisitorCaller<T> ruleAcceptor) {
+ Type(Supplier<ArgumentType<?>> argumentType, Function<GameRules.Type<T>, T> ruleFactory, BiConsumer<net.minecraft.server.level.ServerLevel, T> changeCallback, GameRules.VisitorCaller<T> ruleAcceptor) { // Paper
this.argument = argumentType;
this.constructor = ruleFactory;
this.callback = changeCallback;
@@ -273,10 +273,10 @@ public class GameRules {
public void setFromArgument(CommandContext<CommandSourceStack> context, String name, GameRules.Key<T> gameRuleKey) { // Paper
this.updateFromArgument(context, name, gameRuleKey); // Paper
- this.onChanged(((CommandSourceStack) context.getSource()).getServer());
+ this.onChanged(((CommandSourceStack) context.getSource()).getLevel()); // Paper
}
- public void onChanged(@Nullable MinecraftServer server) {
+ public void onChanged(@Nullable net.minecraft.server.level.ServerLevel server) { // Paper
if (server != null) {
this.type.callback.accept(server, this.getSelf());
}
@@ -297,7 +297,7 @@ public class GameRules {
protected abstract T copy();
- public abstract void setFrom(T rule, @Nullable MinecraftServer server);
+ public abstract void setFrom(T rule, @Nullable net.minecraft.server.level.ServerLevel level); // Paper
}
public interface GameRuleTypeVisitor {
@@ -313,7 +313,7 @@ public class GameRules {
private boolean value;
- static GameRules.Type<GameRules.BooleanValue> create(boolean initialValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changeCallback) {
+ static GameRules.Type<GameRules.BooleanValue> create(boolean initialValue, BiConsumer<net.minecraft.server.level.ServerLevel, GameRules.BooleanValue> changeCallback) { // Paper
return new GameRules.Type<>(BoolArgumentType::bool, (gamerules_gameruledefinition) -> {
return new GameRules.BooleanValue(gamerules_gameruledefinition, initialValue);
}, changeCallback, GameRules.GameRuleTypeVisitor::visitBoolean);
@@ -341,7 +341,7 @@ public class GameRules {
return this.value;
}
- public void set(boolean value, @Nullable MinecraftServer server) {
+ public void set(boolean value, @Nullable net.minecraft.server.level.ServerLevel server) { // Paper
this.value = value;
this.onChanged(server);
}
@@ -371,7 +371,7 @@ public class GameRules {
return new GameRules.BooleanValue(this.type, this.value);
}
- public void setFrom(GameRules.BooleanValue rule, @Nullable MinecraftServer server) {
+ public void setFrom(GameRules.BooleanValue rule, @Nullable net.minecraft.server.level.ServerLevel server) { // Paper
this.value = rule.value;
this.onChanged(server);
}
@@ -381,7 +381,7 @@ public class GameRules {
private int value;
- private static GameRules.Type<GameRules.IntegerValue> create(int initialValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changeCallback) {
+ private static GameRules.Type<GameRules.IntegerValue> create(int initialValue, BiConsumer<net.minecraft.server.level.ServerLevel, GameRules.IntegerValue> changeCallback) { // Paper
return new GameRules.Type<>(IntegerArgumentType::integer, (gamerules_gameruledefinition) -> {
return new GameRules.IntegerValue(gamerules_gameruledefinition, initialValue);
}, changeCallback, GameRules.GameRuleTypeVisitor::visitInteger);
@@ -409,7 +409,7 @@ public class GameRules {
return this.value;
}
- public void set(int value, @Nullable MinecraftServer server) {
+ public void set(int value, @Nullable net.minecraft.server.level.ServerLevel server) { // Paper
this.value = value;
this.onChanged(server);
}
@@ -460,7 +460,7 @@ public class GameRules {
return new GameRules.IntegerValue(this.type, this.value);
}
- public void setFrom(GameRules.IntegerValue rule, @Nullable MinecraftServer server) {
+ public void setFrom(GameRules.IntegerValue rule, @Nullable net.minecraft.server.level.ServerLevel server) { // Paper
this.value = rule.value;
this.onChanged(server);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 7aa3200ef7e8031b7adee71f37e43458cde4e353..e5bafab042767f483e09fa0d164f91e4a6f06160 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1914,7 +1914,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
// Paper end
GameRules.Value<?> handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule));
handle.deserialize(event.getValue()); // Paper
- handle.onChanged(this.getHandle().getServer());
+ handle.onChanged(this.getHandle()); // Paper
return true;
}
@@ -1954,7 +1954,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
// Paper end
GameRules.Value<?> handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule.getName()));
handle.deserialize(event.getValue()); // Paper
- handle.onChanged(this.getHandle().getServer());
+ handle.onChanged(this.getHandle()); // Paper
return true;
}

View file

@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HexedHero <6012891+HexedHero@users.noreply.github.com>
Date: Sun, 10 Apr 2022 06:26:32 +0100
Subject: [PATCH] Add pre-unbreaking amount to PlayerItemDamageEvent
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 1d52646d68ff05a597a41495f288471ce60b2d29..31eed67d07097c7eb1b06547a9f556bcc709d96c 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -572,10 +572,11 @@ public final class ItemStack {
}
}
+ int originalDamage = amount; // Paper
amount -= k;
// CraftBukkit start
if (player instanceof ServerPlayer serverPlayer) { // Paper
- PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount); // Paper
+ PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount, originalDamage); // Paper
event.getPlayer().getServer().getPluginManager().callEvent(event);
if (amount != event.getDamage() || event.isCancelled()) {

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sat, 3 Jul 2021 21:18:28 +0100
Subject: [PATCH] WorldCreator#keepSpawnLoaded
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 3448954294e6c47e71172d616d955c0412fd0e19..70e289c98cf39c5c6eeb7fb8b250be6e5bb52b8b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1258,6 +1258,7 @@ public final class CraftServer implements Server {
internal.setSpawnSettings(true, true);
// Paper - move up
+ internal.keepSpawnInMemory = creator.keepSpawnLoaded().toBooleanOrElse(internal.getWorld().getKeepSpawnInMemory()); // Paper
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
//internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - rewrite chunk system

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 27 Mar 2022 16:00:28 -0700
Subject: [PATCH] Fix NPE for BlockDataMeta#getBlockData
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 34f27913dc80915135bb476447dcbff9b32e302c..58c1d07f41fc382b23df17739090f5031fd41aad 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -1094,7 +1094,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
@Override
public BlockData getBlockData(Material material) {
- return CraftBlockData.fromData(BlockItem.getBlockState(CraftMagicNumbers.getBlock(material).defaultBlockState(), blockData));
+ // Paper start - fix NPE if this.blockData is null
+ final net.minecraft.world.level.block.state.BlockState defaultBlockState = CraftMagicNumbers.getBlock(material).defaultBlockState();
+ return CraftBlockData.fromData(this.blockData == null ? defaultBlockState : BlockItem.getBlockState(defaultBlockState, blockData));
+ // Paper end
}
@Override

View file

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 2 Feb 2022 13:50:06 -0800
Subject: [PATCH] Trigger bee_nest_destroyed trigger in the correct place
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 17c313b9cb45c8158cab751ffc4e0dc3b7e1fa3c..796d17f51496974cfdfed2593753b8c09b5c81c1 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -419,12 +419,16 @@ public class ServerPlayerGameMode {
block.destroy(this.level, pos, iblockdata);
}
+ ItemStack mainHandStack = null; // Paper
+ boolean isCorrectTool = false; // Paper
if (this.isCreative()) {
// return true; // CraftBukkit
} else {
ItemStack itemstack = this.player.getMainHandItem();
ItemStack itemstack1 = itemstack.copy();
boolean flag1 = this.player.hasCorrectToolForDrops(iblockdata);
+ mainHandStack = itemstack1; // Paper
+ isCorrectTool = flag1; // Paper
itemstack.mineBlock(this.level, iblockdata, pos, this.player);
if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
@@ -445,6 +449,13 @@ public class ServerPlayerGameMode {
if (flag && event != null) {
iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper
}
+ // Paper start - trigger after items are dropped (check impls of block#playerDestroy)
+ if (mainHandStack != null) {
+ if (flag && isCorrectTool && event.isDropItems() && block instanceof net.minecraft.world.level.block.BeehiveBlock && tileentity instanceof net.minecraft.world.level.block.entity.BeehiveBlockEntity beehiveBlockEntity) { // simulates the guard on block#playerDestroy above
+ CriteriaTriggers.BEE_NEST_DESTROYED.trigger(player, iblockdata, mainHandStack, beehiveBlockEntity.getOccupantCount());
+ }
+ }
+ // Paper end
return true;
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
index 81048c54c45b77894ee1e2045870446dff7c71d4..fe7daa57119af137eeb76ca2c0e54bf7903ebbca 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -88,7 +88,7 @@ public class BeehiveBlock extends BaseEntityBlock {
this.angerNearbyBees(world, pos);
}
- CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, state, stack, tileentitybeehive.getOccupantCount());
+ // CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, state, stack, tileentitybeehive.getOccupantCount()); // Paper - moved until after items are dropped
}
}

View file

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 18 Mar 2022 21:15:55 -0700
Subject: [PATCH] Add EntityDyeEvent and CollarColorable interface
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java
index 366f32b11f39a79210532c614fdbb2230b87d88f..a0dd4a58937a4e49e430d8c1470fe84b709e8044 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Cat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java
@@ -404,6 +404,13 @@ public class Cat extends TamableAnimal implements VariantHolder<CatVariant> {
DyeColor enumcolor = ((DyeItem) item).getDyeColor();
if (enumcolor != this.getCollarColor()) {
+ // Paper start
+ final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) enumcolor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
+ if (!event.callEvent()) {
+ return InteractionResult.FAIL;
+ }
+ enumcolor = DyeColor.byId(event.getColor().getWoolData());
+ // Paper end
this.setCollarColor(enumcolor);
if (!player.getAbilities().instabuild) {
itemstack.shrink(1);
diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java
index c44bbdea03856ac3a7652674263d1ec78ed02473..a6a50eb4f4ac85751071571876ac804d44ee1ee6 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java
@@ -392,6 +392,13 @@ public class Wolf extends TamableAnimal implements NeutralMob {
DyeColor enumcolor = ((DyeItem) item).getDyeColor();
if (enumcolor != this.getCollarColor()) {
+ // Paper start
+ final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) enumcolor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
+ if (!event.callEvent()) {
+ return InteractionResult.FAIL;
+ }
+ enumcolor = DyeColor.byId(event.getColor().getWoolData());
+ // Paper end
this.setCollarColor(enumcolor);
if (!player.getAbilities().instabuild) {
itemstack.shrink(1);

View file

@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 29 Mar 2022 13:46:23 -0700
Subject: [PATCH] Fire CauldronLevelChange on initial fill
Also don't fire level events or game events if stalactite
drip is cancelled
diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
index 53089c3a36bf2c0ec1bc9b436884deff0c30f028..2f85b893dd0abc39fcedec65acc89e1567faf6f0 100644
--- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
@@ -36,10 +36,18 @@ public class CauldronBlock extends AbstractCauldronBlock {
public void handlePrecipitation(BlockState state, Level world, BlockPos pos, Biome.Precipitation precipitation) {
if (CauldronBlock.shouldHandlePrecipitation(world, precipitation)) {
if (precipitation == Biome.Precipitation.RAIN) {
- world.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState());
+ // Paper start - call event for initial fill
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, Blocks.WATER_CAULDRON.defaultBlockState(), null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL, false)) { // avoid duplicate game event
+ return;
+ }
+ // Paper end
world.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, pos);
} else if (precipitation == Biome.Precipitation.SNOW) {
- world.setBlockAndUpdate(pos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState());
+ // Paper start - call event for initial fill
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState(), null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL, false)) { // avoid duplicate game event
+ return;
+ }
+ // Paper end
world.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, pos);
}
@@ -57,11 +65,19 @@ public class CauldronBlock extends AbstractCauldronBlock {
if (fluid == Fluids.WATER) {
iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState();
- LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit
+ // Paper start - don't send level event or game event if cancelled
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { // CraftBukkit
+ return;
+ }
+ // Paper end
world.levelEvent(1047, pos, 0);
} else if (fluid == Fluids.LAVA) {
iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState();
- LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit
+ // Paper start - don't send level event or game event if cancelled
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { // CraftBukkit
+ return;
+ }
+ // Paper end
world.levelEvent(1046, pos, 0);
}
diff --git a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
index 24d2da792bc498adf4251555a538df4cafe2e827..14164aa59fa5e315788cd7a207228081a05fd18f 100644
--- a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
@@ -91,7 +91,13 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock {
}
// CraftBukkit start
- public static boolean changeLevel(BlockState iblockdata, Level world, BlockPos blockposition, BlockState newBlock, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) {
+ // Paper start
+ public static boolean changeLevel(BlockState iblockdata, Level world, BlockPos blockposition, BlockState newBlock, @javax.annotation.Nullable Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { // Paper - entity is nullable
+ return changeLevel(iblockdata, world, blockposition, newBlock, entity, reason, true);
+ }
+
+ public static boolean changeLevel(BlockState iblockdata, Level world, BlockPos blockposition, BlockState newBlock, @javax.annotation.Nullable Entity entity, CauldronLevelChangeEvent.ChangeReason reason, boolean sendGameEvent) { // Paper - entity is nullable
+ // Paper end
CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition);
newState.setData(newBlock);
@@ -104,7 +110,7 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock {
return false;
}
newState.update(true);
- world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock));
+ if (sendGameEvent) world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock)); // Paper
return true;
}
// CraftBukkit end

View file

@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 30 Dec 2021 14:02:13 -0800
Subject: [PATCH] fix powder snow cauldrons not turning to water
Powder snow cauldrons should turn to water when
extinguishing an entity
diff --git a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
index 14164aa59fa5e315788cd7a207228081a05fd18f..2932419b7ca3f066b1db329829af36ba31e17c65 100644
--- a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
@@ -64,7 +64,7 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock {
if (!world.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) {
// CraftBukkit start
if (entity.mayInteract(world, pos)) {
- if (!LayeredCauldronBlock.lowerFillLevel(state, world, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH)) {
+ if (!this.handleEntityOnFireInsideWithEvent(state, world, pos, entity)) { // Paper - fix powdered snow cauldron extinguishing entities
return;
}
}
@@ -74,9 +74,15 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock {
}
+ @Deprecated // Paper - use #handleEntityOnFireInsideWithEvent
protected void handleEntityOnFireInside(BlockState state, Level world, BlockPos pos) {
LayeredCauldronBlock.lowerFillLevel(state, world, pos);
}
+ // Paper start
+ protected boolean handleEntityOnFireInsideWithEvent(BlockState state, Level world, BlockPos pos, Entity entity) {
+ return LayeredCauldronBlock.lowerFillLevel(state, world, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH);
+ }
+ // Paper end
public static void lowerFillLevel(BlockState state, Level world, BlockPos pos) {
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/level/block/PowderSnowCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/PowderSnowCauldronBlock.java
index 54c8f2ccadd685b43d7ee032a95bfcf193357ce9..7f6b240bbbb773ca49e0e6290169cc81f5529af5 100644
--- a/src/main/java/net/minecraft/world/level/block/PowderSnowCauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PowderSnowCauldronBlock.java
@@ -16,7 +16,14 @@ public class PowderSnowCauldronBlock extends LayeredCauldronBlock {
}
@Override
+ @Deprecated // Paper - use #handleEntityOnFireInsideWithEvent
protected void handleEntityOnFireInside(BlockState state, Level world, BlockPos pos) {
lowerFillLevel(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LEVEL, state.getValue(LEVEL)), world, pos);
}
+ // Paper - replace powdered snow with water (taken from #handleEntityOnFireInside)
+ @Override
+ protected boolean handleEntityOnFireInsideWithEvent(BlockState state, Level world, BlockPos pos, net.minecraft.world.entity.Entity entity) {
+ return super.handleEntityOnFireInsideWithEvent(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LEVEL, state.getValue(LEVEL)), world, pos, entity);
+ }
+ // Paper end
}

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: u9g <git@u9g.dev>
Date: Tue, 3 May 2022 20:41:37 -0400
Subject: [PATCH] Add PlayerStopUsingItemEvent
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 13ff58b76d7c1c02921ee3266a67f7c5befef30e..98dac3d0288902265beb07ff17c5ae1bebeb2cfc 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3974,6 +3974,7 @@ public abstract class LivingEntity extends Entity {
public void releaseUsingItem() {
if (!this.useItem.isEmpty()) {
+ if (this instanceof ServerPlayer) new io.papermc.paper.event.player.PlayerStopUsingItemEvent((Player) getBukkitEntity(), useItem.asBukkitMirror(), getTicksUsingItem()).callEvent(); // Paper
this.useItem.releaseUsing(this.level, this, this.getUseItemRemainingTicks());
if (this.useItem.useOnRelease()) {
this.updatingUsingItem();

View file

@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 5 Dec 2021 14:58:17 -0500
Subject: [PATCH] FallingBlock auto expire setting
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index 06f6fe4d1be4b14c45d2576561201c9386988dc1..eacb8a407fe99af2c13f23c12b5544696bda8890 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -63,6 +63,7 @@ public class FallingBlockEntity extends Entity {
@Nullable
public CompoundTag blockData;
protected static final EntityDataAccessor<BlockPos> DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
+ public boolean autoExpire = true; // Paper - Auto expire setting
public FallingBlockEntity(EntityType<? extends FallingBlockEntity> type, Level world) {
super(type, world);
@@ -177,7 +178,7 @@ public class FallingBlockEntity extends Entity {
}
if (!this.onGround && !flag1) {
- if (!this.level.isClientSide && (this.time > 100 && (blockposition.getY() <= this.level.getMinBuildHeight() || blockposition.getY() > this.level.getMaxBuildHeight()) || this.time > 600)) {
+ if (!this.level.isClientSide && ((this.time > 100 && autoExpire) && (blockposition.getY() <= this.level.getMinBuildHeight() || blockposition.getY() > this.level.getMaxBuildHeight()) || (this.time > 600 && autoExpire))) { // Paper - Auto expire setting
if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
this.spawnAtLocation((ItemLike) block);
}
@@ -323,6 +324,7 @@ public class FallingBlockEntity extends Entity {
if (this.blockData != null) {
nbt.put("TileEntityData", this.blockData);
}
+ if (!autoExpire) {nbt.putBoolean("Paper.AutoExpire", false);} // Paper - AutoExpire setting
}
@@ -357,6 +359,10 @@ public class FallingBlockEntity extends Entity {
int srcZ = nbt.getInt("SourceLoc_z");
this.setOrigin(new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ));
}
+
+ if (nbt.contains("Paper.AutoExpire")) {
+ this.autoExpire = nbt.getBoolean("Paper.AutoExpire");
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java
index 0de415236fe9997fc3ffedba20b8df68647cb822..87c413c2f3b59ae9ef36e5becc10b29a81348022 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java
@@ -58,6 +58,17 @@ public class CraftFallingBlock extends CraftEntity implements FallingBlock {
public void setHurtEntities(boolean hurtEntities) {
this.getHandle().hurtEntities = hurtEntities;
}
+ // Paper Start - Auto expire setting
+ @Override
+ public boolean doesAutoExpire() {
+ return this.getHandle().autoExpire;
+ }
+
+ @Override
+ public void shouldAutoExpire(boolean autoExpires) {
+ this.getHandle().autoExpire = autoExpires;
+ }
+ // Paper End - Auto expire setting
@Override
public void setTicksLived(int value) {

View file

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Fri, 7 Jan 2022 11:58:26 +0100
Subject: [PATCH] Don't tick markers
Fixes https://github.com/PaperMC/Paper/issues/7276 by not adding markers to the entity
tick list at all and ignoring them in Spigot's activation range checks. The entity tick
list is only used in the tick and tickPassenger methods, so we can safely not add the
markers to it.
diff --git a/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java b/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java
index ff99336e0b8131ae161cfa5c4fc83c6905e3dbc8..4ec1e8ded06c60d81446c67bba2aa8a04111fa9b 100644
--- a/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java
+++ b/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java
@@ -109,7 +109,7 @@ public final class EntityCommand implements PaperSubcommand {
ChunkPos chunk = e.chunkPosition();
info.left++;
info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1);
- if (!chunkProviderServer.isPositionTicking(e)) {
+ if (!chunkProviderServer.isPositionTicking(e) || e instanceof net.minecraft.world.entity.Marker) { // Markers aren't ticked.
nonEntityTicking.merge(key, 1, Integer::sum);
}
});
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 6b17c008926287f2c9f828ba656c3a77aef0fb2c..a81eaee4339d7f4b0bf94c012cdbf8f4fa2f78f8 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2498,6 +2498,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
public void onTickingStart(Entity entity) {
+ if (entity instanceof net.minecraft.world.entity.Marker) return; // Paper - Don't tick markers
ServerLevel.this.entityTickList.add(entity);
}
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index f158fc8a151272428a33dc5f6e1742876edc80d5..e881584d38dc354204479863f004e974a0ac6c07 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -212,7 +212,7 @@ public class ActivationRange
// Paper end
// Paper start
- java.util.List<Entity> entities = world.getEntities((Entity)null, maxBB, null);
+ java.util.List<Entity> entities = world.getEntities((Entity)null, maxBB, (e) -> !(e instanceof net.minecraft.world.entity.Marker)); // Don't tick markers
for (int i = 0; i < entities.size(); i++) {
Entity entity = entities.get(i);
ActivationRange.activateEntity(entity);

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 7 May 2022 14:58:53 -0700
Subject: [PATCH] Do not accept invalid client settings
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 3d4ad106222d0bc365c3207e5b414539ffc861ec..9834ee213dcffc35aba1df8d3f9f00a9bbfc1b45 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3465,6 +3465,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@Override
public void handleClientInformation(ServerboundClientInformationPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
+ // Paper start - do not accept invalid information
+ if (packet.viewDistance() < 0) {
+ LOGGER.warn("Disconnecting " + this.player.getScoreboardName() + " for invalid view distance: " + packet.viewDistance());
+ this.disconnect("Invalid client settings", PlayerKickEvent.Cause.ILLEGAL_ACTION);
+ return;
+ }
+ // Paper end - do not accept invalid information
this.player.updateOptions(packet);
}

View file

@ -1,66 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: PanSzelescik <panszelescik@gmail.com>
Date: Thu, 7 Apr 2022 16:13:39 +0200
Subject: [PATCH] Add support for Proxy Protocol
diff --git a/build.gradle.kts b/build.gradle.kts
index dc61ebe468740b0b9359bf6e3a6050726136941c..1919a8e9cb7c995b2a9c876ff4980bdc98977133 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -20,6 +20,7 @@ dependencies {
*/
implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation
annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for our Log4j plugins
+ implementation("io.netty:netty-codec-haproxy:4.1.87.Final") // Paper - Add support for proxy protocol
// Paper end
implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion
implementation("org.ow2.asm:asm:9.4")
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
index cfdbcd024de6ad0f9d4e83b2f912b36ef3299458..abcc3266d18f34d160eac87fdea153dce24c60b8 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
@@ -111,6 +111,12 @@ public class ServerConnectionListener {
ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
// Paper end
+ // Paper start - indicate Proxy Protocol usage
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.proxyProtocol) {
+ ServerConnectionListener.LOGGER.info("Paper: Using Proxy Protocol");
+ }
+ // Paper end
+
this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) {
try {
@@ -124,6 +130,30 @@ public class ServerConnectionListener {
int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond();
Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND);
+ // Paper start - Add support for Proxy Protocol
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.proxyProtocol) {
+ channel.pipeline().addAfter("timeout", "haproxy-decoder", new io.netty.handler.codec.haproxy.HAProxyMessageDecoder());
+ channel.pipeline().addAfter("haproxy-decoder", "haproxy-handler", new ChannelInboundHandlerAdapter() {
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+ if (msg instanceof io.netty.handler.codec.haproxy.HAProxyMessage message) {
+ if (message.command() == io.netty.handler.codec.haproxy.HAProxyCommand.PROXY) {
+ String realaddress = message.sourceAddress();
+ int realport = message.sourcePort();
+
+ SocketAddress socketaddr = new java.net.InetSocketAddress(realaddress, realport);
+
+ Connection connection = (Connection) channel.pipeline().get("packet_handler");
+ connection.address = socketaddr;
+ }
+ } else {
+ super.channelRead(ctx, msg);
+ }
+ }
+ });
+ }
+ // Paper end
+
// ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error
pending.add((Connection) object); // Paper
channel.pipeline().addLast("packet_handler", (ChannelHandler) object);

View file

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 30 May 2022 16:03:36 -0700
Subject: [PATCH] Fix OfflinePlayer#getBedSpawnLocation
When calling getBedSpawnLocation on an
instance of CraftOfflinePlayer the world was incorrect
due to the logic for reading the NBT not being up-to-date.
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
index 17b3d5de58a9ef3acc67624c46cd6bbd96394f87..714afc98b5150907b45a00060be4e41582333204 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
@@ -31,6 +31,7 @@ import org.bukkit.profile.PlayerProfile;
@SerializableAs("Player")
public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializable {
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
private final GameProfile profile;
private final CraftServer server;
private final PlayerDataStorage storage;
@@ -319,11 +320,20 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
if (data == null) return null;
if (data.contains("SpawnX") && data.contains("SpawnY") && data.contains("SpawnZ")) {
- String spawnWorld = data.getString("SpawnWorld");
- if (spawnWorld.equals("")) {
- spawnWorld = this.server.getWorlds().get(0).getName();
+ // Paper start - fix wrong world
+ final float respawnAngle = data.getFloat("SpawnAngle");
+ org.bukkit.World spawnWorld = this.server.getWorld(data.getString("SpawnWorld")); // legacy
+ if (data.contains("SpawnDimension")) {
+ com.mojang.serialization.DataResult<net.minecraft.resources.ResourceKey<net.minecraft.world.level.Level>> result = net.minecraft.world.level.Level.RESOURCE_KEY_CODEC.parse(net.minecraft.nbt.NbtOps.INSTANCE, data.get("SpawnDimension"));
+ net.minecraft.resources.ResourceKey<net.minecraft.world.level.Level> levelKey = result.resultOrPartial(LOGGER::error).orElse(net.minecraft.world.level.Level.OVERWORLD);
+ net.minecraft.server.level.ServerLevel level = this.server.console.getLevel(levelKey);
+ spawnWorld = level != null ? level.getWorld() : spawnWorld;
}
- return new Location(this.server.getWorld(spawnWorld), data.getInt("SpawnX"), data.getInt("SpawnY"), data.getInt("SpawnZ"));
+ if (spawnWorld == null) {
+ return null;
+ }
+ return new Location(spawnWorld, data.getInt("SpawnX"), data.getInt("SpawnY"), data.getInt("SpawnZ"), respawnAngle, 0);
+ // Paper end
}
return null;
}

View file

@ -1,49 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 1 Jan 2022 23:11:26 -0800
Subject: [PATCH] Fix FurnaceInventory for smokers and blast furnaces
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
index 54e61b9b058bee2167461aaaf828ed7a00949c29..53421f780ac8bc2a67f64671fcad632fcdb8bede 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
@@ -65,7 +65,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
return new CraftInventory(tileEntity);
}
- public static class Furnace extends CraftTileInventoryConverter {
+ public static class Furnace extends AbstractFurnaceInventoryConverter { // Paper - Furnace, BlastFurnace, and Smoker are pretty much identical
@Override
public Container getTileEntity() {
@@ -73,6 +73,11 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
return furnace;
}
+ // Paper start - abstract furnace converter to apply to all 3 furnaces
+ }
+
+ public static abstract class AbstractFurnaceInventoryConverter extends CraftTileInventoryConverter {
+ // Paper end
// Paper start
@Override
public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
@@ -170,7 +175,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
}
}
- public static class BlastFurnace extends CraftTileInventoryConverter {
+ public static class BlastFurnace extends AbstractFurnaceInventoryConverter { // Paper - Furnace, BlastFurnace, and Smoker are pretty much identical
@Override
public Container getTileEntity() {
@@ -186,7 +191,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
}
}
- public static class Smoker extends CraftTileInventoryConverter {
+ public static class Smoker extends AbstractFurnaceInventoryConverter { // Paper - Furnace, BlastFurnace, and Smoker are pretty much identical
@Override
public Container getTileEntity() {

View file

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Fri, 3 Dec 2021 16:55:50 -0500
Subject: [PATCH] Sanitize Sent BlockEntity NBT
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket.java
index d79284a790569141c2ac8178d6ecc20b17cdd0d3..3944852921335c78a04a9dc301882ab5b152b1ed 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket.java
@@ -17,7 +17,7 @@ public class ClientboundBlockEntityDataPacket implements Packet<ClientGamePacket
private final CompoundTag tag;
public static ClientboundBlockEntityDataPacket create(BlockEntity blockEntity, Function<BlockEntity, CompoundTag> nbtGetter) {
- return new ClientboundBlockEntityDataPacket(blockEntity.getBlockPos(), blockEntity.getType(), nbtGetter.apply(blockEntity));
+ return new ClientboundBlockEntityDataPacket(blockEntity.getBlockPos(), blockEntity.getType(), blockEntity.sanitizeSentNbt(nbtGetter.apply(blockEntity))); // Paper - Sanitize sent data
}
public static ClientboundBlockEntityDataPacket create(BlockEntity blockEntity) {
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 40a42a632540d497c1393b112731c41c6e448228..f3fa2678796c33f3a408a02a1995ad117eac9169 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -183,6 +183,7 @@ public class ClientboundLevelChunkPacketData {
CompoundTag compoundTag = blockEntity.getUpdateTag();
BlockPos blockPos = blockEntity.getBlockPos();
int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());
+ blockEntity.sanitizeSentNbt(compoundTag); // Paper - Sanitize sent data
return new ClientboundLevelChunkPacketData.BlockEntityInfo(i, blockPos.getY(), blockEntity.getType(), compoundTag.isEmpty() ? null : compoundTag);
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
index 9b1e2af71728c1a0842c690cee01161342dc35f1..1b248db497500aa6bd346b306dcb908af77626f3 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -256,4 +256,12 @@ public abstract class BlockEntity {
return null;
}
// CraftBukkit end
+ // Paper start
+ public CompoundTag sanitizeSentNbt(CompoundTag tag) {
+ tag.remove("PublicBukkitValues");
+
+ return tag;
+ }
+ // Paper end
+
}

View file

@ -1,73 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 6 Mar 2022 11:09:09 -0500
Subject: [PATCH] Prevent entity loading causing async lookups
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 5597c0ff49179e4978b82d36d92ba96f147c590c..0e27a7b943a5e4d580fdbce4cd14d0528c808735 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -788,6 +788,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
public void baseTick() {
this.level.getProfiler().push("entityBaseTick");
+ if (firstTick && this instanceof net.minecraft.world.entity.NeutralMob neutralMob) neutralMob.tickInitialPersistentAnger(level); // Paper - Update last hurt when ticking
this.feetBlockState = null;
if (this.isPassenger() && this.getVehicle().isRemoved()) {
this.stopRiding();
diff --git a/src/main/java/net/minecraft/world/entity/NeutralMob.java b/src/main/java/net/minecraft/world/entity/NeutralMob.java
index dedf76de5d6f46b9626ca4a98cfffe125b90dd0c..7dac62b6370dae3ad6d098857c3136d5acf2bd74 100644
--- a/src/main/java/net/minecraft/world/entity/NeutralMob.java
+++ b/src/main/java/net/minecraft/world/entity/NeutralMob.java
@@ -42,18 +42,11 @@ public interface NeutralMob {
UUID uuid = nbt.getUUID("AngryAt");
this.setPersistentAngerTarget(uuid);
- Entity entity = ((ServerLevel) world).getEntity(uuid);
-
- if (entity != null) {
- if (entity instanceof Mob) {
- this.setLastHurtByMob((Mob) entity);
- }
-
- if (entity.getType() == EntityType.PLAYER) {
- this.setLastHurtByPlayer((Player) entity);
- }
-
- }
+ // Paper - Moved diff to separate method
+ // If this entity already survived its first tick, e.g. is loaded and ticked in sync, actively
+ // tick the initial persistent anger.
+ // If not, let the first tick on the baseTick call the method later down the line.
+ if (this instanceof Entity entity && !entity.firstTick) this.tickInitialPersistentAnger(world);
}
}
}
@@ -127,4 +120,26 @@ public interface NeutralMob {
@Nullable
LivingEntity getTarget();
+
+ // Paper start - Update last hurt when ticking
+ default void tickInitialPersistentAnger(Level level) {
+ UUID target = getPersistentAngerTarget();
+ if (target == null) {
+ return;
+ }
+
+ Entity entity = ((ServerLevel) level).getEntity(target);
+
+ if (entity != null) {
+ if (entity instanceof Mob) {
+ this.setLastHurtByMob((Mob) entity);
+ }
+
+ if (entity.getType() == EntityType.PLAYER) {
+ this.setLastHurtByPlayer((Player) entity);
+ }
+
+ }
+ }
+ // Paper end
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Thu, 2 Jun 2022 20:35:58 +0200
Subject: [PATCH] Disable component selector resolving in books by default
diff --git a/src/main/java/net/minecraft/world/item/WrittenBookItem.java b/src/main/java/net/minecraft/world/item/WrittenBookItem.java
index a324df312d9bb87d9e0962f8028d900933e70c07..31911c09fe15753ae32fa39417bdc9e9de552a88 100644
--- a/src/main/java/net/minecraft/world/item/WrittenBookItem.java
+++ b/src/main/java/net/minecraft/world/item/WrittenBookItem.java
@@ -111,7 +111,7 @@ public class WrittenBookItem extends Item {
public static boolean resolveBookComponents(ItemStack book, @Nullable CommandSourceStack commandSource, @Nullable Player player) {
CompoundTag compoundTag = book.getTag();
- if (compoundTag != null && !compoundTag.getBoolean("resolved")) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.resolveSelectorsInBooks && compoundTag != null && !compoundTag.getBoolean("resolved")) { // Paper
compoundTag.putBoolean("resolved", true);
if (!makeSureTagIsValid(compoundTag)) {
return false;

View file

@ -1,78 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 22 Mar 2022 12:44:30 -0700
Subject: [PATCH] Throw exception on world create while being ticked
There are no plans to support creating worlds while worlds are
being ticked themselvess.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0d027c99eaa049d7e99c50df10e2131eaa8bafee..1b56bb2869d3cf22670b508133968e66493a5bec 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -308,6 +308,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public volatile Thread shutdownThread; // Paper
public volatile boolean abnormalExit = false; // Paper
+ public boolean isIteratingOverLevels = false; // Paper
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
AtomicReference<S> atomicreference = new AtomicReference();
@@ -1475,7 +1476,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getFunctions().tick();
MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper
this.profiler.popPush("levels");
- Iterator iterator = this.getAllLevels().iterator();
+ //Iterator iterator = this.getAllLevels().iterator(); // Paper - moved down
// CraftBukkit start
// Run tasks that are waiting on processing
@@ -1507,6 +1508,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end
MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper
+ this.isIteratingOverLevels = true; // Paper
+ Iterator iterator = this.getAllLevels().iterator(); // Paper - move down
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
@@ -1554,6 +1557,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.pop();
worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
}
+ this.isIteratingOverLevels = false; // Paper
this.profiler.popPush("connection");
MinecraftTimings.connectionTimer.startTiming(); // Spigot
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 70e289c98cf39c5c6eeb7fb8b250be6e5bb52b8b..c51f9a26c6a41158ebdc83adfb495a5412a1197b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -850,6 +850,11 @@ public final class CraftServer implements Server {
return new ArrayList<World>(this.worlds.values());
}
+ @Override
+ public boolean isTickingWorlds() {
+ return console.isIteratingOverLevels;
+ }
+
public DedicatedPlayerList getHandle() {
return this.playerList;
}
@@ -1135,6 +1140,7 @@ public final class CraftServer implements Server {
@Override
public World createWorld(WorldCreator creator) {
Preconditions.checkState(this.console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP");
+ //Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot create a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes.
Validate.notNull(creator, "Creator may not be null");
String name = creator.name();
@@ -1273,6 +1279,7 @@ public final class CraftServer implements Server {
@Override
public boolean unloadWorld(World world, boolean save) {
+ //Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot unload a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes.
if (world == null) {
return false;
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Wed, 8 Jun 2022 11:04:47 -0400
Subject: [PATCH] Dont resent entity on art update
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java
index 1d54465f1835f5e419899a7585d3dec920e1a73b..b7610e880e857058b621228583c841b5d9338fc7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java
@@ -38,7 +38,7 @@ public class CraftPainting extends CraftHanging implements Painting {
painting.setDirection(painting.getDirection());
return false;
}
- this.update();
+ //this.update(); Paper - Don't resent entity on art update
return true;
}

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: nopjar <code.nopjar@gmail.com>
Date: Sun, 12 Jun 2022 02:26:04 +0200
Subject: [PATCH] Add WardenAngerChangeEvent
diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/AngerManagement.java b/src/main/java/net/minecraft/world/entity/monster/warden/AngerManagement.java
index 02abc5f387d781094bd2f39233444add3a470be1..ece82743df21f0b776382821ad75dee96d0a0748 100644
--- a/src/main/java/net/minecraft/world/entity/monster/warden/AngerManagement.java
+++ b/src/main/java/net/minecraft/world/entity/monster/warden/AngerManagement.java
@@ -146,7 +146,7 @@ public class AngerManagement {
public int increaseAnger(Entity entity, int amount) {
boolean bl = !this.angerBySuspect.containsKey(entity);
int i = this.angerBySuspect.computeInt(entity, (suspect, anger) -> {
- return Math.min(150, (anger == null ? 0 : anger) + amount);
+ return Math.min(150, (anger == null ? 0 : anger) + amount); // Paper - diff on change
});
if (bl) {
int j = this.angerByUuid.removeInt(entity.getUUID());
diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
index 9fb1bfc394362108aa5ae0d7ec9feeda7753abfb..1ae7408048f951cb94d7cfbea60efc5567b1af84 100644
--- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
+++ b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
@@ -495,6 +495,15 @@ public class Warden extends Monster implements VibrationListener.VibrationListen
@VisibleForTesting
public void increaseAngerAt(@Nullable Entity entity, int amount, boolean listening) {
if (!this.isNoAi() && this.canTargetEntity(entity)) {
+ // Paper start
+ int activeAnger = this.angerManagement.getActiveAnger(entity);
+ io.papermc.paper.event.entity.WardenAngerChangeEvent event = new io.papermc.paper.event.entity.WardenAngerChangeEvent((org.bukkit.entity.Warden) this.getBukkitEntity(), entity.getBukkitEntity(), activeAnger, Math.min(150, activeAnger + amount));
+ this.level.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
+ }
+ amount = event.getNewAnger() - activeAnger;
+ // Paper end
WardenAi.setDigCooldown(this);
boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player); // CraftBukkit - decompile error
int j = this.angerManagement.increaseAnger(entity, amount);

View file

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 12 Jun 2022 11:47:24 -0700
Subject: [PATCH] Add option for strict advancement dimension checks
Craftbukkit attempts to translate worlds that use the
same generation as the Overworld, The Nether, or The End
to use those dimensions when checking the `changed_dimension`
criteria trigger, or whether to trigger the `NETHER_TRAVEL`
distance trigger. This adds a config option to ignore that
and use the exact dimension key of the worlds involved.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index f01586da79b5e3965d90ed143204f9636d35ecaa..c7b030ee8973e9e7fdc3ed584229d049d5afe134 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1258,6 +1258,12 @@ public class ServerPlayer extends Player {
// CraftBukkit start
ResourceKey<Level> maindimensionkey = CraftDimensionUtil.getMainDimensionKey(origin);
ResourceKey<Level> maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level);
+ // Paper start - config for strict advancement checks for dimensions
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.strictAdvancementDimensionCheck) {
+ maindimensionkey = resourcekey;
+ maindimensionkey1 = resourcekey1;
+ }
+ // Paper end
CriteriaTriggers.CHANGED_DIMENSION.trigger(this, maindimensionkey, maindimensionkey1);
if (maindimensionkey != resourcekey || maindimensionkey1 != resourcekey1) {

View file

@ -1,71 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 12 Jun 2022 13:25:52 -0400
Subject: [PATCH] Add missing important BlockStateListPopulator methods
Without these methods it causes exceptions due to these being used by certain feature generators.
diff --git a/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java b/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java
index 4bd59614606962a5371fd0da54bde25bf6a01325..602ce766f00dfde057c735eae3351068d09feab1 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java
@@ -128,7 +128,7 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
@Override
public boolean isFluidAtPosition(BlockPos pos, Predicate<FluidState> state) {
- return this.world.isFluidAtPosition(pos, state);
+ return state.test(this.getFluidState(pos)); // Paper - fix
}
@Override
@@ -140,4 +140,28 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
public RegistryAccess registryAccess() {
return this.world.registryAccess();
}
+
+ // Paper start
+ @Override
+ public <T extends BlockEntity> java.util.Optional<T> getBlockEntity(BlockPos pos, net.minecraft.world.level.block.entity.BlockEntityType<T> type) {
+ BlockEntity tileentity = this.getBlockEntity(pos);
+
+ return tileentity != null && tileentity.getType() == type ? (java.util.Optional<T>) java.util.Optional.of(tileentity) : java.util.Optional.empty();
+ }
+
+ @Override
+ public BlockPos getHeightmapPos(net.minecraft.world.level.levelgen.Heightmap.Types heightmap, BlockPos pos) {
+ return world.getHeightmapPos(heightmap, pos);
+ }
+
+ @Override
+ public int getHeight(net.minecraft.world.level.levelgen.Heightmap.Types heightmap, int x, int z) {
+ return world.getHeight(heightmap, x, z);
+ }
+
+ @Override
+ public net.minecraft.world.level.storage.LevelData getLevelData() {
+ return world.getLevelData();
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
index 57acc7195f83b23c9b84ec4b94e0d7ab22851604..b303eb2989be28dadf183d12a4bd706e43d1fa98 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
@@ -274,5 +274,17 @@ public class DummyGeneratorAccess implements WorldGenLevel {
@Override
public <T> void getEntitiesByClass(Class<? extends T> clazz, Entity except, AABB box, List<? super T> into, Predicate<? super T> predicate) {}
+
+ @Override
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay) {
+ }
+
+ @Override
+ public void scheduleTick(BlockPos pos, Block block, int delay, net.minecraft.world.ticks.TickPriority priority) {
+ }
+
+ @Override
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay, net.minecraft.world.ticks.TickPriority priority) {
+ }
// Paper end
}

View file

@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Thu, 7 Apr 2022 17:49:25 -0400
Subject: [PATCH] Nameable Banner API
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
index 85f7ed3041befcc37729e9cd25723644600c7f62..31d916bc2364d0c518652b5b5868ab3d45a77ccc 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
@@ -99,4 +99,25 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
}
banner.itemPatterns = newPatterns;
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component customName() {
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getSnapshot().getCustomName());
+ }
+
+ @Override
+ public void customName(net.kyori.adventure.text.Component customName) {
+ this.getSnapshot().setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(customName));
+ }
+
+ @Override
+ public String getCustomName() {
+ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serializeOrNull(this.customName());
+ }
+
+ @Override
+ public void setCustomName(String name) {
+ this.customName(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(name));
+ }
+ // Paper end
}

View file

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 16 Jun 2022 14:22:56 -0700
Subject: [PATCH] Don't broadcast messages to command blocks
Previously the broadcast method would update the last output
in command blocks, and if called asynchronously, would throw
an error
diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
index 7c7e5f3c0f9cd1f16192a8fc8163da9b2d9519d5..888936385196a178ab8b730fd5e4fff4a5466428 100644
--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
+++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
@@ -172,6 +172,7 @@ public abstract class BaseCommandBlock implements CommandSource {
@Override
public void sendSystemMessage(Component message) {
if (this.trackOutput) {
+ org.spigotmc.AsyncCatcher.catchOp("sendSystemMessage to a command block"); // Paper
SimpleDateFormat simpledateformat = BaseCommandBlock.TIME_FORMAT;
Date date = new Date();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index c51f9a26c6a41158ebdc83adfb495a5412a1197b..52dec44a061b773c4467279c766f504d079dd1a4 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1773,7 +1773,7 @@ public final class CraftServer implements Server {
// Paper end
Set<CommandSender> recipients = new HashSet<>();
for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) {
- if (permissible instanceof CommandSender && permissible.hasPermission(permission)) {
+ if (permissible instanceof CommandSender && !(permissible instanceof org.bukkit.command.BlockCommandSender) && permissible.hasPermission(permission)) { // Paper - don't broadcast to BlockCommandSender (specifically Command Blocks)
recipients.add((CommandSender) permissible);
}
}

View file

@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Wed, 15 Jun 2022 21:52:57 -0400
Subject: [PATCH] Prevent empty items from being added to world
The previous solution caused a bunch of bandaid fixes inorder to resolve edge cases where minecraft/the api might spawn items that are air.
Just simply prevent them from being added to the world instead.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index dd4bd208fba1806a298ccc76d64efdcb2a061be7..e9457d8a29d1f54af8415ad006b75d567e524a46 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1504,6 +1504,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit
return false;
} else {
+ if (entity instanceof net.minecraft.world.entity.item.ItemEntity itemEntity && itemEntity.getItem().isEmpty()) return false; // Paper - Prevent empty items from being added
// Paper start - capture all item additions to the world
if (captureDrops != null && entity instanceof net.minecraft.world.entity.item.ItemEntity) {
captureDrops.add((net.minecraft.world.entity.item.ItemEntity) entity);
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index 1f965e4428d627eaab69ace45486f1d14d2bb504..62f2a070e4c80846a9d696445212c65289037928 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -505,7 +505,7 @@ public class ItemEntity extends Entity {
}
public void setItem(ItemStack stack) {
- com.google.common.base.Preconditions.checkArgument(!stack.isEmpty(), "Cannot drop air"); // CraftBukkit
+ // com.google.common.base.Preconditions.checkArgument(!stack.isEmpty(), "Cannot drop air"); // CraftBukkit // Paper - Remove check
this.getEntityData().set(ItemEntity.DATA_ITEM, stack);
this.getEntityData().markDirty(ItemEntity.DATA_ITEM); // CraftBukkit - SPIGOT-4591, must mark dirty
this.despawnRate = level.paperConfig().entities.spawning.altItemDespawnRate.enabled ? level.paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), level.spigotConfig.itemDespawnRate) : level.spigotConfig.itemDespawnRate; // Paper

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 21 Apr 2022 18:18:02 -0700
Subject: [PATCH] Fix CCE for SplashPotion and LingeringPotion spawning
Remove in 1.19 along with the SplashPotion and
LingeringPotion interfaces
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
index 397e0df15a0e64e5bc522f62f3b327a5039ec4c8..a926f4dc51821a05c28872dc90ad000fe8cb51f7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
@@ -14,7 +14,7 @@ import org.bukkit.entity.ThrownPotion;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
-public class CraftThrownPotion extends CraftThrowableProjectile implements ThrownPotion {
+public class CraftThrownPotion extends CraftThrowableProjectile implements ThrownPotion, org.bukkit.entity.SplashPotion, org.bukkit.entity.LingeringPotion { // Paper - implement other classes to avoid violating spawn method generic contracts
public CraftThrownPotion(CraftServer server, net.minecraft.world.entity.projectile.ThrownPotion entity) {
super(server, entity);
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: pop4959 <pop4959@gmail.com>
Date: Fri, 1 Jul 2022 22:00:06 -0700
Subject: [PATCH] Don't print component in resource pack rejection message
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 9834ee213dcffc35aba1df8d3f9f00a9bbfc1b45..6e689b558450a5b2b707cb355418fbe5f1115365 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2041,7 +2041,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
public void handleResourcePackResponse(ServerboundResourcePackPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
if (packet.getAction() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) {
- ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName());
+ ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getGameProfile().getName()); // Paper - Don't print component in resource pack rejection message
this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"), org.bukkit.event.player.PlayerKickEvent.Cause.RESOURCE_PACK_REJECTION); // Paper - add cause
}
// Paper start

View file

@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: u9g <git@u9g.dev>
Date: Tue, 14 Jun 2022 19:36:10 -0400
Subject: [PATCH] Add Player#getFishHook
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 73d8f4af09689eb549047bf1fa79254cc7736158..d69c05223fca71fc5e282095d02bc39fee7ec757 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -153,6 +153,15 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ());
}
// Paper end
+ // Paper start
+ @Override
+ public org.bukkit.entity.FishHook getFishHook() {
+ if (getHandle().fishing == null) {
+ return null;
+ }
+ return (org.bukkit.entity.FishHook) getHandle().fishing.getBukkitEntity();
+ }
+ // Paper end
@Override
public boolean sleep(Location location, boolean force) {
Preconditions.checkArgument(location != null, "Location cannot be null");

View file

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 3 Jul 2022 22:31:37 -0700
Subject: [PATCH] Do not sync load chunk for dynamic game event listener
registration
These can be called while an entity is being added to the world,
and if the entity is being added from a chunk load context the
sync load will block indefinitely (because the chunk load context
is for completing the chunk to FULL).
This does raise questions about the current system for these
dynamic registrations, as it looks like there is _zero_ logic
to account for the case where the chunk is _not_ currently loaded
and then later loaded.
diff --git a/src/main/java/net/minecraft/world/level/gameevent/DynamicGameEventListener.java b/src/main/java/net/minecraft/world/level/gameevent/DynamicGameEventListener.java
index 1977fde5e9b18406389dfb7374ecf4784f362233..7ee6e2dfb3441c992f4206f5bb8389733cea9dfc 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/DynamicGameEventListener.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/DynamicGameEventListener.java
@@ -66,7 +66,7 @@ public class DynamicGameEventListener<T extends GameEventListener> {
private static void ifChunkExists(LevelReader world, @Nullable SectionPos sectionPos, Consumer<GameEventListenerRegistry> dispatcherConsumer) {
if (sectionPos != null) {
- ChunkAccess chunkAccess = world.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.FULL, false);
+ ChunkAccess chunkAccess = world.getChunkIfLoadedImmediately(sectionPos.getX(), sectionPos.getZ()); // Paper - can cause sync loads while completing a chunk, resulting in deadlock
if (chunkAccess != null) {
dispatcherConsumer.accept(chunkAccess.getListenerRegistry(sectionPos.y()));
}

View file

@ -1,73 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 20 Jul 2021 21:35:47 -0700
Subject: [PATCH] Add various missing EntityDropItemEvent calls
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0e27a7b943a5e4d580fdbce4cd14d0528c808735..e46a62a01319e011a79889ee686dd13c6c4d309e 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2544,6 +2544,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe
entityitem.setDefaultPickUpDelay();
+ // Paper start
+ return this.spawnAtLocation(entityitem);
+ }
+ }
+ @Nullable
+ public ItemEntity spawnAtLocation(ItemEntity entityitem) {
+ {
+ // Paper end
// CraftBukkit start
EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
Bukkit.getPluginManager().callEvent(event);
diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
index 7c53dddb598de85abf1eb8b8ee183a6e8e6f9c74..3f100d847fbce6db5b625e99c4f3694576237372 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
@@ -593,7 +593,7 @@ public class Dolphin extends WaterAnimal {
float f2 = 0.02F * Dolphin.this.random.nextFloat();
entityitem.setDeltaMovement((double) (0.3F * -Mth.sin(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.cos(f1) * f2), (double) (0.3F * Mth.sin(Dolphin.this.getXRot() * 0.017453292F) * 1.5F), (double) (0.3F * Mth.cos(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.sin(f1) * f2));
- Dolphin.this.level.addFreshEntity(entityitem);
+ Dolphin.this.spawnAtLocation(entityitem); // Paper - call EntityDropItemEvent
}
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
index f4cfefd72704b3423392ffeb57e78c5d6410ff6f..e4edeeb04fd7183514e53e20dcef8aca56f02f7d 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
@@ -502,14 +502,14 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
entityitem.setPickUpDelay(40);
entityitem.setThrower(this.getUUID());
this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F);
- this.level.addFreshEntity(entityitem);
+ this.spawnAtLocation(entityitem); // Paper - call EntityDropItemEvent
}
}
private void dropItemStack(ItemStack stack) {
ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), stack);
- this.level.addFreshEntity(entityitem);
+ this.spawnAtLocation(entityitem); // Paper - call EntityDropItemEvent
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
index d562ad27bf690927e6a84e416ab74a460950f249..0b0377fa1483e4fcb31456af6c7e1749bd8af484 100644
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
@@ -354,8 +354,7 @@ public class Goat extends Animal {
double d2 = (double) Mth.randomBetween(this.random, -0.2F, 0.2F);
ItemEntity entityitem = new ItemEntity(this.level, vec3d.x(), vec3d.y(), vec3d.z(), itemstack, d0, d1, d2);
- this.level.addFreshEntity(entityitem);
- return true;
+ return this.spawnAtLocation(entityitem) != null; // Paper - call EntityDropItemEvent by calling spawnAtLocation.
}
}

View file

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 6 Jul 2022 05:52:22 +0100
Subject: [PATCH] Add some minimal debug information to chat packet errors
TODO: potentially add some kick leeway
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 6e689b558450a5b2b707cb355418fbe5f1115365..7160297203de40e5158fc34341ebec723ffcf750 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2291,7 +2291,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
private Optional<LastSeenMessages> tryHandleChat(String message, Instant timestamp, LastSeenMessages.Update acknowledgment) {
if (!this.updateChatOrder(timestamp)) {
- ServerGamePacketListenerImpl.LOGGER.warn("{} sent out-of-order chat: '{}'", this.player.getName().getString(), message);
+ ServerGamePacketListenerImpl.LOGGER.warn("{} sent out-of-order chat: '{}': {} > {}", this.player.getName().getString(), message, this.lastChatTimeStamp.get().getEpochSecond(), timestamp.getEpochSecond()); // Paper
this.server.scheduleOnMain(() -> { // Paper - push to main
this.disconnect(Component.translatable("multiplayer.disconnect.out_of_order_chat"), org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event ca
}); // Paper - push to main

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 6 Jul 2022 14:59:38 -0700
Subject: [PATCH] Fix Bee flower NPE
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
index 5cb23a6b85bccb6e873be24a5be39224870dac3c..a3aeab5fa137f80a229db2edba07d9900f7becfe 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -805,7 +805,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
++this.pollinatingTicks;
if (this.pollinatingTicks > 600) {
Bee.this.savedFlowerPos = null;
- } else {
+ } else if (Bee.this.savedFlowerPos != null) { // Paper - add null check since API can manipulate this
Vec3 vec3d = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, 0.6000000238418579D, 0.0D);
if (vec3d.distanceTo(Bee.this.position()) > 1.0D) {

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Doc <nachito94@msn.com>
Date: Sun, 17 Jul 2022 11:49:43 -0400
Subject: [PATCH] Fix Spigot Config not using commands.spam-exclusions
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 7160297203de40e5158fc34341ebec723ffcf750..a603bc195462227a6737d2d3f9bc247c630c4012 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2536,7 +2536,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
}
// Spigot end
// this.chatSpamTickCount += 20;
- if (this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
+ if (counted && this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper - exclude from SpigotConfig.spamExclusions
// CraftBukkit end
this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause
}

View file

@ -1,215 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 5 Sep 2021 12:15:59 -0400
Subject: [PATCH] More Teleport API
== AT ==
public net.minecraft.server.network.ServerGamePacketListenerImpl internalTeleport(DDDFFLjava/util/Set;Z)V
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index a603bc195462227a6737d2d3f9bc247c630c4012..a5734228fbad1b9e704573ea220084a8c142e069 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1718,11 +1718,17 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
return false; // CraftBukkit - Return event status
}
- PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause);
+ // Paper start - Teleport API
+ Set<io.papermc.paper.entity.TeleportFlag.Relative> relativeFlags = java.util.EnumSet.noneOf(io.papermc.paper.entity.TeleportFlag.Relative.class);
+ for (net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument relativeArgument : set) {
+ relativeFlags.add(org.bukkit.craftbukkit.entity.CraftPlayer.toApiRelativeFlag(relativeArgument));
+ }
+ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause, flag, java.util.Set.copyOf(relativeFlags));
+ // Paper end
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled() || !to.equals(event.getTo())) {
- set.clear(); // Can't relative teleport
+ //set.clear(); // Can't relative teleport // Paper - Teleport API: Now you can!
to = event.isCancelled() ? event.getFrom() : event.getTo();
d0 = to.getX();
d1 = to.getY();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 32b9816283c8c1de929d5664733553277cf6bf3c..13dbac3b3aa7d67320203b64eaa130925ba0fbbf 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -550,15 +550,36 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@Override
public boolean teleport(Location location, TeleportCause cause) {
+ // Paper start - Teleport passenger API
+ return teleport(location, cause, new io.papermc.paper.entity.TeleportFlag[0]);
+ }
+
+ @Override
+ public boolean teleport(Location location, TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) {
+ // Paper end
Preconditions.checkArgument(location != null, "location cannot be null");
location.checkFinite();
+ // Paper start - Teleport passenger API
+ Set<io.papermc.paper.entity.TeleportFlag> flagSet = Set.of(flags);
+ boolean dismount = !flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_VEHICLE);
+ boolean ignorePassengers = flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS);
+ // Don't allow teleporting between worlds while keeping passengers
+ if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+
+ // Don't allow to teleport between worlds if remaining on vehicle
+ if (!dismount && this.entity.isPassenger() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+ // Paper end
- if (this.entity.isVehicle() || this.entity.isRemoved()) {
+ if ((!ignorePassengers && this.entity.isVehicle()) || this.entity.isRemoved()) { // Paper - Teleport passenger API
return false;
}
// If this entity is riding another entity, we must dismount before teleporting.
- this.entity.stopRiding();
+ if (dismount) this.entity.stopRiding(); // Paper - Teleport passenger API
// Let the server handle cross world teleports
if (location.getWorld() != null && !location.getWorld().equals(this.getWorld())) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 7034ca7b50c12b000abf33b14fbe216fe8b14a8c..977063eeaa1d8864a86f48f87d820d01d14e5bb6 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1208,13 +1208,100 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setRotation(float yaw, float pitch) {
- throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead.");
+ // Paper start - Teleport API
+ Location targetLocation = this.getEyeLocation();
+ targetLocation.setYaw(yaw);
+ targetLocation.setPitch(pitch);
+
+ org.bukkit.util.Vector direction = targetLocation.getDirection();
+ targetLocation.add(direction);
+ this.lookAt(targetLocation, io.papermc.paper.entity.LookAnchor.EYES);
+ // Paper end
}
@Override
public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) {
+ // Paper start - Teleport API
+ return this.teleport(location, cause, new io.papermc.paper.entity.TeleportFlag[0]);
+ }
+
+ @Override
+ public void lookAt(@NotNull org.bukkit.entity.Entity entity, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor, @NotNull io.papermc.paper.entity.LookAnchor entityAnchor) {
+ this.getHandle().lookAt(toNmsAnchor(playerAnchor), ((CraftEntity) entity).getHandle(), toNmsAnchor(entityAnchor));
+ }
+
+ @Override
+ public void lookAt(double x, double y, double z, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor) {
+ this.getHandle().lookAt(toNmsAnchor(playerAnchor), new Vec3(x, y, z));
+ }
+
+ public static net.minecraft.commands.arguments.EntityAnchorArgument.Anchor toNmsAnchor(io.papermc.paper.entity.LookAnchor nmsAnchor) {
+ return switch (nmsAnchor) {
+ case EYES -> net.minecraft.commands.arguments.EntityAnchorArgument.Anchor.EYES;
+ case FEET -> net.minecraft.commands.arguments.EntityAnchorArgument.Anchor.FEET;
+ };
+ }
+
+ public static io.papermc.paper.entity.LookAnchor toApiAnchor(net.minecraft.commands.arguments.EntityAnchorArgument.Anchor playerAnchor) {
+ return switch (playerAnchor) {
+ case EYES -> io.papermc.paper.entity.LookAnchor.EYES;
+ case FEET -> io.papermc.paper.entity.LookAnchor.FEET;
+ };
+ }
+
+ public static net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument toNmsRelativeFlag(io.papermc.paper.entity.TeleportFlag.Relative apiFlag) {
+ return switch (apiFlag) {
+ case X -> net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument.X;
+ case Y -> net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument.Y;
+ case Z -> net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument.Z;
+ case PITCH -> net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument.X_ROT;
+ case YAW -> net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument.Y_ROT;
+ };
+ }
+
+ public static io.papermc.paper.entity.TeleportFlag.Relative toApiRelativeFlag(net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument nmsFlag) {
+ return switch (nmsFlag) {
+ case X -> io.papermc.paper.entity.TeleportFlag.Relative.X;
+ case Y -> io.papermc.paper.entity.TeleportFlag.Relative.Y;
+ case Z -> io.papermc.paper.entity.TeleportFlag.Relative.Z;
+ case X_ROT -> io.papermc.paper.entity.TeleportFlag.Relative.PITCH;
+ case Y_ROT -> io.papermc.paper.entity.TeleportFlag.Relative.YAW;
+ };
+ }
+
+ @Override
+ public boolean teleport(Location location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) {
+ java.util.Set<net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument> relativeArguments;
+ java.util.Set<io.papermc.paper.entity.TeleportFlag> allFlags;
+ if (flags.length == 0) {
+ relativeArguments = Set.of();
+ allFlags = Set.of();
+ } else {
+ relativeArguments = java.util.EnumSet.noneOf(net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket.RelativeArgument.class);
+ allFlags = new HashSet<>();
+ for (io.papermc.paper.entity.TeleportFlag flag : flags) {
+ if (flag instanceof io.papermc.paper.entity.TeleportFlag.Relative relativeTeleportFlag) {
+ relativeArguments.add(toNmsRelativeFlag(relativeTeleportFlag));
+ }
+ allFlags.add(flag);
+ }
+ }
+ boolean dismount = !allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_VEHICLE);
+ boolean ignorePassengers = allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS);
+ // Paper end - Teleport API
Preconditions.checkArgument(location != null, "location");
Preconditions.checkArgument(location.getWorld() != null, "location.world");
+ // Paper start - Teleport passenger API
+ // Don't allow teleporting between worlds while keeping passengers
+ if (ignorePassengers && entity.isVehicle() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+
+ // Don't allow to teleport between worlds if remaining on vehicle
+ if (!dismount && entity.isPassenger() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+ // Paper end
location.checkFinite();
ServerPlayer entity = this.getHandle();
@@ -1227,7 +1314,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return false;
}
- if (entity.isVehicle()) {
+ if (entity.isVehicle() && !ignorePassengers) { // Paper - Teleport API
return false;
}
@@ -1245,7 +1332,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// If this player is riding another entity, we must dismount before teleporting.
- entity.stopRiding();
+ if (dismount) entity.stopRiding(); // Paper - Teleport API
// SPIGOT-5509: Wakeup, similar to riding
if (this.isSleeping()) {
@@ -1261,13 +1348,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
ServerLevel toWorld = ((CraftWorld) to.getWorld()).getHandle();
// Close any foreign inventory
- if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) {
+ if (this.getHandle().containerMenu != this.getHandle().inventoryMenu && !allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_OPEN_INVENTORY)) { // Paper
this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper
}
// Check if the fromWorld and toWorld are the same.
if (fromWorld == toWorld) {
- entity.connection.teleport(to);
+ entity.connection.internalTeleport(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), relativeArguments, dismount); // Paper - Teleport API
} else {
server.getHandle().respawn(entity, toWorld, true, to, !toWorld.paperConfig().environment.disableTeleportationSuffocationCheck); // Paper
}

View file

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 12 May 2021 04:30:42 -0700
Subject: [PATCH] Add EntityPortalReadyEvent
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index e46a62a01319e011a79889ee686dd13c6c4d309e..10d8e11ea1e851b19f038230a9b1fb5c3a024f25 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2895,6 +2895,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit
this.level.getProfiler().push("portal");
this.portalTime = i;
+ // Paper start
+ io.papermc.paper.event.entity.EntityPortalReadyEvent event = new io.papermc.paper.event.entity.EntityPortalReadyEvent(this.getBukkitEntity(), worldserver1 == null ? null : worldserver1.getWorld(), org.bukkit.PortalType.NETHER);
+ if (!event.callEvent()) {
+ this.portalTime = 0;
+ } else {
+ worldserver1 = event.getTargetWorld() == null ? null : ((CraftWorld) event.getTargetWorld()).getHandle();
+ // Paper end
this.setPortalCooldown();
// CraftBukkit start
if (this instanceof ServerPlayer) {
@@ -2902,6 +2909,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
} else {
this.changeDimension(worldserver1);
}
+ } // Paper
// CraftBukkit end
this.level.getProfiler().pop();
}

View file

@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 10 Jul 2022 14:13:22 -0700
Subject: [PATCH] Don't use level random in entity constructors
Paper makes the entity random thread-safe
and constructing an entity off the main thread
should be supported. Some entities (for whatever
reason) use the level's random in some places.
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
index a3aeab5fa137f80a229db2edba07d9900f7becfe..337a88a7cd6445004d005ef8d56af1b1cdf800d9 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -1031,7 +1031,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
BeeGoToHiveGoal() {
super();
- this.travellingTicks = Bee.this.level.random.nextInt(10);
+ this.travellingTicks = Bee.this./* level. */random.nextInt(10); // Paper - use entity random
this.blacklistedTargets = Lists.newArrayList();
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
}
@@ -1148,7 +1148,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
BeeGoToKnownFlowerGoal() {
super();
- this.travellingTicks = Bee.this.level.random.nextInt(10);
+ this.travellingTicks = Bee.this./* level. */random.nextInt(10); // Paper - use entity random
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
}
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index 62f2a070e4c80846a9d696445212c65289037928..d9da6728d60e97eb9032b0a5aa71757d11f36e22 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -62,7 +62,12 @@ public class ItemEntity extends Entity {
}
public ItemEntity(Level world, double x, double y, double z, ItemStack stack) {
- this(world, x, y, z, stack, world.random.nextDouble() * 0.2D - 0.1D, 0.2D, world.random.nextDouble() * 0.2D - 0.1D);
+ // Paper start - don't use world random in entity constructor
+ this(EntityType.ITEM, world);
+ this.setPos(x, y, z);
+ this.setDeltaMovement(this.random.nextDouble() * 0.2D - 0.1D, 0.2D, this.random.nextDouble() * 0.2D - 0.1D);
+ this.setItem(stack);
+ // Paper end
}
public ItemEntity(Level world, double x, double y, double z, ItemStack stack, double velocityX, double velocityY, double velocityZ) {
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
index 4b81d62d3250b99cbcb4eb2468ef81c149bf177e..bedee2c93bd0aff148f93dcf111e0fc3d9bce4a0 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -32,7 +32,7 @@ public class PrimedTnt extends Entity {
public PrimedTnt(Level world, double x, double y, double z, @Nullable LivingEntity igniter) {
this(EntityType.TNT, world);
this.setPos(x, y, z);
- double d3 = world.random.nextDouble() * 6.2831854820251465D;
+ double d3 = this.random.nextDouble() * 6.2831854820251465D; // Paper - don't use world random in entity constructor
this.setDeltaMovement(-Math.sin(d3) * 0.02D, 0.20000000298023224D, -Math.cos(d3) * 0.02D);
this.setFuse(80);

View file

@ -1,91 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 25 Jun 2022 19:45:20 -0400
Subject: [PATCH] Send block entities after destroy prediction
Minecraft's prediction system does not handle block entities, so if we are manually sending block entities during
block breaking we need to set it after the prediction is finished. This fixes block entities not showing when cancelling the BlockBreakEvent.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 796d17f51496974cfdfed2593753b8c09b5c81c1..13031576c20bda3bb12c926f6cd938fa5fb105f2 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -62,6 +62,8 @@ public class ServerPlayerGameMode {
private BlockPos delayedDestroyPos;
private int delayedTickStart;
private int lastSentState;
+ public boolean captureSentBlockEntities = false; // Paper
+ public boolean capturedBlockEntity = false; // Paper
public ServerPlayerGameMode(ServerPlayer player) {
this.gameModeForPlayer = GameType.DEFAULT_MODE;
@@ -187,10 +189,7 @@ public class ServerPlayerGameMode {
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
this.debugLogging(pos, false, sequence, "may not interact");
// Update any tile entity data for this block
- BlockEntity tileentity = this.level.getBlockEntity(pos);
- if (tileentity != null) {
- this.player.connection.send(tileentity.getUpdatePacket());
- }
+ capturedBlockEntity = true; // Paper - send block entity after predicting
// CraftBukkit end
return;
}
@@ -206,10 +205,7 @@ public class ServerPlayerGameMode {
// Paper end
this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
// Update any tile entity data for this block
- BlockEntity tileentity = this.level.getBlockEntity(pos);
- if (tileentity != null) {
- this.player.connection.send(tileentity.getUpdatePacket());
- }
+ capturedBlockEntity = true; // Paper - send block entity after predicting
return;
}
// CraftBukkit end
@@ -385,10 +381,12 @@ public class ServerPlayerGameMode {
}
// Update any tile entity data for this block
+ if (!captureSentBlockEntities) { // Paper - Toggle this location for capturing as this is used for api
BlockEntity tileentity = this.level.getBlockEntity(pos);
if (tileentity != null) {
this.player.connection.send(tileentity.getUpdatePacket());
}
+ } else {capturedBlockEntity = true;} // Paper end
return false;
}
}
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index a5734228fbad1b9e704573ea220084a8c142e069..aef7e2ee25e9ad17ec85b701b516cc45a5b6f451 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1863,8 +1863,28 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
return;
}
// Paper end - Don't allow digging in unloaded chunks
+ // Paper start - send block entities after prediction
+ this.player.gameMode.capturedBlockEntity = false;
+ this.player.gameMode.captureSentBlockEntities = true;
+ // Paper end - send block entities after prediction
this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level.getMaxBuildHeight(), packet.getSequence());
this.player.connection.ackBlockChangesUpTo(packet.getSequence());
+ // Paper start - send block entities after prediction
+ this.player.gameMode.captureSentBlockEntities = false;
+ // If a block entity was modified speedup the block change ack to avoid the block entity
+ // being overriden.
+ if (this.player.gameMode.capturedBlockEntity) {
+ // manually tick
+ this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo));
+ this.player.connection.ackBlockChangesUpTo = -1;
+
+ this.player.gameMode.capturedBlockEntity = false;
+ BlockEntity tileentity = this.player.level.getBlockEntity(blockposition);
+ if (tileentity != null) {
+ this.player.connection.send(tileentity.getUpdatePacket());
+ }
+ }
+ // Paper end - send block entities after prediction
return;
default:
throw new IllegalArgumentException("Invalid player action");

View file

@ -1,96 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Fri, 29 Jul 2022 12:35:19 -0400
Subject: [PATCH] Warn on plugins accessing faraway chunks
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 807b58b1a7a9a01faef7f42aba022ed467fa607e..2ecd29a24545418a2f6e2b2091d848313baabe91 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -416,7 +416,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
private static boolean isInWorldBoundsHorizontal(BlockPos pos) {
- return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000;
+ return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000; // Dif on change
}
private static boolean isOutsideSpawnableHeight(int y) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index e5bafab042767f483e09fa0d164f91e4a6f06160..c91bac6f3f1d60c950b93d157531cd8f7500e8d8 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -312,9 +312,24 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public boolean setSpawnLocation(int x, int y, int z) {
return this.setSpawnLocation(x, y, z, 0.0F);
}
+ // Paper start
+ private static void warnUnsafeChunk(String reason, int x, int z) {
+ // if any chunk coord is outside of 30 million blocks
+ if (x > 1875000 || z > 1875000 || x < -1875000 || z < -1875000) {
+ Plugin plugin = io.papermc.paper.util.StackWalkerUtil.getFirstPluginCaller();
+ if (plugin != null) {
+ plugin.getLogger().warning("Plugin is %s at (%s, %s), this might cause issues.".formatted(reason, x, z));
+ }
+ if (net.minecraft.server.MinecraftServer.getServer().isDebugging()) {
+ io.papermc.paper.util.TraceUtil.dumpTraceForThread("Dangerous chunk retrieval");
+ }
+ }
+ }
+ // Paper end
@Override
public Chunk getChunkAt(int x, int z) {
+ warnUnsafeChunk("getting a faraway chunk", x, z); // Paper
// Paper start - add ticket to hold chunk for a little while longer if plugin accesses it
net.minecraft.world.level.chunk.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z);
if (chunk == null) {
@@ -419,6 +434,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean regenerateChunk(int x, int z) {
org.spigotmc.AsyncCatcher.catchOp("chunk regenerate"); // Spigot
+ warnUnsafeChunk("regenerating a faraway chunk", x, z); // Paper
// Paper start - implement regenerateChunk method
final ServerLevel serverLevel = this.world;
final net.minecraft.server.level.ServerChunkCache serverChunkCache = serverLevel.getChunkSource();
@@ -515,6 +531,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean loadChunk(int x, int z, boolean generate) {
org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
+ warnUnsafeChunk("loading a faraway chunk", x, z); // Paper
// Paper start - Optimize this method
ChunkPos chunkPos = new ChunkPos(x, z);
ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper
@@ -579,6 +596,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean addPluginChunkTicket(int x, int z, Plugin plugin) {
+ warnUnsafeChunk("adding a faraway chunk ticket", x, z); // Paper
Preconditions.checkArgument(plugin != null, "null plugin");
Preconditions.checkArgument(plugin.isEnabled(), "plugin is not enabled");
@@ -647,6 +665,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public void setChunkForceLoaded(int x, int z, boolean forced) {
+ warnUnsafeChunk("forceloading a faraway chunk", x, z); // Paper
this.getHandle().setChunkForced(x, z, forced);
}
@@ -958,6 +977,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) {
+ warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper
// Transient load for this tick
return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z);
}
@@ -2334,6 +2354,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
// Spigot end
// Paper start
public java.util.concurrent.CompletableFuture<Chunk> getChunkAtAsync(int x, int z, boolean gen, boolean urgent) {
+ warnUnsafeChunk("getting a faraway chunk async", x, z); // Paper
if (Bukkit.isPrimaryThread()) {
net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z);
if (immediate != null) {

View file

@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 30 Jul 2022 11:23:05 -0400
Subject: [PATCH] Custom Chat Completion Suggestions API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 977063eeaa1d8864a86f48f87d820d01d14e5bb6..7d3fe4b49a7a83ea619c1ecb1ec923cda151219c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -665,6 +665,22 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().getServer().getPlayerList().sendPlayerPermissionLevel(this.getHandle(), level, false);
}
+
+ @Override
+ public void addAdditionalChatCompletions(@NotNull Collection<String> completions) {
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket(
+ net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket.Action.ADD,
+ new ArrayList<>(completions)
+ ));
+ }
+
+ @Override
+ public void removeAdditionalChatCompletions(@NotNull Collection<String> completions) {
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket(
+ net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket.Action.REMOVE,
+ new ArrayList<>(completions)
+ ));
+ }
// Paper end
@Override

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Thu, 21 Jul 2022 12:07:54 -0400
Subject: [PATCH] Add missing BlockFadeEvents
diff --git a/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java b/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
index 834c5e3fbff3819f3f72e95a1072d9b9e57f25b3..294d22b6b27e96b59c77527efcfefa9410b756e4 100644
--- a/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
@@ -85,6 +85,11 @@ public class FrogspawnBlock extends Block {
}
private void hatchFrogspawn(ServerLevel world, BlockPos pos, RandomSource random) {
+ // Paper start - Call BlockFadeEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.AIR.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // Paper end
this.destroyBlock(world, pos);
world.playSound((Player)null, pos, SoundEvents.FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F);
this.spawnTadpoles(world, pos, random);

View file

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Wed, 6 Oct 2021 20:10:44 -0400
Subject: [PATCH] Collision API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 446657577aa843e6ebc5143b6c511f33d27b6360..d99f079e03d0541d7aa3c70d9e8c12b8619b2c22 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -973,5 +973,12 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return this.getHandle().clip(new net.minecraft.world.level.ClipContext(vec3d, vec3d1, net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, null)).getType() == net.minecraft.world.phys.HitResult.Type.MISS;
}
+
+ @Override
+ public boolean hasCollisionsIn(@org.jetbrains.annotations.NotNull org.bukkit.util.BoundingBox boundingBox) {
+ net.minecraft.world.phys.AABB aabb = new AABB(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ(), boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ(), false);
+
+ return !this.getHandle().noCollision(aabb);
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 13dbac3b3aa7d67320203b64eaa130925ba0fbbf..0b4686c67276cea153bdd57f11c9b48a4dd1b4ec 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1380,4 +1380,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return getHandle().isInPowderSnow || getHandle().wasInPowderSnow; // depending on the location in the entity "tick" either could be needed.
}
// Paper end
+ // Paper Start - Collision API
+ @Override
+ public boolean collidesAt(@org.jetbrains.annotations.NotNull Location location) {
+ net.minecraft.world.phys.AABB aabb = this.getHandle().getBoundingBoxAt(location.getX(), location.getY(), location.getZ());
+
+ return !this.getHandle().level.noCollision(this.getHandle(), aabb);
+ }
+
+ @Override
+ public boolean wouldCollideUsing(@org.jetbrains.annotations.NotNull BoundingBox boundingBox) {
+ net.minecraft.world.phys.AABB aabb = new AABB(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ(), boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ(), false);
+
+ return !this.getHandle().level.noCollision(this.getHandle(), aabb);
+ }
+ // Paper End - Collision API
}

View file

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: chickeneer <emcchickeneer@gmail.com>
Date: Mon, 1 Aug 2022 20:13:02 -0500
Subject: [PATCH] Fix suggest command message for brigadier syntax exceptions
This is a bug accidentally introduced in upstream CB
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 401a87de8fc48b9e69423d547f79e9e356cc20f1..e92864ecf32dd984f6f87f7b05341e43af3a2977 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -334,7 +334,7 @@ public class Commands {
if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) {
int j = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor());
MutableComponent ichatmutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((chatmodifier) -> {
- return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, label)); // CraftBukkit
+ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + label)); // CraftBukkit // Paper
});
if (j > 10) {

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 10 Jun 2022 16:02:35 +0200
Subject: [PATCH] Remove invalid signature login stacktrace
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index aef7e2ee25e9ad17ec85b701b516cc45a5b6f451..3e884720d242936225b558152763c68dc8370fd8 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3595,7 +3595,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator, Duration.ZERO));
} catch (ProfilePublicKey.ValidationException profilepublickey_b) {
- ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage());
+ // ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); // Paper - unnecessary log
this.disconnect(profilepublickey_b.getComponent(), profilepublickey_b.kickCause); // Paper - kick event causes
}

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Wed, 3 Aug 2022 12:57:36 -0700
Subject: [PATCH] Add async catcher to PlayerConnection internalTeleport
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 3e884720d242936225b558152763c68dc8370fd8..cc780cfc359bb1872cd78136497f94cc7e2a67c4 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1746,6 +1746,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
}
public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<ClientboundPlayerPositionPacket.RelativeArgument> set, boolean flag) {
+ org.spigotmc.AsyncCatcher.catchOp("teleport"); // Paper
// Paper start
if (player.isRemoved()) {
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());

View file

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 26 Dec 2021 13:23:46 -0500
Subject: [PATCH] Block Ticking API
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 0d30b388d8d93a6dbbf8dfb30d26eb44c73e1e4e..962c950ca9c7e047a3aec215d4faa73676049d36 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -756,5 +756,21 @@ public class CraftBlock implements Block {
public boolean isValidTool(ItemStack itemStack) {
return getDrops(itemStack).size() != 0;
}
+
+ @Override
+ public void tick() {
+ net.minecraft.world.level.block.state.BlockState blockData = this.getNMS();
+ net.minecraft.server.level.ServerLevel level = this.world.getMinecraftWorld();
+
+ blockData.getBlock().tick(blockData, level, this.position, level.random);
+ }
+
+ @Override
+ public void randomTick() {
+ net.minecraft.world.level.block.state.BlockState blockData = this.getNMS();
+ net.minecraft.server.level.ServerLevel level = this.world.getMinecraftWorld();
+
+ blockData.getBlock().randomTick(blockData, level, this.position, level.random);
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index 7acf213194f61d04cffabaaee6c1372bfa2e1933..0a04366b3f472bc4ce20ed814dc326b278119c74 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -652,4 +652,10 @@ public class CraftBlockData implements BlockData {
return this.state.isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CraftBlock.blockFaceToNotch(face), CraftBlockSupport.toNMS(support));
}
+ // Paper start - Block tick API
+ @Override
+ public boolean isRandomlyTicked() {
+ return this.state.isRandomlyTicking();
+ }
+ // Paper end
}

View file

@ -1,227 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Mon, 8 Oct 2018 14:36:14 -0400
Subject: [PATCH] Add Velocity IP Forwarding Support
While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users
have a lot of problems setting up firewalls or setting up plugins like IPWhitelist.
Further, the BungeeCord IP forwarding protocol still retains essentially its original
form, when there is brand new support for custom login plugin messages in 1.13.
Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity
of messages, is packed into a binary format that is smaller than BungeeCord's
forwarding, and is integrated into the Minecraft login process by using the 1.13
login plugin message packet.
diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4934979b1ed85bfc4f8d9e6f8848b2beaad95c3
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java
@@ -0,0 +1,75 @@
+package com.destroystokyo.paper.proxy;
+
+import io.papermc.paper.configuration.GlobalConfiguration;
+import com.google.common.net.InetAddresses;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.properties.Property;
+import java.net.InetAddress;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.entity.player.ProfilePublicKey;
+
+public class VelocityProxy {
+ private static final int SUPPORTED_FORWARDING_VERSION = 1;
+ public static final int MODERN_FORWARDING_WITH_KEY = 2;
+ public static final int MODERN_FORWARDING_WITH_KEY_V2 = 3;
+ public static final int MODERN_LAZY_SESSION = 4;
+ public static final byte MAX_SUPPORTED_FORWARDING_VERSION = MODERN_LAZY_SESSION;
+ public static final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info");
+
+ public static boolean checkIntegrity(final FriendlyByteBuf buf) {
+ final byte[] signature = new byte[32];
+ buf.readBytes(signature);
+
+ final byte[] data = new byte[buf.readableBytes()];
+ buf.getBytes(buf.readerIndex(), data);
+
+ try {
+ final Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(GlobalConfiguration.get().proxies.velocity.secret.getBytes(java.nio.charset.StandardCharsets.UTF_8), "HmacSHA256"));
+ final byte[] mySignature = mac.doFinal(data);
+ if (!MessageDigest.isEqual(signature, mySignature)) {
+ return false;
+ }
+ } catch (final InvalidKeyException | NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+
+ return true;
+ }
+
+ public static InetAddress readAddress(final FriendlyByteBuf buf) {
+ return InetAddresses.forString(buf.readUtf(Short.MAX_VALUE));
+ }
+
+ public static GameProfile createProfile(final FriendlyByteBuf buf) {
+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUtf(16));
+ readProperties(buf, profile);
+ return profile;
+ }
+
+ private static void readProperties(final FriendlyByteBuf buf, final GameProfile profile) {
+ final int properties = buf.readVarInt();
+ for (int i1 = 0; i1 < properties; i1++) {
+ final String name = buf.readUtf(Short.MAX_VALUE);
+ final String value = buf.readUtf(Short.MAX_VALUE);
+ final String signature = buf.readBoolean() ? buf.readUtf(Short.MAX_VALUE) : null;
+ profile.getProperties().put(name, new Property(name, value, signature));
+ }
+ }
+
+ public static ProfilePublicKey.Data readForwardedKey(FriendlyByteBuf buf) {
+ return new ProfilePublicKey.Data(buf);
+ }
+
+ public static UUID readSignerUuidOrElse(FriendlyByteBuf buf, UUID orElse) {
+ return buf.readBoolean() ? buf.readUUID() : orElse;
+ }
+}
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 51b3db0b6c2cede95b584268e035c0fb36d38094..a7e133f3495e9132a5fdae2c24f225e7b026295a 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -274,13 +274,20 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP);
// CraftBukkit end
+ // Paper start
+ boolean usingProxy = org.spigotmc.SpigotConfig.bungee || io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled;
+ String proxyFlavor = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "Velocity" : "BungeeCord";
+ String proxyLink = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "https://docs.papermc.io/velocity/security" : "http://www.spigotmc.org/wiki/firewall-guide/";
+ // Paper end
if (!this.usesAuthentication()) {
DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
// Spigot start
- if (org.spigotmc.SpigotConfig.bungee) {
- DedicatedServer.LOGGER.warn("Whilst this makes it possible to use BungeeCord, unless access to your server is properly restricted, it also opens up the ability for hackers to connect with any username they choose.");
- DedicatedServer.LOGGER.warn("Please see http://www.spigotmc.org/wiki/firewall-guide/ for further information.");
+ // Paper start
+ if (usingProxy) {
+ DedicatedServer.LOGGER.warn("Whilst this makes it possible to use " + proxyFlavor + ", unless access to your server is properly restricted, it also opens up the ability for hackers to connect with any username they choose.");
+ DedicatedServer.LOGGER.warn("Please see " + proxyLink + " for further information.");
+ // Paper end
} else {
DedicatedServer.LOGGER.warn("While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose.");
}
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 0bedd9eadbfe1ce290f22d6c648571e25e3ae0e9..093822a5256e8e919350a000239a3e92a2379aaf 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -61,6 +61,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
@Nullable
private ServerPlayer delayedAcceptPlayer;
public boolean iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation = false; // Paper - username validation overriding
+ private int velocityLoginMessageId = -1; // Paper - Velocity support
public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) {
this.state = ServerLoginPacketListenerImpl.State.HELLO;
@@ -256,6 +257,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
this.state = ServerLoginPacketListenerImpl.State.KEY;
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge));
} else {
+ // Paper start - Velocity support
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) {
+ this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt();
+ net.minecraft.network.FriendlyByteBuf buf = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.buffer());
+ buf.writeByte(com.destroystokyo.paper.proxy.VelocityProxy.MAX_SUPPORTED_FORWARDING_VERSION);
+ net.minecraft.network.protocol.login.ClientboundCustomQueryPacket packet1 = new net.minecraft.network.protocol.login.ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, buf);
+ this.connection.send(packet1);
+ return;
+ }
+ // Paper end
// Spigot start
// Paper start - Cache authenticator threads
authenticatorPool.execute(new Runnable() {
@@ -363,6 +374,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
public class LoginHandler {
public void fireEvents() throws Exception {
+ // Paper start - Velocity support
+ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) {
+ disconnect("This server requires you to connect with Velocity.");
+ return;
+ }
+ // Paper end
String playerName = ServerLoginPacketListenerImpl.this.gameProfile.getName();
java.net.InetAddress address = ((java.net.InetSocketAddress) ServerLoginPacketListenerImpl.this.connection.getRemoteAddress()).getAddress();
java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) connection.getRawAddress()).getAddress(); // Paper
@@ -411,6 +428,47 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
// Spigot end
public void handleCustomQueryPacket(ServerboundCustomQueryPacket packet) {
+ // Paper start - Velocity support
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled && packet.getTransactionId() == this.velocityLoginMessageId) {
+ net.minecraft.network.FriendlyByteBuf buf = packet.getData();
+ if (buf == null) {
+ this.disconnect("This server requires you to connect with Velocity.");
+ return;
+ }
+
+ if (!com.destroystokyo.paper.proxy.VelocityProxy.checkIntegrity(buf)) {
+ this.disconnect("Unable to verify player details");
+ return;
+ }
+
+ int version = buf.readVarInt();
+ if (version > com.destroystokyo.paper.proxy.VelocityProxy.MAX_SUPPORTED_FORWARDING_VERSION) {
+ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted upto " + com.destroystokyo.paper.proxy.VelocityProxy.MAX_SUPPORTED_FORWARDING_VERSION);
+ }
+
+ java.net.SocketAddress listening = this.connection.getRemoteAddress();
+ int port = 0;
+ if (listening instanceof java.net.InetSocketAddress) {
+ port = ((java.net.InetSocketAddress) listening).getPort();
+ }
+ this.connection.address = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port);
+
+ this.gameProfile = com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf);
+
+ //TODO Update handling for lazy sessions, might not even have to do anything?
+
+ // Proceed with login
+ authenticatorPool.execute(() -> {
+ try {
+ new LoginHandler().fireEvents();
+ } catch (Exception ex) {
+ disconnect("Failed to verify username!");
+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex);
+ }
+ });
+ return;
+ }
+ // Paper end
this.disconnect(Component.translatable("multiplayer.disconnect.unexpected_query_response"));
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 52dec44a061b773c4467279c766f504d079dd1a4..bbb8335dae0a3e2761e6bbb8dc723bcf28cd82ba 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -779,7 +779,7 @@ public final class CraftServer implements Server {
@Override
public long getConnectionThrottle() {
// Spigot Start - Automatically set connection throttle for bungee configurations
- if (org.spigotmc.SpigotConfig.bungee) {
+ if (org.spigotmc.SpigotConfig.bungee || io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) { // Paper - Velocity support
return -1;
} else {
return this.configuration.getInt("settings.connection-throttle");

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 11 Aug 2022 14:37:33 +0100
Subject: [PATCH] Use thread safe random in ServerLoginPacketListenerImpl
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 093822a5256e8e919350a000239a3e92a2379aaf..a25306fe8a35bb70a490e6a0c01d0340bbc0d781 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -49,7 +49,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
static final Logger LOGGER = LogUtils.getLogger();
private static final int MAX_TICKS_BEFORE_LOGIN = 600;
- private static final RandomSource RANDOM = RandomSource.create();
+ private static final RandomSource RANDOM = new org.bukkit.craftbukkit.util.RandomSourceWrapper(new java.util.Random()); // Paper - This is called across threads, make safe
private final byte[] challenge;
final MinecraftServer server;
public final Connection connection;

View file

@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Josh Roy <10731363+JRoy@users.noreply.github.com>
Date: Sun, 14 Aug 2022 12:23:11 -0400
Subject: [PATCH] Add NamespacedKey biome methods
Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index b25b645df6be2ace22c280473f5f1a2c911ee239..81ffcca62c2ebb15889d286bfe9138b86ccfe71e 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -603,6 +603,19 @@ public final class CraftMagicNumbers implements UnsafeValues {
Preconditions.checkArgument(material.isBlock(), material + " is not a block");
return getBlock(material).hasCollision;
}
+
+ @Override
+ public org.bukkit.NamespacedKey getBiomeKey(org.bukkit.RegionAccessor accessor, int x, int y, int z) {
+ org.bukkit.craftbukkit.CraftRegionAccessor cra = (org.bukkit.craftbukkit.CraftRegionAccessor) accessor;
+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(cra.getHandle().registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME).getKey(cra.getHandle().getBiome(new net.minecraft.core.BlockPos(x, y, z)).value()));
+ }
+
+ @Override
+ public void setBiomeKey(org.bukkit.RegionAccessor accessor, int x, int y, int z, org.bukkit.NamespacedKey biomeKey) {
+ org.bukkit.craftbukkit.CraftRegionAccessor cra = (org.bukkit.craftbukkit.CraftRegionAccessor) accessor;
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> biomeBase = cra.getHandle().registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME).getHolderOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.BIOME, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(biomeKey)));
+ cra.setBiome(x, y, z, biomeBase);
+ }
// Paper end
/**

View file

@ -1,67 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Miguel=20Moreno?= <josemmo@pm.me>
Date: Sat, 5 Jun 2021 13:45:15 +0200
Subject: [PATCH] Fix plugin loggers on server shutdown
diff --git a/src/main/java/io/papermc/paper/log/CustomLogManager.java b/src/main/java/io/papermc/paper/log/CustomLogManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1d3bac79bb8b4796c013ff4472f75dcd79602dc
--- /dev/null
+++ b/src/main/java/io/papermc/paper/log/CustomLogManager.java
@@ -0,0 +1,26 @@
+package io.papermc.paper.log;
+
+import java.util.logging.LogManager;
+
+public class CustomLogManager extends LogManager {
+ private static CustomLogManager instance;
+
+ public CustomLogManager() {
+ instance = this;
+ }
+
+ @Override
+ public void reset() {
+ // Ignore calls to this method
+ }
+
+ private void superReset() {
+ super.reset();
+ }
+
+ public static void forceReset() {
+ if (instance != null) {
+ instance.superReset();
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 1b56bb2869d3cf22670b508133968e66493a5bec..753a917d34a1e1c1521a8916bc8e44a6acd90a46 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -998,6 +998,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender
} catch (Exception e) {
}
+ io.papermc.paper.log.CustomLogManager.forceReset(); // Paper - Reset loggers after shutdown
this.onServerExit();
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 0aef4fc4a89e627bc80504d7402f1ca2cdc95a74..f30621be24c6c3a4f173436fce1ad1c13507c84f 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
@@ -20,6 +20,12 @@ public class Main {
public static boolean useJline = true;
public static boolean useConsole = true;
+ // Paper start - Hijack log manager to ensure logging on shutdown
+ static {
+ System.setProperty("java.util.logging.manager", "io.papermc.paper.log.CustomLogManager");
+ }
+ // Paper end
+
public static void main(String[] args) {
// Paper start
final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected");

View file

@ -1,114 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brokkonaut <hannos17@gmx.de>
Date: Sat, 18 Dec 2021 19:43:36 +0100
Subject: [PATCH] Workaround for client lag spikes (MC-162253)
When crossing certain chunk boundaries, the client needlessly
calculates light maps for chunk neighbours. In some specific map
configurations, these calculations cause a 500ms+ freeze on the Client.
This patch basically serves as a workaround by sending light maps
to the client, so that it doesn't attempt to calculate them.
This mitigates the frametime impact to a minimum (but it's still there).
Original patch by: MeFisto94 <MeFisto94@users.noreply.github.com>
Co-authored-by: =?UTF-8?q?Dani=C3=ABl=20Goossens?= <daniel@goossens.ch>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 7f68b05b4d0789c308b5f90a5d626a633c80191f..2212f9f48636357265d8e44aba415ea4f09f1fe7 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1363,6 +1363,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
+ // Paper start - Fix MC-162253
+ /**
+ * Returns the light mask for the given chunk consisting of all non-empty sections that may need sending.
+ */
+ private BitSet lightMask(final LevelChunk chunk) {
+ final net.minecraft.world.level.chunk.LevelChunkSection[] sections = chunk.getSections();
+ final BitSet mask = new BitSet(this.lightEngine.getLightSectionCount());
+
+ // There are 2 more light sections than chunk sections so when iterating over
+ // sections we have to increment the index by 1
+ for (int i = 0; i < sections.length; i++) {
+ if (!sections[i].hasOnlyAir()) {
+ // Whenever a section is not empty, it can change lighting for the section itself (i + 1), the section below, and the section above
+ mask.set(i);
+ mask.set(i + 1);
+ mask.set(i + 2);
+ i++; // We can skip the already set upper section
+ }
+ }
+ return mask;
+ }
+
+ /**
+ * Returns the ceiling light mask of all sections that are equal or lower to the highest non-empty section.
+ */
+ private BitSet ceilingLightMask(final LevelChunk chunk) {
+ final net.minecraft.world.level.chunk.LevelChunkSection[] sections = chunk.getSections();
+ for (int i = sections.length - 1; i >= 0; i--) {
+ if (!sections[i].hasOnlyAir()) {
+ // Add one to get the light section, one because blocks in the section above may change, and another because BitSet's toIndex is exclusive
+ final int highest = i + 3;
+ final BitSet mask = new BitSet(highest);
+ mask.set(0, highest);
+ return mask;
+ }
+ }
+ return new BitSet();
+ }
+ // Paper end - Fix MC-162253
+
// Paper start - Anti-Xray - Bypass
private void playerLoadedChunk(ServerPlayer player, MutableObject<java.util.Map<Object, ClientboundLevelChunkWithLightPacket>> cachedDataPackets, LevelChunk chunk) {
if (cachedDataPackets.getValue() == null) {
@@ -1371,6 +1411,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
Boolean shouldModify = chunk.getLevel().chunkPacketBlockController.shouldModify(player, chunk);
player.trackChunk(chunk.getPos(), (Packet) cachedDataPackets.getValue().computeIfAbsent(shouldModify, (s) -> {
+ // Paper start - Fix MC-162253
+ final int viewDistance = getEffectiveViewDistance();
+ final int playerChunkX = player.getBlockX() >> 4;
+ final int playerChunkZ = player.getBlockZ() >> 4;
+
+ // For all loaded neighbours, send sky light for empty sections above highest non-empty section (+1) of the center chunk
+ // otherwise the client will try to calculate lighting there on its own
+ final BitSet lightMask = lightMask(chunk);
+ if (!lightMask.isEmpty()) {
+ for (int x = -1; x <= 1; x++) {
+ for (int z = -1; z <= 1; z++) {
+ if (x == 0 && z == 0) {
+ continue;
+ }
+
+ if (!chunk.isNeighbourLoaded(x, z)) {
+ continue;
+ }
+
+ final int neighborChunkX = chunk.getPos().x + x;
+ final int neighborChunkZ = chunk.getPos().z + z;
+ final int distX = Math.abs(playerChunkX - neighborChunkX);
+ final int distZ = Math.abs(playerChunkZ - neighborChunkZ);
+ if (Math.max(distX, distZ) > viewDistance) {
+ continue;
+ }
+
+ final LevelChunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z);
+ final BitSet updateLightMask = (BitSet) lightMask.clone();
+ updateLightMask.andNot(ceilingLightMask(neighbor));
+ if (updateLightMask.isEmpty()) {
+ continue;
+ }
+
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLightUpdatePacket(new ChunkPos(neighborChunkX, neighborChunkZ), this.lightEngine, updateLightMask, null, true));
+ }
+ }
+ }
+ // Paper end - Fix MC-162253
return new ClientboundLevelChunkWithLightPacket(chunk, this.lightEngine, (BitSet) null, (BitSet) null, true, (Boolean) s);
}));
// Paper end

View file

@ -1,74 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MWHunter <s0521458@student.rockvalleycollege.edu>
Date: Wed, 24 Aug 2022 09:54:11 -0400
Subject: [PATCH] Stop large look changes from crashing the server
Co-authored-by: Jaren Knodel <Jaren@Knodel.com>
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 98dac3d0288902265beb07ff17c5ae1bebeb2cfc..c9b072a6324e5facdb85db1caaa7e763191f7104 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3028,37 +3028,15 @@ public abstract class LivingEntity extends Entity {
this.level.getProfiler().pop();
this.level.getProfiler().push("rangeChecks");
- while (this.getYRot() - this.yRotO < -180.0F) {
- this.yRotO -= 360.0F;
- }
-
- while (this.getYRot() - this.yRotO >= 180.0F) {
- this.yRotO += 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.yBodyRot - this.yBodyRotO < -180.0F) {
- this.yBodyRotO -= 360.0F;
- }
+ this.yBodyRotO += Math.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F;
- while (this.yBodyRot - this.yBodyRotO >= 180.0F) {
- this.yBodyRotO += 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.getXRot() - this.xRotO >= 180.0F) {
- this.xRotO += 360.0F;
- }
-
- while (this.yHeadRot - this.yHeadRotO < -180.0F) {
- this.yHeadRotO -= 360.0F;
- }
-
- while (this.yHeadRot - this.yHeadRotO >= 180.0F) {
- this.yHeadRotO += 360.0F;
- }
+ this.yHeadRotO += Math.round((this.yHeadRot - this.yHeadRotO) / 360.0F) * 360.0F;
+ // Paper end
this.level.getProfiler().pop();
this.animStep += f2;
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
index b226800c15f5adbc40c89b36536db23f08e2857d..893975e8587b9036f622e2088c302e33004496d2 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
@@ -246,13 +246,7 @@ public abstract class Projectile extends Entity {
}
protected static float lerpRotation(float prevRot, float newRot) {
- while (newRot - prevRot < -180.0F) {
- prevRot -= 360.0F;
- }
-
- while (newRot - prevRot >= 180.0F) {
- prevRot += 360.0F;
- }
+ prevRot += Math.round((newRot - prevRot) / 360.0F) * 360.0F; // Paper - stop large look changes from crashing the server
return Mth.lerp(0.2F, prevRot, newRot);
}

View file

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TheFruxz <cedricspitzer@outlook.de>
Date: Sat, 26 Mar 2022 18:41:36 +0100
Subject: [PATCH] Add custom destroyerIdentity to sendBlockDamage
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 7d3fe4b49a7a83ea619c1ecb1ec923cda151219c..fb2c4547896fc39a78bc28261a5a6c3764527f6a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1028,13 +1028,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void sendBlockDamage(Location loc, float progress) {
+ // Paper start - customBlockDamage identity
+ sendBlockDamage(loc, progress, this.getHandle().getId());
+ }
+
+ @Override
+ public void sendBlockDamage(Location loc, float progress, int destroyerIdentity) {
+ // Paper end - customBlockDamage identity
Preconditions.checkArgument(loc != null, "loc must not be null");
Preconditions.checkArgument(progress >= 0.0 && progress <= 1.0, "progress must be between 0.0 and 1.0 (inclusive)");
if (this.getHandle().connection == null) return;
int stage = (int) (9 * progress); // There are 0 - 9 damage states
- ClientboundBlockDestructionPacket packet = new ClientboundBlockDestructionPacket(this.getHandle().getId(), new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), stage);
+ ClientboundBlockDestructionPacket packet = new ClientboundBlockDestructionPacket(destroyerIdentity, new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), stage); // Paper - customBlockDamage identity
this.getHandle().connection.send(packet);
}

View file

@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: elmital <54907162+elmital@users.noreply.github.com>
Date: Fri, 16 Sep 2022 17:44:34 +0200
Subject: [PATCH] Fix: EndDragonFight killed statuses should be false for newly
created worlds
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 230de1c71b0a6d6370df2fedb337cf0e332a7596..8cf4ae35eb66e69de32295d707db6845b4b02962 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -113,9 +113,11 @@ public class EndDragonFight {
if (nbt.contains("ExitPortalLocation", 10)) {
this.portalLocation = NbtUtils.readBlockPos(nbt.getCompound("ExitPortalLocation"));
}
- } else {
- this.dragonKilled = true;
- this.previouslyKilled = true;
+ // Paper start - Killed statuses should be false for newly created worlds
+ // } else {
+ // this.dragonKilled = true;
+ // this.previouslyKilled = true;
+ // Paper end
}
if (nbt.contains("Gateways", 9)) {

View file

@ -1,203 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 9 Aug 2021 20:45:46 -0700
Subject: [PATCH] Fire EntityChangeBlockEvent in more places
Co-authored-by: ChristopheG <61288881+chrisgdt@users.noreply.github.com>
diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java
index fa37b34cbd49b97ff0dc270b9d8a58ce2c9eddb3..0142aff35dea5bf5aff55e3293fb2d173c97e677 100644
--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java
+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java
@@ -98,7 +98,7 @@ public class LightningBolt extends Entity {
}
this.powerLightningRod();
- LightningBolt.clearCopperOnLightningStrike(this.level, this.getStrikePosition());
+ LightningBolt.clearCopperOnLightningStrike(this.level, this.getStrikePosition(), this); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
this.gameEvent(GameEvent.LIGHTNING_STRIKE);
}
}
@@ -192,7 +192,7 @@ public class LightningBolt extends Entity {
}
}
- private static void clearCopperOnLightningStrike(Level world, BlockPos pos) {
+ private static void clearCopperOnLightningStrike(Level world, BlockPos pos, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
BlockState iblockdata = world.getBlockState(pos);
BlockPos blockposition1;
BlockState iblockdata1;
@@ -206,24 +206,29 @@ public class LightningBolt extends Entity {
}
if (iblockdata1.getBlock() instanceof WeatheringCopper) {
- world.setBlockAndUpdate(blockposition1, WeatheringCopper.getFirst(world.getBlockState(blockposition1)));
+ // Paper start - call EntityChangeBlockEvent
+ BlockState newBlock = WeatheringCopper.getFirst(world.getBlockState(blockposition1));
+ if (!CraftEventFactory.callEntityChangeBlockEvent(lightning, blockposition1, newBlock).isCancelled()) {
+ world.setBlockAndUpdate(blockposition1, newBlock);
+ }
+ // Paper end
BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable();
int i = world.random.nextInt(3) + 3;
for (int j = 0; j < i; ++j) {
int k = world.random.nextInt(8) + 1;
- LightningBolt.randomWalkCleaningCopper(world, blockposition1, blockposition_mutableblockposition, k);
+ LightningBolt.randomWalkCleaningCopper(world, blockposition1, blockposition_mutableblockposition, k, lightning); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
}
}
}
- private static void randomWalkCleaningCopper(Level world, BlockPos pos, BlockPos.MutableBlockPos mutablePos, int count) {
+ private static void randomWalkCleaningCopper(Level world, BlockPos pos, BlockPos.MutableBlockPos mutablePos, int count, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
mutablePos.set(pos);
for (int j = 0; j < count; ++j) {
- Optional<BlockPos> optional = LightningBolt.randomStepCleaningCopper(world, mutablePos);
+ Optional<BlockPos> optional = LightningBolt.randomStepCleaningCopper(world, mutablePos, lightning); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
if (!optional.isPresent()) {
break;
@@ -234,7 +239,7 @@ public class LightningBolt extends Entity {
}
- private static Optional<BlockPos> randomStepCleaningCopper(Level world, BlockPos pos) {
+ private static Optional<BlockPos> randomStepCleaningCopper(Level world, BlockPos pos, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
Iterator iterator = BlockPos.randomInCube(world.random, 10, pos, 1).iterator();
BlockPos blockposition1;
@@ -251,6 +256,7 @@ public class LightningBolt extends Entity {
BlockPos blockposition1Final = blockposition1; // CraftBukkit - decompile error
WeatheringCopper.getPrevious(iblockdata).ifPresent((iblockdata1) -> {
+ if (!CraftEventFactory.callEntityChangeBlockEvent(lightning, blockposition1Final, iblockdata1).isCancelled()) // Paper - call EntityChangeBlockEvent
world.setBlockAndUpdate(blockposition1Final, iblockdata1); // CraftBukkit - decompile error
});
world.levelEvent(3002, blockposition1, -1);
diff --git a/src/main/java/net/minecraft/world/item/AxeItem.java b/src/main/java/net/minecraft/world/item/AxeItem.java
index 0bff617f422e7bfececcdc6837ad91db20177388..1c096338a90d740a3813274278056017fa1ec844 100644
--- a/src/main/java/net/minecraft/world/item/AxeItem.java
+++ b/src/main/java/net/minecraft/world/item/AxeItem.java
@@ -54,6 +54,11 @@ public class AxeItem extends DiggerItem {
}
if (optional4.isPresent()) {
+ // Paper start - EntityChangeBlockEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, optional4.get()).isCancelled()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
if (player instanceof ServerPlayer) {
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack);
}
diff --git a/src/main/java/net/minecraft/world/item/EnderEyeItem.java b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
index e0c3aa1285709a40ff0ea8c1d74d43d2b341aecc..f4fc8ff3981555e4b560289248a9b02afc04b42f 100644
--- a/src/main/java/net/minecraft/world/item/EnderEyeItem.java
+++ b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
@@ -43,6 +43,11 @@ public class EnderEyeItem extends Item {
return InteractionResult.SUCCESS;
} else {
BlockState iblockdata1 = (BlockState) iblockdata.setValue(EndPortalFrameBlock.HAS_EYE, true);
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), blockposition, iblockdata1).isCancelled()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
Block.pushEntitiesUp(iblockdata, iblockdata1, world, blockposition);
world.setBlock(blockposition, iblockdata1, 2);
diff --git a/src/main/java/net/minecraft/world/item/HoneycombItem.java b/src/main/java/net/minecraft/world/item/HoneycombItem.java
index 68a8d3b16d49c10fc9834f32009095d35c9c55a8..f0b720eafc538f97d788f89bd2f2e9da0ff84a19 100644
--- a/src/main/java/net/minecraft/world/item/HoneycombItem.java
+++ b/src/main/java/net/minecraft/world/item/HoneycombItem.java
@@ -37,6 +37,14 @@ public class HoneycombItem extends Item {
return getWaxed(blockState).map((state) -> {
Player player = context.getPlayer();
ItemStack itemStack = context.getItemInHand();
+ // Paper start - EntityChangeBlockEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, state).isCancelled()) {
+ if (!player.isCreative()) {
+ player.containerMenu.sendAllDataToRemote();
+ }
+ return InteractionResult.PASS;
+ }
+ // Paper end
if (player instanceof ServerPlayer) {
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack);
}
diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java
index 0b344e20ad4093b135c58905fb82ffff05898bb2..900022ef88d2ae4290fe99e868a9b20f95482d99 100644
--- a/src/main/java/net/minecraft/world/item/PotionItem.java
+++ b/src/main/java/net/minecraft/world/item/PotionItem.java
@@ -107,6 +107,12 @@ public class PotionItem extends Item {
BlockState iblockdata = world.getBlockState(blockposition);
if (context.getClickedFace() != Direction.DOWN && iblockdata.is(BlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(itemstack) == Potions.WATER) {
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityhuman, blockposition, Blocks.MUD.defaultBlockState()).isCancelled()) {
+ entityhuman.containerMenu.sendAllDataToRemote();
+ return InteractionResult.PASS;
+ }
+ // Paper end
world.playSound((Player) null, blockposition, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F);
entityhuman.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE)));
entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
diff --git a/src/main/java/net/minecraft/world/item/ShovelItem.java b/src/main/java/net/minecraft/world/item/ShovelItem.java
index 32995cb5efdad0bc34ecacacb78cccd21220ba8d..c7195f2e12bbd6545f7bffcc2b4ba5cc3d48df20 100644
--- a/src/main/java/net/minecraft/world/item/ShovelItem.java
+++ b/src/main/java/net/minecraft/world/item/ShovelItem.java
@@ -36,20 +36,29 @@ public class ShovelItem extends DiggerItem {
Player player = context.getPlayer();
BlockState blockState2 = FLATTENABLES.get(blockState.getBlock());
BlockState blockState3 = null;
+ Runnable afterAction = null; // Paper
if (blockState2 != null && level.getBlockState(blockPos.above()).isAir()) {
- level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
+ afterAction = () -> level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); // Paper
blockState3 = blockState2;
} else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
+ afterAction = () -> { // Paper
if (!level.isClientSide()) {
level.levelEvent((Player)null, 1009, blockPos, 0);
}
CampfireBlock.dowse(context.getPlayer(), level, blockPos, blockState);
+ }; // Paper
blockState3 = blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false));
}
if (blockState3 != null) {
if (!level.isClientSide) {
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), blockPos, blockState3).isCancelled()) {
+ return InteractionResult.PASS;
+ }
+ afterAction.run();
+ // Paper end
level.setBlock(blockPos, blockState3, 11);
level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(player, blockState3));
if (player != null) {
diff --git a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
index f5c53696a7a5b9dcc09c54a1a68267fd2fb37fa3..564822911c25238900b361d564c5db3103900fb3 100644
--- a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
@@ -221,7 +221,14 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
if (i < 8 && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem())) {
if (i < 7 && !world.isClientSide) {
- BlockState iblockdata1 = ComposterBlock.addItem(state, world, pos, itemstack);
+ // Paper start - EntityChangeBlockEvent
+ double rand = world.getRandom().nextDouble();
+ BlockState dummyBlockState = ComposterBlock.addItem(state, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, pos, itemstack, rand);
+ if (state != dummyBlockState && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, dummyBlockState).isCancelled()) { // if block state will change and event cancelled
+ return InteractionResult.sidedSuccess(world.isClientSide);
+ }
+ BlockState iblockdata1 = ComposterBlock.addItem(state, world, pos, itemstack, rand);
+ // Paper end
world.levelEvent(1500, pos, state != iblockdata1 ? 1 : 0);
player.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));

View file

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Fri, 5 Aug 2022 12:16:51 +0200
Subject: [PATCH] Missing eating regain reason
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java
index a0dd4a58937a4e49e430d8c1470fe84b709e8044..0114c1cf3b6b0500149a77ebc190cb7fa2832184 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Cat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java
@@ -389,7 +389,7 @@ public class Cat extends TamableAnimal implements VariantHolder<CatVariant> {
if (!(item instanceof DyeItem)) {
if (item.isEdible() && this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) {
this.usePlayerItem(player, hand, itemstack);
- this.heal((float) item.getFoodProperties().getNutrition());
+ this.heal((float) item.getFoodProperties().getNutrition(), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper
return InteractionResult.CONSUME;
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
index 136da73e372b59f37665743c70833e815cd0070b..d9104d996c854cce1ff167706c93747cd69c3969 100644
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
@@ -361,7 +361,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Rider
} else {
boolean bl = this.getHealth() < this.getMaxHealth();
if (bl) {
- this.heal(2.0F);
+ this.heal(2.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper
}
boolean bl2 = this.isTamed() && this.getAge() == 0 && this.canFallInLove();
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
index 39c6b9b74e072953abe6398ecfcdd444e6d8f194..7ae0e4b3aa8e861500ddc7b38aa671258b532fcd 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
@@ -217,7 +217,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
}
if (this.getHealth() < this.getMaxHealth() && f > 0.0F) {
- this.heal(f);
+ this.heal(f, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper
flag = true;
}

View file

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Tue, 16 Aug 2022 19:44:55 +0200
Subject: [PATCH] Missing effect cause
diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
index 40869fa047ba86d59ca25f691ddea8c55ed0c6dc..0d7f951e3837de7553d93f3d4525276048feb405 100644
--- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
+++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
@@ -428,7 +428,7 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder<Axolo
player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit
}
- player.removeEffect(MobEffects.DIG_SLOWDOWN);
+ player.removeEffect(MobEffects.DIG_SLOWDOWN, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // Paper
}
@Override
diff --git a/src/main/java/net/minecraft/world/item/HoneyBottleItem.java b/src/main/java/net/minecraft/world/item/HoneyBottleItem.java
index b9dbe5301b04cb1aa5da3a3ee7560c806ce6a411..c8d6b5e60b6c8c612fa8580c63a32c4a8f8b0a7b 100644
--- a/src/main/java/net/minecraft/world/item/HoneyBottleItem.java
+++ b/src/main/java/net/minecraft/world/item/HoneyBottleItem.java
@@ -28,7 +28,7 @@ public class HoneyBottleItem extends Item {
}
if (!world.isClientSide) {
- user.removeEffect(MobEffects.POISON);
+ user.removeEffect(MobEffects.POISON, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // Paper
}
if (stack.isEmpty()) {
diff --git a/src/main/java/net/minecraft/world/item/SuspiciousStewItem.java b/src/main/java/net/minecraft/world/item/SuspiciousStewItem.java
index a4d9bdb63847eb0653a0e0772f7121c1bbaa8459..0d86deac578a3d4af15ed75e94ecd74948eb05cb 100644
--- a/src/main/java/net/minecraft/world/item/SuspiciousStewItem.java
+++ b/src/main/java/net/minecraft/world/item/SuspiciousStewItem.java
@@ -71,7 +71,7 @@ public class SuspiciousStewItem extends Item {
@Override
public ItemStack finishUsingItem(ItemStack stack, Level world, LivingEntity user) {
ItemStack itemStack = super.finishUsingItem(stack, world, user);
- listPotionEffects(itemStack, user::addEffect);
+ listPotionEffects(itemStack, effect -> user.addEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD)); // Paper
return user instanceof Player && ((Player)user).getAbilities().instabuild ? itemStack : new ItemStack(Items.BOWL);
}
}

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nex <nex@bits.team>
Date: Thu, 24 Feb 2022 16:28:07 +0100
Subject: [PATCH] Added byte array serialization/deserialization for
PersistentDataContainers
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
index f0588bec9be09cb8273c310fb3de8bfe72dee9e5..20c7144307ecf1eb5c600f3b84df7bc15fa941d6 100644
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
@@ -168,5 +168,26 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
return this.customDataTags.containsKey(key.toString());
}
+
+ @Override
+ public byte[] serializeToBytes() throws java.io.IOException {
+ net.minecraft.nbt.CompoundTag root = this.toTagCompound();
+ java.io.ByteArrayOutputStream byteArrayOutput = new java.io.ByteArrayOutputStream();
+ try (java.io.DataOutputStream dataOutput = new java.io.DataOutputStream(byteArrayOutput)) {
+ net.minecraft.nbt.NbtIo.write(root, dataOutput);
+ return byteArrayOutput.toByteArray();
+ }
+ }
+
+ @Override
+ public void readFromBytes(byte[] bytes, boolean clear) throws java.io.IOException {
+ if (clear) {
+ this.clear();
+ }
+ try (java.io.DataInputStream dataInput = new java.io.DataInputStream(new java.io.ByteArrayInputStream(bytes))) {
+ net.minecraft.nbt.CompoundTag compound = net.minecraft.nbt.NbtIo.read(dataInput);
+ this.putAll(compound);
+ }
+ }
// Paper end
}

View file

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Mon, 19 Sep 2022 14:16:10 -0700
Subject: [PATCH] Add a consumer parameter to ProjectileSource#launchProjectile
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index f7d20efecfee6aaae2e323d543739308c4bb371c..65f8d9b6a4ecffdf50b88c6924402bdf0668a8f2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -499,8 +499,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
}
@Override
- @SuppressWarnings("unchecked")
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
+ // Paper start - launchProjectile consumer
+ return this.launchProjectile(projectile, velocity, null);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity, org.bukkit.util.Consumer<T> function) {
+ // Paper end - launchProjectile consumer
Preconditions.checkState(!this.getHandle().generation, "Cannot launch projectile during world generation");
net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle();
@@ -583,6 +590,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
if (velocity != null) {
((T) launch.getBukkitEntity()).setVelocity(velocity);
}
+ // Paper start - launchProjectile consumer
+ if (function != null) {
+ function.accept((T) launch.getBukkitEntity());
+ }
+ // Paper end - launchProjectile consumer
world.addFreshEntity(launch);
return (T) launch.getBukkitEntity();
diff --git a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
index 388647c2ef814270942f4e6c6eb57a3abaf84212..2afb7af0a90959edd3b0ead2fe4d9018b5560aa4 100644
--- a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
+++ b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
@@ -57,6 +57,13 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
@Override
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
+ // Paper start - launchProjectile consumer
+ return this.launchProjectile(projectile, velocity, null);
+ }
+
+ @Override
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity, org.bukkit.util.Consumer<T> function) {
+ // Paper end - launchProjectile consumer
Validate.isTrue(this.getBlock().getType() == Material.DISPENSER, "Block is no longer dispenser");
// Copied from BlockDispenser.dispense()
BlockSourceImpl isourceblock = new BlockSourceImpl((ServerLevel) this.dispenserBlock.getLevel(), this.dispenserBlock.getBlockPos());
@@ -147,6 +154,11 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
if (velocity != null) {
((T) launch.getBukkitEntity()).setVelocity(velocity);
}
+ // Paper start
+ if (function != null) {
+ function.accept((T) launch.getBukkitEntity());
+ }
+ // Paper end
world.addFreshEntity(launch);
return (T) launch.getBukkitEntity();

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sun, 7 Aug 2022 22:16:36 +0200
Subject: [PATCH] Call BlockPhysicsEvent more often
diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
index af7b535d14ef279073b3b2ffa29cf88ca8305d1e..b1c594dc6a6b8a6c737b99272acab9e7dbd0ed63 100644
--- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
+++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
@@ -119,7 +119,27 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
public boolean runNext(Level world) {
BlockPos blockPos = this.sourcePos.relative(NeighborUpdater.UPDATE_ORDER[this.idx++]);
BlockState blockState = world.getBlockState(blockPos);
- blockState.neighborChanged(world, blockPos, this.sourceBlock, this.sourcePos, false);
+ // Paper start
+ try {
+ boolean cancelled = false;
+ org.bukkit.craftbukkit.CraftWorld cworld = world.getWorld();
+ if (cworld != null) {
+ org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent(
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, blockPos),
+ org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(blockState),
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, sourcePos));
+
+ if (!event.callEvent()) {
+ cancelled = true;
+ }
+ }
+ if (!cancelled) { // continue to check for adjacent block (increase idx)
+ blockState.neighborChanged(world, blockPos, this.sourceBlock, this.sourcePos, false);
+ }
+ } catch (StackOverflowError ex) {
+ world.lastPhysicsProblem = new BlockPos(blockPos);
+ }
+ // Paper end
if (this.idx < NeighborUpdater.UPDATE_ORDER.length && NeighborUpdater.UPDATE_ORDER[this.idx] == this.skipDirection) {
++this.idx;
}

View file

@ -1,55 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 18 Sep 2022 06:33:17 +0100
Subject: [PATCH] Configurable chat thread limit
By default, spigot shifts chat over to an unbounded thread pool,
on a normal server, this really offers no gains, the creation of a thread
on submitting to the pool on these servers eats more time vs just running it in
the netty pipeline, however, on servers using plugins which do work in here, there
could be some overall benefits to moving this stuff outside of the pipeline.
In general, this patch does two things:
1) Exposes the core size for the pool, this allows for ensuring that a number of threads
sit around in the pool, mitigating the need for creating new threads; This IS however
caveated, the ThreadPoolExecutor will ONLY create core threads as they're needed, it
just won't allow for us to dip back under the # of core threads, this can potentially
be mitigated by calling prestartCoreThread, however, I'm not sure if there is much justification
for this
2) Exposes a max size for the pool, as stated, by default this is unbounded, for most
servers limiting the size of the pool is going to have 0 effects given how fast chat
is actually processed, this is honestly really just exposed for the misnomers or people
who just wanna ensure that this won't grow over a specific size if chat gets stupidly active
diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
index 52b02cb1f02d1c65b840f38cfc8baee500aa2259..8d442c5a498ecf288a0cc0c54889c6e2fda849ce 100644
--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
@@ -254,13 +254,26 @@ public class GlobalConfiguration extends ConfigurationPart {
public Misc misc;
public class Misc extends ConfigurationPart {
+
+ public ChatThreads chatThreads;
public class ChatThreads extends ConfigurationPart.Post {
private int chatExecutorCoreSize = -1;
private int chatExecutorMaxSize = -1;
@Override
public void postProcess() {
- // TODO: FILL
+ //noinspection ConstantConditions
+ if (net.minecraft.server.MinecraftServer.getServer() == null) return; // In testing env, this will be null here
+ int _chatExecutorMaxSize = (chatExecutorMaxSize <= 0) ? Integer.MAX_VALUE : chatExecutorMaxSize; // This is somewhat dumb, but, this is the default, do we cap this?;
+ int _chatExecutorCoreSize = Math.max(chatExecutorCoreSize, 0);
+
+ if (_chatExecutorMaxSize < _chatExecutorCoreSize) {
+ _chatExecutorMaxSize = _chatExecutorCoreSize;
+ }
+
+ java.util.concurrent.ThreadPoolExecutor executor = (java.util.concurrent.ThreadPoolExecutor) net.minecraft.server.MinecraftServer.getServer().chatExecutor;
+ executor.setCorePoolSize(_chatExecutorCoreSize);
+ executor.setMaximumPoolSize(_chatExecutorMaxSize);
}
}
public int maxJoinsPerTick = 5;

View file

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 19 Sep 2022 00:13:02 +0100
Subject: [PATCH] Mitigate effects of WorldCreator#keepSpawnLoaded ret type
change
TODO: Remove in 1.21?
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
index d7c1077f2eb2846a17a5872f01ebb8aabf0cb181..ebbbfc318439fec33331d71563e528cd3429e541 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
@@ -443,6 +443,12 @@ public class Commodore
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/advancement/CraftAdvancement", "getDisplay0", desc, false);
return;
}
+ if (owner.equals("org/bukkit/WorldCreator") && name.equals("keepSpawnLoaded") && desc.equals("(Lnet/kyori/adventure/util/TriState;)V")) {
+ super.visitMethodInsn(opcode, owner, name, "(Lnet/kyori/adventure/util/TriState;)Lorg/bukkit/WorldCreator;", itf);
+ // new method has a return, so, make sure we pop it
+ super.visitInsn(Opcodes.POP);
+ return;
+ }
// Paper end
if ( modern )
{

View file

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 6 Aug 2022 18:10:14 -0400
Subject: [PATCH] Set position before player sending on dimension change
This causes a moment where the player entity is sent with the previous location, and the
teleport packet which is sent shortly after is meant to correct that.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index c7b030ee8973e9e7fdc3ed584229d049d5afe134..32ea4c421ef65a4abce168860ccd24c18a416f0a 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1161,6 +1161,7 @@ public class ServerPlayer extends Player {
// CraftBukkit end
this.setLevel(worldserver);
+ this.moveTo(exit.getX(), exit.getY(), exit.getZ(), exit.getYaw(), exit.getPitch()); // Paper - Set the location before
this.connection.teleport(exit); // CraftBukkit - use internal teleport without event
this.connection.resetPosition();
worldserver.addDuringPortalTeleport(this);

View file

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Legitimoose <legitimoose@gmail.com>
Date: Wed, 28 Sep 2022 22:45:49 -0700
Subject: [PATCH] fix Jigsaw block kicking user
diff --git a/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
index 8efdd41fbd14a2127a6d52577550bb781bc8c5f7..182e16c1d968707a11329150d71b7d01df6c6e52 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
@@ -109,7 +109,12 @@ public class JigsawBlockEntity extends BlockEntity {
public void generate(ServerLevel world, int maxDepth, boolean keepJigsaws) {
BlockPos blockPos = this.getBlockPos().relative(this.getBlockState().getValue(JigsawBlock.ORIENTATION).front());
Registry<StructureTemplatePool> registry = world.registryAccess().registryOrThrow(Registries.TEMPLATE_POOL);
- Holder<StructureTemplatePool> holder = registry.getHolderOrThrow(this.pool);
+ // Paper start - Replace getHolderOrThrow with a null check
+ Holder<StructureTemplatePool> holder = registry.getHolder(this.pool).orElse(null);
+ if (holder == null) {
+ return;
+ }
+ // Paper end
JigsawPlacement.generateJigsaw(world, holder, this.target, maxDepth, blockPos, keepJigsaws);
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java b/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java
index 2c5165835dede1abc07ff508c820f0fe1a1027d0..194864460a5508b6b60f445d6c7923c2ae14a15b 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java
@@ -85,7 +85,13 @@ public class StructureTemplatePool {
}
public StructurePoolElement getRandomTemplate(RandomSource random) {
+ //Paper start - Prevent random.nextInt throwing an IllegalArgumentException
+ if (this.templates.size() == 0) {
+ return EmptyPoolElement.INSTANCE;
+ } else {
return this.templates.get(random.nextInt(this.templates.size()));
+ }
+ // Paper end
}
public List<StructurePoolElement> getShuffledTemplates(RandomSource random) {

View file

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Legitimoose <legitimoose@gmail.com>
Date: Thu, 29 Sep 2022 16:25:50 -0700
Subject: [PATCH] use BlockFormEvent for mud converting into clay
diff --git a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
index 01da5a5684692b3ed2e06834d6f926706925f643..1d7149fb6baeaf045c3680b6dec293f074614612 100644
--- a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -213,10 +213,13 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate
if (((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState.is(Blocks.MUD) && fluidtype == Fluids.WATER) {
BlockState iblockdata1 = Blocks.CLAY.defaultBlockState();
- world.setBlockAndUpdate(((PointedDripstoneBlock.FluidInfo) optional.get()).pos, iblockdata1);
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, iblockdata1)) {
Block.pushEntitiesUp(((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState, iblockdata1, world, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos);
world.gameEvent(GameEvent.BLOCK_CHANGE, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, GameEvent.Context.of(iblockdata1));
world.levelEvent(1504, blockposition1, 0);
+ }
+ //Paper end
} else {
BlockPos blockposition2 = PointedDripstoneBlock.findFillableCauldronBelowStalactiteTip(world, blockposition1, fluidtype);

View file

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Fri, 12 Aug 2022 23:24:37 -0700
Subject: [PATCH] Add getDrops to BlockState
Originally added isPreferredTool to BlockData but
upstream added that.
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
index 966ac60daebb7bb211ab8096fc0c5f33db67320a..a8ab1d3ee81664193be39d2735d6495136e0e310 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
@@ -330,5 +330,33 @@ public class CraftBlockState implements BlockState {
public boolean isCollidable() {
return this.data.getBlock().hasCollision;
}
+
+ @Override
+ public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops() {
+ return this.getDrops(null);
+ }
+
+ @Override
+ public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops(org.bukkit.inventory.ItemStack item) {
+ return this.getDrops(item, null);
+ }
+
+ @Override
+ public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) {
+ net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item);
+
+ // Modelled off EntityHuman#hasBlock
+ if (item == null || !data.requiresCorrectToolForDrops() || nms.isCorrectToolForDrops(data)) {
+ return net.minecraft.world.level.block.Block.getDrops(
+ data,
+ world.getHandle(),
+ position,
+ world.getHandle().getBlockEntity(position), entity == null ? null :
+ ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle(), nms
+ ).stream().map(org.bukkit.craftbukkit.inventory.CraftItemStack::asBukkitCopy).toList();
+ } else {
+ return java.util.Collections.emptyList();
+ }
+ }
// Paper end
}

View file

@ -1,299 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 11 Jul 2022 11:56:41 -0700
Subject: [PATCH] Fix a bunch of vanilla bugs
https://bugs.mojang.com/browse/MC-253884
show raid entity event to all tracking players
https://bugs.mojang.com/browse/MC-253721
wrong msg for opping multiple players
https://bugs.mojang.com/browse/MC-248588
respect mob griefing gamerule for draining water cauldrons
https://bugs.mojang.com/browse/MC-244739
play goat eating sound for last item in stack
https://bugs.mojang.com/browse/MC-243057
ignore furnace fuel slot in recipe book click
https://bugs.mojang.com/browse/MC-147659
Some witch huts spawn the incorrect cat
Note: Marked as Won't Fix, makes 0 sense
https://bugs.mojang.com/browse/MC-179072
Creepers do not defuse when switching from Survival to Creative/Spectator
https://bugs.mojang.com/browse/MC-191591
https://bugs.mojang.com/browse/MC-258360
Fix items equipped on AbstractHorse losing NBT
https://bugs.mojang.com/browse/MC-121048
by: MelnCat <melncatuwu@gmail.com>
This moves the setHealth call to below the recordDamage call to prevent
recordDamage from clearing the CombatTracker, since recordDamage will
clear the CombatTracker if the entity is dead. This fixes death messages
such as the "doomed to fall" messages.
https://bugs.mojang.com/browse/MC-257875
by: Jake Potrebic <jake.m.potrebic@gmail.com>
Fixes server not consuming fire charges when igniting a creeper
https://bugs.mojang.com/browse/MC-258535
by: Jake Potrebic <jake.m.potrebic@gmail.com>
Fixes certain explosion damage not scaling with difficulty
Co-authored-by: William Blake Galbreath <blake.galbreath@gmail.com>
Co-authored-by: MelnCat <melncatuwu@gmail.com>
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index c0c31a5d356d0754b478d84f0cef87fc84c4fea1..3c2ed8e7cf54ab5e32df713010b948d568aab9b0 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -347,7 +347,7 @@ public interface DispenseItemBehavior {
}
}
// CraftBukkit end
- ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS);
+ ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS, CraftItemStack.asNMSCopy(event.getItem())); // Paper - Fix saddles losing nbt data - MC-191591
// itemstack.shrink(1); // CraftBukkit - handled above
this.setSuccess(true);
return stack;
diff --git a/src/main/java/net/minecraft/server/commands/DeOpCommands.java b/src/main/java/net/minecraft/server/commands/DeOpCommands.java
index cca2618d90306eed9894c5fa7b6ed96b68210688..10769c60bd53438d44fbc6192667acdf4cc95594 100644
--- a/src/main/java/net/minecraft/server/commands/DeOpCommands.java
+++ b/src/main/java/net/minecraft/server/commands/DeOpCommands.java
@@ -33,7 +33,7 @@ public class DeOpCommands {
if (playerList.isOp(gameProfile)) {
playerList.deop(gameProfile);
++i;
- source.sendSuccess(Component.translatable("commands.deop.success", targets.iterator().next().getName()), true);
+ source.sendSuccess(Component.translatable("commands.deop.success", gameProfile.getName()), true); // Paper - fixes MC-253721
}
}
diff --git a/src/main/java/net/minecraft/server/commands/OpCommand.java b/src/main/java/net/minecraft/server/commands/OpCommand.java
index 43e77cef0fce75f59aeb05e161668bebb8fca229..ef50fbf8cb3f008827850b5ed33422007be09bd2 100644
--- a/src/main/java/net/minecraft/server/commands/OpCommand.java
+++ b/src/main/java/net/minecraft/server/commands/OpCommand.java
@@ -38,7 +38,7 @@ public class OpCommand {
if (!playerList.isOp(gameProfile)) {
playerList.op(gameProfile);
++i;
- source.sendSuccess(Component.translatable("commands.op.success", targets.iterator().next().getName()), true);
+ source.sendSuccess(Component.translatable("commands.op.success", gameProfile.getName()), true); // Paper - fixes MC-253721
}
}
diff --git a/src/main/java/net/minecraft/world/damagesource/EntityDamageSource.java b/src/main/java/net/minecraft/world/damagesource/EntityDamageSource.java
index 11829c65f459c94db31319352d4650278353f0c0..b53e04854f960682fae94bb2ef5a12e4274fcebf 100644
--- a/src/main/java/net/minecraft/world/damagesource/EntityDamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/EntityDamageSource.java
@@ -48,7 +48,7 @@ public class EntityDamageSource extends DamageSource {
@Override
public boolean scalesWithDifficulty() {
- return this.entity instanceof LivingEntity && !(this.entity instanceof Player);
+ return super.scalesWithDifficulty() || this.entity instanceof LivingEntity && !(this.entity instanceof Player); // Paper - fix MC-258535 - respect the scalesWithDifficulty override
}
@Nullable
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index c9b072a6324e5facdb85db1caaa7e763191f7104..ae7ce73074e12584036288b98e38eec0b55d5982 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -2207,8 +2207,10 @@ public abstract class LivingEntity extends Entity {
// CraftBukkit end
float f3 = this.getHealth();
- this.setHealth(f3 - f);
+ // Paper start - MC-121048
this.getCombatTracker().recordDamage(damagesource, f3, f);
+ this.setHealth(f3 - f);
+ // Paper end
// CraftBukkit start
if (!human) {
this.setAbsorptionAmount(this.getAbsorptionAmount() - f);
diff --git a/src/main/java/net/minecraft/world/entity/Saddleable.java b/src/main/java/net/minecraft/world/entity/Saddleable.java
index effe4c4fb37fe13aece70cdef4966047d4719af9..7152674d3f3fb98198585cb5ece2bb88877345f9 100644
--- a/src/main/java/net/minecraft/world/entity/Saddleable.java
+++ b/src/main/java/net/minecraft/world/entity/Saddleable.java
@@ -9,6 +9,11 @@ public interface Saddleable {
boolean isSaddleable();
void equipSaddle(@Nullable SoundSource sound);
+ // Paper start - Fix saddles losing nbt data - MC-191591
+ default void equipSaddle(final @Nullable SoundSource sound, final @Nullable net.minecraft.world.item.ItemStack stack) {
+ this.equipSaddle(sound);
+ }
+ // Paper end
default SoundEvent getSaddleSoundEvent() {
return SoundEvents.HORSE_SADDLE;
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
index 19540fd4a7f992888fadb6501d0c8a5a7e71fcf6..e241ae250f4f04a17ef2c583d00b065a4ca56a4c 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -21,6 +21,13 @@ public class SwellGoal extends Goal {
return this.creeper.getSwellDir() > 0 || livingEntity != null && this.creeper.distanceToSqr(livingEntity) < 9.0D;
}
+ // Paper start - Fix MC-179072
+ @Override
+ public boolean canContinueToUse() {
+ return !net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(this.creeper.getTarget()) && canUse();
+ }
+ // Paper end
+
@Override
public void start() {
this.creeper.getNavigation().stop();
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
index 0b0377fa1483e4fcb31456af6c7e1749bd8af484..e9f7c08ae3ea9c578971b1ede88788572c20e277 100644
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
@@ -236,9 +236,10 @@ public class Goat extends Animal {
player.setItemInHand(hand, itemstack1);
return InteractionResult.sidedSuccess(this.level.isClientSide);
} else {
+ boolean isFood = this.isFood(itemstack); // Paper - track before stack is possibly decreased to 0 (Fixes MC-244739)
InteractionResult enuminteractionresult = super.mobInteract(player, hand);
- if (enuminteractionresult.consumesAction() && this.isFood(itemstack)) {
+ if (enuminteractionresult.consumesAction() && isFood) { // Paper
this.level.playSound((Player) null, (Entity) this, this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level.random, 0.8F, 1.2F));
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
index 821b88d0c32f946af9af1c2e211b38446fab4ecb..72d660cd2ade39335024897cffb8b8a151a7cb71 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -221,7 +221,13 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
@Override
public void equipSaddle(@Nullable SoundSource sound) {
- this.inventory.setItem(0, new ItemStack(Items.SADDLE));
+ // Paper start - Fix saddles losing nbt data - MC-191591
+ this.equipSaddle(sound, null);
+ }
+ @Override
+ public void equipSaddle(@Nullable SoundSource sound, @Nullable ItemStack stack) {
+ this.inventory.setItem(0, stack != null ? stack : new ItemStack(Items.SADDLE));
+ // Paper end
if (sound != null) {
this.level.playSound((Player) null, (Entity) this, this.getSaddleSoundEvent(), sound, 0.5F, 1.0F);
}
@@ -230,7 +236,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
public void equipArmor(Player player, ItemStack stack) {
if (this.isArmor(stack)) {
- this.inventory.setItem(1, new ItemStack(stack.getItem()));
+ this.inventory.setItem(1, stack.copyWithCount(1)); // Paper - fix equipping items with nbt - MC-258360, MC-191591
if (!player.getAbilities().instabuild) {
stack.shrink(1);
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
index 805e267090285d625dbeb75b06f8c5ad141a75a4..338161d2eb15d9264027961b71678b8d2f020fd8 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
@@ -247,9 +247,15 @@ public class Creeper extends Monster implements PowerableMob {
this.level.playSound(player, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F);
if (!this.level.isClientSide) {
this.ignite();
+ if (itemstack.isDamageableItem()) { // Paper - only call hurtAndBreak for a damageable item - MC-257875
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
entityhuman1.broadcastBreakEvent(hand);
});
+ // Paper start - just consume the item - MC-257875
+ } else if (!player.getAbilities().instabuild) {
+ itemstack.shrink(1);
+ }
+ // Paper end
}
return InteractionResult.sidedSuccess(this.level.isClientSide);
diff --git a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java
index f174094febfdfdc309f1b50877be60bae8a98156..5f407535298a31a34cfe114dd863fd6a9b977707 100644
--- a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java
@@ -87,8 +87,8 @@ public class CatSpawner implements CustomSpawner {
if (cat == null) {
return 0;
} else {
+ cat.moveTo(pos, 0.0F, 0.0F); // Paper - move up - Fix MC-147659
cat.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.NATURAL, (SpawnGroupData)null, (CompoundTag)null);
- cat.moveTo(pos, 0.0F, 0.0F);
world.addFreshEntityWithPassengers(cat);
return 1;
}
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raids.java b/src/main/java/net/minecraft/world/entity/raid/Raids.java
index fa8fcdfea51a35e4a482d3d7b18159099da62706..feb89eb69994bdd1d2f95d2b9992e69251b2bee7 100644
--- a/src/main/java/net/minecraft/world/entity/raid/Raids.java
+++ b/src/main/java/net/minecraft/world/entity/raid/Raids.java
@@ -125,7 +125,7 @@ public class Raids extends SavedData {
// CraftBukkit end
} else {
player.removeEffect(MobEffects.BAD_OMEN);
- player.connection.send(new ClientboundEntityEventPacket(player, (byte) 43));
+ this.level.broadcastEntityEvent(player, net.minecraft.world.entity.EntityEvent.BAD_OMEN_TRIGGERED /* (byte) 43 */); // Paper - Fix MC-253884
}
if (flag) {
@@ -140,7 +140,7 @@ public class Raids extends SavedData {
}
// CraftBukkit end
raid.absorbBadOmen(player);
- player.connection.send(new ClientboundEntityEventPacket(player, (byte) 43));
+ this.level.broadcastEntityEvent(player, net.minecraft.world.entity.EntityEvent.BAD_OMEN_TRIGGERED /* (byte) 43 */); // Paper - Fix MC-253884
if (!raid.hasFirstWaveSpawned()) {
player.awardStat(Stats.RAID_TRIGGER);
CriteriaTriggers.BAD_OMEN.trigger(player);
diff --git a/src/main/java/net/minecraft/world/item/SaddleItem.java b/src/main/java/net/minecraft/world/item/SaddleItem.java
index c35375e15c0368fec12d37a4b82668b51d9fe9ff..0c975875f1f2d0236d42a291486a7e78e1702802 100644
--- a/src/main/java/net/minecraft/world/item/SaddleItem.java
+++ b/src/main/java/net/minecraft/world/item/SaddleItem.java
@@ -18,7 +18,7 @@ public class SaddleItem extends Item {
if (entity instanceof Saddleable saddleable && entity.isAlive()) {
if (!saddleable.isSaddled() && saddleable.isSaddleable()) {
if (!user.level.isClientSide) {
- saddleable.equipSaddle(SoundSource.NEUTRAL);
+ saddleable.equipSaddle(SoundSource.NEUTRAL, stack.copyWithCount(1)); // Paper - Fix saddles losing nbt data - MC-191591
entity.level.gameEvent(entity, GameEvent.EQUIP, entity.position());
stack.shrink(1);
}
diff --git a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
index 2932419b7ca3f066b1db329829af36ba31e17c65..e11eced0bf15dfecaf64f5e1c28e973c38746095 100644
--- a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
@@ -63,7 +63,7 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper
if (!world.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) {
// CraftBukkit start
- if (entity.mayInteract(world, pos)) {
+ if ((entity instanceof net.minecraft.world.entity.player.Player || world.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING)) && entity.mayInteract(world, pos)) { // Paper - Fixes MC-248588
if (!this.handleEntityOnFireInsideWithEvent(state, world, pos, entity)) { // Paper - fix powdered snow cauldron extinguishing entities
return;
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index 1e2af7d3a6d2ad0a298d2f6ac2d8110354282988..cac2768fe520b591990c7bc943ae7e95f49efb31 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -663,13 +663,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
@Override
public void fillStackedContents(StackedContents finder) {
- Iterator iterator = this.items.iterator();
-
- while (iterator.hasNext()) {
- ItemStack itemstack = (ItemStack) iterator.next();
-
- finder.accountStack(itemstack);
- }
+ // Paper start - don't account fuel stack (fixes MC-243057)
+ finder.accountStack(this.items.get(SLOT_INPUT));
+ finder.accountStack(this.items.get(SLOT_RESULT));
+ // Paper end
}
}

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Mon, 3 Oct 2022 20:48:19 +0200
Subject: [PATCH] Remove unnecessary onTrackingStart during navigation warning
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index e9457d8a29d1f54af8415ad006b75d567e524a46..fe960b254c2c6e4f7122392ce6b5c599b6de3961 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2534,7 +2534,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
- if (ServerLevel.this.isUpdatingNavigations) {
+ if (false && ServerLevel.this.isUpdatingNavigations) { // Paper
String s = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration"));
@@ -2619,7 +2619,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
- if (ServerLevel.this.isUpdatingNavigations) {
+ if (false && ServerLevel.this.isUpdatingNavigations) { // Paper
String s = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration"));

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jul 2022 21:50:44 -0700
Subject: [PATCH] Fix custom piglin loved items
Upstream didn't modify the isLovedItem check in wantsToPickup
so piglins never actually tried to pickup interestItems
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
index c3a2b83794c612340edf0bc67f58917f1f96db45..d552deba0a4f20d011defb464d31d8638d37c646 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -402,7 +402,7 @@ public class PiglinAi {
} else {
boolean flag = piglin.canAddToInventory(stack);
- return stack.is(Items.GOLD_NUGGET) ? flag : (PiglinAi.isFood(stack) ? !PiglinAi.hasEatenRecently(piglin) && flag : (!PiglinAi.isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : PiglinAi.isNotHoldingLovedItemInOffHand(piglin) && flag));
+ return stack.is(Items.GOLD_NUGGET) ? flag : (PiglinAi.isFood(stack) ? !PiglinAi.hasEatenRecently(piglin) && flag : (!PiglinAi.isLovedItem(stack, piglin) ? piglin.canReplaceCurrentItem(stack) : PiglinAi.isNotHoldingLovedItemInOffHand(piglin) && flag)); // Paper - upstream missed isLovedItem check
}
}

View file

@ -1,66 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jul 2022 21:45:36 -0700
Subject: [PATCH] EntityPickupItemEvent fixes
Fixes double firing of the event in PiglinAi
Fixes cancelling the event for piglins still triggering the
advancement trigger
Fires the event when a Raider tries to pick up a raid banner
to become raid leader.
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
index 7b42f7bd100808cb2367d0d7c7361e8f2e597502..afa7ecfa8453da510ec5ccecb1ceeb1d9893d259 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
@@ -432,7 +432,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
@Override
protected void pickUpItem(ItemEntity item) {
- this.onItemPickup(item);
+ // this.onItemPickup(item); // Paper - call in PiglinAi#pickUpItem after EntityPickupItemEvent is fired
PiglinAi.pickUpItem(this, item);
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
index d552deba0a4f20d011defb464d31d8638d37c646..2e107f10d497a5696c7bc90ae3c5ecea98edb3e1 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -241,7 +241,10 @@ public class PiglinAi {
ItemStack itemstack;
// CraftBukkit start
- if (drop.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, drop, 0, false).isCancelled()) {
+ // Paper start - fix event firing twice
+ if (drop.getItem().is(Items.GOLD_NUGGET) /* && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, drop, 0, false).isCancelled() */) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, drop, 0, false).isCancelled()) return;
+ // Paper end
piglin.take(drop, drop.getItem().getCount());
itemstack = drop.getItem();
drop.discard();
@@ -251,6 +254,7 @@ public class PiglinAi {
} else {
return;
}
+ piglin.onItemPickup(drop); // Paper - moved from Piglin#pickUpItem
// CraftBukkit end
if (PiglinAi.isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java
index 5f68945264d138ae04d6bcbd5bde310b42e30713..e5ccbaf72f29731f1d1aa939b9297b644a408cd4 100644
--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java
+++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java
@@ -245,6 +245,11 @@ public abstract class Raider extends PatrollingMonster {
boolean flag = this.hasActiveRaid() && this.getCurrentRaid().getLeader(this.getWave()) != null;
if (this.hasActiveRaid() && !flag && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance())) {
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, item, 0, false).isCancelled()) {
+ return;
+ }
+ // Paper end
EquipmentSlot enumitemslot = EquipmentSlot.HEAD;
ItemStack itemstack1 = this.getItemBySlot(enumitemslot);
double d0 = (double) this.getEquipmentDropChance(enumitemslot);

View file

@ -1,60 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 16 Jun 2022 21:57:02 -0700
Subject: [PATCH] Correctly handle interactions with items on cooldown
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 13031576c20bda3bb12c926f6cd938fa5fb105f2..58b093bb1de78ee3b3b2ea364aa50474883f443a 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -512,6 +512,7 @@ public class ServerPlayerGameMode {
BlockState iblockdata = world.getBlockState(blockposition);
InteractionResult enuminteractionresult = InteractionResult.PASS;
boolean cancelledBlock = false;
+ boolean cancelledItem = false; // Paper - correctly handle items on cooldown
if (!iblockdata.getBlock().isEnabled(world.enabledFeatures())) {
return InteractionResult.FAIL;
@@ -521,10 +522,10 @@ public class ServerPlayerGameMode {
}
if (player.getCooldowns().isOnCooldown(stack.getItem())) {
- cancelledBlock = true;
+ cancelledItem = true; // Paper - correctly handle items on cooldown
}
- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); // Paper
+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, cancelledItem, hand, hitResult.getLocation()); // Paper
this.firedInteract = true;
this.interactResult = event.useItemInHand() == Event.Result.DENY;
this.interactPosition = blockposition.immutable();
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 4143f72b8df92bee25399f90a759c8a8fb567cba..6a52ae70b5f7fd9953b6b2605cae722f606e7fec 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -499,6 +499,12 @@ public class CraftEventFactory {
}
public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 hitVec) {
+ // Paper start - correctly handle items on cooldown
+ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, false, hand, hitVec);
+ }
+
+ public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, boolean cancelledItem, InteractionHand hand, Vec3 hitVec) {
+ // Paper end - correctly handle items on cooldown
// Paper end
Player player = (who == null) ? null : (Player) who.getBukkitEntity();
CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
@@ -532,6 +538,11 @@ public class CraftEventFactory {
if (cancelledBlock) {
event.setUseInteractedBlock(Event.Result.DENY);
}
+ // Paper start
+ if (cancelledItem) {
+ event.setUseItemInHand(Result.DENY);
+ }
+ // Paper end
craftServer.getPluginManager().callEvent(event);
return event;

View file

@ -1,65 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jakub Zacek <dawon@dawon.eu>
Date: Sun, 24 Apr 2022 22:56:59 +0200
Subject: [PATCH] Add PlayerInventorySlotChangeEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 32ea4c421ef65a4abce168860ccd24c18a416f0a..7baf5c0852b5e2edea6459eb2c8de1ebc1ede822 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -321,6 +321,25 @@ public class ServerPlayer extends Player {
}
}
+ // Paper start
+ @Override
+ public void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack oldStack, ItemStack stack) {
+ Slot slot = handler.getSlot(slotId);
+ if (!(slot instanceof ResultSlot)) {
+ if (slot.container == ServerPlayer.this.getInventory()) {
+ if (io.papermc.paper.event.player.PlayerInventorySlotChangeEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack);
+ return;
+ }
+ io.papermc.paper.event.player.PlayerInventorySlotChangeEvent event = new io.papermc.paper.event.player.PlayerInventorySlotChangeEvent(ServerPlayer.this.getBukkitEntity(), slotId, CraftItemStack.asBukkitCopy(oldStack), CraftItemStack.asBukkitCopy(stack));
+ event.callEvent();
+ if (event.shouldTriggerAdvancements()) {
+ CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack);
+ }
+ }
+ }
+ }
+ // Paper end
@Override
public void dataChanged(AbstractContainerMenu handler, int property, int value) {}
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index f7bce1cdad50aec0f8df9d996de7dbec38baec69..fcedd5afe138a97063d2fdd50edb1da16dcff9fd 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -302,7 +302,7 @@ public abstract class AbstractContainerMenu {
while (iterator.hasNext()) {
ContainerListener icrafting = (ContainerListener) iterator.next();
- icrafting.slotChanged(this, slot, itemstack2);
+ icrafting.slotChanged(this, slot, itemstack1, itemstack2); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerListener.java b/src/main/java/net/minecraft/world/inventory/ContainerListener.java
index 0e19cc55646625bf32a354d3df2dc2d6bcff96f4..8ca9c14310b1e809662dd4ca6d35668992c2fc8d 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerListener.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerListener.java
@@ -5,5 +5,11 @@ import net.minecraft.world.item.ItemStack;
public interface ContainerListener {
void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack stack);
+ // Paper start
+ default void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack oldStack, ItemStack stack) {
+ slotChanged(handler, slotId, stack);
+ }
+ // Paper end
+
void dataChanged(AbstractContainerMenu handler, int property, int value);
}

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Tue, 11 Oct 2022 20:38:47 +0300
Subject: [PATCH] Elder Guardian appearance API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index fb2c4547896fc39a78bc28261a5a6c3764527f6a..8d03824629d7a407f6b94c7ee306cce5ffcea1d3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3046,6 +3046,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// Paper end
+ // Paper start
+ @Override
+ public void showElderGuardian(boolean silent) {
+ if (getHandle().connection != null) getHandle().connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, silent ? 0F : 1F));
+ }
+ // Paper end
+
public Player.Spigot spigot()
{
return this.spigot;

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 12 Oct 2022 00:36:55 +0300
Subject: [PATCH] Allow changing bed's 'occupied' property
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java
index c892c0e37bd4f9b208147e2df16fc9ed024eacf7..71df14b932306aa4c8ea6d4883f6ba053955ec28 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java
@@ -22,4 +22,11 @@ public abstract class CraftBed extends CraftBlockData implements Bed {
public boolean isOccupied() {
return get(CraftBed.OCCUPIED);
}
+
+ // Paper start
+ @Override
+ public void setOccupied(boolean occupied) {
+ set(CraftBed.OCCUPIED, occupied);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
index 66a183fa0af6978dd220a3dde27255ad45e47137..108fbb8ab9142a6f779651f3562a81c6cfaa3c30 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
@@ -51,4 +51,11 @@ public final class CraftBed extends org.bukkit.craftbukkit.block.data.CraftBlock
public java.util.Set<org.bukkit.block.BlockFace> getFaces() {
return getValues(CraftBed.FACING, org.bukkit.block.BlockFace.class);
}
+
+ // Paper start
+ @Override
+ public void setOccupied(boolean occupied) {
+ set(CraftBed.OCCUPIED, occupied);
+ }
+ // Paper end
}

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sun, 16 Oct 2022 12:10:17 -0700
Subject: [PATCH] Add entity knockback API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 65f8d9b6a4ecffdf50b88c6924402bdf0668a8f2..2785c42b9b0a9e22ad544f8a4eb6cb77eaad0db6 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -994,5 +994,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
}
throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category");
}
+
+ @Override
+ public void knockback(double strength, double directionX, double directionZ) {
+ Preconditions.checkArgument(strength > 0, "Knockback strength must be > 0");
+ getHandle().knockback(strength, directionX, directionZ);
+ };
// Paper end
}

View file

@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Sat, 22 Oct 2022 14:47:45 +0200
Subject: [PATCH] Detect headless JREs
Crashes caused by the missing AWT dependency come up in the support channels fairly often.
This patch detects the missing dependency and stops the server with a clear error message,
containing a link to instructions on how to install a non-headless JRE.
diff --git a/src/main/java/io/papermc/paper/util/ServerEnvironment.java b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
index 6bd0afddbcc461149dfe9a5c7a86fff6ea13a5f1..148d233f4f5278ff39eacdaa0f4f0e7d73be936a 100644
--- a/src/main/java/io/papermc/paper/util/ServerEnvironment.java
+++ b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
@@ -37,4 +37,14 @@ public class ServerEnvironment {
public static boolean userIsRootOrAdmin() {
return RUNNING_AS_ROOT_OR_ADMIN;
}
+
+ public static String awtDependencyCheck() {
+ try {
+ new java.awt.Color(0);
+ } catch (UnsatisfiedLinkError e) {
+ return e.getClass().getName() + ": " + e.getMessage();
+ }
+
+ return null;
+ }
}
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index e24b23461c592fae07697d3b2a1929cbc79423df..781b72fd88149642c9fceaecfbfe7546273fb749 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -159,6 +159,18 @@ public class Main {
return;
}
+ // Paper start - Warn on headless
+ String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
+ if (awtException != null) {
+ Main.LOGGER.error("You are using a headless JRE distribution.");
+ Main.LOGGER.error("This distribution is missing certain graphic libraries that the Minecraft server needs to function.");
+ Main.LOGGER.error("For instructions on how to install the non-headless JRE, see https://docs.papermc.io/misc/java-install");
+ Main.LOGGER.error("");
+ Main.LOGGER.error(awtException);
+ return;
+ }
+ // Paper end
+
org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init
// Paper start - fix SPIGOT-5824
File file;

View file

@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lukas81298 <lukas81298@gmail.com>
Date: Tue, 12 Jan 2021 14:41:38 +0100
Subject: [PATCH] fixed entity vehicle collision event not called
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
index fc95865a52e0bffaf55ca9f19e7e6005dcd2ae2e..eec7d7a5b558830111831792c42665724613af23 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
@@ -142,7 +142,15 @@ public abstract class AbstractMinecart extends Entity {
@Override
public boolean canCollideWith(Entity other) {
- return Boat.canVehicleCollide(this, other);
+ // Paper start - fixed VehicleEntityCollisionEvent not called when colliding with player
+ boolean collides = Boat.canVehicleCollide(this, other);
+ if (!collides) {
+ return false;
+ }
+ org.bukkit.event.vehicle.VehicleEntityCollisionEvent collisionEvent = new org.bukkit.event.vehicle.VehicleEntityCollisionEvent((org.bukkit.entity.Vehicle) getBukkitEntity(), other.getBukkitEntity());
+
+ return collisionEvent.callEvent();
+ // Paper end
}
@Override

View file

@ -1,78 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lukas81298 <lukas81298@gommehd.net>
Date: Fri, 22 Jan 2021 21:50:18 +0100
Subject: [PATCH] optimized dirt and snow spreading
diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
index 61783f17b655cbb6430d22fb3a81931ab3ea130c..af46c05a34292d271fd4a809398e6b299e10b12b 100644
--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
@@ -18,8 +18,13 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
}
private static boolean canBeGrass(BlockState state, LevelReader world, BlockPos pos) {
+ // Paper start
+ return canBeGrass(world.getChunk(pos), state, world, pos);
+ }
+ private static boolean canBeGrass(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader world, BlockPos pos) {
+ // Paper end
BlockPos blockposition1 = pos.above();
- BlockState iblockdata1 = world.getBlockState(blockposition1);
+ BlockState iblockdata1 = chunk.getBlockState(blockposition1); // Paper
if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) {
return true;
@@ -33,15 +38,27 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
}
private static boolean canPropagate(BlockState state, LevelReader world, BlockPos pos) {
+ // Paper start
+ return canPropagate(world.getChunk(pos), state, world, pos);
+ }
+
+ private static boolean canPropagate(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader world, BlockPos pos) {
+ // Paper end
BlockPos blockposition1 = pos.above();
- return SpreadingSnowyDirtBlock.canBeGrass(state, world, pos) && !world.getFluidState(blockposition1).is(FluidTags.WATER);
+ return SpreadingSnowyDirtBlock.canBeGrass(chunk, state, world, pos) && !chunk.getFluidState(blockposition1).is(FluidTags.WATER); // Paper
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper
- if (!SpreadingSnowyDirtBlock.canBeGrass(state, world, pos)) {
+ // Paper start
+ net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos);
+ if (cachedBlockChunk == null) { // Is this needed?
+ return;
+ }
+ if (!SpreadingSnowyDirtBlock.canBeGrass(cachedBlockChunk, state, world, pos)) {
+ // Paper end
// CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
return;
@@ -54,9 +71,19 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
for (int i = 0; i < 4; ++i) {
BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
-
- if (world.getBlockState(blockposition1).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(iblockdata1, world, blockposition1)) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, (BlockState) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, world.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit
+ // Paper start
+ if (pos.getX() == blockposition1.getX() && pos.getY() == blockposition1.getY() && pos.getZ() == blockposition1.getZ()) {
+ continue;
+ }
+ net.minecraft.world.level.chunk.ChunkAccess access;
+ if (cachedBlockChunk.locX == blockposition1.getX() >> 4 && cachedBlockChunk.locZ == blockposition1.getZ() >> 4) {
+ access = cachedBlockChunk;
+ } else {
+ access = world.getChunkAt(blockposition1);
+ }
+ if (access.getBlockState(blockposition1).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(access, iblockdata1, world, blockposition1)) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, (BlockState) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, access.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit
+ // Paper end
}
}
}

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: KyGuy2002 <IEatBeans#1165>
Date: Fri, 11 Mar 2022 15:33:10 +0000
Subject: [PATCH] Added EntityToggleSitEvent
diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
index acc25fb309568864dd7b53ad6a7a3ee6ff18e82a..49f52baa02db18af6d8626754423ff157eb9c09c 100644
--- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
@@ -67,7 +67,7 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
}
this.orderedToSit = nbt.getBoolean("Sitting");
- this.setInSittingPose(this.orderedToSit);
+ this.setInSittingPose(this.orderedToSit, false); // Paper - Don't fire event
}
@Override
@@ -125,6 +125,12 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
}
public void setInSittingPose(boolean inSittingPose) {
+ // Paper start
+ this.setInSittingPose(inSittingPose, true);
+ }
+ public void setInSittingPose(boolean inSittingPose, boolean callEvent) {
+ // Paper end
+ if (callEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), inSittingPose).callEvent()) return; // Paper start - call EntityToggleSitEvent
byte b = this.entityData.get(DATA_FLAGS_ID);
if (inSittingPose) {
this.entityData.set(DATA_FLAGS_ID, (byte)(b | 1));
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
index e4edeeb04fd7183514e53e20dcef8aca56f02f7d..bc2b98c9f34ad2b289f5da91d704bd836edec8c1 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
@@ -426,7 +426,7 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
this.setSleeping(nbt.getBoolean("Sleeping"));
this.setVariant(Fox.Type.byName(nbt.getString("Type")));
- this.setSitting(nbt.getBoolean("Sitting"));
+ this.setSitting(nbt.getBoolean("Sitting"), false); // Paper
this.setIsCrouching(nbt.getBoolean("Crouching"));
if (this.level instanceof ServerLevel) {
this.setTargetGoals();
@@ -439,6 +439,12 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
}
public void setSitting(boolean sitting) {
+ this.setSitting(sitting, true);
+ }
+ // Paper start
+ public void setSitting(boolean sitting, boolean fireEvent) {
+ if (fireEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return;
+ // Paper end
this.setFlag(1, sitting);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
index 0a18108fda778af5b600f77533770bd98584d60e..9c1e02c3a990cd0f8bba1c84c170b438278c02a7 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
@@ -132,6 +132,7 @@ public class Panda extends Animal {
}
public void sit(boolean sitting) {
+ if (!new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; // Paper start - call EntityToggleSitEvent
this.setFlag(8, sitting);
}

View file

@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: VytskaLT <VytskaLT@protonmail.com>
Date: Wed, 22 Jun 2022 14:34:28 +0300
Subject: [PATCH] Add fire-tick-delay option
diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java
index cfddfcad9b09970b28dccd2dcd80be2c2dbed0e7..3d3f6b85c8463963d1ba557fab1de7a32cfd1a2f 100644
--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java
@@ -164,7 +164,7 @@ public class FireBlock extends BaseFireBlock {
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world.random));
+ world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world)); // Paper
if (world.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
if (!state.canSurvive(world, pos)) {
fireExtinguished(world, pos); // CraftBukkit - invalid place location
@@ -361,11 +361,13 @@ public class FireBlock extends BaseFireBlock {
public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) {
super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext);
// Paper end
- world.scheduleTick(blockposition, this, getFireTickDelay(world.random));
+ world.scheduleTick(blockposition, this, getFireTickDelay(world)); // Paper
}
- private static int getFireTickDelay(RandomSource random) {
- return 30 + random.nextInt(10);
+ // Paper start - customisable fire tick delay
+ private static int getFireTickDelay(Level world) {
+ return world.paperConfig().environment.fireTickDelay + world.random.nextInt(10);
+ // Paper end
}
@Override

View file

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 4 Dec 2021 13:29:36 -0500
Subject: [PATCH] Add Moving Piston API
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java b/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java
index 04857cc934daee87e8bff1a8bbd8ade349c3952b..b779b4abbf3c257c2aa90697b2ed43172290bf73 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java
@@ -3,9 +3,30 @@ package org.bukkit.craftbukkit.block;
import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import org.bukkit.World;
-public class CraftMovingPiston extends CraftBlockEntityState<PistonMovingBlockEntity> {
+public class CraftMovingPiston extends CraftBlockEntityState<PistonMovingBlockEntity> implements io.papermc.paper.block.MovingPiston { // Paper - Add Moving Piston API
public CraftMovingPiston(World world, PistonMovingBlockEntity tileEntity) {
super(world, tileEntity);
}
+ // Paper start - Add Moving Piston API
+ @Override
+ public org.bukkit.block.data.BlockData getMovingBlock() {
+ return org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(this.getTileEntity().getMovedState());
+ }
+
+ @Override
+ public org.bukkit.block.BlockFace getDirection() {
+ return org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(this.getTileEntity().getDirection());
+ }
+
+ @Override
+ public boolean isExtending() {
+ return this.getTileEntity().isExtending();
+ }
+
+ @Override
+ public boolean isPistonHead() {
+ return this.getTileEntity().isSourcePiston();
+ }
+ // Paper end - Add Moving Piston API
}

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dannyball710 <dannyball710@gmail.com>
Date: Sat, 12 Feb 2022 23:42:48 +0800
Subject: [PATCH] Ignore impossible spawn tick
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index 0e7c2e7640ff2a2cdc3088dcb56314026bfaf95f..af799b61cec48ca290ed66cb47cfc0b244ac41a7 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -80,6 +80,7 @@ public abstract class BaseSpawner {
}
public void serverTick(ServerLevel world, BlockPos pos) {
+ if (spawnCount <= 0 || maxNearbyEntities <= 0) return; // Paper - Ignore impossible spawn tick
// Paper start - Configurable mob spawner tick rate
if (spawnDelay > 0 && --tickDelay > 0) return;
tickDelay = world.paperConfig().tickRates.mobSpawner;

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 23 Jun 2022 19:25:51 -0700
Subject: [PATCH] Track projectile source for fireworks from dispensers
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 3c2ed8e7cf54ab5e32df713010b948d568aab9b0..7ebe73921d197da4f992ddb92cbd4ac7211bd6cf 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -512,6 +512,7 @@ public interface DispenseItemBehavior {
itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed
+ entityfireworks.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.getEntity()); // Paper - track projectile source for fireworks
DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection);
entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F);

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 26 Oct 2022 13:13:12 -0700
Subject: [PATCH] Fix EntityArgument suggestion permissions to align with
EntitySelector#checkPermissions
Fixes where the user has permission for selectors but not their
suggestions, which especially matters when we force suggestions to
the server for this type
diff --git a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
index a2ea64b7ec5f47224312a1e08dd64347be6f7c43..b3c65f6b757c9ca7d26f5e95293c6021ab771a2f 100644
--- a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
+++ b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
@@ -128,7 +128,12 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
StringReader stringreader = new StringReader(suggestionsbuilder.getInput());
stringreader.setCursor(suggestionsbuilder.getStart());
- EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2), true); // Paper
+ // Paper start
+ final boolean permission = object instanceof CommandSourceStack stack
+ ? stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector")
+ : icompletionprovider.hasPermission(2);
+ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, permission, true); // Paper
+ // Paper end
try {
argumentparserselector.parse();

View file

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Denery <dorofeevij@gmail.com>
Date: Mon, 31 Oct 2022 14:20:52 +0300
Subject: [PATCH] Fix EntityCombustEvent cancellation cant fully prevent
entities from being set on fire
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 10d8e11ea1e851b19f038230a9b1fb5c3a024f25..7443fb7fae30f22b2eaa2727c383c56891904068 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3164,6 +3164,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
pluginManager.callEvent(entityCombustEvent);
if (!entityCombustEvent.isCancelled()) {
this.setSecondsOnFire(entityCombustEvent.getDuration(), false);
+ // Paper start - fix EntityCombustEvent cancellation.
+ } else {
+ this.setRemainingFireTicks(this.remainingFireTicks - 1);
+ // Paper end
}
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
index a76c452dc5c2069a3071aec31bfb3e977867161e..2ca656b1323f38eac419563a8306a9d86eaca29f 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
@@ -131,6 +131,10 @@ public abstract class BaseFireBlock extends Block {
if (!event.isCancelled()) {
entity.setSecondsOnFire(event.getDuration(), false);
+ // Paper start - fix EntityCombustEvent cancellation.
+ } else {
+ entity.setRemainingFireTicks(entity.getRemainingFireTicks() - 1);
+ // Paper end
}
// CraftBukkit end
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 6 Nov 2022 22:35:51 +0000
Subject: [PATCH] Prevent compass from loading chunks
diff --git a/src/main/java/net/minecraft/world/item/CompassItem.java b/src/main/java/net/minecraft/world/item/CompassItem.java
index 5d3047a420efe59063e90bfc7b42392127e0ad7d..7c4a2f8bb3efd11db2f8711952cc26a067c6d56b 100644
--- a/src/main/java/net/minecraft/world/item/CompassItem.java
+++ b/src/main/java/net/minecraft/world/item/CompassItem.java
@@ -77,7 +77,7 @@ public class CompassItem extends Item implements Vanishable {
Optional<ResourceKey<Level>> optional = getLodestoneDimension(compoundTag);
if (optional.isPresent() && optional.get() == world.dimension() && compoundTag.contains("LodestonePos")) {
BlockPos blockPos = NbtUtils.readBlockPos(compoundTag.getCompound("LodestonePos"));
- if (!world.isInWorldBounds(blockPos) || !((ServerLevel)world).getPoiManager().existsAtPosition(PoiTypes.LODESTONE, blockPos)) {
+ if (!world.isInWorldBounds(blockPos) || (world.hasChunkAt(blockPos) && !((ServerLevel)world).getPoiManager().existsAtPosition(PoiTypes.LODESTONE, blockPos))) { // Paper
compoundTag.remove("LodestonePos");
}
}

View file

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 18 Sep 2022 13:10:18 -0400
Subject: [PATCH] Add PrePlayerAttackEntityEvent
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 69900f89e7c5f8c6e33025059d7248c7e9371fe9..875a7d2b2ecd75a51af7d158b7acee358b5082fe 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -1233,8 +1233,17 @@ public abstract class Player extends LivingEntity {
}
public void attack(Entity target) {
- if (target.isAttackable()) {
- if (!target.skipAttackInteraction(this)) {
+ // Paper start - PlayerAttackEntityEvent
+ boolean willAttack = target.isAttackable() && !target.skipAttackInteraction(this); // Vanilla logic
+ io.papermc.paper.event.player.PrePlayerAttackEntityEvent playerAttackEntityEvent = new io.papermc.paper.event.player.PrePlayerAttackEntityEvent(
+ (org.bukkit.entity.Player) this.getBukkitEntity(),
+ target.getBukkitEntity(),
+ willAttack
+ );
+
+ if (playerAttackEntityEvent.callEvent() && willAttack) { // Logic moved to willAttack local variable.
+ {
+ // Paper end
float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
float f1;

View file

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 12 Nov 2022 10:08:58 -0800
Subject: [PATCH] ensure reset EnderDragon boss event name
Fix MC-257487
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 8cf4ae35eb66e69de32295d707db6845b4b02962..e9eb32469a5c03f7a3677ef50fd4541c1ed662ad 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -68,7 +68,8 @@ public class EndDragonFight {
private static final int GATEWAY_DISTANCE = 96;
public static final int DRAGON_SPAWN_Y = 128;
private static final Predicate<Entity> VALID_PLAYER = EntitySelector.ENTITY_STILL_ALIVE.and(EntitySelector.withinDistance(0.0D, 128.0D, 0.0D, 192.0D));
- public final ServerBossEvent dragonEvent = (ServerBossEvent)(new ServerBossEvent(Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true);
+ private static final Component DEFAULT_BOSS_EVENT_NAME = Component.translatable("entity.minecraft.ender_dragon"); // Paper
+ public final ServerBossEvent dragonEvent = (ServerBossEvent)(new ServerBossEvent(DEFAULT_BOSS_EVENT_NAME, BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); // Paper
public final ServerLevel level;
private final ObjectArrayList<Integer> gateways = new ObjectArrayList<>();
private final BlockPattern exitPortalPattern;
@@ -450,6 +451,10 @@ public class EndDragonFight {
this.ticksSinceDragonSeen = 0;
if (dragon.hasCustomName()) {
this.dragonEvent.setName(dragon.getDisplayName());
+ // Paper start - reset to default name
+ } else {
+ this.dragonEvent.setName(DEFAULT_BOSS_EVENT_NAME);
+ // Paper end
}
}

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: braindead <totsuka.sama@gmail.com>
Date: Sat, 5 Nov 2022 17:47:26 -0400
Subject: [PATCH] fix MC-252817 (green map markers do not disappear).
this bug is caused by the fact that the itemframe's item is set to empty before the green marker is requested to be removed. this is fixed by getting the mapid from this method's parameter, rather than the air block now stored by the item frame.
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
index db60d29b051bad8d115b333e6c72287860a73123..428523feaa4f30260e32ba03937e88200246c693 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -284,7 +284,9 @@ public class ItemFrame extends HangingEntity {
}
private void removeFramedMap(ItemStack itemstack) {
- this.getFramedMapId().ifPresent((i) -> {
+ // Paper start - fix MC-252817 (green map markers do not disappear)
+ this.getFramedMapIdFromItem(itemstack).ifPresent((i) -> {
+ // Paper end
MapItemSavedData worldmap = MapItem.getSavedData(i, this.level);
if (worldmap != null) {
@@ -302,7 +304,12 @@ public class ItemFrame extends HangingEntity {
public OptionalInt getFramedMapId() {
ItemStack itemstack = this.getItem();
+ // Paper start - fix MC-252817 (green map markers do not disappear)
+ return this.getFramedMapIdFromItem(itemstack);
+ }
+ public OptionalInt getFramedMapIdFromItem(ItemStack itemstack) {
+ // Paper end
if (itemstack.is(Items.FILLED_MAP)) {
Integer integer = MapItem.getMapId(itemstack);

View file

@ -1,57 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dawon <dawon@dawon.eu>
Date: Sat, 15 Oct 2022 00:46:57 +0200
Subject: [PATCH] Add Player Warden Warning API
== AT ==
public net.minecraft.server.level.ServerPlayer wardenSpawnTracker
public net.minecraft.world.entity.monster.warden.WardenSpawnTracker ticksSinceLastWarning
public net.minecraft.world.entity.monster.warden.WardenSpawnTracker cooldownTicks
public net.minecraft.world.entity.monster.warden.WardenSpawnTracker increaseWarningLevel()V
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 8d03824629d7a407f6b94c7ee306cce5ffcea1d3..bd202861639727012506415e4b90f6de808081db 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3051,6 +3051,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void showElderGuardian(boolean silent) {
if (getHandle().connection != null) getHandle().connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, silent ? 0F : 1F));
}
+
+ @Override
+ public int getWardenWarningCooldown() {
+ return this.getHandle().wardenSpawnTracker.cooldownTicks;
+ }
+
+ @Override
+ public void setWardenWarningCooldown(int cooldown) {
+ this.getHandle().wardenSpawnTracker.cooldownTicks = Math.max(cooldown, 0);
+ }
+
+ @Override
+ public int getWardenTimeSinceLastWarning() {
+ return this.getHandle().wardenSpawnTracker.ticksSinceLastWarning;
+ }
+
+ @Override
+ public void setWardenTimeSinceLastWarning(int time) {
+ this.getHandle().wardenSpawnTracker.ticksSinceLastWarning = time;
+ }
+
+ @Override
+ public int getWardenWarningLevel() {
+ return this.getHandle().wardenSpawnTracker.getWarningLevel();
+ }
+
+ @Override
+ public void setWardenWarningLevel(int warningLevel) {
+ this.getHandle().wardenSpawnTracker.setWarningLevel(warningLevel);
+ }
+
+ @Override
+ public void increaseWardenWarningLevel() {
+ this.getHandle().wardenSpawnTracker.increaseWarningLevel();
+ }
// Paper end
public Player.Spigot spigot()

View file

@ -1,75 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sun, 16 Oct 2022 16:12:49 +0200
Subject: [PATCH] More vanilla friendly methods to update trades
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 105f8fcbbc5c7c384b77ca8eb768f1147d6ce4b2..18eac340386a396c9850f53f30d20a41c1437788 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -923,6 +923,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
protected void updateTrades() {
+ // Paper start
+ updateTrades(TRADES_PER_LEVEL);
+ }
+
+ public boolean updateTrades(int amount) {
+ // Paper end
VillagerData villagerdata = this.getVillagerData();
Int2ObjectMap<VillagerTrades.ItemListing[]> int2objectmap = (Int2ObjectMap) VillagerTrades.TRADES.get(villagerdata.getProfession());
@@ -932,9 +938,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
if (avillagertrades_imerchantrecipeoption != null) {
MerchantOffers merchantrecipelist = this.getOffers();
- this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2);
+ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, amount); // Paper
+ return true; // Paper
}
}
+ return false; // Paper
}
public void gossip(ServerLevel world, Villager villager, long time) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index 1fa8026ca63b7e38870daac59936a10b1950561e..a1a8ac55e572156671e47317ba061855be79e5ac 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -99,6 +99,34 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
}
// Paper start
+ @Override
+ public boolean increaseLevel(int amount) {
+ Preconditions.checkArgument(amount > 0, "Level earned must be positive");
+ int supposedFinalLevel = this.getVillagerLevel() + amount;
+ Preconditions.checkArgument(net.minecraft.world.entity.npc.VillagerData.MIN_VILLAGER_LEVEL <= supposedFinalLevel && supposedFinalLevel <= net.minecraft.world.entity.npc.VillagerData.MAX_VILLAGER_LEVEL,
+ "Final level reached after the donation (%d) must be between [%d, %d]".formatted(supposedFinalLevel, net.minecraft.world.entity.npc.VillagerData.MIN_VILLAGER_LEVEL, net.minecraft.world.entity.npc.VillagerData.MAX_VILLAGER_LEVEL));
+
+ it.unimi.dsi.fastutil.ints.Int2ObjectMap<net.minecraft.world.entity.npc.VillagerTrades.ItemListing[]> trades =
+ net.minecraft.world.entity.npc.VillagerTrades.TRADES.get(this.getHandle().getVillagerData().getProfession());
+
+ if (trades == null || trades.isEmpty()) {
+ this.getHandle().setVillagerData(this.getHandle().getVillagerData().setLevel(supposedFinalLevel));
+ return false;
+ }
+
+ while (amount > 0) {
+ this.getHandle().increaseMerchantCareer();
+ amount--;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addTrades(int amount) {
+ Preconditions.checkArgument(amount > 0, "Number of trades unlocked must be positive");
+ return this.getHandle().updateTrades(amount);
+ }
+
@Override
public int getRestocksToday() {
return getHandle().numberOfRestocksToday;

View file

@ -1,205 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Tue, 25 Oct 2022 21:15:37 +0200
Subject: [PATCH] Add /paper dumplisteners command
Co-authored-by: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com>
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
index 5c0b02f1ca8f6594f8f94613edba2783087950f2..f7a92aba7c8b98c44839fd6687dd9b96df893399 100644
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
@@ -2,6 +2,7 @@ package io.papermc.paper.command;
import io.papermc.paper.command.subcommands.ChunkDebugCommand;
import io.papermc.paper.command.subcommands.DumpItemCommand;
+import io.papermc.paper.command.subcommands.DumpListenersCommand;
import io.papermc.paper.command.subcommands.EntityCommand;
import io.papermc.paper.command.subcommands.FixLightCommand;
import io.papermc.paper.command.subcommands.HeapDumpCommand;
@@ -52,6 +53,7 @@ public final class PaperCommand extends Command {
commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
commands.put(Set.of("dumpitem"), new DumpItemCommand());
commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());
+ commands.put(Set.of("dumplisteners"), new DumpListenersCommand());
return commands.entrySet().stream()
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
diff --git a/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java b/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa44d4685de3caee4131449bead7a084868ff976
--- /dev/null
+++ b/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java
@@ -0,0 +1,172 @@
+package io.papermc.paper.command.subcommands;
+
+import com.destroystokyo.paper.util.SneakyThrow;
+import io.papermc.paper.command.PaperSubcommand;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import net.kyori.adventure.text.Component;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.event.HandlerList;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.RegisteredListener;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+import static net.kyori.adventure.text.Component.newline;
+import static net.kyori.adventure.text.Component.space;
+import static net.kyori.adventure.text.Component.text;
+import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
+import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
+
+@DefaultQualifier(NonNull.class)
+public final class DumpListenersCommand implements PaperSubcommand {
+ private static final MethodHandle EVENT_TYPES_HANDLE;
+
+ static {
+ try {
+ final Field eventTypesField = HandlerList.class.getDeclaredField("EVENT_TYPES");
+ eventTypesField.setAccessible(true);
+ EVENT_TYPES_HANDLE = MethodHandles.lookup().unreflectGetter(eventTypesField);
+ } catch (final ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
+ if (args.length >= 1 && args[0].equals("tofile")) {
+ this.dumpToFile(sender);
+ return true;
+ }
+ this.doDumpListeners(sender, args);
+ return true;
+ }
+
+ private void dumpToFile(final CommandSender sender) {
+ final File file = new File("debug/listeners-"
+ + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt");
+ file.getParentFile().mkdirs();
+ try (final PrintWriter writer = new PrintWriter(file)) {
+ for (final String eventClass : eventClassNames()) {
+ final HandlerList handlers;
+ try {
+ handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null);
+ } catch (final ReflectiveOperationException e) {
+ continue;
+ }
+ if (handlers.getRegisteredListeners().length != 0) {
+ writer.println(eventClass);
+ }
+ for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) {
+ writer.println(" - " + registeredListener);
+ }
+ }
+ } catch (final IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ sender.sendMessage(text("Dumped listeners to " + file, GREEN));
+ }
+
+ private void doDumpListeners(final CommandSender sender, final String[] args) {
+ if (args.length == 0) {
+ sender.sendMessage(text("Usage: /paper dumplisteners tofile|<className>", RED));
+ return;
+ }
+
+ try {
+ final HandlerList handlers = (HandlerList) findClass(args[0]).getMethod("getHandlerList").invoke(null);
+
+ if (handlers.getRegisteredListeners().length == 0) {
+ sender.sendMessage(text(args[0] + " does not have any registered listeners."));
+ return;
+ }
+
+ sender.sendMessage(text("Listeners for " + args[0] + ":"));
+
+ for (final RegisteredListener listener : handlers.getRegisteredListeners()) {
+ final Component hoverText = text("Priority: " + listener.getPriority().name() + " (" + listener.getPriority().getSlot() + ")", WHITE)
+ .append(newline())
+ .append(text("Listener: " + listener.getListener()))
+ .append(newline())
+ .append(text("Executor: " + listener.getExecutor()))
+ .append(newline())
+ .append(text("Ignoring cancelled: " + listener.isIgnoringCancelled()));
+
+ sender.sendMessage(text(listener.getPlugin().getName(), GREEN)
+ .append(space())
+ .append(text("(" + listener.getListener().getClass().getName() + ")", GRAY).hoverEvent(hoverText)));
+ }
+
+ sender.sendMessage(text("Total listeners: " + handlers.getRegisteredListeners().length));
+
+ } catch (final ClassNotFoundException e) {
+ sender.sendMessage(text("Unable to find a class named '" + args[0] + "'. Make sure to use the fully qualified name.", RED));
+ } catch (final NoSuchMethodException e) {
+ sender.sendMessage(text("Class '" + args[0] + "' does not have a valid getHandlerList method.", RED));
+ } catch (final ReflectiveOperationException e) {
+ sender.sendMessage(text("Something went wrong, see the console for more details.", RED));
+ MinecraftServer.LOGGER.warn("Error occurred while dumping listeners for class " + args[0], e);
+ }
+ }
+
+ @Override
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
+ return switch (args.length) {
+ case 0 -> suggestions();
+ case 1 -> suggestions().stream()
+ .filter(clazz -> clazz.toLowerCase(Locale.ROOT).contains(args[0].toLowerCase(Locale.ROOT)))
+ .toList();
+ default -> Collections.emptyList();
+ };
+ }
+
+ private static List<String> suggestions() {
+ final List<String> ret = new ArrayList<>();
+ ret.add("tofile");
+ ret.addAll(eventClassNames());
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Set<String> eventClassNames() {
+ try {
+ return (Set<String>) EVENT_TYPES_HANDLE.invokeExact();
+ } catch (final Throwable e) {
+ SneakyThrow.sneaky(e);
+ return Collections.emptySet(); // Unreachable
+ }
+ }
+
+ private static Class<?> findClass(final String className) throws ClassNotFoundException {
+ try {
+ return Class.forName(className);
+ } catch (final ClassNotFoundException ignore) {
+ for (final Plugin plugin : Bukkit.getServer().getPluginManager().getPlugins()) {
+ if (!plugin.isEnabled()) {
+ continue;
+ }
+
+ try {
+ return Class.forName(className, false, plugin.getClass().getClassLoader());
+ } catch (final ClassNotFoundException ignore0) {
+ }
+ }
+ }
+ throw new ClassNotFoundException(className);
+ }
+}

View file

@ -1,109 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 22 Nov 2022 13:16:01 -0800
Subject: [PATCH] check global player list where appropriate
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index fe960b254c2c6e4f7122392ce6b5c599b6de3961..e84c67f02bce4c2f9c4eeca1b888d53377fb20d7 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2656,4 +2656,12 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}
+
+ // Paper start
+ @Override
+ @Nullable
+ public Player getGlobalPlayerByUUID(UUID uuid) {
+ return this.server.getPlayerList().getPlayer(uuid);
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index ae7ce73074e12584036288b98e38eec0b55d5982..b45b17b3c04dd655ad42f5b49c423eab04adce48 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3609,7 +3609,7 @@ public abstract class LivingEntity extends Entity {
}
public void onItemPickup(ItemEntity item) {
- net.minecraft.world.entity.player.Player entityhuman = item.getThrower() != null ? this.level.getPlayerByUUID(item.getThrower()) : null;
+ net.minecraft.world.entity.player.Player entityhuman = item.getThrower() != null ? this.level.getGlobalPlayerByUUID(item.getThrower()) : null; // Paper - check all players
if (entityhuman instanceof ServerPlayer) {
CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entityhuman, item.getItem(), this);
diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java
index 6216513805add7c8f52e1ed6c77e2d26786b3ab5..3c4d142e982c34a23bdb5da1f51c8dcacc0532c1 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java
@@ -210,7 +210,7 @@ public abstract class Animal extends AgeableMob {
if (this.loveCause == null) {
return null;
} else {
- Player entityhuman = this.level.getPlayerByUUID(this.loveCause);
+ Player entityhuman = this.level.getGlobalPlayerByUUID(this.loveCause); // Paper - check all players
return entityhuman instanceof ServerPlayer ? (ServerPlayer) entityhuman : null;
}
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index d9da6728d60e97eb9032b0a5aa71757d11f36e22..b0976c20c0b7ff0637809ed2082771f5b6f10b7a 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -96,7 +96,7 @@ public class ItemEntity extends Entity {
Level world = this.level;
Objects.requireNonNull(this.level);
- return (Entity) Util.mapNullable(uuid, world::getPlayerByUUID);
+ return (Entity) Util.mapNullable(uuid, world::getGlobalPlayerByUUID); // Paper - check all players
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
index aabedf25fa40ffa0d7b378c6006928f806ef0fa6..71a36cf9b976443cca9ab63cd0eb23253f638562 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -269,7 +269,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
entityvillager.finalizeSpawn(world, world.getCurrentDifficultyAt(entityvillager.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null);
entityvillager.refreshBrain(world);
if (this.conversionStarter != null) {
- Player entityhuman = world.getPlayerByUUID(this.conversionStarter);
+ Player entityhuman = world.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check all players
if (entityhuman instanceof ServerPlayer) {
CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager);
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index d860ddae508f53d06f74d8ae0efdfc500c1ddf07..3b959f42d958bf0f426853aee56753d6c455fcdb 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -243,4 +243,11 @@ public interface EntityGetter {
return null;
}
+
+ // Paper start
+ @Nullable
+ default Player getGlobalPlayerByUUID(UUID uuid) {
+ return this.getPlayerByUUID(uuid);
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
index f027c2967fcaf5c22abb03c977689485983382c4..0554afa72ae6d2f01886916031c8b90b0d45eb52 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
@@ -100,6 +100,13 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationLi
@Nullable
public static ServerPlayer tryGetPlayer(@Nullable Entity entity) {
+ // Paper start - ensure level is the same for sculk events
+ final ServerPlayer player = tryGetPlayer0(entity);
+ return player != null && player.level == entity.level ? player : null;
+ }
+ @Nullable
+ private static ServerPlayer tryGetPlayer0(@Nullable Entity entity) {
+ // Paper end
if (entity instanceof ServerPlayer serverPlayer) {
return serverPlayer;
} else {

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 18 Mar 2022 21:30:00 -0700
Subject: [PATCH] Fix async entity add due to fungus trees
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
index 52fd12c474c01f3b53d0f6596b7a6fafee52bd0d..877498729c66de9aa6a27c9148f7494d7895615c 100644
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
@@ -228,6 +228,7 @@ public class WorldGenRegion implements WorldGenLevel {
if (iblockdata.isAir()) {
return false;
} else {
+ if (drop) LOGGER.warn("Potential async entity add during worldgen", new Throwable()); // Paper - log when this happens
if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation
BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index d99f079e03d0541d7aa3c70d9e8c12b8619b2c22..09be3f188f9710fa71c5db67023e654739721f21 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -375,10 +375,10 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
((ChorusFlowerBlock) Blocks.CHORUS_FLOWER).generatePlant(access, pos, random, 8);
return true;
case CRIMSON_FUNGUS:
- gen = TreeFeatures.CRIMSON_FUNGUS_PLANTED;
+ gen = this.isNormalWorld() ? TreeFeatures.CRIMSON_FUNGUS_PLANTED : TreeFeatures.CRIMSON_FUNGUS; // Paper - if world gen, don't use planted version
break;
case WARPED_FUNGUS:
- gen = TreeFeatures.WARPED_FUNGUS_PLANTED;
+ gen = this.isNormalWorld() ? TreeFeatures.WARPED_FUNGUS_PLANTED : TreeFeatures.WARPED_FUNGUS; // Paper - if world gen, don't use planted version
break;
case AZALEA:
gen = TreeFeatures.AZALEA_TREE;

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 8 May 2022 13:35:45 -0700
Subject: [PATCH] ItemStack damage API
Adds methods notify clients about item breaks and
to simulate damage done to an itemstack and all
the logic associated with damaging them
== AT ==
public net.minecraft.world.entity.LivingEntity entityEventForEquipmentBreak(Lnet/minecraft/world/entity/EquipmentSlot;)B
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 2785c42b9b0a9e22ad544f8a4eb6cb77eaad0db6..7a7647fbe7dc4167c4e90fbd63e03a23e9b2729c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -995,6 +995,53 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category");
}
+ @Override
+ public void broadcastSlotBreak(org.bukkit.inventory.EquipmentSlot slot) {
+ this.getHandle().broadcastBreakEvent(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot));
+ }
+
+ @Override
+ public void broadcastSlotBreak(org.bukkit.inventory.EquipmentSlot slot, Collection<org.bukkit.entity.Player> players) {
+ if (players.isEmpty()) {
+ return;
+ }
+ final net.minecraft.network.protocol.game.ClientboundEntityEventPacket packet = new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(
+ this.getHandle(),
+ net.minecraft.world.entity.LivingEntity.entityEventForEquipmentBreak(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot))
+ );
+ players.forEach(player -> ((CraftPlayer) player).getHandle().connection.send(packet));
+ }
+
+ @Override
+ public ItemStack damageItemStack(ItemStack stack, int amount) {
+ final net.minecraft.world.item.ItemStack nmsStack;
+ if (stack instanceof CraftItemStack craftItemStack) {
+ if (craftItemStack.handle == null || craftItemStack.handle.isEmpty()) {
+ return stack;
+ }
+ nmsStack = craftItemStack.handle;
+ } else {
+ nmsStack = CraftItemStack.asNMSCopy(stack);
+ stack = CraftItemStack.asCraftMirror(nmsStack); // mirror to capture changes in hurt logic & events
+ }
+ this.damageItemStack0(nmsStack, amount, null);
+ return stack;
+ }
+
+ @Override
+ public void damageItemStack(org.bukkit.inventory.EquipmentSlot slot, int amount) {
+ final net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot);
+ this.damageItemStack0(this.getHandle().getItemBySlot(nmsSlot), amount, nmsSlot);
+ }
+
+ private void damageItemStack0(net.minecraft.world.item.ItemStack nmsStack, int amount, net.minecraft.world.entity.EquipmentSlot slot) {
+ nmsStack.hurtAndBreak(amount, this.getHandle(), livingEntity -> {
+ if (slot != null) {
+ livingEntity.broadcastBreakEvent(slot);
+ }
+ });
+ }
+
@Override
public void knockback(double strength, double directionX, double directionZ) {
Preconditions.checkArgument(strength > 0, "Knockback strength must be > 0");

View file

@ -1,156 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Wed, 15 Sep 2021 20:44:22 +0200
Subject: [PATCH] Friction API
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index b45b17b3c04dd655ad42f5b49c423eab04adce48..0c4a5991d24ec232d2a95977eb37582b6bd8369c 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -265,6 +265,7 @@ public abstract class LivingEntity extends Entity {
public boolean bukkitPickUpLoot;
public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper
@Override
public float getBukkitYaw() {
@@ -705,7 +706,7 @@ public abstract class LivingEntity extends Entity {
}
public boolean shouldDiscardFriction() {
- return this.discardFriction;
+ return !this.frictionState.toBooleanOrElse(!this.discardFriction); // Paper
}
public void setDiscardFriction(boolean noDrag) {
@@ -750,6 +751,11 @@ public abstract class LivingEntity extends Entity {
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end
nbt.putFloat("Health", this.getHealth());
nbt.putShort("HurtTime", (short) this.hurtTime);
nbt.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -792,6 +798,15 @@ public abstract class LivingEntity extends Entity {
absorptionAmount = 0;
}
this.setAbsorptionAmount(absorptionAmount);
+
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ LOGGER.error("Unknown friction state " + fs + " for " + this);
+ }
+ }
// Paper end
if (nbt.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) {
this.getAttributes().load(nbt.getList("Attributes", 10));
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index b0976c20c0b7ff0637809ed2082771f5b6f10b7a..f0ccdfbd7d7be8c6e302609accf8fe9cac8885c4 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -53,6 +53,7 @@ public class ItemEntity extends Entity {
private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit
public boolean canMobPickup = true; // Paper
private int despawnRate = -1; // Paper
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper
public ItemEntity(EntityType<? extends ItemEntity> type, Level world) {
super(type, world);
@@ -150,7 +151,11 @@ public class ItemEntity extends Entity {
this.move(MoverType.SELF, this.getDeltaMovement());
float f1 = 0.98F;
- if (this.onGround) {
+ // Paper start
+ if (frictionState == net.kyori.adventure.util.TriState.FALSE) {
+ f1 = 1F;
+ } else if (this.onGround) {
+ // Paper end
f1 = this.level.getBlockState(new BlockPos(this.getX(), this.getY() - 1.0D, this.getZ())).getBlock().getFriction() * 0.98F;
}
@@ -351,6 +356,11 @@ public class ItemEntity extends Entity {
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end
nbt.putShort("Health", (short) this.health);
nbt.putShort("Age", (short) this.age);
nbt.putShort("PickupDelay", (short) this.pickupDelay);
@@ -384,6 +394,17 @@ public class ItemEntity extends Entity {
this.thrower = nbt.getUUID("Thrower");
}
+ // Paper start
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ com.mojang.logging.LogUtils.getLogger().error("Unknown friction state " + fs + " for " + this);
+ }
+ }
+ // Paper end
+
CompoundTag nbttagcompound1 = nbt.getCompound("Item");
this.setItem(ItemStack.of(nbttagcompound1));
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index fea44ba6a6584b4a510af6a58cab07eecec6b68b..ecec5e17807a760769fc0ea79c2a0161cc5db1ef 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -103,6 +103,18 @@ public class CraftItem extends CraftEntity implements Item {
item.age = willAge ? 0 : NO_AGE_TIME;
}
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public net.kyori.adventure.util.TriState getFrictionState() {
+ return this.item.frictionState;
+ }
+
+ @Override
+ public void setFrictionState(@org.jetbrains.annotations.NotNull net.kyori.adventure.util.TriState state) {
+ java.util.Objects.requireNonNull(state, "state may not be null");
+ this.item.frictionState = state;
+ }
+
@Override
public int getHealth() {
return item.health;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 7a7647fbe7dc4167c4e90fbd63e03a23e9b2729c..f2a7a10df4c283ef3d7e44121c074156556c9cf2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1042,6 +1042,18 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
});
}
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public net.kyori.adventure.util.TriState getFrictionState() {
+ return this.getHandle().frictionState;
+ }
+
+ @Override
+ public void setFrictionState(@org.jetbrains.annotations.NotNull net.kyori.adventure.util.TriState state) {
+ java.util.Objects.requireNonNull(state, "state may not be null");
+ this.getHandle().frictionState = state;
+ }
+
@Override
public void knockback(double strength, double directionX, double directionZ) {
Preconditions.checkArgument(strength > 0, "Knockback strength must be > 0");