finish some more patches

This commit is contained in:
Jake Potrebic 2023-06-07 16:44:11 -07:00
parent b1a2378144
commit 0ca9f14d58
No known key found for this signature in database
GPG key ID: ECE0B3C133C016C5
48 changed files with 141 additions and 125 deletions

View file

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 24 Jul 2020 15:56:05 -0700
Subject: [PATCH] Fix some rails connecting improperly
diff --git a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java
index 682e1cd0f4307bcc716ab82e375bd04cde095aa0..547d09c3a1cd0c5401aacb78886896365ba192e7 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java
@@ -64,6 +64,7 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
state = this.updateDir(world, pos, state, true);
if (this.isStraight) {
world.neighborChanged(state, pos, this, pos, notify);
+ state = world.getBlockState(pos); // Paper - don't desync, update again
}
return state;
diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java
index fe9b6c89a1f0c98a9c73a409f2aca6a4a1c0f9e7..932a2c279f46c951182d2604b525b473b6945895 100644
--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java
@@ -70,6 +70,7 @@ public class DetectorRailBlock extends BaseRailBlock {
private void checkPressed(Level world, BlockPos pos, BlockState state) {
if (this.canSurvive(state, world, pos)) {
+ if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything
boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED);
boolean flag1 = false;
List<AbstractMinecart> list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (entity) -> {
diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java
index 0cbfad97371b59de95963a09aa16f3dad7a37222..d873625c1b8439a727d39ce207b5e84a1d86e5eb 100644
--- a/src/main/java/net/minecraft/world/level/block/RailState.java
+++ b/src/main/java/net/minecraft/world/level/block/RailState.java
@@ -17,6 +17,12 @@ public class RailState {
private final boolean isStraight;
private final List<BlockPos> connections = Lists.newArrayList();
+ // Paper start - prevent desync
+ public boolean isValid() {
+ return this.level.getBlockState(this.pos).getBlock() == this.state.getBlock();
+ }
+ // Paper end - prevent desync
+
public RailState(Level world, BlockPos pos, BlockState state) {
this.level = world;
this.pos = pos;
@@ -143,6 +149,11 @@ public class RailState {
}
private void connectTo(RailState placementHelper) {
+ // Paper start - prevent desync
+ if (!this.isValid() || !placementHelper.isValid()) {
+ return;
+ }
+ // Paper end - prevent desync
this.connections.add(placementHelper.pos);
BlockPos blockPos = this.pos.north();
BlockPos blockPos2 = this.pos.south();
@@ -333,10 +344,15 @@ public class RailState {
this.state = this.state.setValue(this.block.getShapeProperty(), railShape2);
if (forceUpdate || this.level.getBlockState(this.pos) != this.state) {
this.level.setBlock(this.pos, this.state, 3);
+ // Paper start - prevent desync
+ if (!this.isValid()) {
+ return this;
+ }
+ // Paper end - prevent desync
for(int i = 0; i < this.connections.size(); ++i) {
RailState railState = this.getRail(this.connections.get(i));
- if (railState != null) {
+ if (railState != null && railState.isValid()) { // Paper - prevent desync
railState.removeSoftConnections();
if (railState.canConnectTo(this)) {
railState.connectTo(this);
@@ -349,6 +365,6 @@ public class RailState {
}
public BlockState getState() {
- return this.state;
+ return this.level.getBlockState(this.pos); // Paper - prevent desync
}
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: mbax <matt@phozop.net>
Date: Mon, 17 Aug 2020 12:17:37 -0400
Subject: [PATCH] Fix regex mistake in CB NBT int deserialization
The existing regex is too open and allows for the absence of any actual
number data, detecting an NBT entry of just the letter "i" in upper or
lower case. This causes a single-character NBT entry to be processed as
an integer ending in "i", passing an empty String to to Integer.parseInt,
triggering an exception in loading the item.
This commit forces numbers to be present prior to the ending "i"
letter.
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java
index a7f4054002bd176fccf8357e9a23de66dd9e0dc5..207e4302161b3abe2ade56c9dc9c31820010fa42 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java
@@ -19,7 +19,7 @@ import net.minecraft.nbt.TagParser;
public class CraftNBTTagConfigSerializer {
private static final Pattern ARRAY = Pattern.compile("^\\[.*]");
- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE);
+ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex
private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE);
private static final TagParser MOJANGSON_PARSER = new TagParser(new StringReader(""));

View file

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach@zachbr.io>
Date: Tue, 23 Jul 2019 20:44:47 -0500
Subject: [PATCH] Do not let the server load chunks from newer versions
If the server attempts to load a chunk generated by a newer version of
the game, immediately stop the server to prevent data corruption.
You can override this functionality at your own peril.
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index 24892ae367e19038625e243bcdf1bb694632ede5..b080734582e70e4e8d2313c8dc7ab9e0f1294f3d 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -94,7 +94,20 @@ public class ChunkSerializer {
public ChunkSerializer() {}
+ // Paper start
+ private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion();
+ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion");
+ // Paper end
public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) {
+ // Paper start - Do NOT attempt to load chunks saved with newer versions
+ if (nbt.contains("DataVersion", 99)) {
+ int dataVersion = nbt.getInt("DataVersion");
+ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) {
+ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace();
+ System.exit(1);
+ }
+ }
+ // Paper end
ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
if (!Objects.equals(chunkPos, chunkcoordintpair1)) {

View file

@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DigitalRegent <misterwener@gmail.com>
Date: Sat, 11 Apr 2020 13:10:58 +0200
Subject: [PATCH] Brand support
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 2768e46562f36bcb11cead95e65deb8db4884a12..a7d9ff0e33ae674df20e23561cba9a26bd67395d 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -302,6 +302,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); // Paper
+ private String clientBrandName = null; // Paper - Brand name
+
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) {
this.lastChatTimeStamp = new AtomicReference(Instant.EPOCH);
this.lastSeenMessages = new LastSeenMessagesValidator(20);
@@ -3300,6 +3302,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register");
private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister");
+ private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support
+
@Override
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
@@ -3327,6 +3331,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
try {
byte[] data = new byte[packet.data.readableBytes()];
packet.data.readBytes(data);
+ // Paper start - Brand support
+ if (packet.identifier.equals(MINECRAFT_BRAND)) {
+ try {
+ this.clientBrandName = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.copiedBuffer(data)).readUtf(256);
+ } catch (StringIndexOutOfBoundsException ex) {
+ this.clientBrandName = "illegal";
+ }
+ }
+ // Paper end
this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data);
} catch (Exception ex) {
ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex);
@@ -3336,6 +3349,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
}
+ // Paper start - brand support
+ public String getClientBrandName() {
+ return clientBrandName;
+ }
+ // Paper end
+
public final boolean isDisconnected() {
return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 37e3095e4444097b9b6020d1d0aee27b870c3588..e67e69d36c97bee0880e7f21dab1c9a4ca196baa 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2906,6 +2906,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
// Paper end
};
+ // Paper start - brand support
+ @Override
+ public String getClientBrandName() {
+ return getHandle().connection != null ? getHandle().connection.getClientBrandName() : null;
+ }
+ // Paper end
+
public Player.Spigot spigot()
{
return this.spigot;

View file

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 22 Aug 2020 23:59:30 +0200
Subject: [PATCH] Add #setMaxPlayers API
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 7f59e8acee468a6adcd251c19e2dff15619cd52e..852ced8023b68d77494f1f04eb365b379f95a651 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -155,7 +155,7 @@ public abstract class PlayerList {
private boolean doWhiteList;
private final LayeredRegistryAccess<RegistryLayer> registries;
private final RegistryAccess.Frozen synchronizedRegistries;
- protected final int maxPlayers;
+ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter
private int viewDistance;
private int simulationDistance;
private boolean allowCheatsForAllPlayers;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index fcf6585a66a95c3414c2b4eb384b9321aa678c22..e59844bd1bd6a68314b44b947236e3d3194f9102 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -672,6 +672,13 @@ public final class CraftServer implements Server {
return this.playerList.getMaxPlayers();
}
+ // Paper start
+ @Override
+ public void setMaxPlayers(int maxPlayers) {
+ this.playerList.setMaxPlayers(maxPlayers);
+ }
+ // Paper end
+
// NOTE: These are dependent on the corresponding call in MinecraftServer
// so if that changes this will need to as well
@Override

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 23 Aug 2020 19:36:22 +0200
Subject: [PATCH] Add playPickupItemAnimation to LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 658d4dbb45d17e7064f69b10af8fbfa473a8dffe..fb783efc63e8c782e34380ff98d92b644ea2665c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -901,5 +901,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
((Mob) getHandle()).getJumpControl().jump();
}
}
+
+ @Override
+ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) {
+ getHandle().take(((CraftItem) item).getHandle(), quantity);
+ }
// Paper end
}

View file

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sun, 23 Aug 2020 19:01:04 +0200
Subject: [PATCH] Don't require FACING data
diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
index da6a145b06e217ff82b0a1b04410238dc50d4869..1e6ba6d9cceda1d4867b183c3dbc03d317ed287f 100644
--- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
@@ -14,6 +14,7 @@ import org.bukkit.event.block.BlockDispenseEvent;
// CraftBukkit end
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
+ private Direction enumdirection; // Paper
// CraftBukkit start
private boolean dropper;
@@ -27,15 +28,16 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
@Override
public final ItemStack dispense(BlockSource pointer, ItemStack stack) {
+ enumdirection = pointer.getBlockState().getValue(DispenserBlock.FACING); // Paper - cache facing direction
ItemStack itemstack1 = this.execute(pointer, stack);
this.playSound(pointer);
- this.playAnimation(pointer, (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction
return itemstack1;
}
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
- Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+ // Paper - cached enum direction
Position iposition = DispenserBlock.getDispensePosition(pointer);
ItemStack itemstack1 = stack.split(1);

View file

@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 22 Aug 2020 23:36:21 +0200
Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 1a904c0d832197b5f820b9dd417c6d38f7fcc311..945fdae271d18d9b25012d0b6876ec65ef8f2711 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1771,9 +1771,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
public void setDefaultSpawnPos(BlockPos pos, float angle) {
// Paper - configurable spawn radius
BlockPos prevSpawn = this.getSharedSpawnPos();
+ Location prevSpawnLoc = this.getWorld().getSpawnLocation(); // Paper
//ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c()));
this.levelData.setSpawn(pos, angle);
+ new org.bukkit.event.world.SpawnChangeEvent(this.getWorld(), prevSpawnLoc).callEvent(); // Paper
if (this.keepSpawnInMemory) {
// if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add
this.removeTicketsForSpawn(this.paperConfig().spawn.keepSpawnLoadedRange * 16, prevSpawn);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 4ee07d866c23ffe3061ccf0d663e5d4235b9007e..4e23d00f481697257adf9eae5bed4d02a2d5419b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -260,12 +260,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean setSpawnLocation(int x, int y, int z, float angle) {
try {
- Location previousLocation = this.getSpawnLocation();
- world.levelData.setSpawn(new BlockPos(x, y, z), angle);
+ // Location previousLocation = this.getSpawnLocation(); // Paper - moved to nms.ServerLevel
+ world.setDefaultSpawnPos(new BlockPos(x, y, z), angle); // Paper - use ServerLevel#setDefaultSpawnPos
+ // Paper start - move to nms.ServerLevel
// Notify anyone who's listening.
- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
- this.server.getPluginManager().callEvent(event);
+ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
+ // server.getPluginManager().callEvent(event);
+ // Paper end
return true;
} catch (Exception e) {

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 16:32:11 +0200
Subject: [PATCH] Add moon phase API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index cb6f5fc352aff449173825d4e7fad9fccb9df915..5f9c3c237b65986f8c425bbc691ac301f8fdebbc 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -984,4 +984,11 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
throw new IllegalArgumentException("Cannot spawn an entity for " + clazz.getName());
}
+
+ // Paper start
+ @Override
+ public io.papermc.paper.world.MoonPhase getMoonPhase() {
+ return io.papermc.paper.world.MoonPhase.getPhase(this.getHandle().dayTime() / 24000L);
+ }
+ // Paper end
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: commandblockguy <commandblockguy1@gmail.com>
Date: Fri, 14 Aug 2020 14:44:14 -0500
Subject: [PATCH] Prevent headless pistons from being created
Prevent headless pistons from being created by explosions or tree/mushroom growth.
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index d646660f988994d4fdb05901349c5946a2f6c48c..316df76570a7a6843b5a8ed2c44467a0cdf2a6cd 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -183,6 +183,15 @@ public class Explosion {
if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) {
set.add(blockposition);
+ // Paper start - prevent headless pistons from forming
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) {
+ BlockEntity extension = this.level.getBlockEntity(blockposition);
+ if (extension instanceof net.minecraft.world.level.block.piston.PistonMovingBlockEntity blockEntity && blockEntity.isSourcePiston()) {
+ net.minecraft.core.Direction direction = iblockdata.getValue(net.minecraft.world.level.block.piston.PistonHeadBlock.FACING);
+ set.add(blockposition.relative(direction.getOpposite()));
+ }
+ }
+ // Paper end
}
d4 += d0 * 0.30000001192092896D;

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eearslya Sleiarion <eearslya@gmail.com>
Date: Sun, 23 Aug 2020 13:04:02 +0200
Subject: [PATCH] Add BellRingEvent
Add a new event, BellRingEvent, to trigger whenever a player rings a
village bell. Passes along the bell block and the player who rang it.
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 2502da6e68f97a7c37f1756d6845e531da1663c3..6528757c99c55c1d9926da89efed468def758af3 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -332,10 +332,11 @@ public class CraftEventFactory {
return tradeSelectEvent;
}
+ @SuppressWarnings("deprecation") // Paper use deprecated event to maintain compat (it extends modern event)
public static boolean handleBellRingEvent(Level world, BlockPos position, Direction direction, Entity entity) {
Block block = CraftBlock.at(world, position);
BlockFace bukkitDirection = CraftBlock.notchToBlockFace(direction);
- BellRingEvent event = new BellRingEvent(block, bukkitDirection, (entity != null) ? entity.getBukkitEntity() : null);
+ BellRingEvent event = new io.papermc.paper.event.block.BellRingEvent(block, bukkitDirection, (entity != null) ? entity.getBukkitEntity() : null); // Paper - deprecated BellRingEvent
Bukkit.getPluginManager().callEvent(event);
return !event.isCancelled();
}

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 15:47:34 +0200
Subject: [PATCH] Add zombie targets turtle egg config
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index fae2c89900db222f7319b5675ef4b470beca251b..5371ddc75a371a273b5697e620503da9d23e3fbf 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -108,7 +108,7 @@ public class Zombie extends Monster {
@Override
protected void registerGoals() {
- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3));
+ if (level.paperConfig().entities.behavior.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
this.addBehaviourGoals();

View file

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 19 Aug 2020 05:05:54 +0100
Subject: [PATCH] Buffer joins to world
This patch buffers the number of logins which will attempt to join
the world per tick, this attempts to reduce the impact that join floods
has on the server
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index e857327b796455953e76ddf70913c37a3f1e2ee2..31bdeff1f6bb536c78240efc2dd9c4774e634e11 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -286,14 +286,29 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
}
+ private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper
+ private static int joinAttemptsThisTick; // Paper
+ private static int currTick; // Paper
public void tick() {
this.flushQueue();
+ // Paper start
+ if (Connection.currTick != net.minecraft.server.MinecraftServer.currentTick) {
+ Connection.currTick = net.minecraft.server.MinecraftServer.currentTick;
+ Connection.joinAttemptsThisTick = 0;
+ }
+ // Paper end
PacketListener packetlistener = this.packetListener;
if (packetlistener instanceof TickablePacketListener) {
TickablePacketListener tickablepacketlistener = (TickablePacketListener) packetlistener;
+ // Paper start - limit the number of joins which can be processed each tick
+ if (!(this.packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener)
+ || loginPacketListener.state != net.minecraft.server.network.ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT
+ || Connection.joinAttemptsThisTick++ < MAX_PER_TICK) {
tickablepacketlistener.tick();
+ }
+ // Paper end
}
if (!this.isConnected() && !this.disconnectionHandled) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Thu, 27 Aug 2020 16:57:25 -0400
Subject: [PATCH] Fix hex colors not working in some kick messages
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
index 94b062874ef9d4935a7ad2c7b45b2e6b786eaa81..4fb1fde4983d81cc35e2c8717984d929460959b8 100644
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
@@ -77,12 +77,12 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
}
// CraftBukkit end
if (packet.getProtocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
- MutableComponent ichatmutablecomponent;
+ Component ichatmutablecomponent; // Paper - Fix hex colors not working in some kick messages
if (packet.getProtocolVersion() < 754) {
- ichatmutablecomponent = Component.literal( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot
+ ichatmutablecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages
} else {
- ichatmutablecomponent = Component.literal( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot
+ ichatmutablecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages
}
this.connection.send(new ClientboundLoginDisconnectPacket(ichatmutablecomponent));
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 9858f907e58fa606510f87efbdf8793c35ec711c..c9f8f61c43428c519c0dac1b7416bad775e3429f 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -102,7 +102,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
// CraftBukkit start
@Deprecated
public void disconnect(String s) {
- this.disconnect(Component.literal(s));
+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages
}
// CraftBukkit end

View file

@ -0,0 +1,138 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Fri, 21 Aug 2020 20:57:54 +0200
Subject: [PATCH] PortalCreateEvent needs to know its entity
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 020737fba27b6615905da4ac1724bbac8ec0bf4f..12c0e0096153d1c7166829d6f7417d54d364df67 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -447,7 +447,7 @@ public final class ItemStack {
net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition);
if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically
- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true);
+ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext
}
world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point
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 2bc31c28d0d5469476699b69efa6e07325f2a852..4066dd6a638cf2186c628905915f635326442b3e 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
@@ -138,20 +138,23 @@ public abstract class BaseFireBlock extends Block {
super.entityInside(state, world, pos, entity);
}
+ // Paper start - ItemActionContext param
+ @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { this.onPlace(state, world, pos, oldState, notify, null); }
@Override
- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
- if (!oldState.is(state.getBlock())) {
+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, net.minecraft.world.item.context.UseOnContext itemActionContext) {
+ // Paper end
+ if (!iblockdata1.is(iblockdata.getBlock())) {
if (BaseFireBlock.inPortalDimension(world)) {
- Optional<PortalShape> optional = PortalShape.findEmptyPortalShape(world, pos, Direction.Axis.X);
+ Optional<PortalShape> optional = PortalShape.findEmptyPortalShape(world, blockposition, Direction.Axis.X);
if (optional.isPresent()) {
- ((PortalShape) optional.get()).createPortalBlocks();
+ ((PortalShape) optional.get()).createPortalBlocks(itemActionContext); // Paper - pass ItemActionContext param
return;
}
}
- if (!state.canSurvive(world, pos)) {
- this.fireExtinguished(world, pos); // CraftBukkit - fuel block broke
+ if (!iblockdata.canSurvive(world, blockposition)) {
+ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke
}
}
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 8c6edd032c927f7d1e04e944b4ce5598d71cdd81..7f88b910dfd0303f69b4fd1c7918a401c1f369f2 100644
--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java
@@ -13,6 +13,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BiomeTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
@@ -361,9 +362,11 @@ public class FireBlock extends BaseFireBlock {
}
@Override
- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
- super.onPlace(state, world, pos, oldState, notify);
- world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world.random));
+ // Paper start - ItemActionContext param
+ 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));
}
private static int getFireTickDelay(RandomSource random) {
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index 74f84bfcb1da6186c7a6783512c2fc7ba995215f..a9e8d9c65a809562d4768df348dcd79bec4d0e3c 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -40,6 +40,7 @@ import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.Level;
@@ -143,6 +144,12 @@ public abstract class BlockBehaviour implements FeatureElement {
DebugPackets.sendNeighborsUpdatePacket(world, pos);
}
+ // Paper start - add ItemActionContext param
+ @Deprecated
+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) {
+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag);
+ }
+ // Paper end
/** @deprecated */
@Deprecated
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java
index bc0dfa8efe0b2a891c000e750f436db632607ada..c461e0d04047db9c0c5ecc04063cebd38bf96ec2 100644
--- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java
+++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java
@@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.NetherPortalBlock;
@@ -190,7 +191,10 @@ public class PortalShape {
}
// CraftBukkit start - return boolean
- public boolean createPortalBlocks() {
+ // Paper start - ItemActionContext param
+ @Deprecated public boolean createPortalBlocks() { return this.createPortalBlocks(null); }
+ public boolean createPortalBlocks(UseOnContext itemActionContext) {
+ // Paper end
org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld();
// Copy below for loop
@@ -200,7 +204,7 @@ public class PortalShape {
this.blocks.setBlock(blockposition, iblockdata, 18);
});
- PortalCreateEvent event = new PortalCreateEvent((java.util.List<org.bukkit.block.BlockState>) (java.util.List) this.blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE);
+ PortalCreateEvent event = new PortalCreateEvent((java.util.List<org.bukkit.block.BlockState>) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param
this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event);
if (event.isCancelled()) {

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: foss-mc <69294560+foss-mc@users.noreply.github.com>
Date: Sun, 30 Aug 2020 15:30:29 +0800
Subject: [PATCH] Fix CraftTeam null check
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
index 18d5a26c34c848241c306241b3ad9825b5a0b9a9..60b1cffdccde4715832546d6edbf206fbab4e82f 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
@@ -261,7 +261,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
@Override
public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException {
- Validate.notNull("Entry cannot be null");
+ Validate.notNull(entry, "Entry cannot be null"); // Paper
CraftScoreboard scoreboard = this.checkState();

View file

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 15:28:35 +0200
Subject: [PATCH] Add more Evoker API
== AT ==
public net.minecraft.world.entity.monster.Evoker setWololoTarget(Lnet/minecraft/world/entity/animal/Sheep;)V
public net.minecraft.world.entity.monster.Evoker getWololoTarget()Lnet/minecraft/world/entity/animal/Sheep;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java
index 91d07e6996e315734689ea25336992b0ed21cf25..7e861636710aa44ed36e7f20c6320dabb809c35d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java
@@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.entity;
+import net.minecraft.world.entity.animal.Sheep;
import net.minecraft.world.entity.monster.SpellcasterIllager;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.EntityType;
@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker {
public void setCurrentSpell(Evoker.Spell spell) {
this.getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal()));
}
+
+ // Paper start
+ @Override
+ public org.bukkit.entity.Sheep getWololoTarget() {
+ Sheep sheep = getHandle().getWololoTarget();
+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity();
+ }
+
+ @Override
+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) {
+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle());
+ }
+ // Paper end
}

View file

@ -0,0 +1,130 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 11 Aug 2020 19:16:09 +0200
Subject: [PATCH] Add methods to get translation keys
== AT ==
public org.bukkit.craftbukkit.inventory.CraftMetaFirework
public org.bukkit.craftbukkit.inventory.CraftMetaFirework getNBT(Lorg/bukkit/FireworkEffect$Type;)I
Co-authored-by: MeFisto94 <MeFisto94@users.noreply.github.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index c67de2f3bb8b048b8432add4adcb9e6042fb65ad..f92b0151d9e2655191a3a7a009c5da66022dddc1 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -696,5 +696,10 @@ public class CraftBlock implements Block {
public org.bukkit.SoundGroup getBlockSoundGroup() {
return org.bukkit.craftbukkit.CraftSoundGroup.getSoundGroup(this.getNMS().getSoundType());
}
+
+ @Override
+ public String translationKey() {
+ return this.getNMS().getBlock().getDescriptionId();
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
index e8334e2264510f5101e80b4f130e7ae1442560d7..57decf4156f176ebcc988478c17856cbc555c5e4 100644
--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
@@ -194,6 +194,11 @@ public class CraftEnchantment extends Enchantment {
public net.kyori.adventure.text.Component displayName(int level) {
return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getFullname(level));
}
+
+ @Override
+ public String translationKey() {
+ return this.target.getDescriptionId();
+ }
// Paper end
public net.minecraft.world.item.enchantment.Enchantment getHandle() {
diff --git a/src/test/java/io/papermc/paper/world/TranslationKeyTest.java b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
index fab3063fffa959ac7f0eb5937f2fae94d11b6591..4cc8ca5dd95e9cccd08ada057a9592a1421f434a 100644
--- a/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
+++ b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
@@ -1,12 +1,23 @@
package io.papermc.paper.world;
import com.destroystokyo.paper.ClientOption;
+import java.util.Map;
+import net.minecraft.network.chat.contents.TranslatableContents;
+import net.minecraft.resources.ResourceKey;
import net.minecraft.world.entity.player.ChatVisiblity;
+import net.minecraft.world.level.GameType;
+import net.minecraft.world.level.biome.Biome;
import org.bukkit.Difficulty;
+import org.bukkit.FireworkEffect;
+import org.bukkit.GameMode;
+import org.bukkit.GameRule;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.support.AbstractTestingBase;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
-public class TranslationKeyTest {
+public class TranslationKeyTest extends AbstractTestingBase {
@Test
public void testChatVisibilityKeys() {
@@ -15,4 +26,58 @@ public class TranslationKeyTest {
Assert.assertEquals(chatVisibility + "'s translation key doesn't match", ChatVisiblity.valueOf(chatVisibility.name()).getKey(), chatVisibility.translationKey());
}
}
+
+ @Test
+ public void testDifficultyKeys() {
+ for (Difficulty bukkitDifficulty : Difficulty.values()) {
+ Assert.assertEquals(bukkitDifficulty + "'s translation key doesn't match", ((TranslatableContents) net.minecraft.world.Difficulty.byId(bukkitDifficulty.ordinal()).getDisplayName().getContents()).getKey(), bukkitDifficulty.translationKey());
+ }
+ }
+
+ @Test
+ public void testGameruleKeys() {
+ for (GameRule<?> rule : GameRule.values()) {
+ Assert.assertEquals(rule.getName() + "'s translation doesn't match", org.bukkit.craftbukkit.CraftWorld.getGameRulesNMS().get(rule.getName()).getDescriptionId(), rule.translationKey());
+ }
+ }
+
+ @Test
+ public void testAttributeKeys() {
+ for (Attribute attribute : Attribute.values()) {
+ Assert.assertEquals("translation key mismatch for " + attribute, org.bukkit.craftbukkit.attribute.CraftAttributeMap.toMinecraft(attribute).getDescriptionId(), attribute.translationKey());
+ }
+ }
+
+ @Test
+ public void testFireworkEffectType() {
+ for (FireworkEffect.Type type : FireworkEffect.Type.values()) {
+ Assert.assertEquals("translation key mismatch for " + type, net.minecraft.world.item.FireworkRocketItem.Shape.byId(org.bukkit.craftbukkit.inventory.CraftMetaFirework.getNBT(type)).getName(), org.bukkit.FireworkEffect.Type.NAMES.key(type));
+ }
+ }
+
+ @Test
+ @Ignore // TODO fix
+ public void testCreativeCategory() {
+ // for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
+ // CreativeCategory category = Objects.requireNonNull(CraftCreativeCategory.fromNMS(tab));
+ // Assert.assertEquals("translation key mismatch for " + category, ((TranslatableContents) tab.getDisplayName().getContents()).getKey(), category.translationKey());
+ // }
+ }
+
+ @Test
+ public void testGameMode() {
+ for (GameType nms : GameType.values()) {
+ GameMode bukkit = GameMode.getByValue(nms.getId());
+ Assert.assertNotNull(bukkit);
+ Assert.assertEquals("translation key mismatch for " + bukkit, ((TranslatableContents) nms.getLongDisplayName().getContents()).getKey(), bukkit.translationKey());
+ }
+ }
+
+ @Test
+ public void testBiome() {
+ for (Map.Entry<ResourceKey<Biome>, Biome> nms : AbstractTestingBase.BIOMES.entrySet()) {
+ org.bukkit.block.Biome bukkit = org.bukkit.block.Biome.valueOf(nms.getKey().location().getPath().toUpperCase());
+ Assert.assertEquals("translation key mismatch for " + bukkit, nms.getKey().location().toLanguageKey("biome"), bukkit.translationKey());
+ }
+ }
}

View file

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ysl3000 <yannicklamprecht@live.de>
Date: Mon, 6 Jul 2020 22:18:04 +0200
Subject: [PATCH] Create HoverEvent from ItemStack Entity
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
index f81ed24f624ff6f99ccad8361209cc409c6b9187..f5610d0746b67dfe69dc79d71c4d082c083f2ee4 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -473,5 +473,40 @@ public final class CraftItemFactory implements ItemFactory {
return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId(nms)) : null;
}
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) {
+ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString());
+ return new net.md_5.bungee.api.chat.hover.content.Item(
+ itemStack.getType().getKey().toString(),
+ itemStack.getAmount(),
+ itemTag);
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) {
+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName()));
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) {
+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName));
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) {
+ return new net.md_5.bungee.api.chat.hover.content.Entity(
+ entity.getType().getKey().toString(),
+ entity.getUniqueId().toString(),
+ customName);
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) {
+ return new net.md_5.bungee.api.chat.hover.content.Entity(
+ entity.getType().getKey().toString(),
+ entity.getUniqueId().toString(),
+ new net.md_5.bungee.api.chat.TextComponent(customName));
+ }
// Paper end
}

View file

@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: miclebrick <miclebrick@outlook.com>
Date: Thu, 6 Dec 2018 19:52:50 -0500
Subject: [PATCH] Cache block data strings
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b5cc8a2c46b928796c47832ee7430f63f616bfd2..13e5b02080177925e089fc05a02c0f52bd3e3ab3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2057,6 +2057,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getPlayerList().reloadResources();
this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary());
this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager);
+ org.bukkit.craftbukkit.block.data.CraftBlockData.reloadCache(); // Paper - cache block data strings, they can be defined by datapacks so refresh it here
}, this);
if (this.isSameThread()) {
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 12ea3a50126cd324dd3ee25a0f6c17deb05bd3a1..cd40c4c86b1f5de37fea9c0cd71b2e7b30b9136f 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -525,9 +525,39 @@ public class CraftBlockData implements BlockData {
Preconditions.checkState(CraftBlockData.MAP.put(nms, bukkit) == null, "Duplicate mapping %s->%s", nms, bukkit);
}
+ // Paper start - cache block data strings
+ private static Map<String, CraftBlockData> stringDataCache = new java.util.concurrent.ConcurrentHashMap<>();
+
+ static {
+ // cache all of the default states at startup, will not cache ones with the custom states inside of the
+ // brackets in a different order, though
+ reloadCache();
+ }
+
+ public static void reloadCache() {
+ stringDataCache.clear();
+ Block.BLOCK_STATE_REGISTRY.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData()));
+ }
+ // Paper end
+
public static CraftBlockData newData(Material material, String data) {
Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material);
+ // Paper start - cache block data strings
+ if (material != null) {
+ Block block = CraftMagicNumbers.getBlock(material);
+ if (block != null) {
+ net.minecraft.resources.ResourceLocation key = BuiltInRegistries.BLOCK.getKey(block);
+ data = data == null ? key.toString() : key + data;
+ }
+ }
+
+ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s));
+ return (CraftBlockData) cached.clone();
+ }
+
+ private static CraftBlockData createNewData(Material material, String data) {
+ // Paper end - cache block data strings
BlockState blockData;
Block block = CraftMagicNumbers.getBlock(material);
Map<Property<?>, Comparable<?>> parsed = null;

View file

@ -0,0 +1,83 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 25 Aug 2020 20:45:36 -0400
Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported
Uses correct setPositionRotation for Entity teleporting instead of setLocation
as this is how Vanilla teleports entities.
Cancel any pending motion when teleported.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index a7d9ff0e33ae674df20e23561cba9a26bd67395d..461b9838fb1201d203892941ef535d47839e4d4f 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -760,7 +760,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
return;
}
- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
+ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); // Paper - use proper moveTo for teleportation
this.lastGoodX = this.awaitingPositionFromClient.x;
this.lastGoodY = this.awaitingPositionFromClient.y;
this.lastGoodZ = this.awaitingPositionFromClient.z;
@@ -1649,7 +1649,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
// CraftBukkit end
this.awaitingTeleportTime = this.tickCount;
- this.player.absMoveTo(d0, d1, d2, f, f1);
+ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper moveTo for teleportation
this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport));
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 316597f54e6ce8da0869e6398b048c618b4a1a7b..70c5cb20e230d8556612bb3b9728898b5d4d329c 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -158,6 +158,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
+ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation
static boolean isLevelAtLeast(CompoundTag tag, int level) {
return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
}
@@ -1771,6 +1772,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
public void moveTo(double x, double y, double z, float yaw, float pitch) {
+ // Paper - cancel entity velocity if teleported
+ if (!preserveMotion) {
+ this.deltaMovement = Vec3.ZERO;
+ } else {
+ this.preserveMotion = false;
+ }
+ // Paper end
this.setPosRaw(x, y, z);
this.setYRot(yaw);
this.setXRot(pitch);
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index 65d78f1c93c98695e9a4369693f54751d3a69b25..c63d5df91726839471c1eaaf7fafab3fa1be153b 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -167,6 +167,7 @@ public abstract class BaseSpawner {
return;
}
+ entity.preserveMotion = true; // Paper - preserve entity motion from tag
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), randomsource.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 5d01b33df41ecc51e2c2b44bad34a65e823d69ce..7fb674cea2953b10c26f1a2c3b3369ab7767324b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -574,7 +574,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
// entity.setLocation() throws no event, and so cannot be cancelled
- this.entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+ entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper moveTo, as per vanilla teleporting
// SPIGOT-619: Force sync head rotation also
this.entity.setYHeadRot(location.getYaw());

