[ci skip] Add more identifying patch comments

This commit is contained in:
Nassim Jahnke
2024-01-21 12:11:43 +01:00
parent dee90322eb
commit f6609428b6
46 changed files with 136 additions and 140 deletions

View File

@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return !entity.isSpectator(); return !entity.isSpectator();
}; };
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith); public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
- public static Predicate<Player> IS_INSOMNIAC = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - public static Predicate<Player> IS_INSOMNIAC = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - Add phantom creative and insomniac controls
+ // Paper start - Ability to control player's insomnia and phantoms + // Paper start - Ability to control player's insomnia and phantoms
+ public static Predicate<Player> IS_INSOMNIAC = (player) -> { + public static Predicate<Player> IS_INSOMNIAC = (player) -> {
+ net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player; + net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player;

View File

@@ -370,7 +370,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
- BlockPos blockposition = BlockPos.containing(d4, d5, d6); - BlockPos blockposition = BlockPos.containing(d4, d5, d6);
- BlockState iblockdata = this.level.getBlockState(blockposition); - BlockState iblockdata = this.level.getBlockState(blockposition);
- if (!iblockdata.isDestroyable()) continue; // Paper - if (!iblockdata.isDestroyable()) continue; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
- FluidState fluid = iblockdata.getFluidState(); // Paper - FluidState fluid = iblockdata.getFluidState(); // Paper
+ // Paper start - optimise explosions + // Paper start - optimise explosions
+ final int blockX = Mth.floor(d4); + final int blockX = Mth.floor(d4);
@@ -403,11 +403,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (optional.isPresent()) { - if (optional.isPresent()) {
- f -= ((Float) optional.get() + 0.3F) * 0.3F; - f -= ((Float) optional.get() + 0.3F) * 0.3F;
- } - }
-
- if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) {
+ if (!iblockdata.isDestroyable()) continue; // Paper + if (!iblockdata.isDestroyable()) continue; // Paper
+ // Paper - optimise explosions + // Paper - optimise explosions
+
- if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) {
+ f -= cachedBlock.resistance; // Paper - optimise explosions + f -= cachedBlock.resistance; // Paper - optimise explosions
+ +
+ if (f > 0.0F && cachedBlock.shouldExplode == null) { // Paper - optimise explosions + if (f > 0.0F && cachedBlock.shouldExplode == null) { // Paper - optimise explosions

View File

@@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } else { + } else {
+ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); + ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker();
+ } + }
+ // Paper end + // Paper end - PlayerAttackEntityCooldownResetEvent
} }
if (event.isCancelled()) { if (event.isCancelled()) {
return false; return false;

View File

@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return; return;
} }
- this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed - this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed
// Paper end // Paper end - validate pick item position
+ // Paper start - Add PlayerPickItemEvent + // Paper start - Add PlayerPickItemEvent
+ Player bukkitPlayer = this.player.getBukkitEntity(); + Player bukkitPlayer = this.player.getBukkitEntity();
+ int targetSlot = this.player.getInventory().getSuitableHotbarSlot(); + int targetSlot = this.player.getInventory().getSuitableHotbarSlot();

View File

@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return !entity.isSpectator(); return !entity.isSpectator();
}; };
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith); public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
+ public static Predicate<Player> IS_INSOMNIAC = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper + public static Predicate<Player> IS_INSOMNIAC = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - Add phantom creative and insomniac controls
private EntitySelector() {} private EntitySelector() {}
// Paper start // Paper start
@@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
Player entityhuman = (Player) iterator.next(); Player entityhuman = (Player) iterator.next();
if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) { if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) {
+ if (!level().paperConfig().entities.behavior.phantomsOnlyAttackInsomniacs || EntitySelector.IS_INSOMNIAC.test(entityhuman)) // Paper + if (!level().paperConfig().entities.behavior.phantomsOnlyAttackInsomniacs || EntitySelector.IS_INSOMNIAC.test(entityhuman)) // Paper - Add phantom creative and insomniac controls
Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason
return true; return true;
} }
@@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ServerPlayer entityplayer = (ServerPlayer) iterator.next();
- if (!entityplayer.isSpectator()) { - if (!entityplayer.isSpectator()) {
+ if (!entityplayer.isSpectator() && (!world.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !entityplayer.isCreative())) { // Paper + if (!entityplayer.isSpectator() && (!world.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !entityplayer.isCreative())) { // Paper - Add phantom creative and insomniac controls
BlockPos blockposition = entityplayer.blockPosition(); BlockPos blockposition = entityplayer.blockPosition();
if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) { if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) {

View File

@@ -132,11 +132,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private int playerIdleTimeout; private int playerIdleTimeout;
private final long[] tickTimesNanos; private final long[] tickTimesNanos;
private long aggregatedTickTimesNanos; private long aggregatedTickTimesNanos;
+ // Paper start + // Paper start - Add tick times API and /mspt command
+ public final TickTimes tickTimes5s = new TickTimes(100); + public final TickTimes tickTimes5s = new TickTimes(100);
+ public final TickTimes tickTimes10s = new TickTimes(200); + public final TickTimes tickTimes10s = new TickTimes(200);
+ public final TickTimes tickTimes60s = new TickTimes(1200); + public final TickTimes tickTimes60s = new TickTimes(1200);
+ // Paper end + // Paper end - Add tick times API and /mspt command
@Nullable @Nullable
private KeyPair keyPair; private KeyPair keyPair;
@Nullable @Nullable
@@ -144,11 +144,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) j / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) j / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
long l = Util.getNanos(); long l = Util.getNanos();
+ // Paper start + // Paper start - Add tick times API and /mspt command
+ tickTimes5s.add(this.tickCount, j); + tickTimes5s.add(this.tickCount, j);
+ tickTimes10s.add(this.tickCount, j); + tickTimes10s.add(this.tickCount, j);
+ tickTimes60s.add(this.tickCount, j); + tickTimes60s.add(this.tickCount, j);
+ // Paper end + // Paper end - Add tick times API and /mspt command
this.logTickTime(l - i); this.logTickTime(l - i);
this.profiler.pop(); this.profiler.pop();
org.spigotmc.WatchdogThread.tick(); // Spigot org.spigotmc.WatchdogThread.tick(); // Spigot
@@ -157,7 +157,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
+ +
+ // Paper start + // Paper start - Add tick times API and /mspt command
+ public static class TickTimes { + public static class TickTimes {
+ private final long[] times; + private final long[] times;
+ +
@@ -181,7 +181,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return ((double) total / (double) times.length) * 1.0E-6D; + return ((double) total / (double) times.length) * 1.0E-6D;
+ } + }
+ } + }
+ // Paper end + // Paper end - Add tick times API and /mspt command
} }
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View File

