This commit is contained in:
Owen1212055 2024-04-24 09:46:45 -04:00
parent 5be858e9b7
commit 2d9d0d8b1d
No known key found for this signature in database
GPG key ID: 2133292072886A30
146 changed files with 767 additions and 747 deletions

View file

@ -25,10 +25,10 @@ index f041b5d80bff9c022b007e04ef1558e9116acc6b..a586442422a2b2c06b785af0d261d3e1
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
index f24b4732db849893fd870b4b6a49f1c4b3eacdec..3feaaca5aaee12e48fa2e5f5d05329c9980b161e 100644
index d839a0edf31f6803e5813b28a23fa17e20916b2c..bb8a3e670924ebcce48669c5dce57e2df03fad77 100644
--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
@@ -152,6 +152,11 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
@@ -145,6 +145,11 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
public net.kyori.adventure.text.Component displayName(int level) {
return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getFullname(level));
}

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Create HoverEvent from ItemStack Entity
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
index 71db89105c70cb70726fb6a732b899297aeee82a..12f90520e4d6d5fcea0c2f8e19dad9102970cd99 100644
index fc51a93785ffc464d2719b440f49022f24b3983a..3ebba8af1cf2d2eaf6670860b011c7dc1da62890 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -527,4 +527,41 @@ public final class CraftItemFactory implements ItemFactory {
@@ -537,4 +537,41 @@ public final class CraftItemFactory implements ItemFactory {
return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId(nms)) : null;
}
// Paper end - add getI18NDisplayName

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Cache block data strings
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index adc93e0e7a57907e824bdd8bb7b3012f28b515f4..dd98174480eedfcb348798d9070219581009f16f 100644
index 3ec35f0aff38e6cbd969ec3442b924bc51365f4a..90cd5e6a5564f3b2002c2a4415fe130bf672b5d8 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2068,6 +2068,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2128,6 +2128,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getPlayerList().reloadResources();
this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary());
this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager);
@ -17,10 +17,10 @@ index adc93e0e7a57907e824bdd8bb7b3012f28b515f4..dd98174480eedfcb348798d907021958
if (this.isSameThread()) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index fce3fec5e1ff164b0596fdd6b3d7b5b0277253ef..587396f5ed01939cd3ddce10fecf86ba80eb9c73 100644
index 19fab0d8d8a6211782df1fd99b5d60681aecd2f5..b875bebb8b63c6f60301180fc2e3fc9c1bc87193 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -154,7 +154,7 @@ public class CraftBlockData implements BlockData {
@@ -153,7 +153,7 @@ public class CraftBlockData implements BlockData {
return exactMatch;
}
@ -29,7 +29,7 @@ index fce3fec5e1ff164b0596fdd6b3d7b5b0277253ef..587396f5ed01939cd3ddce10fecf86ba
/**
* Convert an NMS Enum (usually a BlockStateEnum) to its appropriate Bukkit
@@ -537,9 +537,39 @@ public class CraftBlockData implements BlockData {
@@ -538,9 +538,39 @@ public class CraftBlockData implements BlockData {
Preconditions.checkState(CraftBlockData.MAP.put(nms, bukkit) == null, "Duplicate mapping %s->%s", nms, bukkit);
}

View file

@ -9,10 +9,10 @@ as this is how Vanilla teleports entities.
Cancel any pending motion when teleported.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 36ff9acf571d670fda225bce2f4ed16dc1d20fe3..07c5c01c2f5c18b1d6162275ca091b0ababd72c5 100644
index 51e97ca80f25cd1e49033cfbc41b595f3fa54d66..5175475d75c393bfd5516d7dbede5200b7091b64 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -656,7 +656,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@@ -682,7 +682,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
return;
}
@ -21,20 +21,20 @@ index 36ff9acf571d670fda225bce2f4ed16dc1d20fe3..07c5c01c2f5c18b1d6162275ca091b0a
this.lastGoodX = this.awaitingPositionFromClient.x;
this.lastGoodY = this.awaitingPositionFromClient.y;
this.lastGoodZ = this.awaitingPositionFromClient.z;
@@ -1587,7 +1587,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
// CraftBukkit end
@@ -1589,7 +1589,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.awaitingTeleportTime = this.tickCount;
this.player.resetCurrentImpulseContext();
- this.player.absMoveTo(d0, d1, d2, f, f1);
+ this.player.moveTo(d0, d1, d2, f, f1); // Paper - Fix Entity Teleportation and cancel velocity if teleported
this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport));
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0c6680bf15b57cf314638ab70d849e033719c0e1..f45b148884b305628411d57f7662ea454fde3906 100644
index e6422024dd4aa472156d9751dcdeb55b5e210f53..c8e4e37b706bd8cb9698ac2d13d0d8668e2d1d14 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -162,6 +162,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
@@ -165,6 +165,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
@ -42,7 +42,7 @@ index 0c6680bf15b57cf314638ab70d849e033719c0e1..f45b148884b305628411d57f7662ea45
static boolean isLevelAtLeast(CompoundTag tag, int level) {
return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
}
@@ -1785,6 +1786,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
@@ -1809,6 +1810,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public void moveTo(double x, double y, double z, float yaw, float pitch) {
@ -57,10 +57,10 @@ index 0c6680bf15b57cf314638ab70d849e033719c0e1..f45b148884b305628411d57f7662ea45
this.setYRot(yaw);
this.setXRot(pitch);
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index b771f954f3fccd92e15196bf542e0d3703cfb71a..41d2793e69bd664456b5e3c5891b03bdcb31d103 100644
index b90127f9f805fdb5bb43a4b8ad2b10499b0b6b78..8efc06d29c62fa2be8515ed3359d52a6d4b807d2 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -162,6 +162,7 @@ public abstract class BaseSpawner {
@@ -164,6 +164,7 @@ public abstract class BaseSpawner {
return;
}
@ -69,7 +69,7 @@ index b771f954f3fccd92e15196bf542e0d3703cfb71a..41d2793e69bd664456b5e3c5891b03bd
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 326978aedbd9cc81db2bf1d5398c1cd2ce68a866..f664fd4aa8d79e95787848b5a3e0ed7bc182fa25 100644
index 40e4b8233e27b8ebd94a89bb43b5c14808edaa68..3da47cf8968c1917e2f216a410eece51a693dfb2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -238,7 +238,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {

View file

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

View file

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

View file

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 17 Sep 2020 00:36:05 +0100
Subject: [PATCH] Extend block drop capture to capture all items added to the
world
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index ccc5e57bfaaa51b05c66349475212f2079a4428c..4e1027f00fba2084073aa926805753224aa8b153 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1230,6 +1230,12 @@ public class ServerLevel extends Level implements WorldGenLevel {
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit
return false;
} else {
+ // Paper start - capture all item additions to the world
+ if (captureDrops != null && entity instanceof net.minecraft.world.entity.item.ItemEntity) {
+ captureDrops.add((net.minecraft.world.entity.item.ItemEntity) entity);
+ return true;
+ }
+ // Paper end - capture all item additions to the world
// SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world.
if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) {
return false;
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 2f0d56c78584abe27ef050258827103fb60d5785..486d9c4dbe3ee23198eba7f34ea8b5f4e9048c0b 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -432,10 +432,12 @@ public class ServerPlayerGameMode {
// return true; // CraftBukkit
}
// CraftBukkit start
+ java.util.List<net.minecraft.world.entity.item.ItemEntity> itemsToDrop = this.level.captureDrops; // Paper - capture all item additions to the world
+ this.level.captureDrops = null; // Paper - capture all item additions to the world; Remove this earlier so that we can actually drop stuff
if (event.isDropItems()) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, this.level.captureDrops);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world
}
- this.level.captureDrops = null;
+ //this.level.captureDrops = null; // Paper - capture all item additions to the world; move up
// Drop event experience
if (flag && event != null) {

View file

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

View file

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

View file

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 21:39:16 -0500
Subject: [PATCH] Entity#isTicking
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 909575a02bf5f7040eb9c8edb034e7b6578e92b9..bbce55b02f848be720ad95cb5b896ff9ad1f66d0 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4444,5 +4444,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public static int nextEntityId() {
return ENTITY_COUNTER.incrementAndGet();
}
+
+ public boolean isTicking() {
+ return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this);
+ }
// Paper end - Expose entity id counter
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 3da47cf8968c1917e2f216a410eece51a693dfb2..2080733ebae1af51b7b4d3cd2fbd1a4a2703a920 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1045,4 +1045,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return getHandle().isInLava();
}
// Paper end - entity liquid API
+
+ // Paper start - isTicking API
+ @Override
+ public boolean isTicking() {
+ return getHandle().isTicking();
+ }
+ // Paper end - isTicking API
}

View file

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

View file

@ -0,0 +1,67 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 6 Jul 2020 18:36:41 -0400
Subject: [PATCH] Fix Concurrency issue in ShufflingList
if multiple threads from worldgen sort at same time, it will crash.
So make a copy of the list for sorting purposes.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
index 334962f1bf5988059fec506f0d3aaf4302205220..6a270c9adb044a6e0b1c8e09b9106d51989fd761 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
@@ -18,7 +18,7 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
private final Set<MemoryModuleType<?>> exitErasedMemories;
private final GateBehavior.OrderPolicy orderPolicy;
private final GateBehavior.RunningPolicy runningPolicy;
- private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>();
+ private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>(false); // Paper - Fix Concurrency issue in ShufflingList during worldgen
private Behavior.Status status = Behavior.Status.STOPPED;
public GateBehavior(
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
index 195eea55fabc7a9a665e0a8f04934a3aaf9f8b71..3fac11bf02652b5f51f30f99bdf516504467d0d2 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
@@ -16,12 +16,25 @@ import net.minecraft.util.RandomSource;
public class ShufflingList<U> implements Iterable<U> {
protected final List<ShufflingList.WeightedEntry<U>> entries;
private final RandomSource random = RandomSource.create();
+ private final boolean isUnsafe; // Paper - Fix Concurrency issue in ShufflingList during worldgen
public ShufflingList() {
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen
+ this(true);
+ }
+ public ShufflingList(boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end - Fix Concurrency issue in ShufflingList during worldgen
this.entries = Lists.newArrayList();
}
private ShufflingList(List<ShufflingList.WeightedEntry<U>> list) {
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen
+ this(list, true);
+ }
+ private ShufflingList(List<ShufflingList.WeightedEntry<U>> list, boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end - Fix Concurrency issue in ShufflingList during worldgen
this.entries = Lists.newArrayList(list);
}
@@ -35,9 +48,12 @@ public class ShufflingList<U> implements Iterable<U> {
}
public ShufflingList<U> shuffle() {
- this.entries.forEach(entry -> entry.setRandom(this.random.nextFloat()));
- this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
- return this;
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen
+ List<ShufflingList.WeightedEntry<U>> list = this.isUnsafe ? Lists.newArrayList(this.entries) : this.entries;
+ list.forEach(entry -> entry.setRandom(this.random.nextFloat()));
+ list.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
+ return this.isUnsafe ? new ShufflingList<>(list, this.isUnsafe) : this;
+ // Paper end - Fix Concurrency issue in ShufflingList during worldgen
}
public Stream<U> stream() {

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 1 Jun 2016 23:29:17 -0400
Subject: [PATCH] Reset Ender Crystals on Dragon Spawn
Crystals can end up in a bad state in certain conditions which causes
an exception on the expected number of crystals going negative.
This ensures the crystals/pillars are in expected state when the dragon spawns.
See #3522
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 6f9c78b124a33212125e98905efc8a09a1891500..79b63082e849f29244352b9d0d6ac9b7df7813f6 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -472,6 +472,7 @@ public class EndDragonFight {
entityenderdragon.moveTo((double) this.origin.getX(), (double) (128 + this.origin.getY()), (double) this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F);
this.level.addFreshEntity(entityenderdragon);
this.dragonUUID = entityenderdragon.getUUID();
+ this.resetSpikeCrystals(); // Paper - Reset ender crystals on dragon spawn
}
return entityenderdragon;

View file

@ -0,0 +1,86 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 17 May 2020 23:47:33 -0700
Subject: [PATCH] Fix for large move vectors crashing server
Check movement distance also based on current position.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 5175475d75c393bfd5516d7dbede5200b7091b64..355b1726e90eb796fa2c1e21108bcf793637bf6c 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -498,9 +498,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
float prevYaw = this.player.getYRot();
float prevPitch = this.player.getXRot();
// CraftBukkit end
- double d0 = entity.getX();
- double d1 = entity.getY();
- double d2 = entity.getZ();
+ double d0 = entity.getX();final double fromX = d0; // Paper - OBFHELPER
+ double d1 = entity.getY();final double fromY = d1; // Paper - OBFHELPER
+ double d2 = entity.getZ();final double fromZ = d2; // Paper - OBFHELPER
double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX()); final double toX = d3; // Paper - OBFHELPER
double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY()); final double toY = d4; // Paper - OBFHELPER
double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ()); final double toZ = d5; // Paper - OBFHELPER
@@ -510,7 +510,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
double d7 = d4 - this.vehicleFirstGoodY;
double d8 = d5 - this.vehicleFirstGoodZ;
double d9 = entity.getDeltaMovement().lengthSqr();
- double d10 = d6 * d6 + d7 * d7 + d8 * d8;
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - fromX;
+ double currDeltaY = toY - fromY;
+ double currDeltaZ = toZ - fromZ;
+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ double otherFieldX = d3 - this.vehicleLastGoodX;
+ double otherFieldY = d4 - this.vehicleLastGoodY - 1.0E-6D;
+ double otherFieldZ = d5 - this.vehicleLastGoodZ;
+ d10 = Math.max(d10, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
// CraftBukkit start - handle custom speeds and skipped ticks
this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
@@ -556,9 +565,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
- d6 = d3 - this.vehicleLastGoodX;
- d7 = d4 - this.vehicleLastGoodY - 1.0E-6D;
- d8 = d5 - this.vehicleLastGoodZ;
+ d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
+ d8 = d5 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag1 = entity.verticalCollisionBelow;
if (entity instanceof LivingEntity) {
@@ -1265,7 +1274,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
double d7 = d1 - this.firstGoodY;
double d8 = d2 - this.firstGoodZ;
double d9 = this.player.getDeltaMovement().lengthSqr();
- double d10 = d6 * d6 + d7 * d7 + d8 * d8;
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - prevX;
+ double currDeltaY = toY - prevY;
+ double currDeltaZ = toZ - prevZ;
+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ double otherFieldX = d0 - this.lastGoodX;
+ double otherFieldY = d1 - this.lastGoodY;
+ double otherFieldZ = d2 - this.lastGoodZ;
+ d10 = Math.max(d10, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
if (this.player.isSleeping()) {
if (d10 > 1.0D) {
@@ -1321,9 +1339,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
AABB axisalignedbb = this.player.getBoundingBox();
- d6 = d0 - this.lastGoodX;
- d7 = d1 - this.lastGoodY;
- d8 = d2 - this.lastGoodZ;
+ d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
+ d8 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag1 = d7 > 0.0D;
if (this.player.onGround() && !packet.isOnGround() && flag1) {

View file

@ -0,0 +1,93 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Wed, 3 Jun 2020 11:37:13 -0700
Subject: [PATCH] Optimise getType calls
Remove the map lookup for converting from Block->Bukkit Material
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
index 065d140ca4f987e14138a37f4c7d60879dd7b6e1..601135f3368272bf1ca3a43ec9c199e3ee838462 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
@@ -10,6 +10,16 @@ import net.minecraft.world.level.block.state.properties.Property;
public class BlockState extends BlockBehaviour.BlockStateBase {
public static final Codec<BlockState> CODEC = codec(BuiltInRegistries.BLOCK.byNameCodec(), Block::defaultBlockState).stable();
+ // Paper start - optimise getType calls
+ org.bukkit.Material cachedMaterial;
+
+ public final org.bukkit.Material getBukkitMaterial() {
+ if (this.cachedMaterial == null) {
+ this.cachedMaterial = org.bukkit.craftbukkit.block.CraftBlockType.minecraftToBukkit(this.getBlock());
+ }
+ return this.cachedMaterial;
+ }
+ // Paper end - optimise getType calls
public BlockState(Block block, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
super(block, propertyMap, codec);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
index f2ce97e46cdbda0f8960eed9b601c797d8eaef48..85029f1acfdbb411d9ebdf95838d6db3898f4e58 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
@@ -99,7 +99,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
public Material getBlockType(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
- return CraftBlockType.minecraftToBukkit(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBlock());
+ return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index a586442422a2b2c06b785af0d261d3e19eb1d59b..aa644231425b9622437538b5c092d4064a40cced 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -220,7 +220,7 @@ public class CraftBlock implements Block {
@Override
public Material getType() {
- return CraftBlockType.minecraftToBukkit(this.world.getBlockState(this.position).getBlock());
+ return this.world.getBlockState(this.position).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
index fabdec2d66cc6d676ed58fa570e2c318ab0927e2..1002123cd0c6f57cecc4e80f5f21cc6ff5886d37 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
@@ -175,7 +175,7 @@ public class CraftBlockState implements BlockState {
@Override
public Material getType() {
- return CraftBlockType.minecraftToBukkit(this.data.getBlock());
+ return this.data.getBukkitMaterial(); // Paper - optimise getType calls
}
public void setFlag(int flag) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index b875bebb8b63c6f60301180fc2e3fc9c1bc87193..2303525542daa933a8de5978ac43d16223c6e5fd 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -60,7 +60,7 @@ public class CraftBlockData implements BlockData {
@Override
public Material getMaterial() {
- return CraftBlockType.minecraftToBukkit(this.state.getBlock());
+ return this.state.getBukkitMaterial(); // Paper - optimise getType calls
}
public net.minecraft.world.level.block.state.BlockState getState() {
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
index c96aaa185d9d929cb19f427be82053f0cfa13bad..0fb580530d0b6d4d63ea4b85fec9240eb5c74df4 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
@@ -96,7 +96,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData {
@Override
public Material getType(int x, int y, int z) {
- return CraftBlockType.minecraftToBukkit(this.getTypeId(x, y, z).getBlock());
+ return this.getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,142 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Mon, 9 Nov 2020 20:44:51 +0100
Subject: [PATCH] Add ignore discounts API
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 4d7f95d2bd415bacccee145bfc47f2b480530c11..4d3a04e1d7910c4e71ac9a1cebb58e482958671a 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -491,6 +491,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator.hasNext()) {
MerchantOffer merchantrecipe = (MerchantOffer) iterator.next();
+ if (merchantrecipe.ignoreDiscounts) continue; // Paper - Add ignore discounts API
merchantrecipe.addToSpecialPriceDiff(-Mth.floor((float) i * merchantrecipe.getPriceMultiplier()));
}
@@ -503,6 +504,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator1.hasNext()) {
MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next();
+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper - Add ignore discounts API
double d0 = 0.3D + 0.0625D * (double) j;
int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount());
diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
index 89982d25f60c8b60ba91e559ef88278f338fe215..bffa088b13312d525efaab3d7988a08953c4d9c3 100644
--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
@@ -33,6 +33,10 @@ public class MerchantOffer {
return merchantrecipe.priceMultiplier;
}), Codec.INT.lenientOptionalFieldOf("xp", 1).forGetter((merchantrecipe) -> {
return merchantrecipe.xp;
+ // Paper start
+ }), Codec.BOOL.lenientOptionalFieldOf("Paper.IgnoreDiscounts", false).forGetter((merchantrecipe) -> {
+ return merchantrecipe.ignoreDiscounts;
+ // Paper end
})).apply(instance, MerchantOffer::new);
});
public static final StreamCodec<RegistryFriendlyByteBuf, MerchantOffer> STREAM_CODEC = StreamCodec.of(MerchantOffer::writeToStream, MerchantOffer::createFromStream);
@@ -46,6 +50,7 @@ public class MerchantOffer {
public int demand;
public float priceMultiplier;
public int xp;
+ public boolean ignoreDiscounts; // Paper - Add ignore discounts API
// CraftBukkit start
private CraftMerchantRecipe bukkitHandle;
@@ -59,7 +64,7 @@ public class MerchantOffer {
}
// CraftBukkit end
- private MerchantOffer(ItemCost firstBuyItem, Optional<ItemCost> secondBuyItem, ItemStack sellItem, int uses, int maxUses, boolean rewardingPlayerExperience, int specialPrice, int demandBonus, float priceMultiplier, int merchantExperience) {
+ private MerchantOffer(ItemCost firstBuyItem, Optional<ItemCost> secondBuyItem, ItemStack sellItem, int uses, int maxUses, boolean rewardingPlayerExperience, int specialPrice, int demandBonus, float priceMultiplier, int merchantExperience, boolean ignoreDiscounts) { // Paper
this.baseCostA = firstBuyItem;
this.costB = secondBuyItem;
this.result = sellItem;
@@ -70,6 +75,7 @@ public class MerchantOffer {
this.demand = demandBonus;
this.priceMultiplier = priceMultiplier;
this.xp = merchantExperience;
+ this.ignoreDiscounts = ignoreDiscounts;
}
public MerchantOffer(ItemCost buyItem, ItemStack sellItem, int maxUses, int merchantExperience, float priceMultiplier) {
@@ -85,11 +91,11 @@ public class MerchantOffer {
}
public MerchantOffer(ItemCost firstBuyItem, Optional<ItemCost> secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus) {
- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, true, 0, demandBonus, priceMultiplier, merchantExperience);
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, true, 0, demandBonus, priceMultiplier, merchantExperience, false); // Paper
}
private MerchantOffer(MerchantOffer offer) {
- this(offer.baseCostA, offer.costB, offer.result.copy(), offer.uses, offer.maxUses, offer.rewardExp, offer.specialPriceDiff, offer.demand, offer.priceMultiplier, offer.xp);
+ this(offer.baseCostA, offer.costB, offer.result.copy(), offer.uses, offer.maxUses, offer.rewardExp, offer.specialPriceDiff, offer.demand, offer.priceMultiplier, offer.xp, offer.ignoreDiscounts); // Paper
}
public ItemStack getBaseCostA() {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
index 3bf9b5c016fa638fd0377d2a031a7359430b79ce..a18088125254178d362fdd283bff704a9ccdd0a7 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
@@ -22,11 +22,19 @@ public class CraftMerchantRecipe extends MerchantRecipe {
@Deprecated
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) {
- this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0);
+ // Paper start - add ignoreDiscounts param
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) {
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0, ignoreDiscounts);
}
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice) {
- super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice);
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice, boolean ignoreDiscounts) {
+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice, ignoreDiscounts);
+ // Paper end
this.handle = new net.minecraft.world.item.trading.MerchantOffer(
new ItemCost(Items.AIR),
Optional.empty(),
@@ -36,6 +44,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
experience,
priceMultiplier,
demand,
+ ignoreDiscounts, // Paper - add ignoreDiscounts param
this
);
this.setSpecialPrice(specialPrice);
@@ -112,6 +121,18 @@ public class CraftMerchantRecipe extends MerchantRecipe {
this.handle.priceMultiplier = priceMultiplier;
}
+ // Paper start
+ @Override
+ public boolean shouldIgnoreDiscounts() {
+ return this.handle.ignoreDiscounts;
+ }
+
+ @Override
+ public void setIgnoreDiscounts(boolean ignoreDiscounts) {
+ this.handle.ignoreDiscounts = ignoreDiscounts;
+ }
+ // Paper end
+
public net.minecraft.world.item.trading.MerchantOffer toMinecraft() {
List<ItemStack> ingredients = this.getIngredients();
Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients");
@@ -128,7 +149,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
if (recipe instanceof CraftMerchantRecipe) {
return (CraftMerchantRecipe) recipe;
} else {
- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.getDemand(), recipe.getSpecialPrice());
+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.getDemand(), recipe.getSpecialPrice(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts
craft.setIngredients(recipe.getIngredients());
return craft;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Wed, 30 Sep 2020 22:49:14 +0200
Subject: [PATCH] Toggle for removing existing dragon
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 79b63082e849f29244352b9d0d6ac9b7df7813f6..3ea0ca395e0561d96044f0f84442a08b42b539bd 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -209,7 +209,7 @@ public class EndDragonFight {
this.dragonUUID = entityenderdragon.getUUID();
EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon);
this.dragonKilled = false;
- if (!flag) {
+ if (!flag && this.level.paperConfig().entities.behavior.shouldRemoveDragon) { // Paper - Toggle for removing existing dragon
EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it.");
entityenderdragon.discard(null); // CraftBukkit - add Bukkit remove cause
this.dragonUUID = null;

View file

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

View file

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

View file

@ -0,0 +1,131 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 24 Jun 2020 12:39:08 -0600
Subject: [PATCH] Beacon API - custom effect ranges
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 18450017bc3df2f0b1a5715e6021e8e5defa24a1..32a242d4b67b4edbc1996fa64a151dc60e7e996e 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -86,6 +86,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null;
}
// CraftBukkit end
+ // Paper start - Custom beacon ranges
+ private final String PAPER_RANGE_TAG = "Paper.Range";
+ private double effectRange = -1;
+
+ public double getEffectRange() {
+ if (this.effectRange < 0) {
+ return this.levels * 10 + 10;
+ } else {
+ return effectRange;
+ }
+ }
+
+ public void setEffectRange(double range) {
+ this.effectRange = range;
+ }
+
+ public void resetEffectRange() {
+ this.effectRange = -1;
+ }
+ // Paper end - Custom beacon ranges
@Nullable
static Holder<MobEffect> filterEffect(@Nullable Holder<MobEffect> effect) {
@@ -201,7 +221,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
- BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower);
+ BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper - Custom beacon ranges
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
}
}
@@ -287,8 +307,13 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
public static List getHumansInRange(Level world, BlockPos blockposition, int i) {
+ // Paper start - Custom beacon ranges
+ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null);
+ }
+ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end - Custom beacon ranges
{
- double d0 = (double) (i * 10 + 10);
+ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10); // Paper - Custom beacon ranges
AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
@@ -329,12 +354,17 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect) {
+ // Paper start - Custom beacon ranges
+ BeaconBlockEntity.applyEffects(world, pos, beaconLevel, primaryEffect, secondaryEffect, null);
+ }
+ private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end - Custom beacon ranges
if (!world.isClientSide && primaryEffect != null) {
double d0 = (double) (beaconLevel * 10 + 10);
byte b0 = BeaconBlockEntity.getAmplification(beaconLevel, primaryEffect, secondaryEffect);
int j = BeaconBlockEntity.getLevel(beaconLevel);
- List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel);
+ List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel, blockEntity); // Paper - Custom beacon ranges
BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent
@@ -395,6 +425,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
this.lockKey = LockCode.fromTag(nbt);
+ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper - Custom beacon ranges
}
@Override
@@ -408,6 +439,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
this.lockKey.addToTag(nbt);
+ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper - Custom beacon ranges
}
public void setCustomName(@Nullable Component customName) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
index 2dfbe061a064b0c79b96f644a1c3639bb900eca4..3f1bb225c4e6acdd9104e856d6a11d519119c9f4 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
@@ -33,7 +33,7 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
if (tileEntity instanceof BeaconBlockEntity) {
BeaconBlockEntity beacon = (BeaconBlockEntity) tileEntity;
- Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels);
+ Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels, beacon); // Paper - Custom beacon ranges
Collection<LivingEntity> bukkit = new ArrayList<LivingEntity>(nms.size());
for (Player human : nms) {
@@ -120,4 +120,21 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
public CraftBeacon copy(Location location) {
return new CraftBeacon(this, location);
}
+
+ // Paper start
+ @Override
+ public double getEffectRange() {
+ return this.getSnapshot().getEffectRange();
+ }
+
+ @Override
+ public void setEffectRange(double range) {
+ this.getSnapshot().setEffectRange(range);
+ }
+
+ @Override
+ public void resetEffectRange() {
+ this.getSnapshot().resetEffectRange();
+ }
+ // Paper end
}

View file

@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 14 Nov 2020 16:19:52 +0100
Subject: [PATCH] Add API for quit reason
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 68d5be903a0d13e59c9e4bd6d85baaf0773547a0..fe89e8f509f3972ceb71c9aa6277524baa39985b 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -167,12 +167,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.handlingFault = true;
if (this.channel.isOpen()) {
+ net.minecraft.server.level.ServerPlayer player = this.getPlayer(); // Paper - Add API for quit reason
if (throwable instanceof TimeoutException) {
Connection.LOGGER.debug("Timeout", throwable);
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper - Add API for quit reason
this.disconnect(Component.translatable("disconnect.timeout"));
} else {
MutableComponent ichatmutablecomponent = Component.translatable("disconnect.genericReason", "Internal Exception: " + String.valueOf(throwable));
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - Add API for quit reason
if (flag) {
Connection.LOGGER.debug("Failed to sent packet", throwable);
if (this.getSending() == PacketFlow.CLIENTBOUND) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index a182ab1c06c4644e9c14d7a2eff2620d827dfb2c..edfcfb91d907d6e1837e5a5d0e7abb8c8f6bcb66 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -290,6 +290,7 @@ public class ServerPlayer extends Player {
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
public @Nullable String clientBrandName = null; // Paper - Brand support
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 215da3c52dc7b9e92c23f352fa7cffc2fb3d8a1a..d947eb533ba4dfd3b711e644d2a68238d1ec007a 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -360,6 +360,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
final Component ichatbasecomponent = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.reason()); // Paper - Adventure
// CraftBukkit end
+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper - Add API for quit reason
this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> {
this.connection.disconnect(ichatbasecomponent);
}));
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 7af0239dbcaf46ee9f793072e832978400cdee0c..27069c61441c3abd59d922911f18143045363bdf 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -576,7 +576,7 @@ public abstract class PlayerList {
entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - Inventory close reason
}
- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(entityplayer.getDisplayName()))); // Paper - Adventure
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(entityplayer.getDisplayName())), entityplayer.quitReason); // Paper - Adventure & Add API for quit reason
this.cserver.getPluginManager().callEvent(playerQuitEvent);
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());

View file

@ -0,0 +1,87 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Thu, 20 Aug 2020 11:20:12 -0700
Subject: [PATCH] Add Wandering Trader spawn rate config options
Adds config options for modifying the spawn rates of Wandering Traders.
These values are all easy to understand and configure after a quick read of this
page on the Minecraft wiki: https://minecraft.wiki/wiki/Wandering_Trader#Spawning
Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values
in IWorldServerData are removed as they were only used in certain places, with hardcoded
values used in other places.
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
index 4b7e9bc8aa253d0eb12a2195416c618cccdc8690..d5d27b0d352ca3fd57a26605cb35c499e88b57fc 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
@@ -40,43 +40,53 @@ public class WanderingTraderSpawner implements CustomSpawner {
public WanderingTraderSpawner(ServerLevelData properties) {
this.serverLevelData = properties;
- this.tickDelay = 1200;
- this.spawnDelay = properties.getWanderingTraderSpawnDelay();
- this.spawnChance = properties.getWanderingTraderSpawnChance();
- if (this.spawnDelay == 0 && this.spawnChance == 0) {
- this.spawnDelay = 24000;
- properties.setWanderingTraderSpawnDelay(this.spawnDelay);
- this.spawnChance = 25;
- properties.setWanderingTraderSpawnChance(this.spawnChance);
- }
+ // Paper start - Add Wandering Trader spawn rate config options
+ this.tickDelay = Integer.MIN_VALUE;
+ //this.spawnDelay = properties.getWanderingTraderSpawnDelay(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value
+ //this.spawnChance = properties.getWanderingTraderSpawnChance(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value
+ //if (this.spawnDelay == 0 && this.spawnChance == 0) {
+ // this.spawnDelay = 24000;
+ // properties.setWanderingTraderSpawnDelay(this.spawnDelay);
+ // this.spawnChance = 25;
+ // properties.setWanderingTraderSpawnChance(this.spawnChance);
+ //}
+ // Paper end - Add Wandering Trader spawn rate config options
}
@Override
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
+ // Paper start - Add Wandering Trader spawn rate config options
+ if (this.tickDelay == Integer.MIN_VALUE) {
+ this.tickDelay = world.paperConfig().entities.spawning.wanderingTrader.spawnMinuteLength;
+ this.spawnDelay = world.paperConfig().entities.spawning.wanderingTrader.spawnDayLength;
+ this.spawnChance = world.paperConfig().entities.spawning.wanderingTrader.spawnChanceMin;
+ }
if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) {
return 0;
- } else if (--this.tickDelay > 0) {
+ } else if (this.tickDelay - 1 > 0) {
+ this.tickDelay = this.tickDelay - 1;
return 0;
} else {
- this.tickDelay = 1200;
- this.spawnDelay -= 1200;
- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay);
+ this.tickDelay = world.paperConfig().entities.spawning.wanderingTrader.spawnMinuteLength;
+ this.spawnDelay = this.spawnDelay - world.paperConfig().entities.spawning.wanderingTrader.spawnMinuteLength;
+ //this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways
if (this.spawnDelay > 0) {
return 0;
} else {
- this.spawnDelay = 24000;
+ this.spawnDelay = world.paperConfig().entities.spawning.wanderingTrader.spawnDayLength;
if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
return 0;
} else {
int i = this.spawnChance;
- this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75);
- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance);
+ // this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways
+ this.spawnChance = Mth.clamp(i + world.paperConfig().entities.spawning.wanderingTrader.spawnChanceFailureIncrement, world.paperConfig().entities.spawning.wanderingTrader.spawnChanceMin, world.paperConfig().entities.spawning.wanderingTrader.spawnChanceMax);
if (this.random.nextInt(100) > i) {
return 0;
} else if (this.spawn(world)) {
- this.spawnChance = 25;
+ this.spawnChance = world.paperConfig().entities.spawning.wanderingTrader.spawnChanceMin;
+ // Paper end - Add Wandering Trader spawn rate config options
return 1;
} else {
return 0;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
Date: Tue, 17 Nov 2020 19:13:09 +0200
Subject: [PATCH] Expose world spawn angle
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 27069c61441c3abd59d922911f18143045363bdf..b665cad02cf3ec79270a99d6733cb075c7e1940c 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -847,7 +847,7 @@ public abstract class PlayerList {
if (location == null) {
worldserver1 = this.server.getLevel(Level.OVERWORLD);
blockposition = entityplayer1.getSpawnPoint(worldserver1);
- location = CraftLocation.toBukkit(blockposition, worldserver1.getWorld()).add(0.5F, 0.1F, 0.5F);
+ location = CraftLocation.toBukkit(blockposition, worldserver1.getWorld(), worldserver1.levelData.getSpawnAngle(), 0.0F).add(0.5F, 0.1F, 0.5F); // Paper - Expose world spawn angle
}
Player respawnPlayer = entityplayer1.getBukkitEntity();

View file

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ineusia <ineusia@yahoo.com>
Date: Mon, 26 Oct 2020 11:48:06 -0500
Subject: [PATCH] Add Destroy Speed API
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index 2303525542daa933a8de5978ac43d16223c6e5fd..48e8d0cc267706d3d8e29333d7fd6b89fdd88553 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -721,4 +721,19 @@ public class CraftBlockData implements BlockData {
public BlockState createBlockState() {
return CraftBlockStates.getBlockState(this.state, null);
}
+
+ // Paper start - destroy speed API
+ @Override
+ public float getDestroySpeed(final ItemStack itemStack, final boolean considerEnchants) {
+ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.unwrap(itemStack);
+ float speed = nmsItemStack.getDestroySpeed(this.state);
+ if (speed > 1.0F && considerEnchants) {
+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack);
+ if (enchantLevel > 0) {
+ speed += enchantLevel * enchantLevel + 1;
+ }
+ }
+ return speed;
+ }
+ // Paper end - destroy speed API
}

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Esophose <esophose@gmail.com>
Date: Sat, 3 Oct 2020 18:57:47 -0600
Subject: [PATCH] Fix Player spawnParticle x/y/z precision loss
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 777f48d31b8b1d3a47471caba00ffb77a335c03b..8f437587d8989f3aa709ce36d1a10f237d28f0fa 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2686,7 +2686,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
if (data != null) {
Preconditions.checkArgument(particle.getDataType().isInstance(data), "data (%s) should be %s", data.getClass(), particle.getDataType());
}
- ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.createParticleParam(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count);
+ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.createParticleParam(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss
this.getHandle().connection.send(packetplayoutworldparticles);
}

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anrza <andrzejrzeczycki314@gmail.com>
Date: Wed, 15 Jul 2020 12:08:49 +0200
Subject: [PATCH] Add LivingEntity#clearActiveItem
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index aff940a7bacf53571f8e7bcd520419994596ebb3..7158f88e90c624b7ed3345ad7fb47745d4491d88 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -934,6 +934,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return this.getHandle().getUseItem().asBukkitMirror();
}
+ // Paper start
+ @Override
+ public void clearActiveItem() {
+ getHandle().stopUsingItem();
+ }
+ // Paper end
+
@Override
public int getActiveItemRemainingTime() {
return this.getHandle().getUseItemRemainingTicks();

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Tue, 25 Aug 2020 13:48:33 +0200
Subject: [PATCH] Add PlayerItemCooldownEvent
diff --git a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java
index 47283d2a49209839002212e663a503a82ea86587..e0c4c0a9bab0bbc32358030a482aa04c2e1d3894 100644
--- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java
+++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java
@@ -10,6 +10,16 @@ public class ServerItemCooldowns extends ItemCooldowns {
this.player = player;
}
+ // Paper start - Add PlayerItemCooldownEvent
+ @Override
+ public void addCooldown(Item item, int duration) {
+ io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent(this.player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemType.minecraftToBukkit(item), duration);
+ if (event.callEvent()) {
+ super.addCooldown(item, event.getCooldown());
+ }
+ }
+ // Paper end - Add PlayerItemCooldownEvent
+
@Override
protected void onCooldownStarted(Item item, int duration) {
super.onCooldownStarted(item, duration);

View file

@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com>
Date: Tue, 3 Nov 2020 23:48:05 -0600
Subject: [PATCH] Significantly improve performance of the end generation
This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement.
Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric)
Co-authored-by: Gegy <gegy1000@gmail.com>
Co-authored-by: Dylan Xaldin <Puremin0rez515@gmail.com>
Co-authored-by: pop4959 <pop4959@gmail.com>
diff --git a/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java b/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java
index b09bc1dac649ce9f4826edc1923c843804226993..ac8447e20531ad59d5e26c6db541d6e844d56c0f 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java
@@ -509,6 +509,16 @@ public final class DensityFunctions {
);
private static final float ISLAND_THRESHOLD = -0.9F;
private final SimplexNoise islandNoise;
+ // Paper start - Perf: Optimize end generation
+ private static final class NoiseCache {
+ public long[] keys = new long[8192];
+ public float[] values = new float[8192];
+ public NoiseCache() {
+ java.util.Arrays.fill(keys, Long.MIN_VALUE);
+ }
+ }
+ private static final ThreadLocal<java.util.Map<SimplexNoise, NoiseCache>> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new);
+ // Paper end - Perf: Optimize end generation
public EndIslandDensityFunction(long seed) {
RandomSource randomSource = new LegacyRandomSource(seed);
@@ -524,12 +534,26 @@ public final class DensityFunctions {
float f = 100.0F - Mth.sqrt((long) x * (long) x + (long) z * (long) z) * 8.0F; // Paper - cast ints to long to avoid integer overflow
f = Mth.clamp(f, -100.0F, 80.0F);
+ NoiseCache cache = noiseCache.get().computeIfAbsent(sampler, noiseKey -> new NoiseCache()); // Paper - Perf: Optimize end generation
for (int m = -12; m <= 12; m++) {
for (int n = -12; n <= 12; n++) {
long o = (long)(i + m);
long p = (long)(j + n);
- if (o * o + p * p > 4096L && sampler.getValue((double)o, (double)p) < -0.9F) {
- float g = (Mth.abs((float)o) * 3439.0F + Mth.abs((float)p) * 147.0F) % 13.0F + 9.0F;
+ // Paper start - Perf: Optimize end generation by using a noise cache
+ long key = net.minecraft.world.level.ChunkPos.asLong((int) o, (int) p);
+ int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191;
+ float g = Float.MIN_VALUE;
+ if (cache.keys[index] == key) {
+ g = cache.values[index];
+ } else {
+ if (o * o + p * p > 4096L && sampler.getValue((double)o, (double)p) < -0.9F) {
+ g = (Mth.abs((float)o) * 3439.0F + Mth.abs((float)p) * 147.0F) % 13.0F + 9.0F;
+ }
+ cache.keys[index] = key;
+ cache.values[index] = g;
+ }
+ if (g != Float.MIN_VALUE) {
+ // Paper end - Perf: Optimize end generation
float h = (float)(k - m * 2);
float q = (float)(l - n * 2);
float r = 100.0F - Mth.sqrt(h * h + q * q) * g;

View file

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Sun, 26 Jul 2020 14:44:09 +0200
Subject: [PATCH] More lightning API
== AT ==
public net.minecraft.world.entity.LightningBolt life
public net.minecraft.world.entity.LightningBolt flashes
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
index 0b2ba5c93355a5b7548d4634d964732e45477a34..6fed8075aa75e3852dc826a45ca44603c0446a56 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
@@ -66,4 +66,23 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike
return this.spigot;
}
// Spigot end
+
+ // Paper start
+ @Override
+ public int getFlashCount() {
+ return getHandle().flashes;
+ }
+
+ @Override
+ public void setFlashCount(int flashes) {
+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!");
+ getHandle().flashes = flashes;
+ }
+
+ @Override
+ public @org.jetbrains.annotations.Nullable org.bukkit.entity.Entity getCausingEntity() {
+ final var cause = this.getHandle().getCause();
+ return cause == null ? null : cause.getBukkitEntity();
+ }
+ // Paper end
}

View file

@ -0,0 +1,156 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 23 Aug 2020 20:59:00 +0200
Subject: [PATCH] Climbing should not bypass cramming gamerule
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index bbce55b02f848be720ad95cb5b896ff9ad1f66d0..717d596b2479a66861a83445ed87f40c7c0f69d8 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2011,6 +2011,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean isPushable() {
+ // Paper start - Climbing should not bypass cramming gamerule
+ return isCollidable(false);
+ }
+
+ public boolean isCollidable(boolean ignoreClimbing) {
+ // Paper end - Climbing should not bypass cramming gamerule
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index ee4495b67c46cf1282cdd6ad15b224b0b7b10bfb..e382a29b441b656f35bc24cb90f95cb4def433d2 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -46,11 +46,16 @@ public final class EntitySelector {
}
public static Predicate<Entity> pushableBy(Entity entity) {
+ // Paper start - Climbing should not bypass cramming gamerule
+ return pushable(entity, false);
+ }
+ public static Predicate<Entity> pushable(Entity entity, boolean ignoreClimbing) {
+ // Paper end - Climbing should not bypass cramming gamerule
PlayerTeam scoreboardteam = entity.getTeam();
Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteam == null ? Team.CollisionRule.ALWAYS : scoreboardteam.getCollisionRule();
return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> {
- if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API
+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
return false;
} else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) {
return false;
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 914c6499eb94665f0e3c4654dd05fc10d93f87d4..e38f0659836be4bebff06e8d8e7848abdcbda455 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3534,7 +3534,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
return;
}
// Paper end - don't run getEntities if we're not going to use its result
- List<Entity> list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this));
+ 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()) {
// Paper - don't run getEntities if we're not going to use its result; moved up
@@ -3724,9 +3724,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
return !this.isRemoved() && this.collides; // CraftBukkit
}
+ // Paper start - Climbing should not bypass cramming gamerule
@Override
public boolean isPushable() {
- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit
+ return this.isCollidable(this.level().paperConfig().collisions.fixClimbingBypassingCrammingRule);
+ }
+
+ @Override
+ public boolean isCollidable(boolean ignoreClimbing) {
+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit
+ // Paper end - Climbing should not bypass cramming gamerule
}
// CraftBukkit start - collidable API
diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
index 934fa26b8f347b8b2d90f79370b62165c0cdc312..dc27ddf5131e7398a5390a5187261d4c7fb6ccaa 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
@@ -88,7 +88,7 @@ public class Bat extends AmbientCreature {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
index 1a129f43dc737218746b21ae5d03e3749bfee092..5ca96541abbb754f4d9fbe01f37ebaf19c532bbb 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
@@ -367,8 +367,8 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder<Parrot
}
@Override
- public boolean isPushable() {
- return super.isPushable(); // CraftBukkit - collidable API
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
index bff2627aa0c2cc48020e65c71a5862ab6e995f99..d53ef42e64d87790ea86d806153f047005accb9f 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -353,7 +353,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
return !this.isVehicle();
}
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
index bf717b5bcd14291a99414eae5366c0b91ce68a68..b1b0b0554e0ad035463fd53aa440d9c079b7cfb4 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -350,7 +350,7 @@ public class ArmorStand extends LivingEntity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
index 2c97c8ee6dccb7f517e5edcd0c5d9620a3433f1e..1aecb6cc62b4b411ab0ff3b7fb11a5d9d050b959 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
@@ -169,7 +169,7 @@ public abstract class AbstractMinecart extends VehicleEntity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
return true;
}
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
index 164468371e9a52ef96a183fdbcfe097d2fc24b56..d1eaadba8ce1f472a174afcfe8e0d059a121612c 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
@@ -150,7 +150,7 @@ public class Boat extends VehicleEntity implements VariantHolder<Boat.Type> {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - Climbing should not bypass cramming gamerule
return true;
}

View file

@ -0,0 +1,175 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 16 Nov 2020 12:01:52 -0800
Subject: [PATCH] Add missing default perms for commands
diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
index a9ea2e38e4673686c9994a58c94ad19e59fd423c..dd95b3bfe59f2bb635afe92317288efcd2986326 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
@@ -24,13 +24,74 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stop", "Allows the user to stop the server", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands);
- DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "xp", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands);
- DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "toggledownfall", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "experience", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands); // Paper - wrong permission; redirects are de-redirected and the root literal name is used, so xp -> experience
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "defaultgamemode", "Allows the user to change the default gamemode of the server", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "seed", "Allows the user to view the seed of the world", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands);
+ // Paper start
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to the ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to the ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display the ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "damage", "Allows the user to use the damage command to damage entities", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "fillbiome", "Allows the user to fill a region with a specific biome", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "jfr", "Allows a user to use the vanilla Java FlightRecorder profiling system", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the player ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon-ip", "Allows the user to remove entries from the ip address ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "perf", "Allows the user to start/stop the vanilla performance metrics capture", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ride", "Allows the user to use the /ride command to control passengers", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); // defaults to all players
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tick", "Allows the user to control the tick rate of the server", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "place", "Allows the user to place features and structures", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "return", "Allows the user to use the /return command", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "random", "Allows the user to generate a random number", PermissionDefault.OP, commands);
+ // Paper end
DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands);
diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..afeb4271fffb7546209f1e651214065187c88302
--- /dev/null
+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
@@ -0,0 +1,82 @@
+package io.papermc.paper.permissions;
+
+import com.mojang.brigadier.tree.CommandNode;
+import com.mojang.brigadier.tree.RootCommandNode;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.server.Bootstrap;
+import net.minecraft.world.flag.FeatureFlags;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
+import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions;
+import org.bukkit.permissions.Permission;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class MinecraftCommandPermissionsTest extends AbstractTestingBase {
+
+ private static PrintStream old;
+ @BeforeAll
+ public static void before() {
+ old = System.out;
+ System.setOut(Bootstrap.STDOUT);
+ }
+
+ @Test
+ public void test() {
+ CraftDefaultPermissions.registerCorePermissions();
+ Set<String> perms = collectMinecraftCommandPerms();
+
+ Commands commands = new Commands(Commands.CommandSelection.DEDICATED, CommandBuildContext.configurable(AbstractTestingBase.REGISTRY_CUSTOM, FeatureFlags.VANILLA_SET));
+ RootCommandNode<CommandSourceStack> root = commands.getDispatcher().getRoot();
+ Set<String> missing = new LinkedHashSet<>();
+ Set<String> foundPerms = new HashSet<>();
+ for (CommandNode<CommandSourceStack> child : root.getChildren()) {
+ final String vanillaPerm = VanillaCommandWrapper.getPermission(child);
+ if (!perms.contains(vanillaPerm)) {
+ missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command");
+ } else {
+ foundPerms.add(vanillaPerm);
+ }
+ }
+ assertTrue(missing.isEmpty(), "Commands missing permissions: \n" + String.join("\n", missing));
+ perms.removeAll(foundPerms);
+ assertTrue(perms.isEmpty(), "Extra permissions not associated with a command: \n" + String.join("\n", perms));
+ }
+
+ private static final List<String> TO_SKIP = List.of(
+ "minecraft.command.selector"
+ );
+
+ private static Set<String> collectMinecraftCommandPerms() {
+ Set<String> perms = new TreeSet<>();
+ for (Permission perm : Bukkit.getPluginManager().getPermissions()) {
+ if (perm.getName().startsWith("minecraft.command.")) {
+ if (TO_SKIP.contains(perm.getName())) {
+ continue;
+ }
+ perms.add(perm.getName());
+ }
+ }
+ return perms;
+ }
+
+ @AfterAll
+ public static void after() {
+ if (old != null) {
+ System.setOut(old);
+ }
+ }
+}

View file

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Thu, 27 Aug 2020 15:02:48 -0400
Subject: [PATCH] Add PlayerShearBlockEvent
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
index ce108f1cea8027aa7aab444689f7a29f2e54cc20..7b311f60ceae9942eeee0d2c7a170278e5983f2d 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -127,7 +127,7 @@ public class BeehiveBlock extends BaseEntityBlock {
}
public static void dropHoneycomb(Level world, BlockPos pos) {
- popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3));
+ popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); // Paper - Add PlayerShearBlockEvent; conflict on change, item needs to be set below
}
@Override
@@ -139,8 +139,19 @@ public class BeehiveBlock extends BaseEntityBlock {
Item item = stack.getItem();
if (stack.is(Items.SHEARS)) {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
- BeehiveBlock.dropHoneycomb(world, pos);
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack itemDrop : event.getDrops()) {
+ popResource(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemDrop));
+ }
+ // Paper end - Add PlayerShearBlockEvent
stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
flag = true;
world.gameEvent((Entity) player, (Holder) GameEvent.SHEAR, pos);
diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
index aa8667f0b14dc8944dd3457b431162e59bf54ada..4f4667cb036e8f5700ce175da5bf94725c64c9a7 100644
--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
@@ -40,10 +40,18 @@ public class PumpkinBlock extends Block {
} else if (world.isClientSide) {
return ItemInteractionResult.sidedSuccess(world.isClientSide);
} else {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end - Add PlayerShearBlockEvent
Direction direction = hit.getDirection();
Direction direction2 = direction.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : direction;
world.playSound(null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F);
world.setBlock(pos, Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, direction2), 11);
+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { // Paper - Add PlayerShearBlockEvent
ItemEntity itemEntity = new ItemEntity(
world,
(double)pos.getX() + 0.5 + (double)direction2.getStepX() * 0.65,
@@ -57,6 +65,7 @@ public class PumpkinBlock extends Block {
0.05 * (double)direction2.getStepZ() + world.random.nextDouble() * 0.02
);
world.addFreshEntity(itemEntity);
+ } // Paper - Add PlayerShearBlockEvent
stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
world.gameEvent(player, GameEvent.SHEAR, pos);
player.awardStat(Stats.ITEM_USED.get(Items.SHEARS));

View file

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sat, 12 Dec 2020 23:45:28 +0000
Subject: [PATCH] Limit recipe packets
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 355b1726e90eb796fa2c1e21108bcf793637bf6c..10f0a84c119826e52fac6ca8e1d3e6276cc72392 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -267,6 +267,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
// CraftBukkit start - multithreaded fields
private final AtomicInteger chatSpamTickCount = new AtomicInteger();
private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits
+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit
// CraftBukkit end
private int dropSpamTickCount;
private double firstGoodX;
@@ -390,6 +391,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
// CraftBukkit start
for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ;
if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - configurable tab spam limits
+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper - auto recipe limit
/* Use thread-safe field access instead
if (this.chatSpamTickCount > 0) {
--this.chatSpamTickCount;
@@ -3063,6 +3065,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@Override
public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {
+ // Paper start - auto recipe limit
+ if (!org.bukkit.Bukkit.isPrimaryThread()) {
+ if (this.recipeSpamPackets.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamLimit) {
+ this.server.scheduleOnMain(() -> this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam")));
+ return;
+ }
+ }
+ // Paper end - auto recipe limit
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
this.player.resetLastActionTime();
if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) {

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 17 Dec 2020 15:25:49 -0600
Subject: [PATCH] Fix CraftSound backwards compatibility
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
index 260a738d5d61cf931b939502ea9c66451855b91e..dce716b6ac407d1e1ae07272ee5c8b14f891f5fa 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
@@ -40,4 +40,10 @@ public class CraftSound {
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own sound effect with out properly registering it.");
}
+
+ // Paper start
+ public static String getSound(Sound sound) {
+ return sound.getKey().getKey();
+ }
+ // Paper end
}

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ysl3000 <yannicklamprecht@live.de>
Date: Mon, 5 Oct 2020 21:25:16 +0200
Subject: [PATCH] Player Chunk Load/Unload Events
diff --git a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
index 3548be0bfacc7ff2cf0ed5fac4d8de09bd2a415f..c502d9b85eb68b277ae17dfea34e0475f0156647 100644
--- a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
+++ b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
@@ -44,6 +44,11 @@ public class PlayerChunkSender {
public void dropChunk(ServerPlayer player, ChunkPos pos) {
if (!this.pendingChunks.remove(pos.toLong()) && player.isAlive()) {
player.connection.send(new ClientboundForgetLevelChunkPacket(pos));
+ // Paper start - PlayerChunkUnloadEvent
+ if (io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(pos.longKey), player.getBukkitEntity()).callEvent();
+ }
+ // Paper end - PlayerChunkUnloadEvent
}
}
@@ -75,6 +80,11 @@ public class PlayerChunkSender {
private static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) {
handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), null, null));
+ // Paper start - PlayerChunkLoadEvent
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), handler.getPlayer().getBukkitEntity()).callEvent();
+ }
+ // Paper end - PlayerChunkLoadEvent
ChunkPos chunkPos = chunk.getPos();
DebugPackets.sendPoiPacketsForChunk(world, chunkPos);
}

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 21 Dec 2020 11:01:42 -0500
Subject: [PATCH] Optimize Dynamic#get Missing Keys
get was calling toString() on every NBT object that was ever asked for an optional
key from the object to build a string for the error text.
When done on large NBT objects, this was using a ton of computation time building the
JSON representation of the NBT object.
Now we will just skip the value when 99.9999% of the time the text is never even printed.
diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java
index d73bb05272d69471644b28f8c704a3bfceca72c2..8b4ea53b891bb7a5ceb791c4afaaf33814d9b6f6 100644
--- a/src/main/java/com/mojang/serialization/Dynamic.java
+++ b/src/main/java/com/mojang/serialization/Dynamic.java
@@ -19,6 +19,7 @@ import java.util.stream.Stream;
@SuppressWarnings("unused")
public class Dynamic<T> extends DynamicLike<T> {
+ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper - Perf: Skip toString on values like NBT
private final T value;
public Dynamic(final DynamicOps<T> ops) {
@@ -120,7 +121,7 @@ public class Dynamic<T> extends DynamicLike<T> {
return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> {
final T value = m.get(key);
if (value == null) {
- return DataResult.error(() -> "key missing: " + key + " in " + this.value);
+ return DataResult.error(() -> DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper - Perf: Skip toString on values like NBT
}
return DataResult.success(new Dynamic<>(ops, value));
}));

View file

@ -0,0 +1,58 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
Date: Sun, 13 Dec 2020 05:32:05 +0200
Subject: [PATCH] Expose LivingEntity hurt direction
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 8fe41d4291736fd8c45d73429062a597d54ac30b..ecae1708feee507df1440ad2822e7af8c3c278de 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -187,7 +187,7 @@ public abstract class Player extends LivingEntity {
private Optional<GlobalPos> lastDeathLocation;
@Nullable
public FishingHook fishing;
- protected float hurtDir;
+ public float hurtDir; // Paper - protected -> public
@Nullable
public Vec3 currentImpulseImpactPos;
@Nullable
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 9393e9d21fcc41cb0f20b98d9f28c95b0e523f62..796945fb1a8b43987ed9f01375113b2c13ff67c0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -125,6 +125,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
}
}
+ // Paper start
+ @Override
+ public void setHurtDirection(float hurtDirection) {
+ this.getHandle().hurtDir = hurtDirection;
+ }
+ // Paper end
+
@Override
public int getSleepTicks() {
return this.getHandle().sleepCounter;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 7158f88e90c624b7ed3345ad7fb47745d4491d88..b88077ac1ed99057b8a9361ea550cd2b00040f88 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -991,4 +991,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
this.getHandle().take(((CraftItem) item).getHandle(), quantity);
}
// Paper end - pickup animation API
+
+ // Paper start - hurt direction API
+ @Override
+ public float getHurtDirection() {
+ return this.getHandle().getHurtDir();
+ }
+
+ @Override
+ public void setHurtDirection(final float hurtDirection) {
+ throw new UnsupportedOperationException("Cannot set the hurt direction on a non player");
+ }
+ // Paper end - hurt direction API
}

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 24 Dec 2020 12:43:39 -0800
Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index f0e1bb3d9e4254d2c32f28fb715ea429c7646cec..253563371aa05954c19607b98675e37450e772ef 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -302,6 +302,10 @@ public class CraftEventFactory {
return BedEnterResult.TOO_FAR_AWAY;
case NOT_SAFE:
return BedEnterResult.NOT_SAFE;
+ // Paper start
+ case OBSTRUCTED:
+ return BedEnterResult.OBSTRUCTED;
+ // Paper end
default:
return BedEnterResult.OTHER_PROBLEM;
}

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 27 Dec 2020 11:31:06 +0000
Subject: [PATCH] Fix crash from invalid ingredient lists in
VillagerAcquireTradeEvent
diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
index 79e81fd5490a493b595dc1034641e13451e5a61a..6e29b5729b8184d13065c9c4e18f6e450c9d88a6 100644
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
@@ -269,7 +269,11 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa
Bukkit.getPluginManager().callEvent(event);
}
if (!event.isCancelled()) {
- recipeList.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft());
+ // Paper start - Fix crash from invalid ingredient list
+ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe());
+ if (craftMerchantRecipe.getIngredients().isEmpty()) return;
+ recipeList.add(craftMerchantRecipe.toMinecraft());
+ // Paper end - Fix crash from invalid ingredient list
}
// CraftBukkit end
++j;

View file

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 25 Nov 2020 23:20:44 -0800
Subject: [PATCH] Add TargetHitEvent
diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java
index 549ca8e9b265635bd3d5863682fe240f3f9f3f58..ee4eb863b6c02f2bcbb03ca413fc98811d409ac5 100644
--- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java
@@ -42,6 +42,10 @@ public class TargetBlock extends Block {
@Override
protected void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) {
int i = updateRedstoneOutput(world, state, hit, projectile);
+ // Paper start - Add TargetHitEvent
+ }
+ private static void awardTargetHitCriteria(Projectile projectile, BlockHitResult hit, int i) {
+ // Paper end - Add TargetHitEvent
if (projectile.getOwner() instanceof ServerPlayer serverPlayer) {
serverPlayer.awardStat(Stats.TARGET_HIT);
CriteriaTriggers.TARGET_BLOCK_HIT.trigger(serverPlayer, projectile, hit.getLocation(), i);
@@ -51,10 +55,31 @@ public class TargetBlock extends Block {
private static int updateRedstoneOutput(LevelAccessor world, BlockState state, BlockHitResult hitResult, Entity entity) {
int i = getRedstoneStrength(hitResult, hitResult.getLocation());
int j = entity instanceof AbstractArrow ? 20 : 8;
+ // Paper start - Add TargetHitEvent
+ boolean shouldAward = false;
+ if (entity instanceof Projectile) {
+ final Projectile projectile = (Projectile) entity;
+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, hitResult.getBlockPos());
+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(hitResult.getDirection());
+ final io.papermc.paper.event.block.TargetHitEvent targetHitEvent = new io.papermc.paper.event.block.TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i);
+ if (targetHitEvent.callEvent()) {
+ i = targetHitEvent.getSignalStrength();
+ shouldAward = true;
+ } else {
+ return i;
+ }
+ }
+ // Paper end - Add TargetHitEvent
if (!world.getBlockTicks().hasScheduledTick(hitResult.getBlockPos(), state.getBlock())) {
setOutputPower(world, state, i, hitResult.getBlockPos(), j);
}
+ // Paper start - Award Hit Criteria after Block Update
+ if (shouldAward) {
+ awardTargetHitCriteria((Projectile) entity, hitResult, i);
+ }
+ // Paper end - Award Hit Criteria after Block Update
+
return i;
}

View file

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Tue, 8 Dec 2020 20:24:52 -0600
Subject: [PATCH] MC-4: Fix item position desync
This fixes item position desync (MC-4) by running the item coordinates
through the encode/decode methods of the packet that causes the precision
loss, which forces the server to lose the same precision as the client
keeping them in sync.
diff --git a/src/main/java/net/minecraft/network/protocol/game/VecDeltaCodec.java b/src/main/java/net/minecraft/network/protocol/game/VecDeltaCodec.java
index ffec3deb9bcd31d51974c1deda2e76bc8374e5c5..a3d247c93ac1a2d872ff0e3841efc3d7b84fcbc1 100644
--- a/src/main/java/net/minecraft/network/protocol/game/VecDeltaCodec.java
+++ b/src/main/java/net/minecraft/network/protocol/game/VecDeltaCodec.java
@@ -9,12 +9,12 @@ public class VecDeltaCodec {
@VisibleForTesting
static long encode(double value) {
- return Math.round(value * 4096.0);
+ return Math.round(value * 4096.0); // Paper - Fix MC-4; diff on change
}
@VisibleForTesting
static double decode(long value) {
- return (double)value / 4096.0;
+ return value / 4096.0; // Paper - Fix MC-4; diff on change
}
public Vec3 decode(long x, long y, long z) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 717d596b2479a66861a83445ed87f40c7c0f69d8..31911870e5056391d67c49fa68d59010534bf35f 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4212,6 +4212,16 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return;
}
// Paper end - Block invalid positions and bounding box
+ // Paper start - Fix MC-4
+ if (this instanceof ItemEntity) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.fixEntityPositionDesync) {
+ // encode/decode from ClientboundMoveEntityPacket
+ x = Mth.lfloor(x * 4096.0) * (1 / 4096.0);
+ y = Mth.lfloor(y * 4096.0) * (1 / 4096.0);
+ z = Mth.lfloor(z * 4096.0) * (1 / 4096.0);
+ }
+ }
+ // Paper end - Fix MC-4
if (this.position.x != x || this.position.y != y || this.position.z != z) {
this.position = new Vec3(x, y, z);
int i = Mth.floor(x);

View file

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 30 Dec 2020 19:43:01 -0500
Subject: [PATCH] Additional Block Material API
Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower
process to do this in the Bukkit API
Adds API for buildable, replaceable, burnable too.
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index aa644231425b9622437538b5c092d4064a40cced..98e87dc15e2ed23f6897ba6359846ff5bc32b655 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -440,6 +440,25 @@ public class CraftBlock implements Block {
return this.getNMS().liquid();
}
+ // Paper start
+ @Override
+ public boolean isBuildable() {
+ return this.getNMS().isSolid(); // This is in fact isSolid, despite the fact that isSolid below returns blocksMotion
+ }
+ @Override
+ public boolean isBurnable() {
+ return this.getNMS().ignitedByLava();
+ }
+ @Override
+ public boolean isReplaceable() {
+ return this.getNMS().canBeReplaced();
+ }
+ @Override
+ public boolean isSolid() {
+ return this.getNMS().blocksMotion();
+ }
+ // Paper end
+
@Override
public PistonMoveReaction getPistonMoveReaction() {
return PistonMoveReaction.getById(this.getNMS().getPistonPushReaction().ordinal());

View file

@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com>
Date: Thu, 23 Jul 2020 14:25:07 -0700
Subject: [PATCH] Fix harming potion dupe
EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory.
Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory.
This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground.
diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java
index de0b68b128e6ffbd31aebb4361e4859d495f89b5..042a9cf9c15fd30bc30e03d0e0311c70e40e6950 100644
--- a/src/main/java/net/minecraft/world/item/PotionItem.java
+++ b/src/main/java/net/minecraft/world/item/PotionItem.java
@@ -55,12 +55,13 @@ public class PotionItem extends Item {
CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack);
}
+ List<net.minecraft.world.effect.MobEffectInstance> instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe
if (!world.isClientSide) {
PotionContents potioncontents = (PotionContents) stack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
potioncontents.forEachEffect((mobeffect) -> {
if (((MobEffect) mobeffect.getEffect().value()).isInstantenous()) {
- ((MobEffect) mobeffect.getEffect().value()).applyInstantenousEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D);
+ instantLater.add(mobeffect); // Paper
} else {
user.addEffect(mobeffect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit
}
@@ -73,7 +74,18 @@ public class PotionItem extends Item {
stack.consume(1, entityhuman);
}
+ // Paper start - Fix harming potion dupe
+ for (net.minecraft.world.effect.MobEffectInstance mobeffect : instantLater) {
+ mobeffect.getEffect().value().applyInstantenousEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D);
+ }
+ // Paper end - Fix harming potion dupe
if (entityhuman == null || !entityhuman.hasInfiniteMaterials()) {
+ // Paper start - Fix harming potion dupe
+ if (user.getHealth() <= 0 && !user.level().getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_KEEPINVENTORY)) {
+ user.spawnAtLocation(new ItemStack(Items.GLASS_BOTTLE), 0);
+ return ItemStack.EMPTY;
+ }
+ // Paper end - Fix harming potion dupe
if (stack.isEmpty()) {
return new ItemStack(Items.GLASS_BOTTLE);
}

View file

@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Madeline Miller <mnmiller1@me.com>
Date: Thu, 31 Dec 2020 12:48:19 +1000
Subject: [PATCH] API to get Material from Boats and Minecarts
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
index f332bd4e6f663147c9ef6ce03d926feb74b55e93..d161cbf9c83cd78593864850b98f688da2c85aa5 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
@@ -79,6 +79,13 @@ public class CraftBoat extends CraftVehicle implements Boat {
this.getHandle().landBoats = workOnLand;
}
+ // Paper start
+ @Override
+ public org.bukkit.Material getBoatMaterial() {
+ return org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getHandle().getDropItem());
+ }
+ // Paper end
+
@Override
public Status getStatus() {
return CraftBoat.boatStatusFromNms(this.getHandle().status);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java
index ee010d53f8c671d17d68f3f43dca9978e23ac8ab..8920af5a0dfe737c1f38d906b53e6a278456d2aa 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java
@@ -1,8 +1,10 @@
package org.bukkit.craftbukkit.entity;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
+import net.minecraft.world.item.Items; // Paper
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
+import org.bukkit.Material; // Paper
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
@@ -68,6 +70,22 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart {
this.getHandle().setDerailedVelocityMod(derailed);
}
+ // Paper start
+ @Override
+ public Material getMinecartMaterial() {
+ net.minecraft.world.item.Item minecartItem = switch (getHandle().getMinecartType()) {
+ case CHEST -> Items.CHEST_MINECART;
+ case FURNACE -> Items.FURNACE_MINECART;
+ case TNT -> Items.TNT_MINECART;
+ case HOPPER -> Items.HOPPER_MINECART;
+ case COMMAND_BLOCK -> Items.COMMAND_BLOCK_MINECART;
+ case RIDEABLE, SPAWNER -> Items.MINECART;
+ };
+
+ return CraftMagicNumbers.getMaterial(minecartItem);
+ }
+ // Paper end
+
@Override
public AbstractMinecart getHandle() {
return (AbstractMinecart) this.entity;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BrodyBeckwith <brody@beckwith.dev>
Date: Fri, 9 Oct 2020 20:30:12 -0400
Subject: [PATCH] Allow disabling mob spawner spawn egg transformation
diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
index 6e91fec416493b2fabe1e8a6214ab7673212e451..9cea8da84f39bb3f687139ef213ccea358724dee 100644
--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java
+++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
@@ -69,6 +69,8 @@ public class SpawnEggItem extends Item {
EntityType entitytypes;
if (tileentity instanceof Spawner) {
+ if (world.paperConfig().entities.spawning.disableMobSpawnerSpawnEggTransformation) return InteractionResult.FAIL; // Paper - Allow disabling mob spawner spawn egg transformation
+
Spawner spawner = (Spawner) tileentity;
entitytypes = this.getType(itemstack);

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 8 Oct 2020 00:00:25 -0400
Subject: [PATCH] Fix "Not a string" Map Conversion spam
The maps did convert successfully, but had noisy logs due to Spigot
implementing this logic incorrectly.
This stops the spam by converting the old format to new before
requesting the world.
Track spigot issue to see when fixed: https://hub.spigotmc.org/jira/browse/SPIGOT-6181
diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index d42d39dff5aeb91c5b1e6a7fb967ce70f1a88b7e..38c0855a6f9398f8d075f304288cf9e9f695770a 100644
--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -21,6 +21,8 @@ import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
+import net.minecraft.nbt.NumericTag;
+import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
@@ -120,7 +122,26 @@ public class MapItemSavedData extends SavedData {
}
public static MapItemSavedData load(CompoundTag nbt, HolderLookup.Provider registryLookup) {
- DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbt.get("dimension"))); // CraftBukkit - decompile error
+ // Paper start - fix "Not a string" spam
+ Tag dimension = nbt.get("dimension");
+ if (dimension instanceof NumericTag && ((NumericTag) dimension).getAsInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) {
+ long least = nbt.getLong("UUIDLeast");
+ long most = nbt.getLong("UUIDMost");
+
+ if (least != 0L && most != 0L) {
+ UUID uuid = new UUID(most, least);
+ CraftWorld world = (CraftWorld) Bukkit.getWorld(uuid);
+ if (world != null) {
+ dimension = StringTag.valueOf("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH));
+ } else {
+ dimension = StringTag.valueOf("bukkit:_invalidworld_");
+ }
+ } else {
+ dimension = StringTag.valueOf("bukkit:_invalidworld_");
+ }
+ }
+ DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, dimension)); // CraftBukkit - decompile error
+ // Paper end - fix "Not a string" spam
Logger logger = MapItemSavedData.LOGGER;
Objects.requireNonNull(logger);

View file

@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MisterVector <whizkid3000@hotmail.com>
Date: Tue, 13 Aug 2019 19:45:06 -0700
Subject: [PATCH] Add PlayerFlowerPotManipulateEvent
diff --git a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java
index b0c950fa7426dc762b99080d98831b961fc19da2..7194565ad1a910fe300d8664a30b35c4eff18cb7 100644
--- a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java
@@ -63,6 +63,18 @@ public class FlowerPotBlock extends Block {
} else if (!this.isEmpty()) {
return ItemInteractionResult.CONSUME;
} else {
+ // Paper start - Add PlayerFlowerPotManipulateEvent
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ org.bukkit.inventory.ItemStack placedStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack);
+
+ io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent event = new io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent((org.bukkit.entity.Player) player.getBukkitEntity(), block, placedStack, true);
+ if (!event.callEvent()) {
+ // Update client
+ player.containerMenu.sendAllDataToRemote();
+
+ return ItemInteractionResult.CONSUME;
+ }
+ // Paper end - Add PlayerFlowerPotManipulateEvent
world.setBlock(pos, blockState, 3);
world.gameEvent(player, GameEvent.BLOCK_CHANGE, pos);
player.awardStat(Stats.POT_FLOWER);
@@ -77,6 +89,18 @@ public class FlowerPotBlock extends Block {
return InteractionResult.CONSUME;
} else {
ItemStack itemStack = new ItemStack(this.potted);
+ // Paper start - Add PlayerFlowerPotManipulateEvent
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ org.bukkit.inventory.ItemStack pottedStack = new org.bukkit.inventory.ItemStack(org.bukkit.craftbukkit.block.CraftBlockType.minecraftToBukkit(this.potted));
+
+ io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent event = new io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent((org.bukkit.entity.Player) player.getBukkitEntity(), block, pottedStack, false);
+ if (!event.callEvent()) {
+ // Update client
+ player.containerMenu.sendAllDataToRemote();
+
+ return InteractionResult.PASS;
+ }
+ // Paper end - Add PlayerFlowerPotManipulateEvent
if (!player.addItem(itemStack)) {
player.drop(itemStack, false);
}

View file

@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TheMolkaPL <themolkapl@gmail.com>
Date: Sun, 21 Jun 2020 17:21:46 +0200
Subject: [PATCH] Fix interact event not being called sometimes
* Call PlayerInteractEvent when left-clicking on a block in adventure
mode.
* Call PlayerInteractEvent when left-clicking an Entity that is out of
range in adventure/survival (entity reach is 3.0).
Co-authored-by: Moulberry <james.jenour@protonmail.com>
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 10f0a84c119826e52fac6ca8e1d3e6276cc72392..e0c11559295d00445d5ba0543a81f49dc2314266 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1765,7 +1765,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
MutableComponent ichatmutablecomponent = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED);
this.player.sendSystemMessage(ichatmutablecomponent, true);
- } else if (enuminteractionresult.shouldSwing()) {
+ } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) { // Paper - Call interact event
this.player.swing(enumhand, true);
}
}
@@ -2381,13 +2381,20 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
double d3 = this.player.gameMode.getGameModeForPlayer() == GameType.CREATIVE ? 5.0D : 4.5D;
// SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time
// SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities
- org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> {
+ org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.0, entity -> { // Paper - Call interact event; change raySize from 0.1 to 0.0
Entity handle = ((CraftEntity) entity).getHandle();
return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(this.player);
});
if (result == null) {
CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
- }
+ } else { // Paper start - Call interact event
+ GameType gameType = this.player.gameMode.getGameModeForPlayer();
+ if (gameType == GameType.ADVENTURE && result.getHitBlock() != null) {
+ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, ((org.bukkit.craftbukkit.block.CraftBlock) result.getHitBlock()).getPosition(), org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(result.getHitBlockFace()), this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
+ } else if (gameType != GameType.CREATIVE && result.getHitEntity() != null && origin.toVector().distanceSquared(result.getHitPosition()) > 3.0D * 3.0D) {
+ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
+ }
+ } // Paper end - Call interact event
// Arm swing animation
PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), (packet.getHand() == InteractionHand.MAIN_HAND) ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING);

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 18 Nov 2020 11:32:46 -0800
Subject: [PATCH] Zombie API - breaking doors
== AT ==
public net.minecraft.world.entity.monster.Zombie supportsBreakDoorGoal()Z
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
index 4412c913123f7521f449c98b60378e8d3b1671ce..46336111dcf62a29390e724b1879c84c697076e9 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
@@ -122,6 +122,11 @@ public class CraftZombie extends CraftMonster implements Zombie {
public void setShouldBurnInDay(boolean shouldBurnInDay) {
getHandle().setShouldBurnInDay(shouldBurnInDay);
}
+
+ @Override
+ public boolean supportsBreakingDoors() {
+ return getHandle().supportsBreakDoorGoal();
+ }
// Paper end
@Override

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 24 Aug 2020 08:39:06 -0700
Subject: [PATCH] Fix nerfed slime when splitting
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
index 7062ef1cfd7d6279a4c6693cbdb80da49f23c542..b32213c5a3a1ecaf602cf34bed44c537521c2846 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
@@ -252,6 +252,7 @@ public class Slime extends Mob implements Enemy {
entityslime.setPersistenceRequired();
}
+ entityslime.aware = this.aware; // Paper - Fix nerfed slime when splitting
entityslime.setCustomName(ichatbasecomponent);
entityslime.setNoAi(flag);
entityslime.setInvulnerable(this.isInvulnerable());

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Wed, 7 Oct 2020 12:04:01 -0400
Subject: [PATCH] Add EntityLoadCrossbowEvent
diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java
index 65f23bfb2de91be7560800ff87eab7ad88cb1849..0f6504a7160bc304b3af554f8740c65e2987cd37 100644
--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java
+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java
@@ -80,7 +80,14 @@ public class CrossbowItem extends ProjectileWeaponItem {
public void releaseUsing(ItemStack stack, Level world, LivingEntity user, int remainingUseTicks) {
int i = this.getUseDuration(stack) - remainingUseTicks;
float f = getPowerForTime(i, stack);
- if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(user, stack)) {
+ // Paper start
+ if (f >= 1.0F && !isCharged(stack)) {
+ final io.papermc.paper.event.entity.EntityLoadCrossbowEvent event = new io.papermc.paper.event.entity.EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(user.getUsedItemHand()));
+ if (!event.callEvent() || !tryLoadProjectiles(user, stack, event.shouldConsumeItem())) {
+ if (user instanceof ServerPlayer player) player.containerMenu.sendAllDataToRemote();
+ return;
+ }
+ // Paper end - Add EntityLoadCrossbowEvent
world.playSound(
null,
user.getX(),
@@ -94,8 +101,14 @@ public class CrossbowItem extends ProjectileWeaponItem {
}
}
- private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow) {
- List<ItemStack> list = draw(crossbow, shooter.getProjectile(crossbow), shooter);
+ @io.papermc.paper.annotation.DoNotUse // Paper - Add EntityLoadCrossbowEvent
+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow) {
+ // Paper start - Add EntityLoadCrossbowEvent
+ return CrossbowItem.tryLoadProjectiles(shooter, crossbow, true);
+ }
+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow, boolean consume) {
+ List<ItemStack> list = draw(crossbow, shooter.getProjectile(crossbow), shooter, consume);
+ // Paper end - Add EntityLoadCrossbowEvent
if (!list.isEmpty()) {
crossbow.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(list));
return true;
diff --git a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java
index 416bdff5cda842143038180592ad231a1d19d926..f91ce87491b18f4f4ae6458192d1f320b308102a 100644
--- a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java
+++ b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java
@@ -139,6 +139,11 @@ public abstract class ProjectileWeaponItem extends Item {
}
protected static List<ItemStack> draw(ItemStack weaponStack, ItemStack projectileStack, LivingEntity shooter) {
+ // Paper start
+ return draw(weaponStack, projectileStack, shooter, false);
+ }
+ protected static List<ItemStack> draw(ItemStack weaponStack, ItemStack projectileStack, LivingEntity shooter, boolean consume) {
+ // Paper end
if (projectileStack.isEmpty()) {
return List.of();
} else {
@@ -148,7 +153,7 @@ public abstract class ProjectileWeaponItem extends Item {
ItemStack itemstack2 = projectileStack.copy();
for (int k = 0; k < j; ++k) {
- list.add(ProjectileWeaponItem.useAmmo(weaponStack, k == 0 ? projectileStack : itemstack2, shooter, k > 0));
+ list.add(ProjectileWeaponItem.useAmmo(weaponStack, k == 0 ? projectileStack : itemstack2, shooter, k > 0 || consume)); // Paper
}
return list;

View file

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 20 Dec 2020 16:41:44 -0800
Subject: [PATCH] Add WorldGameRuleChangeEvent
diff --git a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java
index c8c358531dbc167e249bac2af246c5e34fbdd4df..10c1790226e25da3b9b599c9a40de57d5727ddc4 100644
--- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java
+++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java
@@ -33,7 +33,7 @@ public class GameRuleCommand {
CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource();
T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit
- t0.setFromArgument(context, "value");
+ t0.setFromArgument(context, "value", key); // Paper - Add WorldGameRuleChangeEvent
commandlistenerwrapper.sendSuccess(() -> {
return Component.translatable("commands.gamerule.set", key.getId(), t0.toString());
}, true);
diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java
index 0b46ad360be919e4aeb0ffc0eebae9fe712fb861..51e560d7856f230c5aa2dc32706c3a4996720aa5 100644
--- a/src/main/java/net/minecraft/world/level/GameRules.java
+++ b/src/main/java/net/minecraft/world/level/GameRules.java
@@ -293,10 +293,10 @@ public class GameRules {
this.type = type;
}
- protected abstract void updateFromArgument(CommandContext<CommandSourceStack> context, String name);
+ protected abstract void updateFromArgument(CommandContext<CommandSourceStack> context, String name, GameRules.Key<T> gameRuleKey); // Paper - Add WorldGameRuleChangeEvent
- public void setFromArgument(CommandContext<CommandSourceStack> context, String name) {
- this.updateFromArgument(context, name);
+ public void setFromArgument(CommandContext<CommandSourceStack> context, String name, GameRules.Key<T> gameRuleKey) { // Paper - Add WorldGameRuleChangeEvent
+ this.updateFromArgument(context, name, gameRuleKey); // Paper - Add WorldGameRuleChangeEvent
this.onChanged(((CommandSourceStack) context.getSource()).getLevel()); // CraftBukkit - per-world
}
@@ -354,8 +354,11 @@ public class GameRules {
}
@Override
- protected void updateFromArgument(CommandContext<CommandSourceStack> context, String name) {
- this.value = BoolArgumentType.getBool(context, name);
+ protected void updateFromArgument(CommandContext<CommandSourceStack> context, String name, GameRules.Key<BooleanValue> gameRuleKey) { // Paper start - Add WorldGameRuleChangeEvent
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule<Boolean>) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(context, name)));
+ if (!event.callEvent()) return;
+ this.value = Boolean.parseBoolean(event.getValue());
+ // Paper end - Add WorldGameRuleChangeEvent
}
public boolean get() {
@@ -427,8 +430,11 @@ public class GameRules {
}
@Override
- protected void updateFromArgument(CommandContext<CommandSourceStack> context, String name) {
- this.value = IntegerArgumentType.getInteger(context, name);
+ protected void updateFromArgument(CommandContext<CommandSourceStack> context, String name, GameRules.Key<IntegerValue> gameRuleKey) { // Paper start - Add WorldGameRuleChangeEvent
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule<Integer>) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(context, name)));
+ if (!event.callEvent()) return;
+ this.value = Integer.parseInt(event.getValue());
+ // Paper end - Add WorldGameRuleChangeEvent
}
public int get() {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 4d75cf0ec9e835b4274297275d52f08a6a65aeca..4a51d0125d59b1edd2da7aac1db1ca49374c008c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1883,8 +1883,13 @@ public class CraftWorld extends CraftRegionAccessor implements World {
if (!this.isGameRule(rule)) return false;
+ // Paper start - Add WorldGameRuleChangeEvent
+ GameRule<?> gameRule = GameRule.getByName(rule);
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value);
+ if (!event.callEvent()) return false;
+ // Paper end - Add WorldGameRuleChangeEvent
GameRules.Value<?> handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule));
- handle.deserialize(value);
+ handle.deserialize(event.getValue()); // Paper - Add WorldGameRuleChangeEvent
handle.onChanged(this.getHandle());
return true;
}
@@ -1920,8 +1925,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
if (!this.isGameRule(rule.getName())) return false;
+ // Paper start - Add WorldGameRuleChangeEvent
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue));
+ if (!event.callEvent()) return false;
+ // Paper end - Add WorldGameRuleChangeEvent
GameRules.Value<?> handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule.getName()));
- handle.deserialize(newValue.toString());
+ handle.deserialize(event.getValue()); // Paper - Add WorldGameRuleChangeEvent
handle.onChanged(this.getHandle());
return true;
}

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 2 Dec 2020 20:04:01 -0800
Subject: [PATCH] Add ServerResourcesReloadedEvent
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 18efcf55bf13fa17ac532cca4c213e5b6e14979f..b083298d2bcf0d4c6213d6ac8645b8c084cfc6de 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2097,7 +2097,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.functionManager;
}
+ // Paper start - Add ServerResourcesReloadedEvent
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
public CompletableFuture<Void> reloadResources(Collection<String> dataPacks) {
+ return this.reloadResources(dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
+ }
+ public CompletableFuture<Void> reloadResources(Collection<String> dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
+ // Paper end - Add ServerResourcesReloadedEvent
CompletableFuture<Void> completablefuture = CompletableFuture.supplyAsync(() -> {
Stream<String> stream = dataPacks.stream(); // CraftBukkit - decompile error
PackRepository resourcepackrepository = this.packRepository;
@@ -2129,6 +2135,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary());
this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager);
org.bukkit.craftbukkit.block.data.CraftBlockData.reloadCache(); // Paper - cache block data strings; they can be defined by datapacks so refresh it here
+ new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper - Add ServerResourcesReloadedEvent; fire after everything has been reloaded
}, this);
if (this.isSameThread()) {
diff --git a/src/main/java/net/minecraft/server/commands/ReloadCommand.java b/src/main/java/net/minecraft/server/commands/ReloadCommand.java
index fa18d018a8458b30c0048f7e59aea39f928d974a..c020c86194723a5c89816f91e0b7c5eeaf132b7e 100644
--- a/src/main/java/net/minecraft/server/commands/ReloadCommand.java
+++ b/src/main/java/net/minecraft/server/commands/ReloadCommand.java
@@ -20,7 +20,7 @@ public class ReloadCommand {
public ReloadCommand() {}
public static void reloadPacks(Collection<String> dataPacks, CommandSourceStack source) {
- source.getServer().reloadResources(dataPacks).exceptionally((throwable) -> {
+ source.getServer().reloadResources(dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper - Add ServerResourcesReloadedEvent
ReloadCommand.LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure"));
return null;
@@ -50,7 +50,7 @@ public class ReloadCommand {
WorldData savedata = minecraftserver.getWorldData();
Collection<String> collection = resourcepackrepository.getSelectedIds();
Collection<String> collection1 = ReloadCommand.discoverNewPacks(resourcepackrepository, savedata, collection);
- minecraftserver.reloadResources(collection1);
+ minecraftserver.reloadResources(collection1, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - Add ServerResourcesReloadedEvent
}
// CraftBukkit end

View file

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 28 Nov 2020 18:43:52 -0800
Subject: [PATCH] Add world settings for mobs picking up loot
diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
index a19a51a40d69ad71b85b2e7e8b4cfab6d8343196..7013f1b76311a11fb7e2543ab1e792479ecad610 100644
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -145,7 +145,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
this.populateDefaultEquipmentSlots(randomsource, difficulty);
this.populateDefaultEquipmentEnchantments(randomsource, difficulty);
this.reassessWeaponGoal();
- this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier());
+ this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
LocalDate localdate = LocalDate.now();
int i = localdate.get(ChronoField.DAY_OF_MONTH);
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index eacfdfb47299af6900bd39595da8daedb640b959..c8ce36d67901e2897f521d5b4f5041348f235ae7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -498,7 +498,7 @@ public class Zombie extends Monster {
Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData);
float f = difficulty.getSpecialMultiplier();
- this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * f);
+ this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.zombies || randomsource.nextFloat() < 0.55F * f); // Paper - Add world settings for mobs picking up loot
if (object == null) {
object = new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(randomsource), true);
}

View file

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TheViperShow <29604693+TheViperShow@users.noreply.github.com>
Date: Wed, 22 Apr 2020 09:40:38 +0200
Subject: [PATCH] Add BlockFailedDispenseEvent
diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
index c7256ffbe57c594556ee85134c9ab166f8c0e0c7..94bcbaf7daf7dfe566f508d1170a433930d9d49a 100644
--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
@@ -101,8 +101,10 @@ public class DispenserBlock extends BaseEntityBlock {
int i = tileentitydispenser.getRandomSlot(world.random);
if (i < 0) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) { // Paper - Add BlockFailedDispenseEvent
world.levelEvent(1001, pos, 0);
world.gameEvent((Holder) GameEvent.BLOCK_ACTIVATE, pos, GameEvent.Context.of(tileentitydispenser.getBlockState()));
+ } // Paper - Add BlockFailedDispenseEvent
} else {
ItemStack itemstack = tileentitydispenser.getItem(i);
DispenseItemBehavior idispensebehavior = this.getDispenseMethod(world, itemstack);
diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java
index e772b6f8f78ad1292b8fa268e8bb4001a38706c6..efa7cf50b5577f87a2dfa61b59bf81052794fbf1 100644
--- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java
@@ -60,6 +60,7 @@ public class DropperBlock extends DispenserBlock {
int i = tileentitydispenser.getRandomSlot(world.random);
if (i < 0) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) // Paper - Add BlockFailedDispenseEvent
world.levelEvent(1001, pos, 0);
} else {
ItemStack itemstack = tileentitydispenser.getItem(i);
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 253563371aa05954c19607b98675e37450e772ef..13e4cb7af50b3a03523d84dd72ca6a122ca041ad 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -2034,4 +2034,12 @@ public class CraftEventFactory {
return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion());
}
// Paper end - WitchReadyPotionEvent
+
+ // Paper start
+ public static boolean handleBlockFailedDispenseEvent(ServerLevel serverLevel, BlockPos pos) {
+ org.bukkit.block.Block block = CraftBlock.at(serverLevel, pos);
+ io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block);
+ return event.callEvent();
+ }
+ // Paper end
}

View file

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 23 Nov 2020 12:58:51 -0800
Subject: [PATCH] Add PlayerLecternPageChangeEvent
diff --git a/src/main/java/net/minecraft/world/inventory/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java
index 19858ecd7cfaaf0fb09552292bf573bb02b3a6ec..ccba06c419732c63f6b255f5f8c1f7a95f3ecbee 100644
--- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java
@@ -64,6 +64,7 @@ public class LecternMenu extends AbstractContainerMenu {
@Override
public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) {
int j;
+ io.papermc.paper.event.player.PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - Add PlayerLecternPageChangeEvent
if (id >= 100) {
j = id - 100;
@@ -73,11 +74,25 @@ public class LecternMenu extends AbstractContainerMenu {
switch (id) {
case 1:
j = this.lecternData.get(0);
- this.setData(0, j - 1);
+ // Paper start - Add PlayerLecternPageChangeEvent
+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory();
+ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1);
+ if (!playerLecternPageChangeEvent.callEvent()) {
+ return false;
+ }
+ this.setData(0, playerLecternPageChangeEvent.getNewPage());
+ // Paper end - Add PlayerLecternPageChangeEvent
return true;
case 2:
j = this.lecternData.get(0);
- this.setData(0, j + 1);
+ // Paper start - Add PlayerLecternPageChangeEvent
+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory();
+ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1);
+ if (!playerLecternPageChangeEvent.callEvent()) {
+ return false;
+ }
+ this.setData(0, playerLecternPageChangeEvent.getNewPage());
+ // Paper end - Add PlayerLecternPageChangeEvent
return true;
case 3:
if (!player.mayBuild()) {

View file

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 25 Nov 2020 16:33:27 -0800
Subject: [PATCH] Add PlayerLoomPatternSelectEvent
diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
index 4bd720a97da27c4fd97788d4c504c0174f0f6c25..03b6622ec13338005005c9a11e0e6395da1b15a7 100644
--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
@@ -174,8 +174,36 @@ public class LoomMenu extends AbstractContainerMenu {
@Override
public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) {
if (id >= 0 && id < this.selectablePatterns.size()) {
- this.selectedBannerPatternIndex.set(id);
- this.setupResultSlot((Holder) this.selectablePatterns.get(id));
+ // Paper start - Add PlayerLoomPatternSelectEvent
+ int selectablePatternIndex = id;
+ io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(this.selectablePatterns.get(selectablePatternIndex).value().getHashname()));
+ if (!event.callEvent()) {
+ player.containerMenu.sendAllDataToRemote();
+ return false;
+ }
+ Holder<BannerPattern> selectedPattern = null;
+ for (int i = 0; i < this.selectablePatterns.size(); i++) {
+ final Holder<BannerPattern> holder = this.selectablePatterns.get(i);
+ if (event.getPatternType().getIdentifier().equals(holder.value().getHashname())) {
+ selectablePatternIndex = i;
+ selectedPattern = holder;
+ break;
+ }
+ }
+ if (selectedPattern == null) {
+ for (BannerPattern pattern : BuiltInRegistries.BANNER_PATTERN) {
+ if (event.getPatternType().getIdentifier().equals(pattern.getHashname())) {
+ selectedPattern = BuiltInRegistries.BANNER_PATTERN.wrapAsHolder(pattern);
+ break;
+ }
+ }
+ selectablePatternIndex = -1;
+ }
+
+ player.containerMenu.sendAllDataToRemote();
+ this.selectedBannerPatternIndex.set(selectablePatternIndex);
+ this.setupResultSlot(java.util.Objects.requireNonNull(selectedPattern, "selectedPattern was null, this is unexpected"));
+ // Paper end - Add PlayerLoomPatternSelectEvent
return true;
} else {
return false;

View file

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 3 Jan 2021 22:27:43 -0800
Subject: [PATCH] Configurable door breaking difficulty
== AT ==
public net.minecraft.world.entity.monster.Vindicator DOOR_BREAKING_PREDICATE
public net.minecraft.world.entity.monster.Zombie DOOR_BREAKING_PREDICATE
Co-authored-by: Doc <nachito94@msn.com>
diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
index d4ed75afc61620cbc79da07b6511c247b829e41f..b3da310d6fd1d533da805c38c2f449cf06d01492 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
@@ -176,7 +176,7 @@ public class Vindicator extends AbstractIllager {
static class VindicatorBreakDoorGoal extends BreakDoorGoal {
public VindicatorBreakDoorGoal(Mob mob) {
- super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE);
+ super(mob, 6, com.google.common.base.Predicates.in(mob.level().paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(mob.getType(), mob.level().paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityType.VINDICATOR)))); // Paper - Configurable door breaking difficulty
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index c8ce36d67901e2897f521d5b4f5041348f235ae7..e4fc7f96aac9cc2ed5b4158b6663de397ee1162f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -97,7 +97,7 @@ public class Zombie extends Monster {
public Zombie(EntityType<? extends Zombie> type, Level world) {
super(type, world);
- this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE);
+ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(world.paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(type, world.paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityType.ZOMBIE)))); // Paper - Configurable door breaking difficulty
}
public Zombie(Level world) {

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Wed, 6 Jan 2021 23:38:43 +0100
Subject: [PATCH] Empty commands shall not be dispatched
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 2fb4660147294de9e9dec70bc3527327f2d859ee..83091987b320171ef9071cbef6b10a1bd72d38e2 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -290,6 +290,7 @@ public class Commands {
command = event.getCommand();
String[] args = command.split(" ");
+ if (args.length == 0) return; // Paper - empty commands shall not be dispatched
String cmd = args[0];
if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length());

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sat, 9 Jan 2021 14:17:07 +0100
Subject: [PATCH] Remove stale POIs
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 4e1027f00fba2084073aa926805753224aa8b153..2c1ca55e1919c29956b3d95f65f8f08eb7529d1e 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1743,6 +1743,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
});
optional1.ifPresent((holder) -> {
this.getServer().execute(() -> {
+ // Paper start - Remove stale POIs
+ if (optional.isEmpty() && this.getPoiManager().exists(blockposition1, poiType -> true)) {
+ this.getPoiManager().remove(blockposition1);
+ }
+ // Paper end - Remove stale POIs
this.getPoiManager().add(blockposition1, holder);
DebugPackets.sendPoiAddedPacket(this, blockposition1);
});

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Mon, 11 Jan 2021 12:43:51 -0800
Subject: [PATCH] Fix villager boat exploit
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index b665cad02cf3ec79270a99d6733cb075c7e1940c..c9f4d50834d8544bafe973258b59105b2b83bf1d 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -601,6 +601,14 @@ public abstract class PlayerList {
PlayerList.LOGGER.debug("Removing player mount");
entityplayer.stopRiding();
entity.getPassengersAndSelf().forEach((entity1) -> {
+ // Paper start - Fix villager boat exploit
+ if (entity1 instanceof net.minecraft.world.entity.npc.AbstractVillager villager) {
+ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer();
+ if (human != null) {
+ villager.setTradingPlayer(null);
+ }
+ }
+ // Paper end - Fix villager boat exploit
entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER, EntityRemoveEvent.Cause.PLAYER_QUIT); // CraftBukkit - add Bukkit remove cause
});
}

View file

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Tue, 29 Dec 2020 15:03:03 +0100
Subject: [PATCH] Add sendOpLevel API
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index c9f4d50834d8544bafe973258b59105b2b83bf1d..dd360250ca784421e0f8fffe786bec88a8f38b3d 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1100,6 +1100,11 @@ public abstract class PlayerList {
}
private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) {
+ // Paper start - Add sendOpLevel API
+ this.sendPlayerPermissionLevel(player, permissionLevel, true);
+ }
+ public void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel, boolean recalculatePermissions) {
+ // Paper end - Add sendOpLevel API
if (player.connection != null) {
byte b0;
@@ -1114,8 +1119,10 @@ public abstract class PlayerList {
player.connection.send(new ClientboundEntityEventPacket(player, b0));
}
+ if (recalculatePermissions) { // Paper - Add sendOpLevel API
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
this.server.getCommands().sendCommands(player);
+ } // Paper - Add sendOpLevel API
}
public boolean isWhiteListed(GameProfile profile) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 8f437587d8989f3aa709ce36d1a10f237d28f0fa..0cfc8b5faa56ae2a3dd94c5dbcb22a7e208b38bd 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -674,6 +674,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// Paper end
+ // Paper start - Add sendOpLevel API
+ @Override
+ public void sendOpLevel(byte level) {
+ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]");
+
+ this.getHandle().getServer().getPlayerList().sendPlayerPermissionLevel(this.getHandle(), level, false);
+ }
+ // Paper end - Add sendOpLevel API
+
@Override
public void setCompassTarget(Location loc) {
Preconditions.checkArgument(loc != null, "Location cannot be null");

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 27 Feb 2023 18:28:39 -0800
Subject: [PATCH] TODO Registry Modification API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 4209a45af2bfe772f678b07b49070522de4195a8..480313506bf41410de090c59e047323345ea78da 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -138,6 +138,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
if (bukkitClass == Wolf.Variant.class) {
return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new);
}
+ // TODO registry modification API
return null;
}

View file

@ -0,0 +1,219 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dfsek <dfsek@protonmail.com>
Date: Wed, 16 Sep 2020 01:12:29 -0700
Subject: [PATCH] Add StructuresLocateEvent
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
new file mode 100644
index 0000000000000000000000000000000000000000..2667067fd13f61e0464ba88ae4e4a7078351d1a8
--- /dev/null
+++ b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
@@ -0,0 +1,35 @@
+package io.papermc.paper.world.structure;
+
+import java.util.Objects;
+import net.minecraft.core.Registry;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.level.levelgen.structure.Structure;
+import org.bukkit.NamespacedKey;
+import org.bukkit.StructureType;
+import org.bukkit.craftbukkit.CraftRegistry;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+@Deprecated(forRemoval = true)
+public final class PaperConfiguredStructure {
+
+ private PaperConfiguredStructure() {
+ }
+
+ @Deprecated(forRemoval = true)
+ public static final class LegacyRegistry extends CraftRegistry<ConfiguredStructure, Structure> {
+
+ public LegacyRegistry(final Registry<Structure> minecraftRegistry) {
+ super(ConfiguredStructure.class, minecraftRegistry, LegacyRegistry::minecraftToBukkit);
+ }
+
+ private static @Nullable ConfiguredStructure minecraftToBukkit(NamespacedKey key, Structure nms) {
+ final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type());
+ final @Nullable StructureType structureType = StructureType.getStructureTypes().get(structureTypeLoc.getPath());
+ return structureType == null ? null : new ConfiguredStructure(key, structureType);
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
index 7cdb59cd2f2ffe1195d21519ef97dae0e430285b..a8768f1925d5824ca985be1b53694ee233273758 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -127,6 +127,24 @@ public abstract class ChunkGenerator {
@Nullable
public Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel world, HolderSet<Structure> structures, BlockPos center, int radius, boolean skipReferencedStructures) {
+ // Paper start - StructuresLocateEvent
+ final org.bukkit.World bukkitWorld = world.getWorld();
+ final org.bukkit.Location origin = io.papermc.paper.util.MCUtil.toLocation(world, center);
+ final List<org.bukkit.generator.structure.Structure> apiStructures = structures.stream().map(Holder::value).map(nms -> org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(nms)).toList();
+ if (!apiStructures.isEmpty()) {
+ final io.papermc.paper.event.world.StructuresLocateEvent event = new io.papermc.paper.event.world.StructuresLocateEvent(bukkitWorld, origin, apiStructures, radius, skipReferencedStructures);
+ if (!event.callEvent()) {
+ return null;
+ }
+ if (event.getResult() != null) {
+ return Pair.of(io.papermc.paper.util.MCUtil.toBlockPos(event.getResult().pos()), world.registryAccess().registryOrThrow(Registries.STRUCTURE).wrapAsHolder(org.bukkit.craftbukkit.generator.structure.CraftStructure.bukkitToMinecraft(event.getResult().structure())));
+ }
+ center = io.papermc.paper.util.MCUtil.toBlockPosition(event.getOrigin());
+ radius = event.getRadius();
+ skipReferencedStructures = event.shouldFindUnexplored();
+ structures = HolderSet.direct(api -> world.registryAccess().registryOrThrow(Registries.STRUCTURE).wrapAsHolder(org.bukkit.craftbukkit.generator.structure.CraftStructure.bukkitToMinecraft(api)), event.getStructures());
+ }
+ // Paper end
ChunkGeneratorStructureState chunkgeneratorstructurestate = world.getChunkSource().getGeneratorState();
Map<StructurePlacement, Set<Holder<Structure>>> map = new Object2ObjectArrayMap();
Iterator iterator = structures.iterator();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 480313506bf41410de090c59e047323345ea78da..c7d377dbb53cdc1f823a839e3a113136efc16349 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -139,6 +139,11 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new);
}
// TODO registry modification API
+ // Paper start - remove this after a while along with all ConfiguredStructure stuff
+ if (bukkitClass == io.papermc.paper.world.structure.ConfiguredStructure.class) {
+ return new io.papermc.paper.world.structure.PaperConfiguredStructure.LegacyRegistry(registryHolder.registryOrThrow(Registries.STRUCTURE));
+ }
+ // Paper end
return null;
}
diff --git a/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9178fe0d01b998ca1442bf2511f8fc00db9388ba
--- /dev/null
+++ b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
@@ -0,0 +1,96 @@
+package io.papermc.paper.world.structure;
+
+import io.papermc.paper.registry.Reference;
+import net.minecraft.core.Registry;
+import net.minecraft.core.registries.Registries;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.Bootstrap;
+import net.minecraft.world.level.levelgen.structure.Structure;
+import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
+import org.bukkit.NamespacedKey;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Deprecated(forRemoval = true)
+public class ConfiguredStructureTest extends AbstractTestingBase {
+
+ private static final Map<ResourceLocation, String> BUILT_IN_STRUCTURES = new LinkedHashMap<>();
+ private static final Map<NamespacedKey, Reference<?>> DEFAULT_CONFIGURED_STRUCTURES = new LinkedHashMap<>();
+
+ private static PrintStream out;
+
+ @BeforeAll
+ public static void collectStructures() throws ReflectiveOperationException {
+ out = System.out;
+ System.setOut(Bootstrap.STDOUT);
+ for (Field field : BuiltinStructures.class.getDeclaredFields()) {
+ if (field.getType().equals(ResourceKey.class) && Modifier.isStatic(field.getModifiers())) {
+ BUILT_IN_STRUCTURES.put(((ResourceKey<?>) field.get(null)).location(), field.getName());
+ }
+ }
+ for (Field field : ConfiguredStructure.class.getDeclaredFields()) {
+ if (field.getType().equals(Reference.class) && Modifier.isStatic(field.getModifiers())) {
+ final Reference<?> ref = (Reference<?>) field.get(null);
+ DEFAULT_CONFIGURED_STRUCTURES.put(ref.getKey(), ref);
+ }
+ }
+ }
+
+ @Test
+ public void testMinecraftToApi() {
+ Registry<Structure> structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
+ assertEquals(BUILT_IN_STRUCTURES.size(), structureRegistry.size(), "configured structure maps should be the same size");
+
+ Map<ResourceLocation, Structure> missing = new LinkedHashMap<>();
+ for (Structure feature : structureRegistry) {
+ final ResourceLocation key = structureRegistry.getKey(feature);
+ assertNotNull(key, "Missing built-in registry key");
+ if (key.equals(BuiltinStructures.ANCIENT_CITY.location()) || key.equals(BuiltinStructures.TRAIL_RUINS.location()) || key.equals(BuiltinStructures.TRIAL_CHAMBERS.location())) {
+ continue; // TODO remove when upstream adds "jigsaw" StructureType
+ }
+ if (DEFAULT_CONFIGURED_STRUCTURES.get(CraftNamespacedKey.fromMinecraft(key)) == null) {
+ missing.put(key, feature);
+ }
+ }
+
+ assertTrue(missing.isEmpty(), printMissing(missing));
+ }
+
+ @Test
+ public void testApiToMinecraft() {
+ Registry<Structure> structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
+ for (NamespacedKey apiKey : DEFAULT_CONFIGURED_STRUCTURES.keySet()) {
+ assertTrue(structureRegistry.containsKey(CraftNamespacedKey.toMinecraft(apiKey)), apiKey + " does not have a minecraft counterpart");
+ }
+ }
+
+ private static String printMissing(Map<ResourceLocation, Structure> missing) {
+ final StringJoiner joiner = new StringJoiner("\n", "Missing: \n", "");
+
+ missing.forEach((key, configuredFeature) -> {
+ joiner.add("public static final Reference<ConfiguredStructure> " + BUILT_IN_STRUCTURES.get(key) + " = create(\"" + key.getPath() + "\");");
+ });
+
+ return joiner.toString();
+ }
+
+ @AfterAll
+ public static void after() {
+ System.setOut(out);
+ }
+}
diff --git a/src/test/java/org/bukkit/registry/PerRegistryTest.java b/src/test/java/org/bukkit/registry/PerRegistryTest.java
index 4e4ea083063daf22f1bb785ef212958ea889c43b..1c4966520b6401e6571aa44d5934dfa280bc80e3 100644
--- a/src/test/java/org/bukkit/registry/PerRegistryTest.java
+++ b/src/test/java/org/bukkit/registry/PerRegistryTest.java
@@ -36,6 +36,7 @@ public class PerRegistryTest extends AbstractTestingBase {
if (!(object instanceof CraftRegistry<?, ?> registry)) {
continue;
}
+ if (object instanceof io.papermc.paper.world.structure.PaperConfiguredStructure.LegacyRegistry) continue; // Paper - skip
data.add(Arguments.of(registry));
} catch (ReflectiveOperationException e) {
diff --git a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
index 4adaafafb7140e983a4e90f0ff0deaaf0887a9a5..65cc33c45553e755371ec4313dd38bb61eb7d61c 100644
--- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
+++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
@@ -23,6 +23,7 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase {
Set<Class<?>> loadedRegistries = new HashSet<>(DummyServer.registers.keySet());
Set<Class<?>> notFound = new HashSet<>();
+ loadedRegistries.remove(io.papermc.paper.world.structure.ConfiguredStructure.class); // Paper - ignore
RegistriesArgumentProvider
.getData()

View file

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 14 Nov 2020 16:48:37 +0100
Subject: [PATCH] Collision option for requiring a player participant
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 31911870e5056391d67c49fa68d59010534bf35f..04581cd90272775208a0192ef36f9c7458ad3a0c 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1872,6 +1872,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public void push(Entity entity) {
if (!this.isPassengerOfSameVehicle(entity)) {
if (!entity.noPhysics && !this.noPhysics) {
+ if (this.level.paperConfig().collisions.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper - Collision option for requiring a player participant
double d0 = entity.getX() - this.getX();
double d1 = entity.getZ() - this.getZ();
double d2 = Mth.absMax(d0, d1);
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
index 1aecb6cc62b4b411ab0ff3b7fb11a5d9d050b959..2f73ca283f2d6e6bc5265c95ef767b3f606a3d69 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
@@ -789,6 +789,7 @@ public abstract class AbstractMinecart extends VehicleEntity {
public void push(Entity entity) {
if (!this.level().isClientSide) {
if (!entity.noPhysics && !this.noPhysics) {
+ if (!this.level().paperConfig().collisions.allowVehicleCollisions && this.level().paperConfig().collisions.onlyPlayersCollide && !(entity instanceof Player)) return; // Paper - Collision option for requiring a player participant
if (!this.hasPassenger(entity)) {
// CraftBukkit start
VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity());
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
index d1eaadba8ce1f472a174afcfe8e0d059a121612c..549202706396fee91c23f6e34f7faa7672e4b03f 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
@@ -200,6 +200,7 @@ public class Boat extends VehicleEntity implements VariantHolder<Boat.Type> {
@Override
public void push(Entity entity) {
+ if (!this.level().paperConfig().collisions.allowVehicleCollisions && this.level().paperConfig().collisions.onlyPlayersCollide && !(entity instanceof Player)) return; // Paper - Collision option for requiring a player participant
if (entity instanceof Boat) {
if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) {
// CraftBukkit start

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 16 Jan 2021 14:30:12 -0500
Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead
The duplicate ProjectileHitEvent in EntityFireball was removed. The
event was always called before the duplicate call.
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
index b5a46c2c8e7e139a1b5cdad69459a37d4448efb1..a81d6a52674ddf7f818a7665cccd21dd8ea86cbe 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
@@ -92,7 +92,7 @@ public abstract class AbstractHurtingProjectile extends Projectile {
// CraftBukkit start - Fire ProjectileHitEvent
if (this.isRemoved()) {
- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition);
+ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event
}
// CraftBukkit end
}

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: CDFN <codefun@protonmail.com>
Date: Tue, 7 Jul 2020 17:53:23 +0200
Subject: [PATCH] Return chat component with empty text instead of throwing
exception
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index 810662eeb9ef7f2239a7937e58654a0407f9d8df..00031a013d8e1e9f40bc1ef9491da6df3b061d5f 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -89,7 +89,12 @@ public abstract class AbstractContainerMenu {
}
private Component title;
public final Component getTitle() {
- Preconditions.checkState(this.title != null, "Title not set");
+ // Paper start - return chat component with empty text instead of throwing error
+ // Preconditions.checkState(this.title != null, "Title not set");
+ if (this.title == null){
+ return Component.literal("");
+ }
+ // Paper end - return chat component with empty text instead of throwing error
return this.title;
}
public final void setTitle(Component title) {

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jan 2021 19:52:44 -0800
Subject: [PATCH] Make schedule command per-world
diff --git a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java
index f2d1430d714debc9e9b53eef0cbcda0d8cdcd459..d090f94a9a8a314df01e83a031dd18d5c6f1caf9 100644
--- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java
+++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java
@@ -30,7 +30,7 @@ public class ScheduleCommand {
return Component.translatableEscape("commands.schedule.cleared.failure", object);
});
private static final SuggestionProvider<CommandSourceStack> SUGGEST_SCHEDULE = (commandcontext, suggestionsbuilder) -> {
- return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder);
+ return SharedSuggestionProvider.suggest((Iterable) ((net.minecraft.commands.CommandSourceStack) commandcontext.getSource()).getLevel().serverLevelData.getScheduledEvents().getEventsIds(), suggestionsbuilder); // Paper - Make schedule command per-world
};
public ScheduleCommand() {}
@@ -85,7 +85,7 @@ public class ScheduleCommand {
}
private static int remove(CommandSourceStack source, String eventName) throws CommandSyntaxException {
- int i = source.getServer().getWorldData().overworldData().getScheduledEvents().remove(eventName);
+ int i = source.getLevel().serverLevelData.getScheduledEvents().remove(eventName); // Paper - Make schedule command per-world
if (i == 0) {
throw ScheduleCommand.ERROR_CANT_REMOVE.create(eventName);

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 3 Jan 2021 21:04:03 -0800
Subject: [PATCH] Configurable max leash distance
diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java
index 5e2f10f5fd7219ebaefb1c5b5ac9bc7c71fae179..e92831739603ef1b5678c9d44e85ab70d62be0e7 100644
--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java
+++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java
@@ -71,7 +71,7 @@ public abstract class PathfinderMob extends Mob {
float f = this.distanceTo(entity);
if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) {
- if (f > 10.0F) {
+ if (f > entity.level().paperConfig().misc.maxLeashDistance) { // Paper - Configurable max leash distance
this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit
this.dropLeash(true, true);
}
@@ -80,7 +80,7 @@ public abstract class PathfinderMob extends Mob {
}
this.onLeashDistance(f);
- if (f > 10.0F) {
+ if (f > entity.level().paperConfig().misc.maxLeashDistance) { // Paper - Configurable max leash distance
this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit
this.dropLeash(true, true);
this.goalSelector.disableControlFlag(Goal.Flag.MOVE);

View file

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Madeline Miller <mnmiller1@me.com>
Date: Sun, 17 Jan 2021 13:16:09 +1000
Subject: [PATCH] Add BlockPreDispenseEvent
diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
index 94bcbaf7daf7dfe566f508d1170a433930d9d49a..f6edfea463b3725d3a79aca38825e86dbf82175c 100644
--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
@@ -110,6 +110,7 @@ public class DispenserBlock extends BaseEntityBlock {
DispenseItemBehavior idispensebehavior = this.getDispenseMethod(world, itemstack);
if (idispensebehavior != DispenseItemBehavior.NOOP) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent
DispenserBlock.eventFired = false; // CraftBukkit - reset event status
tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack));
}
diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java
index efa7cf50b5577f87a2dfa61b59bf81052794fbf1..b4a742e8c513e458b34c216d1e907b47e3aac292 100644
--- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java
@@ -71,6 +71,7 @@ public class DropperBlock extends DispenserBlock {
ItemStack itemstack1;
if (iinventory == null) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent
itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(sourceblock, itemstack);
} else {
// CraftBukkit start - Fire event when pushing items into other inventories
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 13e4cb7af50b3a03523d84dd72ca6a122ca041ad..e6bb82928af3378847722421ce3bad7f5b994890 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -2041,5 +2041,11 @@ public class CraftEventFactory {
io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block);
return event.callEvent();
}
+
+ public static boolean handleBlockPreDispenseEvent(ServerLevel serverLevel, BlockPos pos, ItemStack itemStack, int slot) {
+ org.bukkit.block.Block block = CraftBlock.at(serverLevel, pos);
+ io.papermc.paper.event.block.BlockPreDispenseEvent event = new io.papermc.paper.event.block.BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot);
+ return event.callEvent();
+ }
// Paper end
}

View file

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 24 Jun 2020 15:14:51 -0600
Subject: [PATCH] Add PlayerChangeBeaconEffectEvent
diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
index c2fa423e14fc08c10483415baa2148af269c3758..866dd476829bd59501021a8c24bde6d8e8778963 100644
--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
@@ -171,12 +171,25 @@ public class BeaconMenu extends AbstractContainerMenu {
return BeaconMenu.decodeEffect(this.beaconData.get(2));
}
+ // Paper start - Add PlayerChangeBeaconEffectEvent
+ private static @Nullable org.bukkit.potion.PotionEffectType convert(Optional<Holder<MobEffect>> optionalEffect) {
+ return optionalEffect.map(org.bukkit.craftbukkit.potion.CraftPotionEffectType::minecraftToBukkit).orElse(null);
+ }
+ // Paper end - Add PlayerChangeBeaconEffectEvent
+
public void updateEffects(Optional<Holder<MobEffect>> primary, Optional<Holder<MobEffect>> secondary) {
if (this.paymentSlot.hasItem()) {
- this.beaconData.set(1, BeaconMenu.encodeEffect((Holder) primary.orElse(null)));// CraftBukkit - decompile error
- this.beaconData.set(2, BeaconMenu.encodeEffect((Holder) secondary.orElse(null)));// CraftBukkit - decompile error
+ // Paper start - Add PlayerChangeBeaconEffectEvent
+ io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), convert(primary), convert(secondary), this.access.getLocation().getBlock());
+ if (event.callEvent()) {
+ // Paper end - Add PlayerChangeBeaconEffectEvent
+ this.beaconData.set(1, BeaconMenu.encodeEffect(event.getPrimary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getPrimary())));// CraftBukkit - decompile error
+ this.beaconData.set(2, BeaconMenu.encodeEffect(event.getSecondary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getSecondary())));// CraftBukkit - decompile error
+ if (event.willConsumeItem()) { // Paper
this.paymentSlot.remove(1);
+ } // Paper
this.access.execute(Level::blockEntityChanged);
+ } // Paper end - Add PlayerChangeBeaconEffectEvent
}
}

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 26 Nov 2020 11:47:24 +0000
Subject: [PATCH] Add toggle for always placing the dragon egg
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 3ea0ca395e0561d96044f0f84442a08b42b539bd..f81dab25fedeed08f4d3ba2d7435e2da526e6056 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -407,7 +407,7 @@ public class EndDragonFight {
this.dragonEvent.setVisible(false);
this.spawnExitPortal(true);
this.spawnNewGateway();
- if (!this.previouslyKilled) {
+ if (this.level.paperConfig().entities.behavior.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - Add toggle for always placing the dragon egg
this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin)), Blocks.DRAGON_EGG.defaultBlockState());
}

View file

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 27 Nov 2020 17:14:27 -0800
Subject: [PATCH] Add PlayerStonecutterRecipeSelectEvent
Co-Authored-By: MiniDigger <admin@benndorf.dev>
diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
index e40d9dbdbe5359c38af6d764d01c9be422654aaa..1a5d8debc053b24e5856de916f1d248b36f645ba 100644
--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
@@ -63,7 +63,7 @@ public class StonecutterMenu extends AbstractContainerMenu {
public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) {
super(MenuType.STONECUTTER, syncId);
- this.selectedRecipeIndex = DataSlot.standalone();
+ this.selectedRecipeIndex = DataSlot.shared(new int[1], 0); // Paper - Add PlayerStonecutterRecipeSelectEvent
this.recipes = Lists.newArrayList();
this.input = ItemStack.EMPTY;
this.slotUpdateListener = () -> {
@@ -161,7 +161,30 @@ public class StonecutterMenu extends AbstractContainerMenu {
@Override
public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) {
if (this.isValidRecipeIndex(id)) {
- this.selectedRecipeIndex.set(id);
+ // Paper start - Add PlayerStonecutterRecipeSelectEvent
+ int recipeIndex = id;
+ this.selectedRecipeIndex.set(recipeIndex);
+ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed
+ if (this.isValidRecipeIndex(id)) {
+ io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent event = new io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe());
+ if (!event.callEvent()) {
+ player.containerMenu.sendAllDataToRemote();
+ return false;
+ }
+
+ net.minecraft.resources.ResourceLocation key = org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey());
+ if (!this.getRecipes().get(recipeIndex).id().equals(key)) { // If the recipe did NOT stay the same
+ for (int newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) {
+ if (this.getRecipes().get(newRecipeIndex).id().equals(key)) {
+ recipeIndex = newRecipeIndex;
+ break;
+ }
+ }
+ }
+ }
+ player.containerMenu.sendAllDataToRemote();
+ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it
+ // Paper end - Add PlayerStonecutterRecipeSelectEvent
this.setupResultSlot();
}

View file

@ -0,0 +1,140 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 29 Jan 2021 15:13:11 +0100
Subject: [PATCH] Expand EntityUnleashEvent
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 2b282ba23444110949508dac11a25fee4e472f5d..b7cc2b5ee85e8e6a5c8cb8ce1f3c934773be32e6 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -1428,12 +1428,15 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
return InteractionResult.PASS;
} else if (this.getLeashHolder() == player) {
// CraftBukkit start - fire PlayerUnleashEntityEvent
- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) {
+ // Paper start - Expand EntityUnleashEvent
+ org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.hasInfiniteMaterials());
+ if (event.isCancelled()) {
+ // Paper end - Expand EntityUnleashEvent
((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder()));
return InteractionResult.PASS;
}
// CraftBukkit end
- this.dropLeash(true, !player.hasInfiniteMaterials());
+ this.dropLeash(true, event.isDropLeash()); // Paper - Expand EntityUnleashEvent
this.gameEvent(GameEvent.ENTITY_INTERACT, player);
return InteractionResult.sidedSuccess(this.level().isClientSide);
} else {
@@ -1601,8 +1604,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
if (this.leashHolder != null) {
if (!this.isAlive() || !this.leashHolder.isAlive()) {
- this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit
- this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin
+ // Paper start - Expand EntityUnleashEvent
+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH : EntityUnleashEvent.UnleashReason.HOLDER_GONE, !this.leashHolder.pluginRemoved);
+ this.level().getCraftServer().getPluginManager().callEvent(event); // CraftBukkit
+ this.dropLeash(true, event.isDropLeash());
+ // Paper end - Expand EntityUnleashEvent
}
}
@@ -1670,8 +1676,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
boolean flag1 = super.startRiding(entity, force);
if (flag1 && this.isLeashed()) {
- this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
- this.dropLeash(true, true);
+ // Paper start - Expand EntityUnleashEvent
+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN, true);
+ if (!event.callEvent()) { return flag1; }
+ this.dropLeash(true, event.isDropLeash());
+ // Paper end - Expand EntityUnleashEvent
}
return flag1;
@@ -1848,8 +1857,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
@Override
protected void removeAfterChangingDimensions() {
super.removeAfterChangingDimensions();
- this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
- this.dropLeash(true, false);
+ // Paper start - Expand EntityUnleashEvent
+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN, false);
+ this.level().getCraftServer().getPluginManager().callEvent(event); // CraftBukkit
+ this.dropLeash(true, event.isDropLeash());
+ // Paper end - Expand EntityUnleashEvent
this.getAllSlots().forEach((itemstack) -> {
if (!itemstack.isEmpty()) {
itemstack.setCount(0);
diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java
index e92831739603ef1b5678c9d44e85ab70d62be0e7..cdd07093342521ff9944bf7a342bbf142ba3f0b7 100644
--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java
+++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java
@@ -72,8 +72,11 @@ public abstract class PathfinderMob extends Mob {
if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) {
if (f > entity.level().paperConfig().misc.maxLeashDistance) { // Paper - Configurable max leash distance
- this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit
- this.dropLeash(true, true);
+ // Paper start - Expand EntityUnleashEvent
+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true);
+ if (!event.callEvent()) return;
+ this.dropLeash(true, event.isDropLeash());
+ // Paper end - Expand EntityUnleashEvent
}
return;
@@ -81,8 +84,11 @@ public abstract class PathfinderMob extends Mob {
this.onLeashDistance(f);
if (f > entity.level().paperConfig().misc.maxLeashDistance) { // Paper - Configurable max leash distance
- this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit
- this.dropLeash(true, true);
+ // Paper start - Expand EntityUnleashEvent
+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true);
+ if (!event.callEvent()) return;
+ this.dropLeash(true, event.isDropLeash());
+ // Paper end - Expand EntityUnleashEvent
this.goalSelector.disableControlFlag(Goal.Flag.MOVE);
} else if (f > 6.0F) {
double d0 = (entity.getX() - this.getX()) / (double) f;
diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
index b43b1f81828bf1d57e98c52964053db7127519ad..952321d4e34a6524bbb494a56d7658068f74124c 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
@@ -120,11 +120,14 @@ public class LeashFenceKnotEntity extends HangingEntity {
if (entityinsentient1.isLeashed() && entityinsentient1.getLeashHolder() == this) {
// CraftBukkit start
- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, player, hand).isCancelled()) {
+ // Paper start - Expand EntityUnleashEvent
+ org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, player, hand, !player.getAbilities().instabuild);
+ if (event.isCancelled()) {
+ // Paper end - Expand EntityUnleashEvent
die = false;
continue;
}
- entityinsentient1.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean
+ entityinsentient1.dropLeash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - Expand EntityUnleashEvent
// CraftBukkit end
flag1 = true;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e6bb82928af3378847722421ce3bad7f5b994890..dadb4f13ec6b9915108603aa34d4112c47337c44 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1565,8 +1565,10 @@ public class CraftEventFactory {
Bukkit.getPluginManager().callEvent(new PlayerRecipeBookSettingsChangeEvent(player.getBukkitEntity(), bukkitType, open, filter));
}
- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player, InteractionHand enumhand) {
- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), CraftEquipmentSlot.getHand(enumhand));
+ // Paper start - Expand EntityUnleashEvent
+ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player, InteractionHand enumhand, boolean dropLeash) {
+ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), CraftEquipmentSlot.getHand(enumhand), dropLeash);
+ // Paper end - Expand EntityUnleashEvent
entity.level().getCraftServer().getPluginManager().callEvent(event);
return event;
}

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yive <admin@yive.me>
Date: Sun, 24 Jan 2021 08:55:19 -0800
Subject: [PATCH] Reset shield blocking on dimension change
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index edfcfb91d907d6e1837e5a5d0e7abb8c8f6bcb66..2db78d991ef0595a0d8806414a959479e289c0fc 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1265,6 +1265,11 @@ public class ServerPlayer extends Player {
this.level().getCraftServer().getPluginManager().callEvent(changeEvent);
// CraftBukkit end
}
+ // Paper start - Reset shield blocking on dimension change
+ if (this.isBlocking()) {
+ this.stopUsingItem();
+ }
+ // Paper end - Reset shield blocking on dimension change
return this;
}

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Mon, 25 Jan 2021 14:53:57 +0100
Subject: [PATCH] Add DragonEggFormEvent
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index f81dab25fedeed08f4d3ba2d7435e2da526e6056..609b20e2b222c5b1fddf22c2621d0d7a88cabcfa 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -407,8 +407,22 @@ public class EndDragonFight {
this.dragonEvent.setVisible(false);
this.spawnExitPortal(true);
this.spawnNewGateway();
+ // Paper start - Add DragonEggFormEvent
+ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin));
+ org.bukkit.craftbukkit.block.CraftBlockState eggState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(this.level, eggPosition);
+ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState());
+ io.papermc.paper.event.block.DragonEggFormEvent eggEvent = new io.papermc.paper.event.block.DragonEggFormEvent(org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition), eggState,
+ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this));
+ // Paper end - Add DragonEggFormEvent
if (this.level.paperConfig().entities.behavior.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - Add toggle for always placing the dragon egg
- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin)), Blocks.DRAGON_EGG.defaultBlockState());
+ // Paper start - Add DragonEggFormEvent
+ // this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin)), Blocks.DRAGON_EGG.defaultBlockState());
+ } else {
+ eggEvent.setCancelled(true);
+ }
+ if (eggEvent.callEvent()) {
+ eggEvent.getNewState().update(true);
+ // Paper end - Add DragonEggFormEvent
}
this.previouslyKilled = true;

View file

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Tue, 11 Feb 2020 21:56:48 -0600
Subject: [PATCH] Add EntityMoveEvent
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b083298d2bcf0d4c6213d6ac8645b8c084cfc6de..e9ea8ad5689c0e6edd2e7335ab9932b3a6abbbf3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1583,6 +1583,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
+ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
this.profiler.push(() -> {
String s = String.valueOf(worldserver);
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 2c1ca55e1919c29956b3d95f65f8f08eb7529d1e..35ccccfea9aec44a85e08b0e383b6650554b8bd3 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -227,6 +227,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
public final LevelStorageSource.LevelStorageAccess convertable;
public final UUID uuid;
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
+ public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
public LevelChunk getChunkIfLoaded(int x, int z) {
return this.chunkSource.getChunk(x, z, false);
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index e38f0659836be4bebff06e8d8e7848abdcbda455..83730b9da452d27b420770adf6ff179b936f2bbd 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3471,6 +3471,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.pushEntities();
this.level().getProfiler().pop();
+ // Paper start - Add EntityMoveEvent
+ if (((ServerLevel) this.level()).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) {
+ if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
+ Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO);
+ Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
+ io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone());
+ if (!event.callEvent()) {
+ this.absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch());
+ } else if (!to.equals(event.getTo())) {
+ this.absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch());
+ }
+ }
+ }
+ // Paper end - Add EntityMoveEvent
if (!this.level().isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) {
this.hurt(this.damageSources().drown(), 1.0F);
}

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lukas81298 <lukas81298@gommehd.net>
Date: Mon, 25 Jan 2021 14:37:57 +0100
Subject: [PATCH] added option to disable pathfinding updates on block changes
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 35ccccfea9aec44a85e08b0e383b6650554b8bd3..93d66d85be2dcc52e8f3fa138561f2126d91c732 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1375,6 +1375,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
this.getChunkSource().blockChanged(pos);
+ if(this.paperConfig().misc.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates
this.pathTypesByPosCache.invalidate(pos);
VoxelShape voxelshape = oldState.getCollisionShape(this, pos);
VoxelShape voxelshape1 = newState.getCollisionShape(this, pos);
@@ -1417,6 +1418,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
}
+ } // Paper - option to disable pathfinding updates
}
@Override

View file

@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Mon, 18 Jan 2021 20:45:25 -0500
Subject: [PATCH] Inline shift direction fields
Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the
critical section for much of the server, including the lighting engine.
diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java
index c47e6acbd36737aa7af13b452f51b3f017d324f4..03c45ee77276462818a6f774b5945b25924aa3f0 100644
--- a/src/main/java/net/minecraft/core/Direction.java
+++ b/src/main/java/net/minecraft/core/Direction.java
@@ -55,6 +55,12 @@ public enum Direction implements StringRepresentable {
.sorted(Comparator.comparingInt(direction -> direction.data2d))
.toArray(Direction[]::new);
+ // Paper start - Perf: Inline shift direction fields
+ private final int adjX;
+ private final int adjY;
+ private final int adjZ;
+ // Paper end - Perf: Inline shift direction fields
+
private Direction(
final int id,
final int idOpposite,
@@ -71,6 +77,11 @@ public enum Direction implements StringRepresentable {
this.axis = axis;
this.axisDirection = direction;
this.normal = vector;
+ // Paper start - Perf: Inline shift direction fields
+ this.adjX = vector.getX();
+ this.adjY = vector.getY();
+ this.adjZ = vector.getZ();
+ // Paper end - Perf: Inline shift direction fields
}
public static Direction[] orderedByNearest(Entity entity) {
@@ -234,15 +245,15 @@ public enum Direction implements StringRepresentable {
}
public int getStepX() {
- return this.normal.getX();
+ return this.adjX; // Paper - Perf: Inline shift direction fields
}
public int getStepY() {
- return this.normal.getY();
+ return this.adjY; // Paper - Perf: Inline shift direction fields
}
public int getStepZ() {
- return this.normal.getZ();
+ return this.adjZ; // Paper - Perf: Inline shift direction fields
}
public Vector3f step() {

View file

@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Wed, 20 Jan 2021 14:23:37 -0600
Subject: [PATCH] Allow adding items to BlockDropItemEvent
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index dadb4f13ec6b9915108603aa34d4112c47337c44..ea9a12ff01203072975bb2f22a077d1d2e46376f 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -451,13 +451,30 @@ public class CraftEventFactory {
}
public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer player, List<ItemEntity> items) {
- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity()));
+ // Paper start - Allow adding items to BlockDropItemEvent
+ List<Item> list = new ArrayList<>();
+ for (ItemEntity item : items) {
+ list.add((Item) item.getBukkitEntity());
+ }
+ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list);
+ // Paper end - Allow adding items to BlockDropItemEvent
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
- for (ItemEntity item : items) {
- item.level().addFreshEntity(item);
+ // Paper start - Allow adding items to BlockDropItemEvent
+ for (Item bukkit : list) {
+ if (!bukkit.isValid()) {
+ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle();
+ item.level().addFreshEntity(item);
+ }
+ }
+ } else {
+ for (Item bukkit : list) {
+ if (bukkit.isValid()) {
+ bukkit.remove();
+ }
}
+ // Paper end - Allow adding items to BlockDropItemEvent
}
}

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aleksander Jagiello <themolkapl@gmail.com>
Date: Sun, 24 Jan 2021 22:17:54 +0100
Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
index 71a147df3bcbd5bb82934da3e6e14326746cf2e3..e85b9bb3f9c225d289a4959921970b9963881199 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
@@ -653,4 +653,15 @@ public class CraftScheduler implements BukkitScheduler {
public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException {
throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)");
}
+
+ // Paper start - add getMainThreadExecutor
+ @Override
+ public Executor getMainThreadExecutor(Plugin plugin) {
+ Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
+ return command -> {
+ Preconditions.checkArgument(command != null, "Command cannot be null");
+ this.runTask(plugin, command);
+ };
+ }
+ // Paper end
}

View file

@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ysl3000 <yannicklamprecht@live.de>
Date: Sat, 24 Oct 2020 16:37:44 +0200
Subject: [PATCH] living entity allow attribute registration
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index f03f40e2624d0e8e27a6fb7ae33d82cb614252f4..b02c8514aac174db1c04a6c8240851eff474906f 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -106,4 +106,12 @@ public class AttributeMap {
}
}
}
+
+ // Paper - start - living entity allow attribute registration
+ public void registerAttribute(Attribute attributeBase) {
+ AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute);
+ attributes.put(attributeBase, attributeModifiable);
+ }
+ // Paper - end - living entity allow attribute registration
+
}
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
index a0a34f680e21007ebf2c2497d2e6505eedae6481..5314905063e62f0f5ed56e476718ba7610bb711f 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
@@ -35,4 +35,11 @@ public class CraftAttributeMap implements Attributable {
return (nms == null) ? null : new CraftAttributeInstance(nms, attribute);
}
+ // Paper start - living entity allow attribute registration
+ @Override
+ public void registerAttribute(Attribute attribute) {
+ Preconditions.checkArgument(attribute != null, "attribute");
+ handle.registerAttribute(CraftAttribute.bukkitToMinecraft(attribute));
+ }
+ // Paper end - living entity allow attribute registration
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index b88077ac1ed99057b8a9361ea550cd2b00040f88..2701e53086f4be07c341cd1e4fcd7a351e77c486 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -754,6 +754,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return this.getHandle().craftAttributes.getAttribute(attribute);
}
+ // Paper start - living entity allow attribute registration
+ @Override
+ public void registerAttribute(Attribute attribute) {
+ getHandle().craftAttributes.registerAttribute(attribute);
+ }
+ // Paper end - living entity allow attribute registration
+
@Override
public void setAI(boolean ai) {
if (this.getHandle() instanceof Mob) {

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Fri, 5 Feb 2021 22:12:13 +0100
Subject: [PATCH] fix dead slime setSize invincibility
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java
index 3d9b7c0e128ea05bec5600c774e9685998b71cac..e48f7d1cbec4a2319745ba48a5d44ab9925214e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java
@@ -16,7 +16,7 @@ public class CraftSlime extends CraftMob implements Slime, CraftEnemy {
@Override
public void setSize(int size) {
- this.getHandle().setSize(size, true);
+ this.getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility
}
@Override

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 10 Feb 2021 14:53:36 -0800
Subject: [PATCH] Merchant#getRecipes should return an immutable list
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java
index 425c8de426cecc9919d03dc64325494104d1b294..71be1e4f17ded6ea42e36be0a9b534c6a65ec640 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java
@@ -24,7 +24,7 @@ public class CraftMerchant implements Merchant {
@Override
public List<MerchantRecipe> getRecipes() {
- return Collections.unmodifiableList(Lists.transform(this.merchant.getOffers(), new Function<net.minecraft.world.item.trading.MerchantOffer, MerchantRecipe>() {
+ return List.copyOf(Lists.transform(this.merchant.getOffers(), new Function<net.minecraft.world.item.trading.MerchantOffer, MerchantRecipe>() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes())
@Override
public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantOffer recipe) {
return recipe.asBukkit();

View file

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tom <cryptite@gmail.com>
Date: Fri, 26 Feb 2021 16:24:25 -0600
Subject: [PATCH] Expose Tracked Players
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 2080733ebae1af51b7b4d3cd2fbd1a4a2703a920..d30e1dd1b4525674c8a52da9b677c09a251b2467 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1052,4 +1052,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return getHandle().isTicking();
}
// Paper end - isTicking API
+
+ // Paper start - tracked players API
+ @Override
+ public Set<org.bukkit.entity.Player> getTrackedPlayers() {
+ if (this.entity.tracker == null) {
+ return java.util.Collections.emptySet();
+ }
+
+ Set<org.bukkit.entity.Player> set = new java.util.HashSet<>(this.entity.tracker.seenBy.size());
+ for (net.minecraft.server.network.ServerPlayerConnection connection : this.entity.tracker.seenBy) {
+ set.add(connection.getPlayer().getBukkitEntity().getPlayer());
+ }
+ return set;
+ }
+ // Paper end - tracked players API
}

View file

@ -0,0 +1,426 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com>
Date: Sat, 3 Oct 2020 08:27:40 +0200
Subject: [PATCH] Improve ServerGUI
- Added logo to server frame
- Show tps in the server stats
diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
index f93373d28d741e1f8a53e07b4e328ce9c4e1657f..039a86034928a5eb7aaa2d7ca76a7bddcca346bd 100644
--- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
@@ -58,9 +58,17 @@ public class RAMDetails extends JList<String> {
public void update() {
GraphData data = RAMGraph.DATA.peekLast();
Vector<String> vector = new Vector<>();
+
+ double[] tps = org.bukkit.Bukkit.getTPS();
+ String[] tpsAvg = new String[tps.length];
+
+ for ( int g = 0; g < tps.length; g++) {
+ tpsAvg[g] = format( tps[g] );
+ }
vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)");
vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb");
vector.add("Avg tick: " + DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND) + " ms");
+ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg));
setListData(vector);
}
@@ -71,4 +79,8 @@ public class RAMDetails extends JList<String> {
}
return ((double) total / (double) tickTimes.length) * 1.0E-6D;
}
+
+ private static String format(double tps) {
+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 );
+ }
}
diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
index 8b570b0c3967a22c085f390110cb29cbd9c8feff..4d3fe4f56e0b264fa030409919caf52d5f421d46 100644
--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
+++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
@@ -59,6 +59,15 @@ public class MinecraftServerGui extends JComponent {
jframe.pack();
jframe.setLocationRelativeTo((Component) null);
jframe.setVisible(true);
+ jframe.setName("Minecraft server"); // Paper - Improve ServerGUI
+
+ // Paper start - Improve ServerGUI
+ try {
+ jframe.setIconImage(javax.imageio.ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png"))));
+ } catch (java.io.IOException ignore) {
+ }
+ // Paper end - Improve ServerGUI
+
jframe.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowevent) {
if (!servergui.isClosing.getAndSet(true)) {
diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java
index 6e9c6d556ed55325e36d191fc9d1508c00879671..096c89bd01cec2abd151bf6fffc4847d1bcd548f 100644
--- a/src/main/java/net/minecraft/server/gui/StatsComponent.java
+++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java
@@ -34,10 +34,19 @@ public class StatsComponent extends JComponent {
private void tick() {
long l = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
+ // Paper start - Improve ServerGUI
+ double[] tps = org.bukkit.Bukkit.getTPS();
+ String[] tpsAvg = new String[tps.length];
+
+ for ( int g = 0; g < tps.length; g++) {
+ tpsAvg[g] = format( tps[g] );
+ }
this.msgs[0] = "Memory use: " + l / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)";
this.msgs[1] = "Avg tick: "
+ DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / (double)TimeUtil.NANOSECONDS_PER_MILLISECOND)
+ " ms";
+ this.msgs[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg);
+ // Paper end - Improve ServerGUI
this.values[this.vp++ & 0xFF] = (int)(l * 100L / Runtime.getRuntime().maxMemory());
this.repaint();
}
@@ -66,4 +75,10 @@ public class StatsComponent extends JComponent {
public void close() {
this.timer.stop();
}
+
+ // Paper start - Improve ServerGUI
+ private static String format(double tps) {
+ return (( tps > 21.0 ) ? "*" : "") + Math.min(Math.round(tps * 100.0) / 100.0, 20.0); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise
+ }
+ // Paper end - Improve ServerGUI
}
diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b924977b7886df9ab8790b1e4ff9b1c04a2af45
GIT binary patch
literal 16900
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
LFIp>X81%mY^Bg|U
literal 0
HcmV?d00001

View file

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jan 2021 19:49:15 -0800
Subject: [PATCH] fix converting txt to json file
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java
index 929f59bce01c8e6ed4b0b551744d42e131b8fc80..22c4f8dea99f92a1eb3da2baf0a15bf9d2ca0462 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java
@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList {
this.setViewDistance(dedicatedServerProperties.viewDistance);
this.setSimulationDistance(dedicatedServerProperties.simulationDistance);
super.setUsingWhiteList(dedicatedServerProperties.whiteList.get());
+ // Paper start - fix converting txt to json file; moved from constructor
+ }
+ @Override
+ public void loadAndSaveFiles() {
+ // Paper end - fix converting txt to json file
this.loadUserBanList();
this.saveUserBanList();
this.loadIpBanList();
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 4d7c2832a9cd9a88b99c837a02df7fa91e572658..4b00c14332f3d514f402fc82345a02d51c3ac58a 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -212,6 +212,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
// Paper end - initialize global and world-defaults configuration
+ // Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
+ if (this.convertOldUsers()) {
+ this.getProfileCache().save(false); // Paper
+ }
+ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames
+ // Paper end - fix converting txt to json file
org.spigotmc.WatchdogThread.doStart(org.spigotmc.SpigotConfig.timeoutTime, org.spigotmc.SpigotConfig.restartOnCrash); // Paper - start watchdog thread
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
@@ -266,9 +272,6 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file.");
}
- if (this.convertOldUsers()) {
- this.getProfileCache().save(false); // Paper - Perf: Async GameProfileCache saving
- }
if (!OldUsersConverter.serverReadyAfterUserconversion(this)) {
return false;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index dd360250ca784421e0f8fffe786bec88a8f38b3d..b1cf71350661baf027bd45ebd9c80e8273cbad1e 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -179,6 +179,7 @@ public abstract class PlayerList {
this.maxPlayers = maxPlayers;
this.playerIo = saveHandler;
}
+ abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) {
player.isRealPlayer = true; // Paper

View file

@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jan 2021 22:40:34 -0800
Subject: [PATCH] Add worldborder events
diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java
index 580eb275942570da9e68287ca75da886ba1248c0..6c6eb7deed281678c05ef27f933e1693b11dae7c 100644
--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java
+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java
@@ -123,6 +123,14 @@ public class WorldBorder {
}
public void setCenter(double x, double z) {
+ // Paper start - Add worldborder events
+ if (this.world != null) {
+ io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z));
+ if (!event.callEvent()) return;
+ x = event.getNewCenter().getX();
+ z = event.getNewCenter().getZ();
+ }
+ // Paper end - Add worldborder events
this.centerX = x;
this.centerZ = z;
this.extent.onCenterChange();
@@ -149,6 +157,17 @@ public class WorldBorder {
}
public void setSize(double size) {
+ // Paper start - Add worldborder events
+ if (this.world != null) {
+ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0);
+ if (!event.callEvent()) return;
+ if (event.getType() == io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition
+ lerpSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration());
+ return;
+ }
+ size = event.getNewSize();
+ }
+ // Paper end - Add worldborder events
this.extent = new WorldBorder.StaticBorderExtent(size);
Iterator iterator = this.getListeners().iterator();
@@ -161,6 +180,20 @@ public class WorldBorder {
}
public void lerpSizeBetween(double fromSize, double toSize, long time) {
+ // Paper start - Add worldborder events
+ if (this.world != null) {
+ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type type;
+ if (fromSize == toSize) { // new size = old size
+ type = io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal.
+ } else {
+ type = io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.STARTED_MOVE;
+ }
+ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time);
+ if (!event.callEvent()) return;
+ toSize = event.getNewSize();
+ time = event.getDuration();
+ }
+ // Paper end - Add worldborder events
this.extent = (WorldBorder.BorderExtent) (fromSize == toSize ? new WorldBorder.StaticBorderExtent(toSize) : new WorldBorder.MovingBorderExtent(fromSize, toSize, time));
Iterator iterator = this.getListeners().iterator();
@@ -472,6 +505,7 @@ public class WorldBorder {
@Override
public WorldBorder.BorderExtent update() {
+ if (world != null && this.getLerpRemainingTime() <= 0L) new io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), this.from, this.to, this.lerpDuration).callEvent(); // Paper - Add worldborder events
return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this);
}

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 5 Jul 2020 00:33:54 -0700
Subject: [PATCH] Add PlayerNameEntityEvent
diff --git a/src/main/java/net/minecraft/world/item/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java
index 3ce8c725270510dbaaf2c1edc895d37ea9ca424c..774c982f28b4f127fc3f036c19dfb47fb9ae3264 100644
--- a/src/main/java/net/minecraft/world/item/NameTagItem.java
+++ b/src/main/java/net/minecraft/world/item/NameTagItem.java
@@ -18,8 +18,13 @@ public class NameTagItem extends Item {
Component component = stack.get(DataComponents.CUSTOM_NAME);
if (component != null && !(entity instanceof Player)) {
if (!user.level().isClientSide && entity.isAlive()) {
- entity.setCustomName(component);
- if (entity instanceof Mob mob) {
+ // Paper start - Add PlayerNameEntityEvent
+ io.papermc.paper.event.player.PlayerNameEntityEvent event = new io.papermc.paper.event.player.PlayerNameEntityEvent(((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), io.papermc.paper.adventure.PaperAdventure.asAdventure(stack.getHoverName()), true);
+ if (!event.callEvent()) return InteractionResult.PASS;
+ LivingEntity newEntity = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle();
+ newEntity.setCustomName(event.getName() != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(event.getName()) : null);
+ if (event.isPersistent() && newEntity instanceof Mob mob) {
+ // Paper end - Add PlayerNameEntityEvent
mob.setPersistenceRequired();
}

View file

@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com>
Date: Wed, 6 Jan 2021 12:04:03 -0800
Subject: [PATCH] Add recipe to cook events
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index 4cd7232f538649d99892f3b31f2741b1d7e792e8..e18ebeef377411f1e921e3d769c4a1d379a12be4 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -443,7 +443,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result);
+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result, (org.bukkit.inventory.CookingRecipe<?>) recipeholder.toBukkitRecipe()); // Paper - Add recipe to cook events
world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent);
if (furnaceSmeltEvent.isCancelled()) {
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
index 66fbad74c2ec2f853ec6c74482c6cae1c1746007..e858d32c7e8e228a1f0327a33054671ad105c2eb 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
@@ -68,7 +68,10 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
if (campfire.cookingProgress[i] >= campfire.cookingTime[i]) {
SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack});
- ItemStack itemstack1 = (ItemStack) campfire.quickCheck.getRecipeFor(inventorysubcontainer, world).map((recipeholder) -> {
+ // Paper start - Add recipe to cook events; re-use recipeHolderOptional below
+ Optional<RecipeHolder<CampfireCookingRecipe>> recipeHolderOptional = campfire.quickCheck.getRecipeFor(inventorysubcontainer, world);
+ ItemStack itemstack1 = (ItemStack) recipeHolderOptional.map((recipeholder) -> {
+ // Paper end - Add recipe to cook events
return ((CampfireCookingRecipe) recipeholder.value()).assemble(inventorysubcontainer, world.registryAccess());
}).orElse(itemstack);
@@ -77,7 +80,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result);
+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result, (org.bukkit.inventory.CookingRecipe<?>) recipeHolderOptional.map(RecipeHolder::toBukkitRecipe).orElse(null)); // Paper - Add recipe to cook events
world.getCraftServer().getPluginManager().callEvent(blockCookEvent);
if (blockCookEvent.isCancelled()) {

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 6 Jul 2020 12:44:31 -0700
Subject: [PATCH] Add Block#isValidTool
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 98e87dc15e2ed23f6897ba6359846ff5bc32b655..2034858a53c4c887da334cdc7713997daa01124f 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -693,5 +693,9 @@ public class CraftBlock implements Block {
public String translationKey() {
return this.getNMS().getBlock().getDescriptionId();
}
+
+ public boolean isValidTool(ItemStack itemStack) {
+ return getDrops(itemStack).size() != 0;
+ }
// Paper end
}

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anton Lindroth <ntoonio@gmail.com>
Date: Wed, 15 Apr 2020 01:54:02 +0200
Subject: [PATCH] Allow using signs inside spawn protection
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index e0c11559295d00445d5ba0543a81f49dc2314266..9446d6c2b2f8e535588264af7e1c852005658a17 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1753,8 +1753,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
int i = this.player.level().getMaxBuildHeight();
if (blockposition.getY() < i) {
- if (this.awaitingPositionFromClient == null && worldserver.mayInteract(this.player, blockposition)) {
- this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706
+ if (this.awaitingPositionFromClient == null && (worldserver.mayInteract(this.player, blockposition) || (worldserver.paperConfig().spawn.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof net.minecraft.world.level.block.SignBlock))) { // Paper - Allow using signs inside spawn protection
InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock);
if (enuminteractionresult.consumesAction()) {

View file

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 6 Jan 2021 00:34:04 -0800
Subject: [PATCH] Expand world key API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 9801f78f1d44fd5a72fbdb319681b683e8fb85c4..1e720b96f0367652db6924b8654deaa9467e3d2c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -511,5 +511,10 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
public io.papermc.paper.world.MoonPhase getMoonPhase() {
return io.papermc.paper.world.MoonPhase.getPhase(this.getHandle().dayTime() / 24000L);
}
+
+ @Override
+ public org.bukkit.NamespacedKey getKey() {
+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.getHandle().getLevel().dimension().location());
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 99fa8f65801b1816b788fa42d49d6672bf331579..6debfd5866d4411ef8d51995bd07a0e2ece781b3 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1150,9 +1150,15 @@ public final class CraftServer implements Server {
File folder = new File(this.getWorldContainer(), name);
World world = this.getWorld(name);
- if (world != null) {
- return world;
+ // Paper start
+ World worldByKey = this.getWorld(creator.key());
+ if (world != null || worldByKey != null) {
+ if (world == worldByKey) {
+ return world;
+ }
+ throw new IllegalArgumentException("Cannot create a world with key " + creator.key() + " and name " + name + " one (or both) already match a world that exists");
}
+ // Paper end
if (folder.exists()) {
Preconditions.checkArgument(folder.isDirectory(), "File (%s) exists and isn't a folder", name);
@@ -1278,7 +1284,7 @@ public final class CraftServer implements Server {
} else if (name.equals(levelName + "_the_end")) {
worldKey = net.minecraft.world.level.Level.END;
} else {
- worldKey = ResourceKey.create(Registries.DIMENSION, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH)));
+ worldKey = ResourceKey.create(Registries.DIMENSION, new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper
}
// If set to not keep spawn in memory (changed from default) then adjust rule accordingly
@@ -1374,6 +1380,15 @@ public final class CraftServer implements Server {
return null;
}
+ // Paper start
+ @Override
+ public World getWorld(NamespacedKey worldKey) {
+ ServerLevel worldServer = console.getLevel(ResourceKey.create(net.minecraft.core.registries.Registries.DIMENSION, CraftNamespacedKey.toMinecraft(worldKey)));
+ if (worldServer == null) return null;
+ return worldServer.getWorld();
+ }
+ // Paper end
+
public void addWorld(World world) {
// Check if a World already exists with the UID.
if (this.getWorld(world.getUID()) != null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index c0878cf9948774986996127e250004f0f21d6b31..788a85a65cc77b7c826a9804e52ef5883bb2ab61 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -533,6 +533,11 @@ public final class CraftMagicNumbers implements UnsafeValues {
public int nextEntityId() {
return net.minecraft.world.entity.Entity.nextEntityId();
}
+
+ @Override
+ public String getMainLevelName() {
+ return ((net.minecraft.server.dedicated.DedicatedServer) net.minecraft.server.MinecraftServer.getServer()).getProperties().levelName;
+ }
// Paper end
/**

Some files were not shown because too many files have changed in this diff Show more