View file

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Wed, 26 Aug 2020 02:12:31 -0400
Subject: [PATCH] Add additional open container api to HumanEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 2d3a7bb9f68350df136ee3d2e3aed0bbbe1a91cc..43a98bcd8e9fe8b204d6d750e3e301cc644024cb 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -463,6 +463,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
return this.getHandle().containerMenu.getBukkitView();
}
+ // Paper start - Add additional containers
+ @Override
+ public InventoryView openAnvil(Location location, boolean force) {
+ return openInventory(location, force, Material.ANVIL);
+ }
+
+ @Override
+ public InventoryView openCartographyTable(Location location, boolean force) {
+ return openInventory(location, force, Material.CARTOGRAPHY_TABLE);
+ }
+
+ @Override
+ public InventoryView openGrindstone(Location location, boolean force) {
+ return openInventory(location, force, Material.GRINDSTONE);
+ }
+
+ @Override
+ public InventoryView openLoom(Location location, boolean force) {
+ return openInventory(location, force, Material.LOOM);
+ }
+
+ @Override
+ public InventoryView openSmithingTable(Location location, boolean force) {
+ return openInventory(location, force, Material.SMITHING_TABLE);
+ }
+
+ @Override
+ public InventoryView openStonecutter(Location location, boolean force) {
+ return openInventory(location, force, Material.STONECUTTER);
+ }
+
+ private InventoryView openInventory(Location location, boolean force, Material material) {
+ org.spigotmc.AsyncCatcher.catchOp("open" + material);
+ if (location == null) {
+ location = getLocation();
+ }
+ if (!force) {
+ Block block = location.getBlock();
+ if (block.getType() != material) {
+ return null;
+ }
+ }
+ net.minecraft.world.level.block.Block block;
+ if (material == Material.ANVIL) {
+ block = Blocks.ANVIL;
+ } else if (material == Material.CARTOGRAPHY_TABLE) {
+ block = Blocks.CARTOGRAPHY_TABLE;
+ } else if (material == Material.GRINDSTONE) {
+ block = Blocks.GRINDSTONE;
+ } else if (material == Material.LOOM) {
+ block = Blocks.LOOM;
+ } else if (material == Material.SMITHING_TABLE) {
+ block = Blocks.SMITHING_TABLE;
+ } else if (material == Material.STONECUTTER) {
+ block = Blocks.STONECUTTER;
+ } else {
+ throw new IllegalArgumentException("Unsupported inventory type: " + material);
+ }
+ getHandle().openMenu(block.getMenuProvider(null, getHandle().level, new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ())));
+ getHandle().containerMenu.checkReachable = !force;
+ return getHandle().containerMenu.getBukkitView();
+ }
+ // Paper end
+
@Override
public void closeInventory() {
// Paper start

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 12 Sep 2020 17:21:38 -0400
Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand
Mojang precaches every single potential rewrite rule that could ever
exist on server startup. This includes rules from all the way back to versions from 6+ years ago.
This is the source of why the server hogs every CPU core at 100% every start.
For anyone who hard resets for updates or has force upgraded their entire world, this
results in completely wasted cpu cycles.
This massive CPU usage also delays server startup time.
We improve this by making "min version to precache" that defaults to a future version
so that no rewrite rules are precached.
someone who expects to be converting a lot chunks could theoretically set
-DPaper.minPrecachedDatafixVersion=<dataVersionConvertingFrom> as a startup
parameter and only build from that point on.
However this will likely never be needed as the server will still run
the same cache logic on demand when it's actually needed. The only
cost would be some delay on the FIRST chunk conversion, but paper already
runs chunk conversions on another thread so this will likely never be
a concern for TPS.
This patch will significantly reduce CPU use on startup, reduce memory usage,
and improve server startup time.
diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java
index cd812f3fe362de5ddc414862dedab2e9727ca776..f6598fcf4ed1bd61e1c87cd7107869d49ffe4566 100644
--- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java
+++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java
@@ -30,8 +30,10 @@ public class DataFixerBuilder {
private final Int2ObjectSortedMap<Schema> schemas = new Int2ObjectAVLTreeMap<>();
private final List<DataFix> globalList = Lists.newArrayList();
private final IntSortedSet fixerVersions = new IntAVLTreeSet();
+ private final int minDataFixPrecacheVersion; // Paper
public DataFixerBuilder(final int dataVersion) {
+ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions'
this.dataVersion = dataVersion;
}
@@ -78,6 +80,7 @@ public class DataFixerBuilder {
final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator();
while (iterator.hasNext()) {
final int versionKey = iterator.nextInt();
+ if (versionKey < minDataFixPrecacheVersion) continue; // Paper
final Schema schema = schemas.get(versionKey);
for (final String typeName : schema.types()) {
if (!requiredTypeNames.contains(typeName)) {

View file

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 17 Sep 2020 00:36:05 +0100
Subject: [PATCH] Extend block drop capture to capture all items added to the
world
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 945fdae271d18d9b25012d0b6876ec65ef8f2711..6b47bff5e385bffefbdfa3b9f9f8366d75af6acc 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1275,6 +1275,12 @@ 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 {
+ // 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);
+ return true;
+ }
+ // Paper end
// SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world.
if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) {
return false;
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index c185083abf2b4527a7fe046d83c64cd2cc5b5bb9..7c713c98201c816a70ac999e86685b1c6bbd372d 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -434,10 +434,12 @@ public class ServerPlayerGameMode {
// return true; // CraftBukkit
}
// CraftBukkit start
+ java.util.List<net.minecraft.world.entity.item.ItemEntity> itemsToDrop = level.captureDrops; // Paper - store current list
+ level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff
if (event.isDropItems()) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref
}
- level.captureDrops = null;
+ //world.captureDrops = null; // Paper - move up
// Drop event experience
if (flag && event != null) {

View file

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MeFisto94 <MeFisto94@users.noreply.github.com>
Date: Fri, 28 Aug 2020 01:41:26 +0200
Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and
non-conflicting Entity Ids
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 70c5cb20e230d8556612bb3b9728898b5d4d329c..d223777615fb3636784b33a1f562b7c8a6dff102 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4336,4 +4336,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
void accept(Entity entity, double x, double y, double z);
}
+
+ // Paper start
+ public static int nextEntityId() {
+ return ENTITY_COUNTER.incrementAndGet();
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 447df549a0d371389b086327b06b74aa1d6647cd..cddf16549f45bbb9a598d5677fbc2195200ba876 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -514,6 +514,11 @@ public final class CraftMagicNumbers implements UnsafeValues {
Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!");
return compound;
}
+
+ @Override
+ public int nextEntityId() {
+ return net.minecraft.world.entity.Entity.nextEntityId();
+ }
// Paper end
/**

View file

@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Sat, 3 Oct 2020 04:15:09 -0400
Subject: [PATCH] Lazily track plugin scoreboards by default
On servers with plugins that constantly churn through scoreboards, there is a risk of
degraded GC performance due to the number of scoreboards held on by weak references.
Most plugins don't even need the (vanilla) functionality that requires all plugin
scoreboards to be tracked by the server. Instead, only track scoreboards when an
objective is added with a non-dummy criteria.
This is a breaking change, however the change is a much more sensible default. In case
this breaks your workflow you can always force all scoreboards to be tracked with
settings.track-plugin-scoreboards in paper.yml.
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
index f367261b119ab48c1d17b2b6552cce481c6effbb..a038ede38ebb507d6a0182a4a34f2b0722ef024e 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
@@ -19,6 +19,7 @@ import org.bukkit.scoreboard.Team;
public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
final Scoreboard board;
+ boolean registeredGlobally = false; // Paper
CraftScoreboard(Scoreboard board) {
this.board = board;
@@ -52,6 +53,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
Validate.notNull(renderType, "RenderType cannot be null");
Validate.isTrue(name.length() <= Short.MAX_VALUE, "The name '" + name + "' is longer than the limit of 32767 characters");
Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists");
+ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective
+ if (((CraftCriteria) criteria).criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.DUMMY && !registeredGlobally) {
+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this);
+ registeredGlobally = true;
+ }
+ // Paper end
net.minecraft.world.scores.Objective objective = board.addObjective(name, ((CraftCriteria) criteria).criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
return new CraftObjective(this, objective);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
index 71f73db28ca124a49434e9da9eb39d182b7421e2..39e19bea16419b9cbe53016084b8bbf014dcb056 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager {
public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) {
this.mainScoreboard = new CraftScoreboard(scoreboardServer);
+ mainScoreboard.registeredGlobally = true; // Paper
this.server = minecraftserver;
this.scoreboards.add(mainScoreboard);
}
@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager {
public CraftScoreboard getNewScoreboard() {
org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot
CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(this.server));
- this.scoreboards.add(scoreboard);
+ // Paper start
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().scoreboards.trackPluginScoreboards) {
+ scoreboard.registeredGlobally = true;
+ scoreboards.add(scoreboard);
+ }
+ // Paper end
return scoreboard;
}
+ // Paper start
+ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) {
+ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration");
+ scoreboards.add(scoreboard);
+ }
+ // Paper end
+
// CraftBukkit method
public CraftScoreboard getPlayerBoard(CraftPlayer player) {
CraftScoreboard board = this.playerBoards.get(player);

View file

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 21:39:16 -0500
Subject: [PATCH] Entity#isTicking
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index d223777615fb3636784b33a1f562b7c8a6dff102..a4926cdfeac99b78ca2551a8d0e6f1fab9ca985b 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4341,5 +4341,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
public static int nextEntityId() {
return ENTITY_COUNTER.incrementAndGet();
}
+
+ public boolean isTicking() {
+ return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this);
+ }
// 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 7fb674cea2953b10c26f1a2c3b3369ab7767324b..2b936e32a67c108df9a7f6b335357a25bad6d291 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1343,5 +1343,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isInLava() {
return getHandle().isInLava();
}
+
+ @Override
+ public boolean isTicking() {
+ return getHandle().isTicking();
+ }
// Paper end
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 22:00:27 -0500
Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is
not enabled
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 13e5b02080177925e089fc05a02c0f52bd3e3ab3..648056283bb1cbb99faf3e095886ace7d42e46d3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2140,13 +2140,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (this.isEnforceWhitelist()) {
PlayerList playerlist = source.getServer().getPlayerList();
UserWhiteList whitelist = playerlist.getWhiteList();
+ if (!((DedicatedServer)getServer()).getProperties().whiteList.get()) return; // Paper - white list not enabled
List<ServerPlayer> list = Lists.newArrayList(playerlist.getPlayers());
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
- if (!whitelist.isWhiteListed(entityplayer.getGameProfile())) {
+ if (!whitelist.isWhiteListed(entityplayer.getGameProfile()) && !this.getPlayerList().isOp(entityplayer.getGameProfile())) { // Paper - Fix kicking ops when whitelist is reloaded (MC-171420)
entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.not_whitelisted"));
}
}

View file

@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 6 Jul 2020 18:36:41 -0400
Subject: [PATCH] Fix Concurrency issue in ShufflingList
if multiple threads from worldgen sort at same time, it will crash.
So make a copy of the list for sorting purposes.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
index 419eadbe31b86b7192fd7a63268d547705e7c7ce..b45c4f50705f80163d44d9e588f86a5770f5be38 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
@@ -17,7 +17,7 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
private final Set<MemoryModuleType<?>> exitErasedMemories;
private final GateBehavior.OrderPolicy orderPolicy;
private final GateBehavior.RunningPolicy runningPolicy;
- private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>();
+ private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>(false); // Paper - don't use a clone
private Behavior.Status status = Behavior.Status.STOPPED;
public GateBehavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState, Set<MemoryModuleType<?>> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List<Pair<? extends BehaviorControl<? super E>, Integer>> tasks) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
index 9fb20cd00568aeea25284ea0e80fe52cb1c3eede..731ef21dbbd25d6924717de42f4569a9b5935643 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
@@ -16,12 +16,25 @@ import net.minecraft.util.RandomSource;
public class ShufflingList<U> implements Iterable<U> {
protected final List<ShufflingList.WeightedEntry<U>> entries;
private final RandomSource random = RandomSource.create();
+ private final boolean isUnsafe; // Paper
public ShufflingList() {
+ // Paper start
+ this(true);
+ }
+ public ShufflingList(boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end
this.entries = Lists.newArrayList();
}
private ShufflingList(List<ShufflingList.WeightedEntry<U>> list) {
+ // Paper start
+ this(list, true);
+ }
+ private ShufflingList(List<ShufflingList.WeightedEntry<U>> list, boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end
this.entries = Lists.newArrayList(list);
}
@@ -37,11 +50,12 @@ public class ShufflingList<U> implements Iterable<U> {
}
public ShufflingList<U> shuffle() {
- this.entries.forEach((entry) -> {
- entry.setRandom(this.random.nextFloat());
- });
- this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
- return this;
+ // Paper start - make concurrent safe, work off a clone of the list
+ List<ShufflingList.WeightedEntry<U>> list = this.isUnsafe ? Lists.newArrayList(this.entries) : this.entries;
+ list.forEach(entry -> entry.setRandom(this.random.nextFloat()));
+ list.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
+ return this.isUnsafe ? new ShufflingList<>(list, this.isUnsafe) : this;
+ // Paper end
}
public Stream<U> stream() {

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 1 Jun 2016 23:29:17 -0400
Subject: [PATCH] Reset Ender Crystals on Dragon Spawn
Crystals can end up in a bad state in certain conditions which causes
an exception on the expected number of crystals going negative.
This ensures the crystals/pillars are in expected state when the dragon spawns.
See #3522
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 35304d7a60348a2b4e1eec43418086086502e4ab..cae4c52e239bdbb916d69e14617814fd08279f1b 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
@@ -412,6 +412,7 @@ public class EndDragonFight {
enderDragon.moveTo((double)this.origin.getX(), (double)(128 + this.origin.getY()), (double)this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F);
this.level.addFreshEntity(enderDragon);
this.dragonUUID = enderDragon.getUUID();
+ this.resetSpikeCrystals(); // Paper
}
return enderDragon;

View file

@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 17 May 2020 23:47:33 -0700
Subject: [PATCH] Fix for large move vectors crashing server
Check movement distance also based on current position.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 461b9838fb1201d203892941ef535d47839e4d4f..5cd15898576aa3d3f1c092bf645dd9f1e350cd0e 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -567,9 +567,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) {
ServerLevel worldserver = this.player.serverLevel();
- double d0 = entity.getX();
- double d1 = entity.getY();
- double d2 = entity.getZ();
+ double d0 = entity.getX();final double fromX = d0; // Paper - OBFHELPER
+ double d1 = entity.getY();final double fromY = d1; // Paper - OBFHELPER
+ double d2 = entity.getZ();final double fromZ = d2; // Paper - OBFHELPER
double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX()); final double toX = d3; // Paper - OBFHELPER
double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY()); final double toY = d4; // Paper - OBFHELPER
double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ()); final double toZ = d5; // Paper - OBFHELPER
@@ -579,8 +579,19 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
double d7 = d4 - this.vehicleFirstGoodY;
double d8 = d5 - this.vehicleFirstGoodZ;
double d9 = entity.getDeltaMovement().lengthSqr();
- double d10 = d6 * d6 + d7 * d7 + d8 * d8;
-
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - fromX;
+ double currDeltaY = toY - fromY;
+ double currDeltaZ = toZ - fromZ;
+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ // Paper end - fix large move vectors killing the server
+
+ // Paper start - fix large move vectors killing the server
+ double otherFieldX = d3 - this.vehicleLastGoodX;
+ double otherFieldY = d4 - this.vehicleLastGoodY - 1.0E-6D;
+ double otherFieldZ = d5 - this.vehicleLastGoodZ;
+ d10 = Math.max(d10, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
// CraftBukkit start - handle custom speeds and skipped ticks
this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
@@ -626,9 +637,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
- d6 = d3 - this.vehicleLastGoodX;
- d7 = d4 - this.vehicleLastGoodY - 1.0E-6D;
- d8 = d5 - this.vehicleLastGoodZ;
+ d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
+ d8 = d5 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag1 = entity.verticalCollisionBelow;
if (entity instanceof LivingEntity) {
@@ -1344,7 +1355,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
double d7 = d1 - this.firstGoodY;
double d8 = d2 - this.firstGoodZ;
double d9 = this.player.getDeltaMovement().lengthSqr();
- double d10 = d6 * d6 + d7 * d7 + d8 * d8;
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - prevX;
+ double currDeltaY = toY - prevY;
+ double currDeltaZ = toZ - prevZ;
+ double d10 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ // Paper end - fix large move vectors killing the server
+ // Paper start - fix large move vectors killing the server
+ double otherFieldX = d0 - this.lastGoodX;
+ double otherFieldY = d1 - this.lastGoodY;
+ double otherFieldZ = d2 - this.lastGoodZ;
+ d10 = Math.max(d10, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
if (this.player.isSleeping()) {
if (d10 > 1.0D) {
@@ -1396,9 +1418,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
AABB axisalignedbb = this.player.getBoundingBox();
- d6 = d0 - this.lastGoodX;
- d7 = d1 - this.lastGoodY;
- d8 = d2 - this.lastGoodZ;
+ d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
+ d8 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag = d7 > 0.0D;
if (this.player.onGround() && !packet.isOnGround() && flag) {

View file

@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Wed, 3 Jun 2020 11:37:13 -0700
Subject: [PATCH] Optimise getType calls
Remove the map lookup for converting from Block->Bukkit Material
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
index da878e180c6b94f98dc82c6e8395f63ecc9b2c1e..a9b0f5950b6f97ea4c2a1075946b92008b62c9d9 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
@@ -10,6 +10,17 @@ import net.minecraft.world.level.block.state.properties.Property;
public class BlockState extends BlockBehaviour.BlockStateBase {
public static final Codec<BlockState> CODEC = codec(BuiltInRegistries.BLOCK.byNameCodec(), Block::defaultBlockState).stable();
+ // Paper start - optimise getType calls
+ org.bukkit.Material cachedMaterial;
+
+ public final org.bukkit.Material getBukkitMaterial() {
+ if (this.cachedMaterial == null) {
+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock());
+ }
+
+ return this.cachedMaterial;
+ }
+ // Paper end - optimise getType calls
public BlockState(Block block, ImmutableMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
super(block, propertyMap, codec);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
index eebac2ea211f58c385b2ceb36ab911ac5e115296..d1aaca5de055fd5e3bf2c6d39ef397bbb2deeaae 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
@@ -98,7 +98,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
public Material getBlockType(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
- return CraftMagicNumbers.getMaterial(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBlock());
+ return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index f92b0151d9e2655191a3a7a009c5da66022dddc1..cd39ec0e87974be616f10321d953fd2f3af194f7 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -225,7 +225,7 @@ public class CraftBlock implements Block {
@Override
public Material getType() {
- return CraftMagicNumbers.getMaterial(this.world.getBlockState(position).getBlock());
+ return this.world.getBlockState(this.position).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
index 843a166e43f05fe987e62329593b23656c6a2abb..9068557ac50cfb26e7e3ec4ac64bac583baa582e 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
@@ -167,7 +167,7 @@ public class CraftBlockState implements BlockState {
@Override
public Material getType() {
- return CraftMagicNumbers.getMaterial(this.data.getBlock());
+ return this.data.getBukkitMaterial(); // Paper - optimise getType calls
}
public void setFlag(int flag) {
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 cd40c4c86b1f5de37fea9c0cd71b2e7b30b9136f..58d10e8909fea652810e30bbd4b24aaa5e038277 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -57,7 +57,7 @@ public class CraftBlockData implements BlockData {
@Override
public Material getMaterial() {
- return CraftMagicNumbers.getMaterial(this.state.getBlock());
+ return this.state.getBukkitMaterial(); // Paper - optimise getType calls
}
public BlockState getState() {
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
index ee88ff2ee86bbd3ccf3e4a0b2310f020f137ef4f..5e15feb408b8a05ec5ee393a604c8d39a91ff106 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
@@ -96,7 +96,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData {
@Override
public Material getType(int x, int y, int z) {
- return CraftMagicNumbers.getMaterial(this.getTypeId(x, y, z).getBlock());
+ return this.getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override

View file

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Mon, 7 Oct 2019 00:15:37 -0500
Subject: [PATCH] Villager#resetOffers
diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
index 78f7f1602b34e9d2162446810b0ee1357fd4922c..0a62cf36a95d7bf1287acdd17464fc677c7a4b7d 100644
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
@@ -115,6 +115,13 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa
return this.tradingPlayer != null;
}
+ // Paper start
+ public void resetOffers() {
+ this.offers = new MerchantOffers();
+ this.updateTrades();
+ }
+ // Paper end
+
@Override
public MerchantOffers getOffers() {
if (this.offers == null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java
index 1467232779541a9e38420caabf273662f380794c..762354681315e4c74e414bf7d677b5422385161e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java
@@ -70,4 +70,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla
public HumanEntity getTrader() {
return this.getMerchant().getTrader();
}
+
+ // Paper start
+ @Override
+ public void resetOffers() {
+ getHandle().resetOffers();
+ }
+ // Paper end
}

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 7 Aug 2020 04:27:56 -0700
Subject: [PATCH] Retain block place order when capturing blockstates
Fixes twisted vines not connecting properly when grown via
bonemeal by a player.
In general, look at making this logic more robust (i.e properly handling
cases where a captured entry is overriden) - but for now this will do.
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 4aad91def765910d6e8820cb92a288a304a17b5b..485e45962dcbcdcf720ff70e06092dd846e74031 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -157,7 +157,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
- public Map<BlockPos, BlockEntity> capturedTileEntities = new HashMap<>();
+ public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper
public List<ItemEntity> captureDrops;
public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
// Paper start

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 25 Apr 2020 17:10:55 -0700
Subject: [PATCH] Reduce blockpos allocation from pathfinding
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
index 10503d6d8b6daf645cf4360ee289d5e25144c976..3583fcf5284bc5883308876dbd9886664b391e28 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -473,7 +473,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
return BlockPathTypes.DANGER_FIRE;
}
- if (world.getFluidState(pos).is(FluidTags.WATER)) {
+ if (blockState.getFluidState().is(FluidTags.WATER)) {
return BlockPathTypes.WATER_BORDER;
}
@@ -504,7 +504,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
} else if (blockState.is(Blocks.COCOA)) {
return BlockPathTypes.COCOA;
} else if (!blockState.is(Blocks.WITHER_ROSE) && !blockState.is(Blocks.POINTED_DRIPSTONE)) {
- FluidState fluidState = world.getFluidState(pos);
+ FluidState fluidState = blockState.getFluidState(); // Paper - remove another getFluidState call
if (fluidState.is(FluidTags.LAVA)) {
return BlockPathTypes.LAVA;
} else if (isBurningBlock(blockState)) {

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 20:32:25 -0500
Subject: [PATCH] Fix item locations dropped from campfires
Fixes #4259 by not flooring the blockposition among other weirdness
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
index ba4ce804d1d239ca842b06b3599605847effc35b..ca995270c9b8d7024504a9ba885b1c0214b33a8b 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
@@ -81,7 +81,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
result = blockCookEvent.getResult();
itemstack1 = CraftItemStack.asNMSCopy(result);
// CraftBukkit end
- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1);
+ // Paper start
+ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(world, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemstack1.split(world.random.nextInt(21) + 10));
+ droppedItem.setDeltaMovement(world.random.nextGaussian() * 0.05D, world.random.nextGaussian() * 0.05D + 0.2D, world.random.nextGaussian() * 0.05D);
+ world.addFreshEntity(droppedItem);
+ // Paper end
campfire.items.set(i, ItemStack.EMPTY);
world.sendBlockUpdated(pos, state, state, 3);
world.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state));

View file

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Tue, 14 Apr 2020 12:05:22 +0200
Subject: [PATCH] Player elytra boost API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index e67e69d36c97bee0880e7f21dab1c9a4ca196baa..cfca7a4e71c2f74846238b1bf2fbf2ff094b7a0f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -574,6 +574,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
throw new RuntimeException("Unknown settings type");
}
+
+ @Override
+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) {
+ Validate.isTrue(isGliding(), "Player must be gliding");
+ Validate.isTrue(firework != null, "firework == null");
+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET");
+
+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework);
+ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle();
+ net.minecraft.world.entity.projectile.FireworkRocketEntity entity = new net.minecraft.world.entity.projectile.FireworkRocketEntity(world, item, getHandle());
+ return world.addFreshEntity(entity)
+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity()
+ : null;
+ }
// Paper end
@Override

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: giacomo <32515303+giacomozama@users.noreply.github.com>
Date: Sat, 10 Oct 2020 12:15:33 +0200
Subject: [PATCH] Fixed TileEntityBell memory leak
TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities.
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java
index 30e9d4b20005dc6d20baf578f2ae958bdfcea02a..b446d6549922f3dabaaa05793d8ee3eb45566ac3 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java
@@ -63,6 +63,11 @@ public class BellBlockEntity extends BlockEntity {
if (blockEntity.ticks >= 50) {
blockEntity.shaking = false;
+ // Paper start
+ if (!blockEntity.resonating) {
+ blockEntity.nearbyEntities.clear();
+ }
+ // Paper end
blockEntity.ticks = 0;
}
@@ -76,6 +81,7 @@ public class BellBlockEntity extends BlockEntity {
++blockEntity.resonationTicks;
} else {
bellEffect.run(world, pos, blockEntity.nearbyEntities);
+ blockEntity.nearbyEntities.clear(); // Paper
blockEntity.resonating = false;
}
}
@@ -125,6 +131,7 @@ public class BellBlockEntity extends BlockEntity {
}
}
+ this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper
}
private static boolean areRaidersNearby(BlockPos pos, List<LivingEntity> hearingEntities) {

View file

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Toon Schoenmakers <nighteyes1993@gmail.com>
Date: Fri, 23 Oct 2020 15:01:44 +0200
Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing
loot
This can realistically only happen if there's custom loot active on fishing
which can return 0 items. This would disconnect the player who's fishing.
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
index dbff697927e6a6c745377aafd3b476b58f005882..b8c238287e0639b578170c6fec0d4db5a1a59fe7 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -503,9 +503,15 @@ public class FishingHook extends Projectile {
while (iterator.hasNext()) {
ItemStack itemstack1 = (ItemStack) iterator.next();
- ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1);
+ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty
+ // if the item stack is empty we instead just have our entityitem as null
+ ItemEntity entityitem = null;
+ if (!itemstack1.isEmpty()) {
+ entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1);
+ }
+ // Paper end
// CraftBukkit start
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH);
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null
playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1);
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
@@ -518,8 +524,12 @@ public class FishingHook extends Projectile {
double d2 = entityhuman.getZ() - this.getZ();
double d3 = 0.1D;
- entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D);
- this.level().addFreshEntity(entityitem);
+ // Paper start, entity item can be null, so we need to check against this
+ if (entityitem != null) {
+ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D);
+ this.level().addFreshEntity(entityitem);
+ }
+ // Paper end
// CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop()
if (playerFishEvent.getExpToDrop() > 0) {
entityhuman.level().addFreshEntity(new ExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: oxygencraft <21054297+oxygencraft@users.noreply.github.com>
Date: Sun, 25 Oct 2020 18:34:50 +1100
Subject: [PATCH] Add getOfflinePlayerIfCached(String)
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index e59844bd1bd6a68314b44b947236e3d3194f9102..5a01f8475829cd3e398a095da50bc01c5dcd092b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1829,6 +1829,28 @@ public final class CraftServer implements Server {
return result;
}
+ // Paper start
+ @Override
+ @Nullable
+ public OfflinePlayer getOfflinePlayerIfCached(String name) {
+ Validate.notNull(name, "Name cannot be null");
+ Validate.notEmpty(name, "Name cannot be empty");
+
+ OfflinePlayer result = getPlayerExact(name);
+ if (result == null) {
+ GameProfile profile = console.getProfileCache().getProfileIfCached(name);
+
+ if (profile != null) {
+ result = getOfflinePlayer(profile);
+ }
+ } else {
+ offlinePlayers.remove(result.getUniqueId());
+ }
+
+ return result;
+ }
+ // Paper end
+
@Override
public OfflinePlayer getOfflinePlayer(UUID id) {
Validate.notNull(id, "UUID cannot be null");

View file

@ -0,0 +1,154 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Mon, 9 Nov 2020 20:44:51 +0100
Subject: [PATCH] Add ignore discounts API
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 1e775178f346ef3d2f121e539ba81a75c8a37c36..24434b66d158b10d21579b2db6efb0bdcc788a5c 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -507,6 +507,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator.hasNext()) {
MerchantOffer merchantrecipe = (MerchantOffer) iterator.next();
+ if (merchantrecipe.ignoreDiscounts) continue; // Paper
merchantrecipe.addToSpecialPriceDiff(-Mth.floor((float) i * merchantrecipe.getPriceMultiplier()));
}
@@ -519,6 +520,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator1.hasNext()) {
MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next();
+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper
double d0 = 0.3D + 0.0625D * (double) j;
int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount());
diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
index dc5908374565dd3080679779cbfe7620a4810015..28bdcb14cb5b458d3c990fcf343ef97f08e4f3c6 100644
--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
@@ -19,6 +19,7 @@ public class MerchantOffer {
public int demand;
public float priceMultiplier;
public int xp;
+ public boolean ignoreDiscounts; // Paper
// CraftBukkit start
private CraftMerchantRecipe bukkitHandle;
@@ -31,7 +32,15 @@ public class MerchantOffer {
}
public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) {
- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand);
+ // Paper start - add ignoreDiscounts param
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand, false, bukkit);
+ }
+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) {
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, ignoreDiscounts, bukkit);
+ }
+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) {
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand, ignoreDiscounts);
+ // Paper end
this.bukkitHandle = bukkit;
}
// CraftBukkit end
@@ -63,6 +72,7 @@ public class MerchantOffer {
this.specialPriceDiff = nbt.getInt("specialPrice");
this.demand = nbt.getInt("demand");
+ this.ignoreDiscounts = nbt.getBoolean("Paper.IgnoreDiscounts"); // Paper
}
public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int merchantExperience, float priceMultiplier) {
@@ -74,10 +84,19 @@ public class MerchantOffer {
}
public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier) {
- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0);
+ // Paper start - add ignoreDiscounts param
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, false);
+ }
+ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, boolean ignoreDiscounts) {
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0, ignoreDiscounts);
}
public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus) {
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, demandBonus, false);
+ }
+ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus, boolean ignoreDiscounts) {
+ this.ignoreDiscounts = ignoreDiscounts;
+ // Paper end
this.rewardExp = true;
this.xp = 1;
this.baseCostA = firstBuyItem;
@@ -195,6 +214,7 @@ public class MerchantOffer {
nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier);
nbttagcompound.putInt("specialPrice", this.specialPriceDiff);
nbttagcompound.putInt("demand", this.demand);
+ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper
return nbttagcompound;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
index 335d65c22efc2b8fd53476e3efd6e74fce5609cf..c48f67f4202e32d9793b462609bd3b95c9765bbd 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
@@ -18,11 +18,19 @@ public class CraftMerchantRecipe extends MerchantRecipe {
@Deprecated
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) {
- this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0);
+ // Paper start - add ignoreDiscounts param
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) {
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0, ignoreDiscounts);
}
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice) {
- super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice);
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice, boolean ignoreDiscounts) {
+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice, ignoreDiscounts);
+ // Paper end
this.handle = new net.minecraft.world.item.trading.MerchantOffer(
net.minecraft.world.item.ItemStack.EMPTY,
net.minecraft.world.item.ItemStack.EMPTY,
@@ -32,6 +40,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
experience,
priceMultiplier,
demand,
+ ignoreDiscounts, // Paper - add ignoreDiscounts param
this
);
this.setSpecialPrice(specialPrice);
@@ -108,6 +117,18 @@ public class CraftMerchantRecipe extends MerchantRecipe {
handle.priceMultiplier = priceMultiplier;
}
+ // Paper start
+ @Override
+ public boolean shouldIgnoreDiscounts() {
+ return this.handle.ignoreDiscounts;
+ }
+
+ @Override
+ public void setIgnoreDiscounts(boolean ignoreDiscounts) {
+ this.handle.ignoreDiscounts = ignoreDiscounts;
+ }
+ // Paper end
+
public net.minecraft.world.item.trading.MerchantOffer toMinecraft() {
List<ItemStack> ingredients = getIngredients();
Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients");
@@ -122,7 +143,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
if (recipe instanceof CraftMerchantRecipe) {
return (CraftMerchantRecipe) recipe;
} else {
- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.getDemand(), recipe.getSpecialPrice());
+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.getDemand(), recipe.getSpecialPrice(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts
craft.setIngredients(recipe.getIngredients());
return craft;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Wed, 30 Sep 2020 22:49:14 +0200
Subject: [PATCH] Toggle for removing existing dragon
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 cae4c52e239bdbb916d69e14617814fd08279f1b..58823aeb8316628be716051b74307b01c37ad8a0 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
@@ -195,7 +195,7 @@ public class EndDragonFight {
this.dragonUUID = enderDragon.getUUID();
LOGGER.info("Found that there's a dragon still alive ({})", (Object)enderDragon);
this.dragonKilled = false;
- if (!bl) {
+ if (!bl && this.level.paperConfig().entities.behavior.shouldRemoveDragon) {
LOGGER.info("But we didn't have a portal, let's remove it.");
enderDragon.discard();
this.dragonUUID = null;

View file

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Sat, 31 Oct 2020 11:49:01 -0700
Subject: [PATCH] Fix client lag on advancement loading
When new advancements are added via the UnsafeValues#loadAdvancement
API, it triggers a full datapack reload when this is not necessary. The
advancement is already loaded directly into the advancement registry,
and the point of saving the advancement to the Bukkit datapack seems to
be for persistence. By removing the call to reload datapacks when an
advancement is loaded, the client no longer completely freezes up when
adding a new advancement.
To ensure the client still receives the updated advancement data, we
manually reload the advancement data for all players, which
normally takes place as a part of the datapack reloading.
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index cddf16549f45bbb9a598d5677fbc2195200ba876..fbb674d355f30f34de6bb9608e628d5c49047be6 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -347,7 +347,13 @@ public final class CraftMagicNumbers implements UnsafeValues {
Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex);
}
- MinecraftServer.getServer().getPlayerList().reloadResources();
+ // Paper start
+ //MinecraftServer.getServer().getPlayerList().reload();
+ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> {
+ player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements());
+ player.getAdvancements().flushDirty(player);
+ });
+ // Paper end
return bukkit;
}

View file

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alfie Smith <alfie@alfiesmith.net>
Date: Sat, 7 Nov 2020 01:20:33 +0000
Subject: [PATCH] Item no age & no player pickup
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index 5f36b0fd12ccd0e7ec9a7f61c56f08307844935f..27e961653dc66fbe8d5421eef04260b91ca410f4 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -10,6 +10,12 @@ import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
public class CraftItem extends CraftEntity implements Item {
+
+ // Paper start
+ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE;
+ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE;
+ // Paper end
+
private final ItemEntity item;
public CraftItem(CraftServer server, Entity entity, ItemEntity item) {
@@ -76,6 +82,26 @@ public class CraftItem extends CraftEntity implements Item {
public void setCanMobPickup(boolean canMobPickup) {
item.canMobPickup = canMobPickup;
}
+
+ @Override
+ public boolean canPlayerPickup() {
+ return item.pickupDelay != NO_PICKUP_TIME;
+ }
+
+ @Override
+ public void setCanPlayerPickup(boolean canPlayerPickup) {
+ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME;
+ }
+
+ @Override
+ public boolean willAge() {
+ return item.age != NO_AGE_TIME;
+ }
+
+ @Override
+ public void setWillAge(boolean willAge) {
+ item.age = willAge ? 0 : NO_AGE_TIME;
+ }
// Paper End
@Override

View file

@ -0,0 +1,135 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 4 Aug 2020 22:24:15 +0200
Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections
1.17 Update: Please do this k thx bb
I utilized the IDE to convert streams to non streams code, so shouldn't
be any risk of behavior change. Only did minor optimization of the
generated code set to remove unnecessary things.
I expect us to just drop this patch on next major update and re-apply
it with the IDE again and re-apply the collections optimization.
Optimize collection by creating a list instead of a set of the key and value.
This lets us get faster foreach iteration, as well as avoids map lookups on
the values when needed.
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
index 300c812d513e0b948a7e79c0ed241f514c7a09fc..d23481453717f715124156b5d83f6448f720d049 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
@@ -38,9 +38,12 @@ public class PathFinder {
if (node == null) {
return null;
} else {
- Map<Target, BlockPos> map = positions.stream().collect(Collectors.toMap((pos) -> {
- return this.nodeEvaluator.getGoal((double)pos.getX(), (double)pos.getY(), (double)pos.getZ());
- }, Function.identity()));
+ // Paper start - remove streams - and optimize collection
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
+ for (BlockPos pos : positions) {
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos));
+ }
+ // Paper end
Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
this.nodeEvaluator.done();
return path;
@@ -48,18 +51,19 @@ public class PathFinder {
}
@Nullable
- private Path findPath(ProfilerFiller profiler, Node startNode, Map<Target, BlockPos> positions, float followRange, int distance, float rangeMultiplier) {
+ // Paper start - optimize collection
+ private Path findPath(ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) {
profiler.push("find_path");
profiler.markForCharting(MetricCategory.PATH_FINDING);
- Set<Target> set = positions.keySet();
+ // Set<Target> set = positions.keySet();
startNode.g = 0.0F;
- startNode.h = this.getBestH(startNode, set);
+ startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection
startNode.f = startNode.h;
this.openSet.clear();
this.openSet.insert(startNode);
- Set<Node> set2 = ImmutableSet.of();
+ // Set<Node> set2 = ImmutableSet.of(); // Paper - unused - diff on change
int i = 0;
- Set<Target> set3 = Sets.newHashSetWithExpectedSize(set.size());
+ List<Map.Entry<Target, BlockPos>> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection
int j = (int)((float)this.maxVisitedNodes * rangeMultiplier);
while(!this.openSet.isEmpty()) {
@@ -71,14 +75,18 @@ public class PathFinder {
Node node = this.openSet.pop();
node.closed = true;
- for(Target target : set) {
+ // Paper start - optimize collection
+ for(int i1 = 0; i1 < positions.size(); i1++) {
+ final Map.Entry<Target, BlockPos> entry = positions.get(i1);
+ Target target = entry.getKey();
if (node.distanceManhattan(target) <= (float)distance) {
target.setReached();
- set3.add(target);
+ entryList.add(entry);
+ // Paper end
}
}
- if (!set3.isEmpty()) {
+ if (!entryList.isEmpty()) { // Paper - rename variable
break;
}
@@ -93,7 +101,7 @@ public class PathFinder {
if (node2.walkedDistance < followRange && (!node2.inOpenSet() || g < node2.g)) {
node2.cameFrom = node;
node2.g = g;
- node2.h = this.getBestH(node2, set) * 1.5F;
+ node2.h = this.getBestH(node2, positions) * 1.5F; // Paper - list instead of set
if (node2.inOpenSet()) {
this.openSet.changeCost(node2, node2.g + node2.h);
} else {
@@ -105,23 +113,31 @@ public class PathFinder {
}
}
- Optional<Path> optional = !set3.isEmpty() ? set3.stream().map((node) -> {
- return this.reconstructPath(node.getBestNode(), positions.get(node), true);
- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> {
- return this.reconstructPath(target.getBestNode(), positions.get(target), false);
- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
- profiler.pop();
- return !optional.isPresent() ? null : optional.get();
+ // Paper start - remove streams - and optimize collection
+ Path best = null;
+ boolean entryListIsEmpty = entryList.isEmpty();
+ Comparator<Path> comparator = entryListIsEmpty ? Comparator.comparingInt(Path::getNodeCount)
+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount);
+ for (Map.Entry<Target, BlockPos> entry : entryListIsEmpty ? positions : entryList) {
+ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty);
+ if (best == null || comparator.compare(path, best) < 0)
+ best = path;
+ }
+ return best;
+ // Paper end
}
protected float distance(Node a, Node b) {
return a.distanceTo(b);
}
- private float getBestH(Node node, Set<Target> targets) {
+ private float getBestH(Node node, List<Map.Entry<Target, BlockPos>> targets) { // Paper - optimize collection - Set<Target> -> List<Map.Entry<Target, BlockPos>>
float f = Float.MAX_VALUE;
- for(Target target : targets) {
+ // Paper start - optimize collection
+ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) {
+ final Target target = targets.get(i).getKey();
+ // Paper end
float g = node.distanceTo(target);
target.updateBest(g, node);
f = Math.min(g, f);

View file

@ -0,0 +1,131 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 24 Jun 2020 12:39:08 -0600
Subject: [PATCH] Beacon API - custom effect ranges
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 8b79df496e1fad57e8c5c0aa97d0d84ab0deed1e..c9b0b0c3fd615bda5f6e633ec33a20751a25d8d9 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -78,6 +78,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null;
}
// CraftBukkit end
+ // Paper start - add field/methods for custom range
+ private final String PAPER_RANGE_TAG = "Paper.Range";
+ private double effectRange = -1;
+
+ public double getEffectRange() {
+ if (this.effectRange < 0) {
+ return this.levels * 10 + 10;
+ } else {
+ return effectRange;
+ }
+ }
+
+ public void setEffectRange(double range) {
+ this.effectRange = range;
+ }
+
+ public void resetEffectRange() {
+ this.effectRange = -1;
+ }
+ // Paper end
public BeaconBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.BEACON, pos, state);
@@ -188,7 +208,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
- BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower);
+ BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
}
}
@@ -274,8 +294,13 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
public static List getHumansInRange(Level world, BlockPos blockposition, int i) {
+ // Paper start
+ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null);
+ }
+ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end
{
- double d0 = (double) (i * 10 + 10);
+ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10);// Paper - custom beacon ranges
AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
@@ -316,12 +341,17 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect) {
+ // Paper start
+ BeaconBlockEntity.applyEffects(world, pos, beaconLevel, primaryEffect, secondaryEffect, null);
+ }
+ private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end
if (!world.isClientSide && primaryEffect != null) {
double d0 = (double) (beaconLevel * 10 + 10);
byte b0 = BeaconBlockEntity.getAmplification(beaconLevel, primaryEffect, secondaryEffect);
int j = BeaconBlockEntity.getLevel(beaconLevel);
- List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel);
+ List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel, blockEntity); // Paper
BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent
@@ -371,6 +401,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
this.lockKey = LockCode.fromTag(nbt);
+ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper
}
@Override
@@ -384,6 +415,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
this.lockKey.addToTag(nbt);
+ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper
}
public void setCustomName(@Nullable Component customName) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
index c186a44b927188ed222f8b2f8f76aaef35d9c654..c47e613cae3d9252a8364ccc4d717e410bb0fc0c 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
@@ -29,7 +29,7 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
if (tileEntity instanceof BeaconBlockEntity) {
BeaconBlockEntity beacon = (BeaconBlockEntity) tileEntity;
- Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels);
+ Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels, beacon); // Paper
Collection<LivingEntity> bukkit = new ArrayList<LivingEntity>(nms.size());
for (Player human : nms) {
@@ -106,4 +106,21 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
public void setLock(String key) {
this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key);
}
+
+ // Paper start
+ @Override
+ public double getEffectRange() {
+ return this.getSnapshot().getEffectRange();
+ }
+
+ @Override
+ public void setEffectRange(double range) {
+ this.getSnapshot().setEffectRange(range);
+ }
+
+ @Override
+ public void resetEffectRange() {
+ this.getSnapshot().resetEffectRange();
+ }
+ // Paper end
}

View file

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 14 Nov 2020 16:19:52 +0100
Subject: [PATCH] Add API for quit reason
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 31bdeff1f6bb536c78240efc2dd9c4774e634e11..04f16e56829cc6f2345071a9ca8502a436cb7b44 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -102,6 +102,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.receiving = side;
}
+ // Paper start
+ @Nullable
+ public net.minecraft.server.level.ServerPlayer getPlayer() {
+ if (this.packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl serverGamePacketListener) {
+ return serverGamePacketListener.player;
+ } else {
+ return null;
+ }
+ }
+ // Paper end
+
public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception {
super.channelActive(channelhandlercontext);
this.channel = channelhandlercontext.channel();
@@ -149,12 +160,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.handlingFault = true;
if (this.channel.isOpen()) {
+ net.minecraft.server.level.ServerPlayer player = this.getPlayer(); // Paper
if (throwable instanceof TimeoutException) {
Connection.LOGGER.debug("Timeout", throwable);
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper
this.disconnect(Component.translatable("disconnect.timeout"));
} else {
MutableComponent ichatmutablecomponent = Component.translatable("disconnect.genericReason", "Internal Exception: " + throwable);
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper
if (flag) {
Connection.LOGGER.debug("Failed to sent packet", throwable);
ConnectionProtocol enumprotocol = this.getCurrentProtocol();
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index ad33c444100243b45bd8ee8603b21b41109faa2e..f05900394e0a00b8cad67cfbc7bb817513202553 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -275,6 +275,7 @@ public class ServerPlayer extends Player {
public boolean isRealPlayer; // Paper
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 5cd15898576aa3d3f1c092bf645dd9f1e350cd0e..5a5b3d412d6982efbbe6fca3f794988ba7d5f704 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -507,6 +507,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure
// CraftBukkit end
+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper
this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> {
this.connection.disconnect(ichatbasecomponent);
}));
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 852ced8023b68d77494f1f04eb365b379f95a651..f365eb9705ca78dd586c4e6492015d8710514efc 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -573,7 +573,7 @@ public abstract class PlayerList {
entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper
}
- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : PaperAdventure.asAdventure(entityplayer.getDisplayName()))); // Paper - Adventure
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : PaperAdventure.asAdventure(entityplayer.getDisplayName())), entityplayer.quitReason); // Paper - Adventure & quit reason
this.cserver.getPluginManager().callEvent(playerQuitEvent);
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());