@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} else { } else {
// CraftBukkit start // CraftBukkit start
this.containerMenu = container; this.containerMenu = container;
- if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - Prevent opening inventories when frozen
+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper - Add titleOverride to InventoryOpenEvent + if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper - Add titleOverride to InventoryOpenEvent
// CraftBukkit end // CraftBukkit end
this.initMenu(container); this.initMenu(container);
@@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent + if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
} }
@@ -74,9 +74,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
//String title = inventory.getTitle(); // Paper - comment //String title = inventory.getTitle(); // Paper - comment
net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper
+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent + if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
player.containerMenu = container; player.containerMenu = container;
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View File

@@ -52,7 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ case TRADING -> com.destroystokyo.paper.entity.villager.ReputationType.TRADING; + case TRADING -> com.destroystokyo.paper.entity.villager.ReputationType.TRADING;
+ }; + };
+ } + }
+ // Paper end + // Paper end - Add villager reputation API
} }
static record GossipEntry(UUID target, GossipType type, int value) { static record GossipEntry(UUID target, GossipType type, int value) {

View File

@@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ List<Entity> list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushable(this, this.level().paperConfig().collisions.fixClimbingBypassingCrammingRule)); // Paper - Climbing should not bypass cramming gamerule + List<Entity> list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushable(this, this.level().paperConfig().collisions.fixClimbingBypassingCrammingRule)); // Paper - Climbing should not bypass cramming gamerule
if (!list.isEmpty()) { if (!list.isEmpty()) {
// Paper - moved up // Paper - don't run getEntities if we're not going to use its result; moved up
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
return !this.isRemoved() && this.collides; // CraftBukkit return !this.isRemoved() && this.collides; // CraftBukkit
} }

View File

@@ -586,12 +586,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis @@ -0,0 +0,0 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis
ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception); ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception);
// Paper start // Paper start - Debugging
if (MinecraftServer.getServer().isDebugging()) { if (MinecraftServer.getServer().isDebugging()) {
- exception.printStackTrace(); - exception.printStackTrace();
+ io.papermc.paper.util.TraceUtil.printStackTrace(exception); + io.papermc.paper.util.TraceUtil.printStackTrace(exception);
} }
// Paper end // Paper end - Debugging
this.connection.send(new ClientboundDisconnectPacket(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA)); this.connection.send(new ClientboundDisconnectPacket(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA));
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View File

@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.hivePos == null) { if (this.hivePos == null) {
return false; return false;
} else { } else {
+ if (!this.level().isLoadedAndInBounds(this.hivePos)) return false; // Paper + if (!this.level().isLoadedAndInBounds(this.hivePos)) return false; // Paper - Do not allow bees to load chunks for beehives
BlockEntity tileentity = this.level().getBlockEntity(this.hivePos); BlockEntity tileentity = this.level().getBlockEntity(this.hivePos);
return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby();
@@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
private boolean doesHiveHaveSpace(BlockPos pos) { private boolean doesHiveHaveSpace(BlockPos pos) {
+ if (!this.level().isLoadedAndInBounds(pos)) return false; // Paper + if (!this.level().isLoadedAndInBounds(pos)) return false; // Paper - Do not allow bees to load chunks for beehives
BlockEntity tileentity = this.level().getBlockEntity(pos); BlockEntity tileentity = this.level().getBlockEntity(pos);
return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false;
@@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public boolean canBeeUse() { public boolean canBeeUse() {
if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) { if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) {
+ if (!Bee.this.level().isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper + if (!Bee.this.level().isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper - Do not allow bees to load chunks for beehives
BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos);
if (tileentity instanceof BeehiveBlockEntity) { if (tileentity instanceof BeehiveBlockEntity) {
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public void start() { public void start() {
+ if (!Bee.this.level().isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper + if (!Bee.this.level().isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper - Do not allow bees to load chunks for beehives
BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos);
if (tileentity instanceof BeehiveBlockEntity) { if (tileentity instanceof BeehiveBlockEntity) {

View File

@@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- objectset.remove(player); - objectset.remove(player);
- if (objectset.isEmpty()) { - if (objectset.isEmpty()) {
+ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. + if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully
+ if (objectset == null || objectset.isEmpty()) { // Paper + if (objectset == null || objectset.isEmpty()) { // Paper
this.playersPerChunk.remove(i); this.playersPerChunk.remove(i);
this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false);

View File

@@ -3,7 +3,6 @@ From: Aikar <aikar@aikar.co>
Date: Thu, 23 Apr 2020 01:36:39 -0400 Date: Thu, 23 Apr 2020 01:36:39 -0400
Subject: [PATCH] Don't fire BlockFade on worldgen threads Subject: [PATCH] Don't fire BlockFade on worldgen threads
Caused a deadlock
diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -22,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} }
- return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); - return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE));
+ return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - diff on change, see "don't fire events in world generation" + return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - don't fire events in world generation; diff on change, see "don't fire events in world generation"
// CraftBukkit end // CraftBukkit end
} }

View File

@@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.advancements = server.getPlayerList().getPlayerAdvancements(this); this.advancements = server.getPlayerList().getPlayerAdvancements(this);
this.setMaxUpStep(1.0F); this.setMaxUpStep(1.0F);
- this.fudgeSpawnLocation(world); - this.fudgeSpawnLocation(world);
+ // this.fudgeSpawnLocation(world); // Paper - don't move to spawn on login, only first join + // this.fudgeSpawnLocation(world); // Paper - Don't move existing players to world spawn
this.updateOptions(clientOptions); this.updateOptions(clientOptions);
this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
@@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Paper start // Paper start
if (nbttagcompound == null) { if (nbttagcompound == null) {
player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
+ player.fudgeSpawnLocation(worldserver1); // only move to spawn on first login, otherwise, stay where you are.... + player.fudgeSpawnLocation(worldserver1); // Paper - Don't move existing players to world spawn
} }
// Paper end // Paper end
player.setServerLevel(worldserver1); player.setServerLevel(worldserver1);

View File

@@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!list.isEmpty()) { if (!list.isEmpty()) {
- int i = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); - int i = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING);
+ // Paper - moved up + // Paper - don't run getEntities if we're not going to use its result; moved up
if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) {
int j = 0; int j = 0;

View File

@@ -13,14 +13,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!list.isEmpty()) { if (!list.isEmpty()) {
- TheEndGatewayBlockEntity.teleportEntity(world, pos, state, (Entity) list.get(world.random.nextInt(list.size())), blockEntity); - TheEndGatewayBlockEntity.teleportEntity(world, pos, state, (Entity) list.get(world.random.nextInt(list.size())), blockEntity);
+ // Paper start + // Paper start - Ensure safe gateway teleport
+ for (Entity entity : list) { + for (Entity entity : list) {
+ if (entity.canChangeDimensions()) { + if (entity.canChangeDimensions()) {
+ TheEndGatewayBlockEntity.teleportEntity(world, pos, state, entity, blockEntity); + TheEndGatewayBlockEntity.teleportEntity(world, pos, state, entity, blockEntity);
+ break; + break;
+ } + }
+ } + }
+ // Paper end + // Paper end - Ensure safe gateway teleport
} }
if (blockEntity.age % 2400L == 0L) { if (blockEntity.age % 2400L == 0L) {

View File

@@ -13,10 +13,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) { if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) {
double radius = world.spigotConfig.expMerge; double radius = world.spigotConfig.expMerge;
- if (radius > 0) { - if (radius > 0) {
+ // Paper start - Call EntitySpawnEvent for ExperienceOrb entities + event = CraftEventFactory.callEntitySpawnEvent(entity); // Call spawn event for ExperienceOrb entities
+ event = CraftEventFactory.callEntitySpawnEvent(entity);
+ if (radius > 0 && !event.isCancelled() && !entity.isRemoved()) { + if (radius > 0 && !event.isCancelled() && !entity.isRemoved()) {
+ // Paper end - Call EntitySpawnEvent for ExperienceOrb entities // Paper start - Maximum exp value when merging; Whole section has been tweaked, see comments for specifics
// Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics
final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue; final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue;
final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0; final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0;

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Sun, 19 Apr 2020 00:05:46 -0400 Date: Sun, 19 Apr 2020 00:05:46 -0400
Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent Subject: [PATCH] Fire PlayerJoinEvent when Player is actually ready
For years, plugin developers have had to delay many things they do For years, plugin developers have had to delay many things they do
inside of the PlayerJoinEvent by 1 tick to make it actually work. inside of the PlayerJoinEvent by 1 tick to make it actually work.
@@ -35,13 +35,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
return; return;
} }
+ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets // Paper end - ignore and warn about illegal addEntity calls instead of crashing server
// Paper end + if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Paper - Fire PlayerJoinEvent when Player is actually ready; Delay adding to tracker until after list packets
if (!(entity instanceof EnderDragonPart)) { if (!(entity instanceof EnderDragonPart)) {
EntityType<?> entitytypes = entity.getType(); EntityType<?> entitytypes = entity.getType();
int i = entitytypes.clientTrackingRange() * 16;
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public double maxHealthCache; public double maxHealthCache;
public boolean joining = true; public boolean joining = true;
public boolean sentListPacket = false; public boolean sentListPacket = false;
+ public boolean supressTrackerForLogin = false; // Paper + public boolean supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent
// CraftBukkit end // CraftBukkit end
public boolean isRealPlayer; // Paper public boolean isRealPlayer; // Paper
@@ -62,12 +62,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.playersByUUID.put(player.getUUID(), player); this.playersByUUID.put(player.getUUID(), player);
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below
+ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks + // Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
+ player.supressTrackerForLogin = true; + player.supressTrackerForLogin = true;
+ worldserver1.addNewPlayer(player); + worldserver1.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); + this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer);
+ mountSavedVehicle(player, worldserver1, nbttagcompound); + mountSavedVehicle(player, worldserver1, nbttagcompound);
+ // Paper end + // Paper end - Fire PlayerJoinEvent when Player is actually ready
// CraftBukkit start // CraftBukkit start
CraftPlayer bukkitPlayer = player.getBukkitEntity(); CraftPlayer bukkitPlayer = player.getBukkitEntity();
@@ -75,8 +75,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1)));
} }
player.sentListPacket = true; player.sentListPacket = true;
+ player.supressTrackerForLogin = false; // Paper + player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now + ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
// CraftBukkit end // CraftBukkit end
player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
@@ -84,11 +84,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect));
} }
+ // Paper start - move vehicle into method so it can be called above - short circuit around that code + // Paper start - Fire PlayerJoinEvent when Player is actually ready; move vehicle into method so it can be called above - short circuit around that code
+ onPlayerJoinFinish(player, worldserver1, s1); + onPlayerJoinFinish(player, worldserver1, s1);
+ } + }
+ private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) { + private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) {
+ // Paper end + // Paper end - Fire PlayerJoinEvent when Player is actually ready
if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) {
CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle");
// CraftBukkit start // CraftBukkit start
@@ -96,10 +96,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} }
+ // Paper start + // Paper start - Fire PlayerJoinEvent when Player is actually ready
+ } + }
+ public void onPlayerJoinFinish(ServerPlayer player, ServerLevel worldserver1, String s1) { + public void onPlayerJoinFinish(ServerPlayer player, ServerLevel worldserver1, String s1) {
+ // Paper end + // Paper end - Fire PlayerJoinEvent when Player is actually ready
player.initInventoryMenu(); player.initInventoryMenu();
// CraftBukkit - Moved from above, added world // CraftBukkit - Moved from above, added world
// Paper start - Add to collideRule team if needed // Paper start - Add to collideRule team if needed

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Sat, 25 Apr 2020 06:46:35 -0400 Date: Sat, 25 Apr 2020 06:46:35 -0400
Subject: [PATCH] Fix numerous item duplication issues and teleport issues Subject: [PATCH] Fix item duplication and teleport issues
This notably fixes the newest "Donkey Dupe", but also fixes a lot This notably fixes the newest "Donkey Dupe", but also fixes a lot
of dupe bugs in general around nether portals and entity world transfer of dupe bugs in general around nether portals and entity world transfer
@@ -38,12 +38,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Nullable @Nullable
public Entity teleportTo(ServerLevel worldserver, Vec3 location) { public Entity teleportTo(ServerLevel worldserver, Vec3 location) {
// CraftBukkit end // CraftBukkit end
+ // Paper start - fix bad state entities causing dupes + // Paper start - Fix item duplication and teleport issues
+ if (!this.isAlive() || !this.valid) { + if (!this.isAlive() || !this.valid) {
+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); + LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable());
+ return null; + return null;
+ } + }
+ // Paper end + // Paper end - Fix item duplication and teleport issues
if (this.level() instanceof ServerLevel && !this.isRemoved()) { if (this.level() instanceof ServerLevel && !this.isRemoved()) {
this.level().getProfiler().push("changeDimension"); this.level().getProfiler().push("changeDimension");
// CraftBukkit start // CraftBukkit start
@@ -51,11 +51,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit end // CraftBukkit end
this.level().getProfiler().popPush("reloading"); this.level().getProfiler().popPush("reloading");
+ // Paper start - Change lead drop timing to prevent dupe + // Paper start - Fix item duplication and teleport issues
+ if (this instanceof Mob) { + if (this instanceof Mob) {
+ ((Mob) this).dropLeash(true, true); // Paper drop lead + ((Mob) this).dropLeash(true, true); // Paper drop lead
+ } + }
+ // Paper end + // Paper end - Fix item duplication and teleport issues
Entity entity = this.getType().create(worldserver); Entity entity = this.getType().create(worldserver);
if (entity != null) { if (entity != null) {
@@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean canChangeDimensions() { public boolean canChangeDimensions() {
- return !this.isPassenger() && !this.isVehicle(); - return !this.isPassenger() && !this.isVehicle();
+ return !this.isPassenger() && !this.isVehicle() && isAlive() && valid; // Paper + return !this.isPassenger() && !this.isVehicle() && isAlive() && valid; // Paper - Fix item duplication and teleport issues
} }
public float getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState, float max) { public float getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState, float max) {
@@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (this.deathScore >= 0 && entityliving != null) { - if (this.deathScore >= 0 && entityliving != null) {
- entityliving.awardKillScore(this, this.deathScore, damageSource); - entityliving.awardKillScore(this, this.deathScore, damageSource);
- } - }
+ // if (this.deathScore >= 0 && entityliving != null) { // Paper moved to be run earlier in #dropAllDeathLoot before destroying the drop items in CraftEventFactory#callEntityDeathEvent + // if (this.deathScore >= 0 && entityliving != null) { // Paper - Fix item duplication and teleport issues; moved to be run earlier in #dropAllDeathLoot before destroying the drop items in CraftEventFactory#callEntityDeathEvent
+ // entityliving.awardKillScore(this, this.deathScore, damageSource); + // entityliving.awardKillScore(this, this.deathScore, damageSource);
+ // } + // }
// Paper start - clear equipment if event is not cancelled // Paper start - clear equipment if event is not cancelled

View File

@@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { @@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
public boolean joining = true; public boolean joining = true;
public boolean sentListPacket = false; public boolean sentListPacket = false;
public boolean supressTrackerForLogin = false; // Paper public boolean supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
- public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent - public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent
// CraftBukkit end // CraftBukkit end
public boolean isRealPlayer; // Paper public boolean isRealPlayer; // Paper

View File

@@ -74,7 +74,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
BlockState blockState = Block.updateFromNeighbourShapes(blockEntity.movedState, world, pos); BlockState blockState = Block.updateFromNeighbourShapes(blockEntity.movedState, world, pos);
if (blockState.isAir()) { if (blockState.isAir()) {
- world.setBlock(pos, blockEntity.movedState, 84); - world.setBlock(pos, blockEntity.movedState, 84);
+ world.setBlock(pos, blockEntity.movedState, io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPistonDuplication ? 84 : (84 | Block.UPDATE_CLIENTS)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air + world.setBlock(pos, blockEntity.movedState, io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPistonDuplication ? 84 : (84 | Block.UPDATE_CLIENTS)); // Paper - fix a variety of piston desync dupes; force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air
Block.updateOrDestroy(blockEntity.movedState, blockState, world, pos, 3); Block.updateOrDestroy(blockEntity.movedState, blockState, world, pos, 3);
} else { } else {
if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED)) { if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED)) {

View File

@@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - Fix sticky pistons and BlockPistonRetractEvent + // Paper end - Fix sticky pistons and BlockPistonRetractEvent
world.setBlock(pos, iblockdata2, 20); world.setBlock(pos, iblockdata2, 20);
world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed; diff on change
world.blockUpdated(pos, iblockdata2.getBlock()); world.blockUpdated(pos, iblockdata2.getBlock());
@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { @@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock {
if (type == 1 && !iblockdata3.isAir() && PistonBaseBlock.isPushable(iblockdata3, world, blockposition1, enumdirection.getOpposite(), false, enumdirection) && (iblockdata3.getPistonPushReaction() == PushReaction.NORMAL || iblockdata3.is(Blocks.PISTON) || iblockdata3.is(Blocks.STICKY_PISTON))) { if (type == 1 && !iblockdata3.isAir() && PistonBaseBlock.isPushable(iblockdata3, world, blockposition1, enumdirection.getOpposite(), false, enumdirection) && (iblockdata3.getPistonPushReaction() == PushReaction.NORMAL || iblockdata3.is(Blocks.PISTON) || iblockdata3.is(Blocks.STICKY_PISTON))) {

View File

@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void updateDemand() { public void updateDemand() {
- this.demand = this.demand + this.uses - (this.maxUses - this.uses); - this.demand = this.demand + this.uses - (this.maxUses - this.uses);
+ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper + this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - Fix MC-163962
} }
public ItemStack assemble() { public ItemStack assemble() {

View File

@@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -0,0 +0,0 @@ public abstract class PlayerList {
// Paper start - move vehicle into method so it can be called above - short circuit around that code // Paper start - Fire PlayerJoinEvent when Player is actually ready; move vehicle into method so it can be called above - short circuit around that code
onPlayerJoinFinish(player, worldserver1, s1); onPlayerJoinFinish(player, worldserver1, s1);
+ // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead + // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
+ if (player.isDeadOrDying()) { + if (player.isDeadOrDying()) {
@@ -29,4 +29,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Send empty chunk + // Paper end - Send empty chunk
} }
private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) { private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) {
// Paper end // Paper end - Fire PlayerJoinEvent when Player is actually ready

View File

@@ -751,13 +751,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be.
private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector
+ // Paper start make sure goaltypes is never empty + // Paper start - Mob goal API; make sure goaltypes is never empty
+ public Goal() { + public Goal() {
+ if (this.goalTypes.size() == 0) { + if (this.goalTypes.size() == 0) {
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); + this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+ } + }
+ } + }
+ // Paper end + // Paper end - Mob goal API
+ +
public abstract boolean canUse(); public abstract boolean canUse();
@@ -777,7 +777,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return Mth.positiveCeilDiv(serverTicks, 2); return Mth.positiveCeilDiv(serverTicks, 2);
} }
+ // Paper start - mob goal api + // Paper start - Mob goal api
+ private com.destroystokyo.paper.entity.ai.PaperVanillaGoal<?> vanillaGoal = null; + private com.destroystokyo.paper.entity.ai.PaperVanillaGoal<?> vanillaGoal = null;
+ public <T extends org.bukkit.entity.Mob> com.destroystokyo.paper.entity.ai.Goal<T> asPaperVanillaGoal() { + public <T extends org.bukkit.entity.Mob> com.destroystokyo.paper.entity.ai.Goal<T> asPaperVanillaGoal() {
+ if(this.vanillaGoal == null) { + if(this.vanillaGoal == null) {
@@ -786,7 +786,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ //noinspection unchecked + //noinspection unchecked
+ return (com.destroystokyo.paper.entity.ai.Goal<T>) this.vanillaGoal; + return (com.destroystokyo.paper.entity.ai.Goal<T>) this.vanillaGoal;
+ } + }
+ // Paper end - mob goal api + // Paper end - Mob goal api
+ +
public static enum Flag { public static enum Flag {
+ UNKNOWN_BEHAVIOR, // Paper - add UNKNOWN_BEHAVIOR + UNKNOWN_BEHAVIOR, // Paper - add UNKNOWN_BEHAVIOR

View File

@@ -93,7 +93,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { @@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
this.advancements = server.getPlayerList().getPlayerAdvancements(this); this.advancements = server.getPlayerList().getPlayerAdvancements(this);
this.setMaxUpStep(1.0F); this.setMaxUpStep(1.0F);
// this.fudgeSpawnLocation(world); // Paper - don't move to spawn on login, only first join // this.fudgeSpawnLocation(world); // Paper - Don't move existing players to world spawn
- this.updateOptions(clientOptions); - this.updateOptions(clientOptions);
+ this.updateOptionsNoEvents(clientOptions); // Paper - don't call options events on login + this.updateOptionsNoEvents(clientOptions); // Paper - don't call options events on login

View File

@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<RelativeMovement> set) { // Paper public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<RelativeMovement> set) { // Paper
+ org.spigotmc.AsyncCatcher.catchOp("teleport"); // Paper + org.spigotmc.AsyncCatcher.catchOp("teleport"); // Paper
// Paper start // Paper start - Prevent teleporting dead entities
if (player.isRemoved()) { if (player.isRemoved()) {
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java

View File

@@ -79,11 +79,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Paper start // Paper start
if (nbttagcompound == null) { if (nbttagcompound == null) {
player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
+ // Paper start - reset to main world spawn if first spawn or invalid world + // Paper start - reset to main world spawn if first spawn or invalid world
+ } + }
+ if (nbttagcompound == null || invalidPlayerWorld) { + if (nbttagcompound == null || invalidPlayerWorld) {
+ // Paper end + // Paper end - reset to main world spawn if first spawn or invalid world
player.fudgeSpawnLocation(worldserver1); // only move to spawn on first login, otherwise, stay where you are.... player.fudgeSpawnLocation(worldserver1); // Paper - Don't move existing players to world spawn
} }
// Paper end // Paper end
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java

View File

@@ -162,7 +162,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
//this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); // Paper - no longer used //this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); // Paper - no longer used
} }
@@ -0,0 +0,0 @@ public abstract class DistanceManager { @@ -0,0 +0,0 @@ public abstract class DistanceManager {
if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully
if (objectset == null || objectset.isEmpty()) { // Paper if (objectset == null || objectset.isEmpty()) { // Paper
this.playersPerChunk.remove(i); this.playersPerChunk.remove(i);
- this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); - this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false);

View File

@@ -14,20 +14,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return this.moveTo(this.createPath(x, y, z, 1), speed); return this.moveTo(this.createPath(x, y, z, 1), speed);
} }
+ // Paper start - optimise pathfinding + // Paper start - Perf: Optimise pathfinding
+ private int lastFailure = 0; + private int lastFailure = 0;
+ private int pathfindFailures = 0; + private int pathfindFailures = 0;
+ // Paper end + // Paper end - Perf: Optimise pathfinding
+ +
public boolean moveTo(Entity entity, double speed) { public boolean moveTo(Entity entity, double speed) {
+ // Paper start - Pathfinding optimizations + // Paper start - Perf: Optimise pathfinding
+ if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) { + if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) {
+ return false; + return false;
+ } + }
+ // Paper end + // Paper end - Perf: Optimise pathfinding
Path path = this.createPath(entity, 1); Path path = this.createPath(entity, 1);
- return path != null && this.moveTo(path, speed); - return path != null && this.moveTo(path, speed);
+ // Paper start - Pathfinding optimizations + // Paper start - Perf: Optimise pathfinding
+ if (path != null && this.moveTo(path, speed)) { + if (path != null && this.moveTo(path, speed)) {
+ this.lastFailure = 0; + this.lastFailure = 0;
+ this.pathfindFailures = 0; + this.pathfindFailures = 0;
@@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.lastFailure = net.minecraft.server.MinecraftServer.currentTick; + this.lastFailure = net.minecraft.server.MinecraftServer.currentTick;
+ return false; + return false;
+ } + }
+ // Paper end + // Paper end - Perf: Optimise pathfinding
} }
public boolean moveTo(@Nullable Path path, double speed) { public boolean moveTo(@Nullable Path path, double speed) {

View File

@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) { if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) {
double radius = world.spigotConfig.expMerge; double radius = world.spigotConfig.expMerge;
if (radius > 0) { if (radius > 0) {
+ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics + // Paper start - Maximum exp value when merging; Whole section has been tweaked, see comments for specifics
+ final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue; + final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue;
+ final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0; + final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0;
+ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary + if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary
@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } else { + } else {
xp.value += loopItem.value; xp.value += loopItem.value;
loopItem.discard(); loopItem.discard();
+ } // Paper end + } // Paper end - Maximum exp value when merging
} }
} }
} }

View File

@@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean wonGame; public boolean wonGame;
private int containerUpdateDelay; // Paper private int containerUpdateDelay; // Paper
public long loginTime; // Paper public long loginTime; // Paper
+ public int patrolSpawnDelay; // Paper - per player patrol spawns + public int patrolSpawnDelay; // Paper - Pillager patrol spawn settings and per player options
// Paper start - cancellable death event // Paper start - cancellable death event
public boolean queueHealthUpdatePacket = false; public boolean queueHealthUpdatePacket = false;
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
@@ -30,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
- if (world.paperConfig().entities.behavior.pillagerPatrols.disable) return 0; // Paper - if (world.paperConfig().entities.behavior.pillagerPatrols.disable) return 0; // Paper
+ if (world.paperConfig().entities.behavior.pillagerPatrols.disable || world.paperConfig().entities.behavior.pillagerPatrols.spawnChance == 0) return 0; // Paper + if (world.paperConfig().entities.behavior.pillagerPatrols.disable || world.paperConfig().entities.behavior.pillagerPatrols.spawnChance == 0) return 0; // Paper - Pillager patrol spawn settings and per player options
if (!spawnMonsters) { if (!spawnMonsters) {
return 0; return 0;
} else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) {
@@ -40,7 +40,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- --this.nextTick; - --this.nextTick;
- if (this.nextTick > 0) { - if (this.nextTick > 0) {
+ // Paper start - Patrol settings + // Paper start - Pillager patrol spawn settings and per player options
+ // Random player selection moved up for per player spawning and configuration + // Random player selection moved up for per player spawning and configuration
+ int j = world.players().size(); + int j = world.players().size();
+ if (j < 1) { + if (j < 1) {
@@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (randomsource.nextInt(5) != 0) { - if (randomsource.nextInt(5) != 0) {
+ if (days >= world.paperConfig().entities.behavior.pillagerPatrols.start.day && world.isDay()) { + if (days >= world.paperConfig().entities.behavior.pillagerPatrols.start.day && world.isDay()) {
+ if (randomsource.nextDouble() >= world.paperConfig().entities.behavior.pillagerPatrols.spawnChance) { + if (randomsource.nextDouble() >= world.paperConfig().entities.behavior.pillagerPatrols.spawnChance) {
+ // Paper end + // Paper end - Pillager patrol spawn settings and per player options
return 0; return 0;
} else { } else {
- int j = world.players().size(); - int j = world.players().size();

View File

@@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable()); + + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
+ return; + return;
+ } + }
+ // Paper end + // Paper end - ignore and warn about illegal addEntity calls instead of crashing server
if (!(entity instanceof EnderDragonPart)) { if (!(entity instanceof EnderDragonPart)) {
EntityType<?> entitytypes = entity.getType(); EntityType<?> entitytypes = entity.getType();
int i = entitytypes.clientTrackingRange() * 16; int i = entitytypes.clientTrackingRange() * 16;
@@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void onTrackingStart(Entity entity) { public void onTrackingStart(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
- ServerLevel.this.getChunkSource().addEntity(entity); - ServerLevel.this.getChunkSource().addEntity(entity);
+ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - moved down below valid=true + // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
if (entity instanceof ServerPlayer) { if (entity instanceof ServerPlayer) {
ServerPlayer entityplayer = (ServerPlayer) entity; ServerPlayer entityplayer = (ServerPlayer) entity;

View File

@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
// Paper end // Paper end
- if (!this.level().isClientSide && !this.containerMenu.stillValid(this)) { - if (!this.level().isClientSide && !this.containerMenu.stillValid(this)) {
+ if (!this.level().isClientSide && this.containerMenu != this.inventoryMenu && (this.isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - auto close while frozen + if (!this.level().isClientSide && this.containerMenu != this.inventoryMenu && (this.isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - Prevent opening inventories when frozen
this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper
this.containerMenu = this.inventoryMenu; this.containerMenu = this.inventoryMenu;
} }
@@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit start // CraftBukkit start
this.containerMenu = container; this.containerMenu = container;
- this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); - this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle()));
+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper + if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - Prevent opening inventories when frozen
// CraftBukkit end // CraftBukkit end
this.initMenu(container); this.initMenu(container);
return OptionalInt.of(this.containerCounter); return OptionalInt.of(this.containerCounter);
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper
+ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
player.containerMenu = container; player.containerMenu = container;
player.initMenu(container); player.initMenu(container);
} }
@@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper
+ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
player.containerMenu = container; player.containerMenu = container;
player.initMenu(container); player.initMenu(container);
} }

View File

@@ -12,13 +12,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<RelativeMovement> set) { // Paper public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<RelativeMovement> set) { // Paper
+ // Paper start + // Paper start - Prevent teleporting dead entities
+ if (player.isRemoved()) { + if (player.isRemoved()) {
+ LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); + LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
+ if (server.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Attempt to teleport removed player"); + if (server.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Attempt to teleport removed player");
+ return; + return;
+ } + }
+ // Paper end + // Paper end - Prevent teleporting dead entities
// CraftBukkit start // CraftBukkit start
if (Float.isNaN(f)) { if (Float.isNaN(f)) {
f = 0; f = 0;

View File

@@ -102,7 +102,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/players/PlayerList.java --- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -0,0 +0,0 @@ public abstract class PlayerList {
((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
// CraftBukkit end // CraftBukkit end
- player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn - player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn

View File

@@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
BlockPos blockposition = BlockPos.containing(d4, d5, d6); BlockPos blockposition = BlockPos.containing(d4, d5, d6);
BlockState iblockdata = this.level.getBlockState(blockposition); BlockState iblockdata = this.level.getBlockState(blockposition);
+ if (!iblockdata.isDestroyable()) continue; // Paper + if (!iblockdata.isDestroyable()) continue; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
FluidState fluid = iblockdata.getFluidState(); // Paper FluidState fluid = iblockdata.getFluidState(); // Paper
if (!this.level.isInWorldBounds(blockposition)) { if (!this.level.isInWorldBounds(blockposition)) {
@@ -32,10 +32,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
// CraftBukkit start - tree generation // CraftBukkit start - tree generation
if (this.captureTreeGeneration) { if (this.captureTreeGeneration) {
+ // Paper start + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ BlockState type = getBlockState(pos); + BlockState type = getBlockState(pos);
+ if (!type.isDestroyable()) return false; + if (!type.isDestroyable()) return false;
+ // Paper end + // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
CraftBlockState blockstate = this.capturedBlockStates.get(pos); CraftBlockState blockstate = this.capturedBlockStates.get(pos);
if (blockstate == null) { if (blockstate == null) {
blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
@@ -71,12 +71,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING);
+ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; prevent retracting when we're facing the wrong way (we were replaced before retraction could occur)
+ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below + Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits && enumdirection != directionQueuedAs) { + if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits && enumdirection != directionQueuedAs) {
+ return false; + return false;
+ } + }
+ // Paper end - prevent retracting when we're facing the wrong way + // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
BlockState iblockdata1 = (BlockState) state.setValue(PistonBaseBlock.EXTENDED, true); BlockState iblockdata1 = (BlockState) state.setValue(PistonBaseBlock.EXTENDED, true);
if (!world.isClientSide) { if (!world.isClientSide) {
@@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
world.setBlock(pos, iblockdata2, 20); world.setBlock(pos, iblockdata2, 20);
- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); - world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true));
+ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change + world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed; diff on change
world.blockUpdated(pos, iblockdata2.getBlock()); world.blockUpdated(pos, iblockdata2.getBlock());
iblockdata2.updateNeighbourShapes(world, pos, 2); iblockdata2.updateNeighbourShapes(world, pos, 2);
if (this.isSticky) { if (this.isSticky) {
@@ -94,14 +94,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} else { } else {
- world.removeBlock(pos.relative(enumdirection), false); - world.removeBlock(pos.relative(enumdirection), false);
+ // Paper start - fix headless pistons breaking blocks + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; fix headless pistons breaking blocks
+ BlockPos headPos = pos.relative(enumdirection); + BlockPos headPos = pos.relative(enumdirection);
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston. + if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston.
+ world.removeBlock(headPos, false); + world.removeBlock(headPos, false);
+ } else { + } else {
+ ((ServerLevel)world).getChunkSource().blockChanged(headPos); // ... fix client desync + ((ServerLevel) world).getChunkSource().blockChanged(headPos); // ... fix client desync
+ } + }
+ // Paper end - fix headless pistons breaking blocks + // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
} }
world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F);
@@ -114,7 +114,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Deprecated @Deprecated
public void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) { public void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
- if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) { - if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) {
+ if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK && state.isDestroyable()) { // Paper + if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK && state.isDestroyable()) { // Paper - Protect Bedrock and End Portal/Frames from being destroyed
Block block = state.getBlock(); Block block = state.getBlock();
boolean flag = explosion.getIndirectSourceEntity() instanceof Player; boolean flag = explosion.getIndirectSourceEntity() instanceof Player;
@@ -123,7 +123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Deprecated @Deprecated
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
- return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())); - return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem()));
+ return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper; + return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed
} }
/** @deprecated */ /** @deprecated */
@@ -131,11 +131,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return this.legacySolid; return this.legacySolid;
} }
+ // Paper start + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ public final boolean isDestroyable() { + public final boolean isDestroyable() {
+ return getBlock().isDestroyable(); + return getBlock().isDestroyable();
+ } + }
+ // Paper end + // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
+ +
public boolean isValidSpawn(BlockGetter world, BlockPos pos, EntityType<?> type) { public boolean isValidSpawn(BlockGetter world, BlockPos pos, EntityType<?> type) {
return this.getBlock().properties.isValidSpawn.test(this.asState(), world, pos, type); return this.getBlock().properties.isValidSpawn.test(this.asState(), world, pos, type);
@@ -145,7 +145,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public PushReaction getPistonPushReaction() { public PushReaction getPistonPushReaction() {
- return this.pushReaction; - return this.pushReaction;
+ return !this.isDestroyable() ? PushReaction.BLOCK : this.pushReaction; // Paper + return !this.isDestroyable() ? PushReaction.BLOCK : this.pushReaction; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
} }
public boolean isSolidRender(BlockGetter world, BlockPos pos) { public boolean isSolidRender(BlockGetter world, BlockPos pos) {
@@ -157,13 +157,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
for (int j = -1; j < 3; ++j) { for (int j = -1; j < 3; ++j) {
for (int k = -1; k < 4; ++k) { for (int k = -1; k < 4; ++k) {
temp.setWithOffset(pos, portalDirection.getStepX() * j + enumdirection1.getStepX() * distanceOrthogonalToPortal, k, portalDirection.getStepZ() * j + enumdirection1.getStepZ() * distanceOrthogonalToPortal); temp.setWithOffset(pos, portalDirection.getStepX() * j + enumdirection1.getStepX() * distanceOrthogonalToPortal, k, portalDirection.getStepZ() * j + enumdirection1.getStepZ() * distanceOrthogonalToPortal);
+ // Paper start - prevent destroying unbreakable blocks + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits) { + if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits) {
+ if (!this.level.getBlockState(temp).isDestroyable()) { + if (!this.level.getBlockState(temp).isDestroyable()) {
+ return false; + return false;
+ } + }
+ } + }
+ // Paper end - prevent destroying unbreakable blocks + // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
if (k < 0 && !this.level.getBlockState(temp).isSolid()) { if (k < 0 && !this.level.getBlockState(temp).isSolid()) {
return false; return false;
} }

View File

@@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final class Left<L, R> extends Either<L, R> { private static final class Left<L, R> extends Either<L, R> {
- private final L value; - private final L value;
+ private final L value; private Optional<L> valueOptional; // Paper - reduce the optional allocation... + private final L value; private Optional<L> valueOptional; // Paper - Perf: Reduce Either Optional allocation
public Left(final L value) { public Left(final L value) {
this.value = value; this.value = value;
@@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public Optional<L> left() { public Optional<L> left() {
- return Optional.of(value); - return Optional.of(value);
+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - Perf: Reduce Either Optional allocation
} }
@Override @Override
@@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final class Right<L, R> extends Either<L, R> { private static final class Right<L, R> extends Either<L, R> {
- private final R value; - private final R value;
+ private final R value; private Optional<R> valueOptional; // Paper - reduce the optional allocation... + private final R value; private Optional<R> valueOptional; // Paper - Perf: Reduce Either Optional allocation
public Right(final R value) { public Right(final R value) {
this.value = value; this.value = value;
@@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public Optional<R> right() { public Optional<R> right() {
- return Optional.of(value); - return Optional.of(value);
+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - Perf: Reduce Either Optional allocation
} }
@Override @Override

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com> From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 6 Apr 2020 17:39:25 -0700 Date: Mon, 6 Apr 2020 17:39:25 -0700
Subject: [PATCH] Reduce memory footprint of NBTTagCompound Subject: [PATCH] Reduce memory footprint of CompoundTag
Fastutil maps are going to have a lower memory footprint - which Fastutil maps are going to have a lower memory footprint - which
is important because we clone chunk data after reading it for safety. is important because we clone chunk data after reading it for safety.
@@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static CompoundTag loadCompound(DataInput input, NbtAccounter tracker) throws IOException { private static CompoundTag loadCompound(DataInput input, NbtAccounter tracker) throws IOException {
tracker.accountBytes(48L); tracker.accountBytes(48L);
- Map<String, Tag> map = Maps.newHashMap(); - Map<String, Tag> map = Maps.newHashMap();
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound + it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - Reduce memory footprint of CompoundTag
byte b; byte b;
while((b = input.readByte()) != 0) { while((b = input.readByte()) != 0) {
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public CompoundTag() { public CompoundTag() {
- this(Maps.newHashMap()); - this(Maps.newHashMap());
+ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound + this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - Reduce memory footprint of CompoundTag
} }
@Override @Override
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public CompoundTag copy() { public CompoundTag copy() {
- Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy)); - Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
- return new CompoundTag(map); - return new CompoundTag(map);
+ // Paper start - reduce memory footprint of NBTTagCompound + // Paper start - Reduce memory footprint of CompoundTag
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); + it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);
+ java.util.Iterator<java.util.Map.Entry<String, Tag>> iterator = (this.tags instanceof it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap) ? ((it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); + java.util.Iterator<java.util.Map.Entry<String, Tag>> iterator = (this.tags instanceof it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap) ? ((it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator();
+ while (iterator.hasNext()) { + while (iterator.hasNext()) {
@@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ return new CompoundTag(ret); + return new CompoundTag(ret);
+ // Paper end - reduce memory footprint of NBTTagCompound + // Paper end - Reduce memory footprint of CompoundTag
} }
@Override @Override

View File

@@ -31,14 +31,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.clients.clear(); this.clients.clear();
} }
+ // Paper start + // Paper start - don't wait for remote connections
+ public void stopNonBlocking() { + public void stopNonBlocking() {
+ this.running = false; + this.running = false;
+ for (RconClient client : this.clients) { + for (RconClient client : this.clients) {
+ client.running = false; + client.running = false;
+ } + }
+ } + }
+ // Paper stop + // Paper stop - don't wait for remote connections
private void closeSocket(ServerSocket socket) { private void closeSocket(ServerSocket socket) {
LOGGER.debug("closeSocket: {}", (Object)socket); LOGGER.debug("closeSocket: {}", (Object)socket);

View File

@@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
// Paper end // Paper end
// Todo: Installation script // Todo: Installation script
+ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size + if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size; https://www.evanjones.ca/java-bytebuffer-leak.html
OptionParser parser = new OptionParser() { OptionParser parser = new OptionParser() {
{ {
this.acceptsAll(Main.asList("?", "help"), "Show the help"); this.acceptsAll(Main.asList("?", "help"), "Show the help");

View File

@@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
for (j1 = 0; j1 < 128; ++j1) { for (j1 = 0; j1 < 128; ++j1) {
for (k1 = 0; k1 < 128; ++k1) { for (k1 = 0; k1 < 128; ++k1) {
- Holder<Biome> holder = world.getBiome(blockposition_mutableblockposition.set((l + k1) * i, 0, (i1 + j1) * i)); - Holder<Biome> holder = world.getBiome(blockposition_mutableblockposition.set((l + k1) * i, 0, (i1 + j1) * i));
+ Holder<Biome> holder = world.getUncachedNoiseBiome((l + k1) * i, 0, (i1 + j1) * i); // Paper + Holder<Biome> holder = world.getUncachedNoiseBiome((l + k1) * i, 0, (i1 + j1) * i); // Paper - Perf: Use seed based lookup for treasure maps
aboolean[j1 * 128 + k1] = holder.is(BiomeTags.WATER_ON_MAP_OUTLINES); aboolean[j1 * 128 + k1] = holder.is(BiomeTags.WATER_ON_MAP_OUTLINES);
} }

View File

@@ -47,5 +47,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - Use single player info update packet on join + // Paper end - Use single player info update packet on join
player.sentListPacket = true; player.sentListPacket = true;
player.supressTrackerForLogin = false; // Paper player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now

View File

@@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return; + return;
+ } + }
+ this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed + this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed
+ // Paper end + // Paper end - validate pick item position
this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected))); this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected)));
this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot()))); this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot())));
this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected));

View File

@@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit start // CraftBukkit start
if (this.server != null) { if (this.server != null) {
this.server.disablePlugins(); this.server.disablePlugins();
+ this.server.waitForAsyncTasksShutdown(); // Paper + this.server.waitForAsyncTasksShutdown(); // Paper - Wait for Async Tasks during shutdown
} }
// CraftBukkit end // CraftBukkit end
this.getConnection().stop(); this.getConnection().stop();
@@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
org.spigotmc.WatchdogThread.hasStarted = true; // Paper - Disable watchdog early timeout on reload org.spigotmc.WatchdogThread.hasStarted = true; // Paper - Disable watchdog early timeout on reload
} }
+ // Paper start + // Paper start - Wait for Async Tasks during shutdown
+ public void waitForAsyncTasksShutdown() { + public void waitForAsyncTasksShutdown() {
+ int pollCount = 0; + int pollCount = 0;
+ +
@@ -52,7 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ )); + ));
+ } + }
+ } + }
+ // Paper end + // Paper end - Wait for Async Tasks during shutdown
+ +
@Override @Override
public void reloadData() { public void reloadData() {

View File

@@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
MutableComponent ichatmutablecomponent = Component.literal(exception.getMessage() == null ? exception.getClass().getName() : exception.getMessage()); MutableComponent ichatmutablecomponent = Component.literal(exception.getMessage() == null ? exception.getClass().getName() : exception.getMessage());
- if (Commands.LOGGER.isDebugEnabled()) { - if (Commands.LOGGER.isDebugEnabled()) {
+ if (commandlistenerwrapper.getServer().isDebugging() || Commands.LOGGER.isDebugEnabled()) { // Paper + if (commandlistenerwrapper.getServer().isDebugging() || Commands.LOGGER.isDebugEnabled()) { // Paper - Debugging
Commands.LOGGER.error("Command exception: /{}", s, exception); Commands.LOGGER.error("Command exception: /{}", s, exception);
StackTraceElement[] astacktraceelement = exception.getStackTrace(); StackTraceElement[] astacktraceelement = exception.getStackTrace();
@@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit start // CraftBukkit start
private boolean hasStopped = false; private boolean hasStopped = false;
public volatile boolean hasFullyShutdown = false; // Paper public volatile boolean hasFullyShutdown = false; // Paper
+ private boolean hasLoggedStop = false; // Paper + private boolean hasLoggedStop = false; // Paper - Debugging
private final Object stopLock = new Object(); private final Object stopLock = new Object();
public final boolean hasStopped() { public final boolean hasStopped() {
synchronized (this.stopLock) { synchronized (this.stopLock) {
@@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.hasStopped) return; if (this.hasStopped) return;
this.hasStopped = true; this.hasStopped = true;
} }
+ if (!hasLoggedStop && isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper + if (!hasLoggedStop && isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
// Paper start - kill main thread, and kill it hard // Paper start - kill main thread, and kill it hard
shutdownThread = Thread.currentThread(); shutdownThread = Thread.currentThread();
org.spigotmc.WatchdogThread.doStop(); // Paper org.spigotmc.WatchdogThread.doStop(); // Paper
@@ -65,8 +65,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
public void safeShutdown(boolean waitForShutdown, boolean isRestarting) { public void safeShutdown(boolean waitForShutdown, boolean isRestarting) {
this.isRestarting = isRestarting; this.isRestarting = isRestarting;
+ this.hasLoggedStop = true; // Paper + this.hasLoggedStop = true; // Paper - Debugging
+ if (isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper + if (isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
// Paper end // Paper end
this.running = false; this.running = false;
if (waitForShutdown) { if (waitForShutdown) {
@@ -78,11 +78,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.connection.resumeInboundAfterProtocolChange(); this.connection.resumeInboundAfterProtocolChange();
} catch (Exception exception) { } catch (Exception exception) {
ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception); ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception);
+ // Paper start + // Paper start - Debugging
+ if (MinecraftServer.getServer().isDebugging()) { + if (MinecraftServer.getServer().isDebugging()) {
+ exception.printStackTrace(); + exception.printStackTrace();
+ } + }
+ // Paper end + // Paper end - Debugging
this.connection.send(new ClientboundDisconnectPacket(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA)); this.connection.send(new ClientboundDisconnectPacket(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA));
this.connection.disconnect(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA); this.connection.disconnect(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA);
} }
@@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
plugin.getDescription().getFullName(), plugin.getDescription().getFullName(),
"This plugin is not properly shutting down its async tasks when it is being reloaded. This may cause conflicts with the newly loaded version of the plugin" "This plugin is not properly shutting down its async tasks when it is being reloaded. This may cause conflicts with the newly loaded version of the plugin"
)); ));
+ if (console.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread(worker.getThread(), "still running"); // Paper + if (console.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread(worker.getThread(), "still running"); // Paper - Debugging
} }
io.papermc.paper.plugin.PluginInitializerManager.reload(this.console); // Paper io.papermc.paper.plugin.PluginInitializerManager.reload(this.console); // Paper
this.loadPlugins(); this.loadPlugins();