956
This commit is contained in:
parent
14c03366ed
commit
a399f23903
36 changed files with 185 additions and 186 deletions
|
@ -1,171 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Tue, 27 Jun 2023 21:09:11 -0400
|
||||
Subject: [PATCH] Dont resend blocks on interactions
|
||||
|
||||
In general, the client now has an acknowledgment system which will prevent block changes made by the client to be reverted correctly.
|
||||
|
||||
It should be noted that this system does not yet support block entities, so those still need to resynced when needed.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index dd78a1685bd841577aa9d5010fffda1468901baf..c5f3ba82b3ded415ff4bffc9eabf9526695e1ba7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -202,7 +202,7 @@ public class ServerPlayerGameMode {
|
||||
PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
|
||||
if (event.isCancelled()) {
|
||||
// Let the client know the block still exists
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Paper - Don't resync blocks
|
||||
// Update any tile entity data for this block
|
||||
capturedBlockEntity = true; // Paper - Send block entities after destroy prediction
|
||||
return;
|
||||
@@ -217,7 +217,7 @@ public class ServerPlayerGameMode {
|
||||
// Spigot start - handle debug stick left click for non-creative
|
||||
if (this.player.getMainHandItem().is(net.minecraft.world.item.Items.DEBUG_STICK)
|
||||
&& ((net.minecraft.world.item.DebugStickItem) net.minecraft.world.item.Items.DEBUG_STICK).handleInteraction(this.player, this.level.getBlockState(pos), this.level, pos, false, this.player.getMainHandItem())) {
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Paper - Don't resync block
|
||||
return;
|
||||
}
|
||||
// Spigot end
|
||||
@@ -235,15 +235,17 @@ public class ServerPlayerGameMode {
|
||||
// CraftBukkit start - Swings at air do *NOT* exist.
|
||||
if (event.useInteractedBlock() == Event.Result.DENY) {
|
||||
// If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door.
|
||||
- BlockState data = this.level.getBlockState(pos);
|
||||
- if (data.getBlock() instanceof DoorBlock) {
|
||||
- // For some reason *BOTH* the bottom/top part have to be marked updated.
|
||||
- boolean bottom = data.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER;
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below()));
|
||||
- } else if (data.getBlock() instanceof TrapDoorBlock) {
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
- }
|
||||
+ // Paper start - Don't resync blocks
|
||||
+ //BlockState data = this.level.getBlockState(pos);
|
||||
+ //if (data.getBlock() instanceof DoorBlock) {
|
||||
+ // // For some reason *BOTH* the bottom/top part have to be marked updated.
|
||||
+ // boolean bottom = data.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER;
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below()));
|
||||
+ //} else if (data.getBlock() instanceof TrapDoorBlock) {
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ //}
|
||||
+ // Paper end - Don't resync blocks
|
||||
} else if (!iblockdata.isAir()) {
|
||||
iblockdata.attack(this.level, pos, this.player);
|
||||
f = iblockdata.getDestroyProgress(this.player, this.player.level(), pos);
|
||||
@@ -252,7 +254,7 @@ public class ServerPlayerGameMode {
|
||||
if (event.useItemInHand() == Event.Result.DENY) {
|
||||
// If we 'insta destroyed' then the client needs to be informed.
|
||||
if (f > 1.0f) {
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Paper - Don't resync blocks
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -260,7 +262,7 @@ public class ServerPlayerGameMode {
|
||||
|
||||
if (blockEvent.isCancelled()) {
|
||||
// Let the client know the block still exists
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Paper - Don't resync block
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -351,7 +353,7 @@ public class ServerPlayerGameMode {
|
||||
|
||||
// Tell client the block is gone immediately then process events
|
||||
// Don't tell the client if its a creative sword break because its not broken!
|
||||
- if (this.level.getBlockEntity(pos) == null && !isSwordNoBreak) {
|
||||
+ if (false && this.level.getBlockEntity(pos) == null && !isSwordNoBreak) { // Paper - Don't resync block
|
||||
ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(pos, Blocks.AIR.defaultBlockState());
|
||||
this.player.connection.send(packet);
|
||||
}
|
||||
@@ -377,13 +379,15 @@ public class ServerPlayerGameMode {
|
||||
if (isSwordNoBreak) {
|
||||
return false;
|
||||
}
|
||||
+ // Paper start - Don't resync blocks
|
||||
// Let the client know the block still exists
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ //this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
|
||||
// Brute force all possible updates
|
||||
- for (Direction dir : Direction.values()) {
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos.relative(dir)));
|
||||
- }
|
||||
+ //for (Direction dir : Direction.values()) {
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos.relative(dir)));
|
||||
+ //}
|
||||
+ // Paper end - Don't resync blocks
|
||||
|
||||
// Update any tile entity data for this block
|
||||
if (!captureSentBlockEntities) { // Paper - Send block entities after destroy prediction
|
||||
@@ -532,16 +536,18 @@ public class ServerPlayerGameMode {
|
||||
if (event.useInteractedBlock() == Event.Result.DENY) {
|
||||
// If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door.
|
||||
if (iblockdata.getBlock() instanceof DoorBlock) {
|
||||
- boolean bottom = iblockdata.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER;
|
||||
- player.connection.send(new ClientboundBlockUpdatePacket(world, bottom ? blockposition.above() : blockposition.below()));
|
||||
+ // Paper start - Don't resync blocks
|
||||
+ // boolean bottom = iblockdata.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER;
|
||||
+ // player.connection.send(new ClientboundBlockUpdatePacket(world, bottom ? blockposition.above() : blockposition.below()));
|
||||
+ // Paper end - Don't resync blocks
|
||||
} else if (iblockdata.getBlock() instanceof CakeBlock) {
|
||||
player.getBukkitEntity().sendHealthUpdate(); // SPIGOT-1341 - reset health for cake
|
||||
} else if (this.interactItemStack.getItem() instanceof DoubleHighBlockItem) {
|
||||
// send a correcting update to the client, as it already placed the upper half of the bisected item
|
||||
- player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.relative(hitResult.getDirection()).above()));
|
||||
+ //player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.relative(hitResult.getDirection()).above())); // Paper - Don't resync blocks
|
||||
|
||||
// send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc)
|
||||
- player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above()));
|
||||
+ //player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); // Paper - Don't resync blocks
|
||||
// Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method
|
||||
} else if (iblockdata.is(Blocks.JIGSAW) || iblockdata.is(Blocks.STRUCTURE_BLOCK) || iblockdata.getBlock() instanceof net.minecraft.world.level.block.CommandBlock) {
|
||||
player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId));
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
index 6d494b80ae002aea00afa44adf83dad1ae5bbbc1..49557d6f22c5725c663a231deab019d4f6fe95fa 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
@@ -78,7 +78,7 @@ public class BucketItem extends Item implements DispensibleContainerItem {
|
||||
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
- ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager)
|
||||
+ // ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) // Paper - Don't resend blocks
|
||||
((ServerPlayer) user).getBukkitEntity().updateInventory(); // SPIGOT-4541
|
||||
return InteractionResultHolder.fail(itemstack);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class BucketItem extends Item implements DispensibleContainerItem {
|
||||
if (flag2 && entityhuman != null) {
|
||||
PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand);
|
||||
if (event.isCancelled()) {
|
||||
- ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity
|
||||
+ // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity // Paper - Don't resend blocks
|
||||
((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 4485199c90e3efbce3e6a18a75703e86a9bdde3c..3f6082b656ec8c9b96b40fbd1c926d5211ffe4c6 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -479,10 +479,12 @@ public final class ItemStack implements DataComponentHolder {
|
||||
world.preventPoiUpdated = false;
|
||||
|
||||
// Brute force all possible updates
|
||||
- BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition();
|
||||
- for (Direction dir : Direction.values()) {
|
||||
- ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir)));
|
||||
- }
|
||||
+ // Paper start - Don't resync blocks
|
||||
+ // BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition();
|
||||
+ // for (Direction dir : Direction.values()) {
|
||||
+ // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir)));
|
||||
+ // }
|
||||
+ // Paper end - Don't resync blocks
|
||||
SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
|
||||
} else {
|
||||
// Change the stack to its new contents if it hasn't been tampered with.
|
|
@ -1,79 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 16 Dec 2023 14:46:01 -0800
|
||||
Subject: [PATCH] add more scoreboard API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
index b36e5574c10e6d70a399e2ac0704fd4f43dbb444..2d3abf2a1da487ead74d698cc5ea4eb729c35c8d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
@@ -185,6 +185,19 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective
|
||||
final CraftObjective other = (CraftObjective) obj;
|
||||
return !(this.objective != other.objective && (this.objective == null || !this.objective.equals(other.objective)));
|
||||
}
|
||||
+ // Paper start - add more score API
|
||||
+ @Override
|
||||
+ public boolean willAutoUpdateDisplay() {
|
||||
+ this.checkState();
|
||||
+ return this.objective.displayAutoUpdate();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setAutoUpdateDisplay(final boolean autoUpdateDisplay) {
|
||||
+ this.checkState();
|
||||
+ this.objective.setDisplayAutoUpdate(autoUpdateDisplay);
|
||||
+ }
|
||||
+ // Paper end - add more score API
|
||||
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
index ceb1a39c02c3cfa7632a0fdca414c7046888fcb1..74d9c407e971804bed420370f7b684d8658eb5aa 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
@@ -74,4 +74,44 @@ final class CraftScore implements Score {
|
||||
board.resetSinglePlayerScore(entry, this.objective.getHandle());
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Paper start - add more score API
|
||||
+ @Override
|
||||
+ public boolean isTriggerable() {
|
||||
+ if (this.objective.getTrackedCriteria() != org.bukkit.scoreboard.Criteria.TRIGGER) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ final Scoreboard board = this.objective.checkState().board;
|
||||
+ final ReadOnlyScoreInfo scoreInfo = board.getPlayerScoreInfo(this.entry, this.objective.getHandle());
|
||||
+ return scoreInfo != null && !scoreInfo.isLocked();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTriggerable(final boolean triggerable) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(this.objective.getTrackedCriteria() == org.bukkit.scoreboard.Criteria.TRIGGER, "the criteria isn't 'trigger'");
|
||||
+ final Scoreboard board = this.objective.checkState().board;
|
||||
+ if (triggerable) {
|
||||
+ board.getOrCreatePlayerScore(this.entry, this.objective.getHandle()).unlock();
|
||||
+ } else {
|
||||
+ board.getOrCreatePlayerScore(this.entry, this.objective.getHandle()).lock();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.kyori.adventure.text.Component customName() {
|
||||
+ final Scoreboard board = this.objective.checkState().board;
|
||||
+ final ReadOnlyScoreInfo scoreInfo = board.getPlayerScoreInfo(this.entry, this.objective.getHandle());
|
||||
+ if (scoreInfo == null) {
|
||||
+ return null; // If score doesn't exist, don't create one
|
||||
+ }
|
||||
+ final net.minecraft.network.chat.Component display = board.getOrCreatePlayerScore(this.entry, this.objective.getHandle()).display();
|
||||
+ return display == null ? null : io.papermc.paper.adventure.PaperAdventure.asAdventure(display);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void customName(final net.kyori.adventure.text.Component customName) {
|
||||
+ final Scoreboard board = this.objective.checkState().board;
|
||||
+ board.getOrCreatePlayerScore(this.entry, this.objective.getHandle()).display(io.papermc.paper.adventure.PaperAdventure.asVanilla(customName));
|
||||
+ }
|
||||
+ // Paper end - add more score API
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 20 Dec 2023 02:03:05 -0800
|
||||
Subject: [PATCH] Improve Registry
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
index a644309edb612d97da290f86a1ef6fe597c7d85d..3adf18d5e736abff701a4866ee1f8403aeafca84 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
@@ -143,6 +143,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
||||
|
||||
private final Class<?> bukkitClass; // Paper - relax preload class
|
||||
private final Map<NamespacedKey, B> cache = new HashMap<>();
|
||||
+ private final Map<B, NamespacedKey> byValue = new java.util.IdentityHashMap<>(); // Paper - improve Registry
|
||||
private final net.minecraft.core.Registry<M> minecraftRegistry;
|
||||
private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
|
||||
private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater; // Paper - rename to make it *clear* what it is *only* for
|
||||
@@ -191,6 +192,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
||||
}
|
||||
|
||||
this.cache.put(namespacedKey, bukkit);
|
||||
+ this.byValue.put(bukkit, namespacedKey); // Paper - improve Registry
|
||||
|
||||
return bukkit;
|
||||
}
|
||||
@@ -213,4 +215,11 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
||||
|
||||
return this.minecraftToBukkit.apply(namespacedKey, minecraft);
|
||||
}
|
||||
+
|
||||
+ // Paper start - improve Registry
|
||||
+ @Override
|
||||
+ public NamespacedKey getKey(final B value) {
|
||||
+ return this.byValue.get(value);
|
||||
+ }
|
||||
+ // Paper end - improve Registry
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java
|
||||
index cd3e35867075e65f46051fb88d8a2460a8bb4b53..76627683f256a034a147765db693a9fd2ab9613f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java
|
||||
@@ -54,6 +54,7 @@ public class CraftTrimMaterial implements TrimMaterial, Handleable<net.minecraft
|
||||
@Override
|
||||
@NotNull
|
||||
public NamespacedKey getKey() {
|
||||
+ if (true) return java.util.Objects.requireNonNull(org.bukkit.Registry.TRIM_MATERIAL.getKey(this), () -> this + " doesn't have a key"); // Paper
|
||||
return this.key;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java
|
||||
index 364f8d7a7106259401154d91b1b79869d014a469..f336bf98574e4fdeabc3b210629834393ec11a74 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java
|
||||
@@ -54,6 +54,7 @@ public class CraftTrimPattern implements TrimPattern, Handleable<net.minecraft.w
|
||||
@Override
|
||||
@NotNull
|
||||
public NamespacedKey getKey() {
|
||||
+ if (true) return java.util.Objects.requireNonNull(org.bukkit.Registry.TRIM_PATTERN.getKey(this), () -> this + " doesn't have a key"); // Paper
|
||||
return this.key;
|
||||
}
|
||||
|
||||
diff --git a/src/test/java/org/bukkit/registry/PerRegistryTest.java b/src/test/java/org/bukkit/registry/PerRegistryTest.java
|
||||
index 523b4b208e05c6b70014440200e3196cc84f36cc..12b93a6e091de47522d060fa0cd84fe41318c46a 100644
|
||||
--- a/src/test/java/org/bukkit/registry/PerRegistryTest.java
|
||||
+++ b/src/test/java/org/bukkit/registry/PerRegistryTest.java
|
||||
@@ -49,19 +49,22 @@ public class PerRegistryTest extends AbstractTestingBase {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
- public void testGet(Registry<?> registry) {
|
||||
+ public <T extends Keyed> void testGet(Registry<T> registry) { // Paper - improve Registry
|
||||
registry.forEach(element -> {
|
||||
+ NamespacedKey key = registry.getKey(element); // Paper - improve Registry
|
||||
+ assertNotNull(key); // Paper - improve Registry
|
||||
// Values in the registry should be referentially equal to what is returned with #get()
|
||||
// This ensures that new instances are not created each time #get() is invoked
|
||||
- assertSame(element, registry.get(element.getKey()));
|
||||
+ assertSame(element, registry.get(key)); // Paper - improve Registry
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
- public void testMatch(Registry<?> registry) {
|
||||
+ public <T extends Keyed> void testMatch(Registry<T> registry) { // Paper - improve Registry
|
||||
registry.forEach(element -> {
|
||||
- NamespacedKey key = element.getKey();
|
||||
+ NamespacedKey key = registry.getKey(element); // Paper - improve Registry
|
||||
+ assertNotNull(key); // Paper - improve Registry
|
||||
|
||||
this.assertSameMatchWithKeyMessage(registry, element, key.toString()); // namespace:key
|
||||
this.assertSameMatchWithKeyMessage(registry, element, key.getKey()); // key
|
||||
@@ -72,7 +75,7 @@ public class PerRegistryTest extends AbstractTestingBase {
|
||||
});
|
||||
}
|
||||
|
||||
- private void assertSameMatchWithKeyMessage(Registry<?> registry, Keyed element, String key) {
|
||||
+ private <T extends Keyed> void assertSameMatchWithKeyMessage(Registry<T> registry, T element, String key) { // Paper - improve Registry
|
||||
assertSame(element, registry.match(key), key);
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 9 Dec 2023 19:15:59 -0800
|
||||
Subject: [PATCH] Fix NPE on null loc for EntityTeleportEvent
|
||||
|
||||
EntityTeleportEvent#setTo is marked as nullable and so is the
|
||||
getTo method. This fixes the handling of a null "to" location
|
||||
by treating it the same as the event being cancelled. This is
|
||||
already existing behavior for the EntityPortalEvent (which
|
||||
extends EntityTeleportEvent).
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java
|
||||
index a306b30af19277386a2f3e560b4902a8b5796f2a..54851f6cc0d5fddb32a9a1e84a4f5ae41af18758 100644
|
||||
--- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java
|
||||
+++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java
|
||||
@@ -169,9 +169,10 @@ public class TeleportCommand {
|
||||
Location to = new Location(world.getWorld(), x, y, z, f2, f3);
|
||||
EntityTeleportEvent event = new EntityTeleportEvent(target.getBukkitEntity(), target.getBukkitEntity().getLocation(), to);
|
||||
world.getCraftServer().getPluginManager().callEvent(event);
|
||||
- if (event.isCancelled()) {
|
||||
+ if (event.isCancelled() || event.getTo() == null) { // Paper
|
||||
return;
|
||||
}
|
||||
+ to = event.getTo(); // Paper - actually track new location
|
||||
|
||||
x = to.getX();
|
||||
y = to.getY();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index cb07999629ba2d56602b3ae06ef06e350a8d1fb1..b7af45eac986097ef53fa90bb4edd67f8829f13c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -4173,7 +4173,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (!(this instanceof ServerPlayer)) {
|
||||
EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2));
|
||||
this.level().getCraftServer().getPluginManager().callEvent(teleport);
|
||||
- if (!teleport.isCancelled()) {
|
||||
+ if (!teleport.isCancelled() && teleport.getTo() != null) { // Paper
|
||||
Location to = teleport.getTo();
|
||||
this.teleportTo(to.getX(), to.getY(), to.getZ());
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
|
||||
index 8fa9282acd87132516329083f774345df3310cf2..edd29c2f4d0151d512618115a8fb4b7423171491 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
|
||||
@@ -130,7 +130,7 @@ public class FollowOwnerGoal extends Goal {
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D);
|
||||
- if (event.isCancelled()) {
|
||||
+ if (event.isCancelled() || event.getTo() == null) { // Paper
|
||||
return false;
|
||||
}
|
||||
Location to = event.getTo();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
||||
index c2005b86ac9ff6aa03ef7937c2b7a228addc4f01..bd6171d75fbf4a0debef3892d6f67356dc811b4d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
||||
@@ -415,7 +415,7 @@ public class Shulker extends AbstractGolem implements VariantHolder<Optional<Dye
|
||||
if (enumdirection != null) {
|
||||
// CraftBukkit start
|
||||
EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ());
|
||||
- if (teleportEvent.isCancelled()) {
|
||||
+ if (teleportEvent.isCancelled() || teleportEvent.getTo() == null) { // Paper
|
||||
return false;
|
||||
} else {
|
||||
blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo());
|
|
@ -1,73 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lukas Planz <lukas.planz@web.de>
|
||||
Date: Tue, 5 Sep 2023 20:34:20 +0200
|
||||
Subject: [PATCH] Add experience points API
|
||||
|
||||
|
||||
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 77624e34143dc37ca3b523a81b9a041ffb3199bd..32f6c029bf2f9a16d48ac73ff217c7462c64f175 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1855,7 +1855,7 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
|
||||
public int getXpNeededForNextLevel() {
|
||||
- return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
|
||||
+ return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); // Paper - diff on change; calculateTotalExperiencePoints
|
||||
}
|
||||
// Paper start - send while respecting visibility
|
||||
private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index e9bd24861bca4554898306117bb533d19171cedf..68a0b6b8650e9e80e8e8c4037d92389cae899d72 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -1902,6 +1902,49 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
Preconditions.checkArgument(exp >= 0, "Total experience points must not be negative (%s)", exp);
|
||||
this.getHandle().totalExperience = exp;
|
||||
}
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int calculateTotalExperiencePoints() {
|
||||
+ return calculateTotalExperiencePoints(this.getLevel()) + Math.round(this.getExperiencePointsNeededForNextLevel() * getExp());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setExperienceLevelAndProgress(final int totalExperience) {
|
||||
+ Preconditions.checkArgument(totalExperience >= 0, "Total experience points must not be negative (%s)", totalExperience);
|
||||
+ int level = calculateLevelsForExperiencePoints(totalExperience);
|
||||
+ int remainingPoints = totalExperience - calculateTotalExperiencePoints(level);
|
||||
+
|
||||
+ this.getHandle().experienceLevel = level;
|
||||
+ this.getHandle().experienceProgress = (float) remainingPoints / this.getExperiencePointsNeededForNextLevel();
|
||||
+ this.getHandle().lastSentExp = -1;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getExperiencePointsNeededForNextLevel() {
|
||||
+ return this.getHandle().getXpNeededForNextLevel();
|
||||
+ }
|
||||
+
|
||||
+ // See https://minecraft.wiki/w/Experience#Leveling_up for reference
|
||||
+ private int calculateTotalExperiencePoints(int level) {
|
||||
+ if (level <= 16) {
|
||||
+ return (int) (Math.pow(level, 2) + 6 * level);
|
||||
+ } else if (level <= 31) {
|
||||
+ return (int) (2.5 * Math.pow(level, 2) - 40.5 * level + 360.0);
|
||||
+ } else {
|
||||
+ return (int) (4.5 * Math.pow(level, 2) - 162.5 * level + 2220.0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private int calculateLevelsForExperiencePoints(int points) {
|
||||
+ if (points <= 352) { // Level 0-16
|
||||
+ return (int) Math.floor(Math.sqrt(points + 9) - 3);
|
||||
+ } else if (points <= 1507) { // Level 17-31
|
||||
+ return (int) Math.floor(8.1 + Math.sqrt(0.4 * (points - (7839.0 / 40.0))));
|
||||
+ } else { // 32+
|
||||
+ return (int) Math.floor((325.0 / 18.0) + Math.sqrt((2.0 / 9.0) * (points - (54215.0 / 72.0))));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void sendExperienceChange(float progress) {
|
|
@ -1,368 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 18 May 2021 12:32:02 -0700
|
||||
Subject: [PATCH] Add drops to shear events
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
index fbed5d57db0c0e79996f85571b9af0071fa953c7..a024c697a65bbab27408da1d6a75e531d9719b47 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
@@ -104,11 +104,14 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
|
||||
if (entityliving instanceof Shearable ishearable) {
|
||||
if (ishearable.readyForShearing()) {
|
||||
// CraftBukkit start
|
||||
- if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) {
|
||||
+ // Paper start - Add drops to shear events
|
||||
+ org.bukkit.event.block.BlockShearEntityEvent event = CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem, ishearable.generateDefaultDrops());
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Paper end - Add drops to shear events
|
||||
continue;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- ishearable.shear(SoundSource.BLOCKS);
|
||||
+ ishearable.shear(SoundSource.BLOCKS, CraftItemStack.asNMSCopy(event.getDrops())); // Paper - Add drops to shear events
|
||||
worldserver.gameEvent((Entity) null, (Holder) GameEvent.SHEAR, blockposition);
|
||||
return true;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Shearable.java b/src/main/java/net/minecraft/world/entity/Shearable.java
|
||||
index 5e8cc5cfac8888628c6d513148f41be09ca65a2c..2ee48ac3b665db2b02bcb1a30ec972d43a3725b0 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Shearable.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Shearable.java
|
||||
@@ -3,7 +3,13 @@ package net.minecraft.world.entity;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
|
||||
public interface Shearable {
|
||||
+ default void shear(SoundSource soundCategory, java.util.List<net.minecraft.world.item.ItemStack> drops) { this.shear(soundCategory); } // Paper - Add drops to shear events
|
||||
void shear(SoundSource shearedSoundCategory);
|
||||
|
||||
boolean readyForShearing();
|
||||
+ // Paper start - custom shear drops; ensure all implementing entities override this
|
||||
+ default java.util.List<net.minecraft.world.item.ItemStack> generateDefaultDrops() {
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ // Paper end - custom shear drops
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
index aa125e3043b120935aaa015803f065f99eb8d050..0c21959f57ae88fcd0a4d6dc911c1ce347c96528 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
@@ -123,11 +123,18 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
||||
return InteractionResult.sidedSuccess(this.level().isClientSide);
|
||||
} else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) {
|
||||
- return InteractionResult.PASS;
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops();
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
}
|
||||
+ // Paper end - custom shear drops
|
||||
// CraftBukkit end
|
||||
- this.shear(SoundSource.PLAYERS);
|
||||
+ this.shear(SoundSource.PLAYERS, drops); // Paper - custom shear drops
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
if (!this.level().isClientSide) {
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
@@ -164,6 +171,22 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
||||
|
||||
@Override
|
||||
public void shear(SoundSource shearedSoundCategory) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(shearedSoundCategory, this.generateDefaultDrops());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops() {
|
||||
+ java.util.List<ItemStack> dropEntities = new java.util.ArrayList<>(5);
|
||||
+ for (int i = 0; i < 5; ++i) {
|
||||
+ dropEntities.add(new ItemStack(this.getVariant().getBlockState().getBlock()));
|
||||
+ }
|
||||
+ return dropEntities;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(SoundSource shearedSoundCategory, java.util.List<ItemStack> drops) { // If drops is null, need to generate drops
|
||||
+ // Paper end - custom shear drops
|
||||
this.level().playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
if (!this.level().isClientSide()) {
|
||||
Cow entitycow = (Cow) EntityType.COW.create(this.level());
|
||||
@@ -193,17 +216,12 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
||||
this.discard(EntityRemoveEvent.Cause.TRANSFORMATION); // CraftBukkit - from above and add Bukkit remove cause
|
||||
// CraftBukkit end
|
||||
|
||||
- for (int i = 0; i < 5; ++i) {
|
||||
- // CraftBukkit start
|
||||
- ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock()));
|
||||
- EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
|
||||
- Bukkit.getPluginManager().callEvent(event);
|
||||
- if (event.isCancelled()) {
|
||||
- continue;
|
||||
- }
|
||||
- this.level().addFreshEntity(entityitem);
|
||||
- // CraftBukkit end
|
||||
+ // Paper start - custom shear drops; moved drop generation to separate method
|
||||
+ for (final ItemStack drop : drops) {
|
||||
+ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), drop);
|
||||
+ this.spawnAtLocation(entityitem);
|
||||
}
|
||||
+ // Paper end - custom shear drops
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
||||
index 784a89f39e0b243e2968dca33b60ae40e58d824e..3ce86f952a18cae7fda1903916903b31a63a40b4 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
||||
@@ -258,11 +258,18 @@ public class Sheep extends Animal implements Shearable {
|
||||
if (itemstack.is(Items.SHEARS)) {
|
||||
if (!this.level().isClientSide && this.readyForShearing()) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) {
|
||||
- return InteractionResult.PASS;
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops();
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
}
|
||||
+ // Paper end - custom shear drops
|
||||
// CraftBukkit end
|
||||
- this.shear(SoundSource.PLAYERS);
|
||||
+ this.shear(SoundSource.PLAYERS, drops); // Paper
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -276,13 +283,30 @@ public class Sheep extends Animal implements Shearable {
|
||||
|
||||
@Override
|
||||
public void shear(SoundSource shearedSoundCategory) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(shearedSoundCategory, this.generateDefaultDrops());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops() {
|
||||
+ int count = 1 + this.random.nextInt(3);
|
||||
+ java.util.List<ItemStack> dropEntities = new java.util.ArrayList<>(count);
|
||||
+ for (int j = 0; j < count; ++j) {
|
||||
+ dropEntities.add(new ItemStack(Sheep.ITEM_BY_DYE.get(this.getColor())));
|
||||
+ }
|
||||
+ return dropEntities;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(SoundSource shearedSoundCategory, java.util.List<ItemStack> drops) {
|
||||
+ // Paper end - custom shear drops
|
||||
this.level().playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
this.setSheared(true);
|
||||
int i = 1 + this.random.nextInt(3);
|
||||
|
||||
- for (int j = 0; j < i; ++j) {
|
||||
+ for (final ItemStack drop : drops) { // Paper - custom shear drops (moved drop generation to separate method)
|
||||
this.forceDrops = true; // CraftBukkit
|
||||
- ItemEntity entityitem = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.getColor()), 1);
|
||||
+ ItemEntity entityitem = this.spawnAtLocation(drop, 1); // Paper - custom shear drops
|
||||
this.forceDrops = false; // CraftBukkit
|
||||
|
||||
if (entityitem != null) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
index 2de1a2f666da9db1832907e1651dbff948e37252..5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
@@ -146,11 +146,18 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
||||
|
||||
if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
// CraftBukkit start
|
||||
- if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) {
|
||||
- return InteractionResult.PASS;
|
||||
+ // Paper start - custom shear drops
|
||||
+ java.util.List<ItemStack> drops = this.generateDefaultDrops();
|
||||
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
}
|
||||
+ // Paper end - custom shear drops
|
||||
// CraftBukkit end
|
||||
- this.shear(SoundSource.PLAYERS);
|
||||
+ this.shear(SoundSource.PLAYERS, drops); // Paper
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
if (!this.level().isClientSide) {
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
@@ -164,12 +171,28 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
||||
|
||||
@Override
|
||||
public void shear(SoundSource shearedSoundCategory) {
|
||||
+ // Paper start - custom shear drops
|
||||
+ this.shear(shearedSoundCategory, this.generateDefaultDrops());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops() {
|
||||
+ return java.util.Collections.singletonList(new ItemStack(Items.CARVED_PUMPKIN));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(SoundSource shearedSoundCategory, java.util.List<ItemStack> drops) {
|
||||
+ // Paper end - custom shear drops
|
||||
this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
if (!this.level().isClientSide()) {
|
||||
this.setPumpkin(false);
|
||||
- this.forceDrops = true; // CraftBukkit
|
||||
- this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), this.getEyeHeight());
|
||||
- this.forceDrops = false; // CraftBukkit
|
||||
+ // Paper start - custom shear drops (moved drop generation to separate method)
|
||||
+ for (final ItemStack drop : drops) {
|
||||
+ this.forceDrops = true;
|
||||
+ this.spawnAtLocation(drop, this.getEyeHeight());
|
||||
+ this.forceDrops = false;
|
||||
+ }
|
||||
+ // Paper end - custom shear drops
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
||||
index 9c0bfddd479eef688d2509ad700371c3c860ff1a..e9f9b041ae7195e9d23bd446454b1d8c47a1ace1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
||||
@@ -135,6 +135,15 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
||||
}
|
||||
|
||||
private void spawnShearedMushrooms() {
|
||||
+ // Paper start - shear drops API
|
||||
+ this.generateShearedMushrooms(stack -> {
|
||||
+ this.forceDrops = true;
|
||||
+ this.spawnAtLocation(stack);
|
||||
+ this.forceDrops = false;
|
||||
+ });
|
||||
+ }
|
||||
+ private void generateShearedMushrooms(java.util.function.Consumer<ItemStack> stackConsumer) {
|
||||
+ // Paper end - shear drops API
|
||||
if (this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
LootTable lootTable = serverLevel.getServer().reloadableRegistries().getLootTable(BuiltInLootTables.BOGGED_SHEAR);
|
||||
LootParams lootParams = new LootParams.Builder(serverLevel)
|
||||
@@ -143,11 +152,20 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
||||
.create(LootContextParamSets.SHEARING);
|
||||
|
||||
for (ItemStack itemStack : lootTable.getRandomItems(lootParams)) {
|
||||
- this.spawnAtLocation(itemStack);
|
||||
+ stackConsumer.accept(itemStack); // Paper
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - shear drops API
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> generateDefaultDrops() {
|
||||
+ final java.util.List<ItemStack> drops = new java.util.ArrayList<>();
|
||||
+ this.generateShearedMushrooms(drops::add);
|
||||
+ return drops;
|
||||
+ }
|
||||
+ // Paper end - shear drops API
|
||||
+
|
||||
@Override
|
||||
public boolean readyForShearing() {
|
||||
return !this.isSheared() && this.isAlive();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 8b322ade83e8e571af7c2e91a3c0d0784a7b9fad..e20feab675d05ae5b5b19870546585936c757970 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1666,20 +1666,20 @@ public class CraftEventFactory {
|
||||
player.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
|
||||
- public static BlockShearEntityEvent callBlockShearEntityEvent(Entity animal, org.bukkit.block.Block dispenser, CraftItemStack is) {
|
||||
- BlockShearEntityEvent bse = new BlockShearEntityEvent(dispenser, animal.getBukkitEntity(), is);
|
||||
+ public static BlockShearEntityEvent callBlockShearEntityEvent(Entity animal, org.bukkit.block.Block dispenser, CraftItemStack is, List<ItemStack> drops) { // Paper - custom shear drops
|
||||
+ BlockShearEntityEvent bse = new BlockShearEntityEvent(dispenser, animal.getBukkitEntity(), is, Lists.transform(drops, CraftItemStack::asCraftMirror)); // Paper - custom shear drops
|
||||
Bukkit.getPluginManager().callEvent(bse);
|
||||
return bse;
|
||||
}
|
||||
|
||||
- public static boolean handlePlayerShearEntityEvent(net.minecraft.world.entity.player.Player player, Entity sheared, ItemStack shears, InteractionHand hand) {
|
||||
+ public static PlayerShearEntityEvent handlePlayerShearEntityEvent(net.minecraft.world.entity.player.Player player, Entity sheared, ItemStack shears, InteractionHand hand, List<ItemStack> drops) { // Paper - custom shear drops
|
||||
if (!(player instanceof ServerPlayer)) {
|
||||
- return true;
|
||||
+ return null; // Paper - custom shear drops
|
||||
}
|
||||
|
||||
- PlayerShearEntityEvent event = new PlayerShearEntityEvent((Player) player.getBukkitEntity(), sheared.getBukkitEntity(), CraftItemStack.asCraftMirror(shears), (hand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND));
|
||||
+ PlayerShearEntityEvent event = new PlayerShearEntityEvent((Player) player.getBukkitEntity(), sheared.getBukkitEntity(), CraftItemStack.asCraftMirror(shears), (hand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), Lists.transform(drops, CraftItemStack::asCraftMirror)); // Paper - custom shear drops
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
- return !event.isCancelled();
|
||||
+ return event; // Paper - custom shear drops
|
||||
}
|
||||
|
||||
public static Cancellable handleStatisticsIncrease(net.minecraft.world.entity.player.Player entityHuman, net.minecraft.stats.Stat<?> statistic, int current, int newValue) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index 776437ae42865baccab4fb5d3f2715c8f0519b8a..520b637e0f281d3d3018681ec7b48b06c47f621e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -65,6 +65,16 @@ public final class CraftItemStack extends ItemStack {
|
||||
return stack;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static java.util.List<net.minecraft.world.item.ItemStack> asNMSCopy(java.util.List<? extends ItemStack> originals) {
|
||||
+ final java.util.List<net.minecraft.world.item.ItemStack> items = new java.util.ArrayList<>(originals.size());
|
||||
+ for (final ItemStack original : originals) {
|
||||
+ items.add(asNMSCopy(original));
|
||||
+ }
|
||||
+ return items;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static net.minecraft.world.item.ItemStack copyNMSStack(net.minecraft.world.item.ItemStack original, int amount) {
|
||||
net.minecraft.world.item.ItemStack stack = original.copy();
|
||||
stack.setCount(amount);
|
||||
diff --git a/src/test/java/io/papermc/paper/entity/ShearableDropsTest.java b/src/test/java/io/papermc/paper/entity/ShearableDropsTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e612515f7709dbe5d1fa5751337cdc34fce10a98
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/entity/ShearableDropsTest.java
|
||||
@@ -0,0 +1,34 @@
|
||||
+package io.papermc.paper.entity;
|
||||
+
|
||||
+import io.github.classgraph.ClassGraph;
|
||||
+import io.github.classgraph.ClassInfo;
|
||||
+import io.github.classgraph.MethodInfoList;
|
||||
+import io.github.classgraph.ScanResult;
|
||||
+import java.util.ArrayList;
|
||||
+import net.minecraft.world.entity.Shearable;
|
||||
+import org.bukkit.support.AbstractTestingBase;
|
||||
+import org.junit.jupiter.params.ParameterizedTest;
|
||||
+import org.junit.jupiter.params.provider.MethodSource;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+
|
||||
+class ShearableDropsTest extends AbstractTestingBase {
|
||||
+
|
||||
+ static Iterable<ClassInfo> parameters() {
|
||||
+ try (ScanResult scanResult = new ClassGraph()
|
||||
+ .enableClassInfo()
|
||||
+ .enableMethodInfo()
|
||||
+ .whitelistPackages("net.minecraft")
|
||||
+ .scan()
|
||||
+ ) {
|
||||
+ return new ArrayList<>(scanResult.getClassesImplementing(Shearable.class.getName()));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ParameterizedTest
|
||||
+ @MethodSource("parameters")
|
||||
+ void checkShearableDropOverrides(final ClassInfo classInfo) {
|
||||
+ final MethodInfoList generateDefaultDrops = classInfo.getDeclaredMethodInfo("generateDefaultDrops");
|
||||
+ assertEquals(1, generateDefaultDrops.size(), classInfo.getName() + " doesn't implement Shearable#generateDefaultDrops");
|
||||
+ }
|
||||
+}
|
|
@ -1,53 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cryptite <cryptite@gmail.com>
|
||||
Date: Mon, 1 May 2023 16:22:43 -0500
|
||||
Subject: [PATCH] Add PlayerShieldDisableEvent
|
||||
|
||||
Called whenever a players shield is disabled. This is mainly caused by
|
||||
attacking players or monsters that carry axes.
|
||||
|
||||
The event, while similar to the PlayerItemCooldownEvent, offers other
|
||||
behaviour and can hence not be implemented as a childtype of said event.
|
||||
Specifically, cancelling the event prevents the game events from being
|
||||
sent to the player.
|
||||
|
||||
Plugins listening to just the PlayerItemCooldownEvent may not want said
|
||||
sideeffects, meaning the disable event cannot share a handlerlist with
|
||||
the cooldown event
|
||||
|
||||
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 32f6c029bf2f9a16d48ac73ff217c7462c64f175..9952da86af1a1a050e7485675ca2d6fb83d02422 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -989,7 +989,7 @@ public abstract class Player extends LivingEntity {
|
||||
protected void blockUsingShield(LivingEntity attacker) {
|
||||
super.blockUsingShield(attacker);
|
||||
if (attacker.canDisableShield()) {
|
||||
- this.disableShield();
|
||||
+ this.disableShield(attacker); // Paper - Add PlayerShieldDisableEvent
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1473,8 +1473,21 @@ public abstract class Player extends LivingEntity {
|
||||
this.attack(target);
|
||||
}
|
||||
|
||||
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - Add PlayerShieldDisableEvent
|
||||
public void disableShield() {
|
||||
- this.getCooldowns().addCooldown(Items.SHIELD, 100);
|
||||
+ // Paper start - Add PlayerShieldDisableEvent
|
||||
+ this.disableShield(null);
|
||||
+ }
|
||||
+ public void disableShield(@Nullable LivingEntity attacker) {
|
||||
+ final org.bukkit.entity.Entity finalAttacker = attacker != null ? attacker.getBukkitEntity() : null;
|
||||
+ if (finalAttacker != null) {
|
||||
+ final io.papermc.paper.event.player.PlayerShieldDisableEvent shieldDisableEvent = new io.papermc.paper.event.player.PlayerShieldDisableEvent((org.bukkit.entity.Player) getBukkitEntity(), finalAttacker, 100);
|
||||
+ if (!shieldDisableEvent.callEvent()) return;
|
||||
+ this.getCooldowns().addCooldown(Items.SHIELD, shieldDisableEvent.getCooldown());
|
||||
+ } else {
|
||||
+ this.getCooldowns().addCooldown(Items.SHIELD, 100);
|
||||
+ }
|
||||
+ // Paper end - Add PlayerShieldDisableEvent
|
||||
this.stopUsingItem();
|
||||
this.level().broadcastEntityEvent(this, (byte) 30);
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Thu, 4 Jan 2024 13:49:14 +0100
|
||||
Subject: [PATCH] Validate ResourceLocation in NBT reading
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java
|
||||
index 1d7c20fe14882fdeddf315a8923669e3385652f5..f88dd37783b3c155c23b547c360b8d3c16e030c0 100644
|
||||
--- a/src/main/java/net/minecraft/nbt/NbtUtils.java
|
||||
+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java
|
||||
@@ -149,8 +149,10 @@ public final class NbtUtils {
|
||||
if (!nbt.contains("Name", 8)) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
} else {
|
||||
- ResourceLocation resourceLocation = new ResourceLocation(nbt.getString("Name"));
|
||||
- Optional<? extends Holder<Block>> optional = blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation));
|
||||
+ // Paper start - Validate resource location
|
||||
+ ResourceLocation resourceLocation = ResourceLocation.tryParse(nbt.getString("Name"));
|
||||
+ Optional<? extends Holder<Block>> optional = resourceLocation != null ? blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty();
|
||||
+ // Paper end - Validate resource location
|
||||
if (optional.isEmpty()) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/resources/ResourceLocation.java b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
index d93b623ce973b63d4f3a77bfe459f51af7cb3c1c..2c4553312f2f37f8613ac813708b4b95f9675e9f 100644
|
||||
--- a/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
+++ b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
@@ -37,6 +37,13 @@ public class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
private final String path;
|
||||
|
||||
protected ResourceLocation(String namespace, String path, @Nullable ResourceLocation.Dummy extraData) {
|
||||
+ // Paper start - Validate ResourceLocation
|
||||
+ // Check for the max network string length (capped at Short.MAX_VALUE) as well as the max bytes of a StringTag (length written as an unsigned short)
|
||||
+ final String resourceLocation = namespace + ":" + path;
|
||||
+ if (resourceLocation.length() > Short.MAX_VALUE || io.netty.buffer.ByteBufUtil.utf8MaxBytes(resourceLocation) > 2 * Short.MAX_VALUE + 1) {
|
||||
+ throw new ResourceLocationException("Resource location too long: " + resourceLocation);
|
||||
+ }
|
||||
+ // Paper end - Validate ResourceLocation
|
||||
this.namespace = namespace;
|
||||
this.path = path;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/RandomizableContainer.java b/src/main/java/net/minecraft/world/RandomizableContainer.java
|
||||
index 68fadc351464dde459eb4cc86660cf9add40d04e..a9a80f8bc4a6f250fe3c20482c395058f024fabd 100644
|
||||
--- a/src/main/java/net/minecraft/world/RandomizableContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/RandomizableContainer.java
|
||||
@@ -50,7 +50,7 @@ public interface RandomizableContainer extends Container {
|
||||
|
||||
default boolean tryLoadLootTable(CompoundTag nbt) {
|
||||
if (nbt.contains("LootTable", 8)) {
|
||||
- this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("LootTable"))));
|
||||
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
|
||||
if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(nbt); // Paper - LootTable API
|
||||
if (nbt.contains("LootTableSeed", 4)) {
|
||||
this.setLootTableSeed(nbt.getLong("LootTableSeed"));
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
index 8c7cc9c5af0b8d8bef9b6e2d3d3e723cd76f3212..56b51096ca4147363a843accf6ef2510f05e8f1a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
@@ -623,7 +623,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
}
|
||||
|
||||
public static Optional<EntityType<?>> by(CompoundTag nbt) {
|
||||
- return BuiltInRegistries.ENTITY_TYPE.getOptional(new ResourceLocation(nbt.getString("id")));
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(nbt.getString("id"))); // Paper - Validate ResourceLocation
|
||||
}
|
||||
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index b7af45eac986097ef53fa90bb4edd67f8829f13c..958b25e62b040943c346114ef19d56104ae0a844 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -911,12 +911,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
if (nbt.contains("SleepingX", 99) && nbt.contains("SleepingY", 99) && nbt.contains("SleepingZ", 99)) {
|
||||
BlockPos blockposition = new BlockPos(nbt.getInt("SleepingX"), nbt.getInt("SleepingY"), nbt.getInt("SleepingZ"));
|
||||
-
|
||||
+ if (this.position().distanceToSqr(blockposition.getX(), blockposition.getY(), blockposition.getZ()) < 16 * 16) { // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
|
||||
this.setSleepingPos(blockposition);
|
||||
this.entityData.set(LivingEntity.DATA_POSE, Pose.SLEEPING);
|
||||
if (!this.firstTick) {
|
||||
this.setPosToBed(blockposition);
|
||||
}
|
||||
+ } // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
|
||||
}
|
||||
|
||||
if (nbt.contains("Brain", 10)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index 5581fd6656fc13ea1d036d6caab2aba39c5320ac..748a6d81f409cf91a7aa2c88ded04f1d428cf0f6 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -645,7 +645,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
|
||||
|
||||
this.setLeftHanded(nbt.getBoolean("LeftHanded"));
|
||||
if (nbt.contains("DeathLootTable", 8)) {
|
||||
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("DeathLootTable")));
|
||||
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("DeathLootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
|
||||
this.lootTableSeed = nbt.getLong("DeathLootTableSeed");
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
index f1bf129aecb6840d79c537338e4057557f07790b..5bc4ba7c055992a32197db96d86a3906c11900d8 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
@@ -561,7 +561,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
this.setCritArrow(nbt.getBoolean("crit"));
|
||||
this.setPierceLevel(nbt.getByte("PierceLevel"));
|
||||
if (nbt.contains("SoundEvent", 8)) {
|
||||
- this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(new ResourceLocation(nbt.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent());
|
||||
+ this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(ResourceLocation.tryParse(nbt.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent()); // Paper - Validate resource location
|
||||
}
|
||||
|
||||
this.setShotFromCrossbow(nbt.getBoolean("ShotFromCrossbow"));
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index d976a6e3a79a01392a5033b05864d82782a30916..845eff7401b811c179dc9dee70eca0d724be5c80 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -73,7 +73,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
default void readChestVehicleSaveData(CompoundTag nbt, HolderLookup.Provider registriesLookup) {
|
||||
this.clearItemStacks();
|
||||
if (nbt.contains("LootTable", 8)) {
|
||||
- this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("LootTable"))));
|
||||
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
|
||||
// Paper start - LootTable API
|
||||
if (this.getLootTable() != null) {
|
||||
this.lootableData().loadNbt(nbt);
|
||||
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 f40b2582d9087f9dbb5cab950304698f33fdd879..a99fe191c429bb528209dd0f31b509acf9cccbb5 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
|
||||
@@ -295,7 +295,12 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
while (iterator.hasNext()) {
|
||||
String s = (String) iterator.next();
|
||||
|
||||
- this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s));
|
||||
+ // Paper start - Validate ResourceLocation
|
||||
+ final ResourceLocation resourceLocation = ResourceLocation.tryParse(s);
|
||||
+ if (resourceLocation != null) {
|
||||
+ this.recipesUsed.put(resourceLocation, nbttagcompound1.getInt(s));
|
||||
+ }
|
||||
+ // Paper end - Validate ResourceLocation
|
||||
}
|
||||
|
||||
// Paper start - cook speed multiplier API
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
index f78a9698afc87408fc46de2d3d00c923500885f4..dc02a3d84b397f634f77f4df9c06e245cc4dcb75 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
@@ -202,7 +202,7 @@ public class BrushableBlockEntity extends BlockEntity {
|
||||
|
||||
private boolean tryLoadLootTable(CompoundTag nbt) {
|
||||
if (nbt.contains("LootTable", 8)) {
|
||||
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("LootTable")));
|
||||
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
|
||||
this.lootTableSeed = nbt.getLong("LootTableSeed");
|
||||
return true;
|
||||
} else {
|
|
@ -1,94 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sat, 30 Dec 2023 15:00:06 -0500
|
||||
Subject: [PATCH] Properly handle experience dropping on block break
|
||||
|
||||
This causes spawnAfterBreak to spawn xp by default, removing the need to manually add xp wherever this method is used.
|
||||
For classes that use custom xp amounts, they can drop the resources with disabling
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 2f018922fb12dc4c3c9c28c7b0597a2b97d1cb02..51c4877ffb77ece41e90d9c6ac06c04dc941e35c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -618,7 +618,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (drop) {
|
||||
BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
|
||||
|
||||
- Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY);
|
||||
+ Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
|
||||
+ iblockdata.getBlock().popExperience((ServerLevel) this, pos, xp, breakingEntity); // Paper - Properly handle xp dropping; custom amount
|
||||
}
|
||||
|
||||
boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
index a757a45d423e1729c9374391df4186ae0522e1ac..7f0c0ca49e7575c18935b71e3180d112440289f7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
@@ -313,23 +313,31 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
for (ItemStack drop : Block.getDrops(state, serverLevel, pos, blockEntity)) {
|
||||
items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
|
||||
}
|
||||
+ Block block = state.getBlock(); // Paper - Properly handle xp dropping
|
||||
io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, pos), org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, source), items);
|
||||
+ event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
|
||||
event.callEvent();
|
||||
for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
|
||||
popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
|
||||
}
|
||||
- state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
|
||||
+ state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
|
||||
+ block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Paper end - Add BlockBreakBlockEvent
|
||||
|
||||
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
|
||||
+ // Paper start - Properly handle xp dropping
|
||||
+ dropResources(state, world, pos, blockEntity, entity, tool, true);
|
||||
+ }
|
||||
+ public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) {
|
||||
+ // Paper end - Properly handle xp dropping
|
||||
if (world instanceof ServerLevel) {
|
||||
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
|
||||
Block.popResource(world, pos, itemstack1);
|
||||
});
|
||||
- state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
|
||||
+ state.spawnAfterBreak((ServerLevel) world, pos, tool, dropExperience); // Paper - Properly handle xp dropping
|
||||
}
|
||||
|
||||
}
|
||||
@@ -413,7 +421,7 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
player.awardStat(Stats.BLOCK_MINED.get(this));
|
||||
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
|
||||
if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion
|
||||
- Block.dropResources(state, world, pos, blockEntity, player, tool);
|
||||
+ Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper - Properly handle xp dropping
|
||||
} // Paper - fix drops not preventing stats/food exhaustion
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index c762a006b3f586b32209c20e85f6b8bf169dbd06..f87d9cb38caf3bf92fd32f2118f76799ede418db 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -1118,6 +1118,7 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
|
||||
public void spawnAfterBreak(ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
|
||||
this.getBlock().spawnAfterBreak(this.asState(), world, pos, tool, dropExperience);
|
||||
+ if (dropExperience) {getBlock().popExperience(world, pos, this.getBlock().getExpDrop(asState(), world, pos, tool, true));} // Paper - Properly handle xp dropping
|
||||
}
|
||||
|
||||
public List<ItemStack> getDrops(LootParams.Builder builder) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index 461a66c323a74db5a70981fafc5fa20f54f0f40d..ac11f18690434922179b61ffcc3036dea025b0cb 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -509,7 +509,7 @@ public class CraftBlock implements Block {
|
||||
|
||||
// Modelled off EntityHuman#hasBlock
|
||||
if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
|
||||
- net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem);
|
||||
+ net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem, false); // Paper - Properly handle xp dropping
|
||||
// Paper start - improve Block#breanNaturally
|
||||
if (triggerEffect) {
|
||||
if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
|
|
@ -1,170 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Sat, 6 Jan 2024 14:31:00 +0100
|
||||
Subject: [PATCH] Fixup NamespacedKey handling
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
|
||||
index 4f3f6ea43030853bd9df067358a1f4d16c40e6d4..531336c44c46555fef8c001fe8ca00c93624ad42 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
|
||||
@@ -171,12 +171,28 @@ public class LoomMenu extends AbstractContainerMenu {
|
||||
return stillValid(this.access, player, Blocks.LOOM);
|
||||
}
|
||||
|
||||
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper - handle custom banner pattern, skip the event
|
||||
+ private static boolean PRINTED_PATTERN_TYPE_NAG = false; // Paper - handle custom banner pattern, skip the event
|
||||
+
|
||||
@Override
|
||||
public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) {
|
||||
if (id >= 0 && id < this.selectablePatterns.size()) {
|
||||
+ // Paper start - handle custom banner pattern, skip the event (todo remove once this is supported)
|
||||
+ java.util.Optional<org.bukkit.block.banner.PatternType> patternType = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.BANNER_PATTERN, this.selectablePatterns.get(id));
|
||||
+ if (patternType.isEmpty()) {
|
||||
+ if (!PRINTED_PATTERN_TYPE_NAG) {
|
||||
+ LOGGER.warn("A datapack added a custom banner pattern, those are not supported yet in the API, skipping the PlayerLoomPatternSelectEvent for {}.", player.getScoreboardName());
|
||||
+ PRINTED_PATTERN_TYPE_NAG = true;
|
||||
+ }
|
||||
+ this.selectedBannerPatternIndex.set(id);
|
||||
+ this.setupResultSlot((Holder) this.selectablePatterns.get(id));
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - handle custom banner pattern
|
||||
+
|
||||
// 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.craftbukkit.block.banner.CraftPatternType.minecraftHolderToBukkit((this.selectablePatterns.get(selectablePatternIndex))));
|
||||
+ io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), patternType.get());
|
||||
if (!event.callEvent()) {
|
||||
player.containerMenu.sendAllDataToRemote();
|
||||
return false;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
|
||||
index 209c6b64e79c29ea3bb84ddbe89a8bff66f81d0f..1f90f4b3f310b8cf5750c3a581be178f19b979d2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
|
||||
@@ -38,7 +38,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
|
||||
}
|
||||
|
||||
public static org.bukkit.loot.LootTable minecraftToBukkit(ResourceKey<LootTable> minecraft) {
|
||||
- return (minecraft == null) ? null : Bukkit.getLootTable(CraftLootTable.minecraftToBukkitKey(minecraft));
|
||||
+ return (minecraft == null || minecraft.location().getPath().isEmpty()) ? null : Bukkit.getLootTable(CraftLootTable.minecraftToBukkitKey(minecraft)); // Paper - fix some NamespacedKey parsing
|
||||
}
|
||||
|
||||
public static NamespacedKey minecraftToBukkitKey(ResourceKey<LootTable> minecraft) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
index 3adf18d5e736abff701a4866ee1f8403aeafca84..4a5778d1751b774c825bbce0e870e2998278afe3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
@@ -110,6 +110,16 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
||||
+ ", this can happen if a plugin creates its own registry entry with out properly registering it.");
|
||||
}
|
||||
|
||||
+ // Paper start - fixup upstream being dum
|
||||
+ public static <T extends org.bukkit.Keyed, M> java.util.Optional<T> unwrapAndConvertHolder(final io.papermc.paper.registry.RegistryKey<T> registryKey, final Holder<M> value) {
|
||||
+ return unwrapAndConvertHolder(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(registryKey), value);
|
||||
+ }
|
||||
+
|
||||
+ public static <T extends org.bukkit.Keyed, M> java.util.Optional<T> unwrapAndConvertHolder(final Registry<T> registry, final Holder<M> value) {
|
||||
+ return value.unwrapKey().map(key -> registry.get(CraftNamespacedKey.fromMinecraft(key.location())));
|
||||
+ }
|
||||
+ // Paper end - fixup upstream being dum
|
||||
+
|
||||
// Paper - move to PaperRegistries
|
||||
|
||||
// Paper - NOTE: As long as all uses of the method below relate to *serialization* via ConfigurationSerializable, it's fine
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java
|
||||
index cc97638e038ea64ad180ebfded2528aa07d1809e..10e4318782107644f67818109784fff60d017e0a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java
|
||||
@@ -37,6 +37,7 @@ public class CraftAttribute {
|
||||
string = FieldRename.convertAttributeName(ApiVersion.CURRENT, string);
|
||||
string = string.toLowerCase(Locale.ROOT);
|
||||
NamespacedKey key = NamespacedKey.fromString(string);
|
||||
+ if (key == null) return null; // Paper - Fixup NamespacedKey handling
|
||||
|
||||
// Now also convert from when keys where saved
|
||||
return CraftRegistry.get(Registry.ATTRIBUTE, key, ApiVersion.CURRENT);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
|
||||
index 65a9213ce8197d50a58f94edfd60c25c2be848be..28d8fd2e3eb87e989621ffa6b0e5005bd181391c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
|
||||
@@ -36,7 +36,11 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
|
||||
if (banner.getPatterns() != null) {
|
||||
for (int i = 0; i < banner.getPatterns().layers().size(); i++) {
|
||||
BannerPatternLayers.Layer p = banner.getPatterns().layers().get(i);
|
||||
- this.patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), CraftPatternType.minecraftHolderToBukkit(p.pattern())));
|
||||
+ // Paper start - fix upstream not handling custom banner pattern
|
||||
+ java.util.Optional<org.bukkit.block.banner.PatternType> type = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.BANNER_PATTERN, p.pattern());
|
||||
+ if (type.isEmpty()) continue;
|
||||
+ this.patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), type.get()));
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
|
||||
index 12b95c4455e741b65b844eab362f02bce54eb525..13b91cddffbe8ae6f07ce5c0ae45beba151e1aca 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
|
||||
@@ -69,8 +69,9 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
|
||||
super(tag);
|
||||
|
||||
getOrEmpty(tag, CraftMetaArmor.TRIM).ifPresent((trimCompound) -> {
|
||||
- TrimMaterial trimMaterial = CraftTrimMaterial.minecraftHolderToBukkit(trimCompound.material());
|
||||
- TrimPattern trimPattern = CraftTrimPattern.minecraftHolderToBukkit(trimCompound.pattern());
|
||||
+ TrimMaterial trimMaterial = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_MATERIAL, trimCompound.material()).orElse(null); // Paper - fix upstream not being correct
|
||||
+ TrimPattern trimPattern = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_PATTERN, trimCompound.pattern()).orElse(null); // Paper - fix upstream not being correct
|
||||
+ if (trimMaterial == null || trimPattern == null) return; // Paper - just delete the trim because upstream is not doing this right
|
||||
|
||||
this.trim = new ArmorTrim(trimMaterial, trimPattern);
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
|
||||
index 524aadad91c855f6c201999831824f7ce06f9ed6..d53df6f114c285b880167385807775e400c80fc9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
|
||||
@@ -80,7 +80,7 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
|
||||
for (int i = 0; i < Math.min(patterns.size(), 20); i++) {
|
||||
BannerPatternLayers.Layer p = patterns.get(i);
|
||||
DyeColor color = DyeColor.getByWoolData((byte) p.color().getId());
|
||||
- PatternType pattern = CraftPatternType.minecraftHolderToBukkit(p.pattern());
|
||||
+ PatternType pattern = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.BANNER_PATTERN, p.pattern()).orElse(null); // Paper - fix upstream not handling custom banner pattern
|
||||
|
||||
if (color != null && pattern != null) {
|
||||
this.patterns.add(new Pattern(color, pattern));
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
|
||||
index 67905f804ccc102faa942499f5ba218f710ab9cc..4eb2993903f5fa9fb9fd65282a42f26b3aa1e7bd 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
|
||||
@@ -31,7 +31,7 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst
|
||||
super(tag);
|
||||
|
||||
getOrEmpty(tag, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT).ifPresent((instrument) -> {
|
||||
- this.instrument = CraftMusicInstrument.minecraftHolderToBukkit(instrument);
|
||||
+ this.instrument = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.INSTRUMENT, instrument).orElse(null); // Paper - fix upstream not handling custom instruments
|
||||
});
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java
|
||||
index 82a50b06c08b632f77d73745e1fa9bd22dfd950a..f1d8ed4a2b8959873b02d57f6a40323a841f3d7f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java
|
||||
@@ -69,6 +69,7 @@ public class CraftPotionType implements PotionType.InternalPotionData {
|
||||
string = FieldRename.convertPotionTypeName(ApiVersion.CURRENT, string);
|
||||
string = string.toLowerCase(Locale.ROOT);
|
||||
NamespacedKey key = NamespacedKey.fromString(string);
|
||||
+ if (key == null) return null; // Paper - Fixup NamespacedKey handling
|
||||
|
||||
// Now also convert from when keys where saved
|
||||
return CraftRegistry.get(Registry.POTION, key, ApiVersion.CURRENT);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
|
||||
index 5f40d240b879e3989897b6e45725a8e5a6a7f194..5014192edb9616ce725fc1592832034789527b6f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
|
||||
@@ -13,7 +13,7 @@ public final class CraftNamespacedKey {
|
||||
return null;
|
||||
}
|
||||
ResourceLocation minecraft = ResourceLocation.tryParse(string);
|
||||
- return (minecraft == null) ? null : CraftNamespacedKey.fromMinecraft(minecraft);
|
||||
+ return (minecraft == null || minecraft.getPath().isEmpty()) ? null : CraftNamespacedKey.fromMinecraft(minecraft); // Paper - Bukkit's parser does not match Vanilla for empty paths
|
||||
}
|
||||
|
||||
public static NamespacedKey fromString(String string) {
|
|
@ -1,44 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: FireInstall <kettnerl@hu-berlin.de>
|
||||
Date: Sat, 20 Jan 2024 16:20:06 +0100
|
||||
Subject: [PATCH] Expose LootTable of DecoratedPot
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftDecoratedPot.java b/src/main/java/org/bukkit/craftbukkit/block/CraftDecoratedPot.java
|
||||
index 6e0258d4d6a07e0f471640a9edda0adf7ef6cd9e..47cc3ec5ccd3bb51a08b3f179cb29030948b8c11 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftDecoratedPot.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftDecoratedPot.java
|
||||
@@ -43,6 +43,33 @@ public class CraftDecoratedPot extends CraftBlockEntityState<DecoratedPotBlockEn
|
||||
return new CraftInventoryDecoratedPot(this.getTileEntity());
|
||||
}
|
||||
|
||||
+ // Paper start - expose loot table
|
||||
+ @Override
|
||||
+ public void setLootTable(final org.bukkit.loot.LootTable table) {
|
||||
+ this.setLootTable(table, this.getSeed());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) {
|
||||
+ this.getSnapshot().setLootTable(org.bukkit.craftbukkit.CraftLootTable.bukkitToMinecraft(table), seed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.loot.LootTable getLootTable() {
|
||||
+ return org.bukkit.craftbukkit.CraftLootTable.minecraftToBukkit(this.getSnapshot().getLootTable());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSeed(final long seed) {
|
||||
+ this.getSnapshot().setLootTableSeed(seed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getSeed() {
|
||||
+ return this.getSnapshot().getLootTableSeed();
|
||||
+ }
|
||||
+ // Paper end - expose loot table
|
||||
+
|
||||
@Override
|
||||
public void setSherd(Side face, Material sherd) {
|
||||
Preconditions.checkArgument(face != null, "face must not be null");
|
|
@ -1,59 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 27 Apr 2020 00:04:16 -0700
|
||||
Subject: [PATCH] Reduce allocation of Vec3D by entity tracker
|
||||
|
||||
|
||||
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 a3d247c93ac1a2d872ff0e3841efc3d7b84fcbc1..23fe7c4c1844d321efed6b7b886c422761ad6594 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/VecDeltaCodec.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/VecDeltaCodec.java
|
||||
@@ -5,7 +5,7 @@ import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
public class VecDeltaCodec {
|
||||
private static final double TRUNCATION_STEPS = 4096.0;
|
||||
- private Vec3 base = Vec3.ZERO;
|
||||
+ public Vec3 base = Vec3.ZERO; // Paper
|
||||
|
||||
@VisibleForTesting
|
||||
static long encode(double value) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 027f2734b0ff226437f4c94430215929b6ea2219..35f627c58e93c03ee58b44877398432bba57dc2d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1748,10 +1748,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
public void updatePlayer(ServerPlayer player) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
|
||||
if (player != this.entity) {
|
||||
- Vec3 vec3d = player.position().subtract(this.entity.position());
|
||||
+ // Paper start - remove allocation of Vec3D here
|
||||
+ // Vec3 vec3d = player.position().subtract(this.entity.position());
|
||||
+ double vec3d_dx = player.getX() - this.entity.getX();
|
||||
+ double vec3d_dz = player.getZ() - this.entity.getZ();
|
||||
+ // Paper end - remove allocation of Vec3D here
|
||||
int i = ChunkMap.this.getPlayerViewDistance(player);
|
||||
double d0 = (double) Math.min(this.getEffectiveRange(), i * 16);
|
||||
- double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
|
||||
+ double d1 = vec3d_dx * vec3d_dx + vec3d_dz * vec3d_dz; // Paper
|
||||
double d2 = d0 * d0;
|
||||
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
||||
// Paper start - Configurable entity tracking range by Y
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index 0373b2de2b992b648f346d6df3960a3586a54567..22eec853588ded2d255ab69d408f8e987832abe2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -164,7 +164,13 @@ public class ServerEntity {
|
||||
i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F);
|
||||
j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F);
|
||||
Vec3 vec3d = this.entity.trackingPosition();
|
||||
- boolean flag1 = this.positionCodec.delta(vec3d).lengthSqr() >= 7.62939453125E-6D;
|
||||
+ // Paper start - reduce allocation of Vec3D here
|
||||
+ Vec3 base = this.positionCodec.base;
|
||||
+ double vec3d_dx = vec3d.x - base.x;
|
||||
+ double vec3d_dy = vec3d.y - base.y;
|
||||
+ double vec3d_dz = vec3d.z - base.z;
|
||||
+ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D;
|
||||
+ // Paper end - reduce allocation of Vec3D here
|
||||
Packet<?> packet1 = null;
|
||||
boolean flag2 = flag1 || this.tickCount % 60 == 0;
|
||||
boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1;
|
|
@ -1,240 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 2 Jul 2020 16:12:10 -0700
|
||||
Subject: [PATCH] Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
|
||||
Co-authored-by: Alexander <protonull@protonmail.com>
|
||||
|
||||
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 6e29b5729b8184d13065c9c4e18f6e450c9d88a6..d323cf157f2a910916baa9ce3f7e5bc81648c47d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
@@ -139,11 +139,24 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa
|
||||
@Override
|
||||
public void overrideXp(int experience) {}
|
||||
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+ @Override
|
||||
+ public void processTrade(MerchantOffer recipe, @Nullable io.papermc.paper.event.player.PlayerPurchaseEvent event) { // The MerchantRecipe passed in here is the one set by the PlayerPurchaseEvent
|
||||
+ if (event == null || event.willIncreaseTradeUses()) {
|
||||
+ recipe.increaseUses();
|
||||
+ }
|
||||
+ if (event == null || event.isRewardingExp()) {
|
||||
+ this.rewardTradeXp(recipe);
|
||||
+ }
|
||||
+ this.notifyTrade(recipe);
|
||||
+ }
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+
|
||||
@Override
|
||||
public void notifyTrade(MerchantOffer offer) {
|
||||
- offer.increaseUses();
|
||||
+ // offer.increaseUses(); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
this.ambientSoundTime = -this.getAmbientSoundInterval();
|
||||
- this.rewardTradeXp(offer);
|
||||
+ // this.rewardTradeXp(offer); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
if (this.tradingPlayer instanceof ServerPlayer) {
|
||||
CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult());
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 4c7e91977fa590abfe7eb3704d8008ed6d4e3ab3..32910f677b0522ac8ec513fa0d00b714b52cfae4 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -768,6 +768,14 @@ public abstract class AbstractContainerMenu {
|
||||
public abstract boolean stillValid(Player player);
|
||||
|
||||
protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean fromLast) {
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+ return this.moveItemStackTo(stack, startIndex, endIndex, fromLast, false);
|
||||
+ }
|
||||
+ protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean fromLast, boolean isCheck) {
|
||||
+ if (isCheck) {
|
||||
+ stack = stack.copy();
|
||||
+ }
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
boolean flag1 = false;
|
||||
int k = startIndex;
|
||||
|
||||
@@ -791,6 +799,11 @@ public abstract class AbstractContainerMenu {
|
||||
|
||||
slot = (Slot) this.slots.get(k);
|
||||
itemstack1 = slot.getItem();
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent; clone if only a check
|
||||
+ if (isCheck) {
|
||||
+ itemstack1 = itemstack1.copy();
|
||||
+ }
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
if (!itemstack1.isEmpty() && ItemStack.isSameItemSameComponents(stack, itemstack1)) {
|
||||
l = itemstack1.getCount() + stack.getCount();
|
||||
int i1 = slot.getMaxStackSize(itemstack1);
|
||||
@@ -798,12 +811,16 @@ public abstract class AbstractContainerMenu {
|
||||
if (l <= i1) {
|
||||
stack.setCount(0);
|
||||
itemstack1.setCount(l);
|
||||
+ if (!isCheck) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
slot.setChanged();
|
||||
+ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
flag1 = true;
|
||||
} else if (itemstack1.getCount() < i1) {
|
||||
stack.shrink(i1 - itemstack1.getCount());
|
||||
itemstack1.setCount(i1);
|
||||
+ if (!isCheck) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
slot.setChanged();
|
||||
+ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
flag1 = true;
|
||||
}
|
||||
}
|
||||
@@ -834,10 +851,21 @@ public abstract class AbstractContainerMenu {
|
||||
|
||||
slot = (Slot) this.slots.get(k);
|
||||
itemstack1 = slot.getItem();
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+ if (isCheck) {
|
||||
+ itemstack1 = itemstack1.copy();
|
||||
+ }
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
if (itemstack1.isEmpty() && slot.mayPlace(stack)) {
|
||||
l = slot.getMaxStackSize(stack);
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+ if (isCheck) {
|
||||
+ stack.shrink(Math.min(stack.getCount(), l));
|
||||
+ } else {
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
slot.setByPlayer(stack.split(Math.min(stack.getCount(), l)));
|
||||
slot.setChanged();
|
||||
+ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
flag1 = true;
|
||||
break;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/MerchantMenu.java b/src/main/java/net/minecraft/world/inventory/MerchantMenu.java
|
||||
index ecefd4075c097e2118ec23e87baf36465c40f85f..2992e86f5f83431e230162380b33721df785ba91 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/MerchantMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/MerchantMenu.java
|
||||
@@ -135,12 +135,12 @@ public class MerchantMenu extends AbstractContainerMenu {
|
||||
|
||||
itemstack = itemstack1.copy();
|
||||
if (slot == 2) {
|
||||
- if (!this.moveItemStackTo(itemstack1, 3, 39, true)) {
|
||||
+ if (!this.moveItemStackTo(itemstack1, 3, 39, true, true)) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- slot1.onQuickCraft(itemstack1, itemstack);
|
||||
- this.playTradeSound();
|
||||
+ // slot1.onQuickCraft(itemstack1, itemstack); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; moved to after the non-check moveItemStackTo call
|
||||
+ // this.playTradeSound();
|
||||
} else if (slot != 0 && slot != 1) {
|
||||
if (slot >= 3 && slot < 30) {
|
||||
if (!this.moveItemStackTo(itemstack1, 30, 39, false)) {
|
||||
@@ -153,6 +153,7 @@ public class MerchantMenu extends AbstractContainerMenu {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
+ if (slot != 2) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; moved down for slot 2
|
||||
if (itemstack1.isEmpty()) {
|
||||
slot1.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
@@ -164,6 +165,21 @@ public class MerchantMenu extends AbstractContainerMenu {
|
||||
}
|
||||
|
||||
slot1.onTake(player, itemstack1);
|
||||
+ } // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent; handle slot 2
|
||||
+ if (slot == 2) { // is merchant result slot
|
||||
+ slot1.onTake(player, itemstack1);
|
||||
+ if (itemstack1.isEmpty()) {
|
||||
+ slot1.set(ItemStack.EMPTY);
|
||||
+ return ItemStack.EMPTY;
|
||||
+ }
|
||||
+
|
||||
+ this.moveItemStackTo(itemstack1, 3, 39, true, false); // This should always succeed because it's checked above
|
||||
+
|
||||
+ slot1.onQuickCraft(itemstack1, itemstack);
|
||||
+ this.playTradeSound();
|
||||
+ slot1.set(ItemStack.EMPTY); // itemstack1 should ALWAYS be empty
|
||||
+ }
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/MerchantResultSlot.java b/src/main/java/net/minecraft/world/inventory/MerchantResultSlot.java
|
||||
index 26227033613a641a9d5a6f29356b19e54753b3f1..c2376538215604210d08acd33e8e5fdc8a35c7d3 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/MerchantResultSlot.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/MerchantResultSlot.java
|
||||
@@ -47,13 +47,32 @@ public class MerchantResultSlot extends Slot {
|
||||
|
||||
@Override
|
||||
public void onTake(Player player, ItemStack stack) {
|
||||
- this.checkTakeAchievements(stack);
|
||||
+ // this.checkTakeAchievements(stack); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; move to after event is called and not cancelled
|
||||
MerchantOffer merchantOffer = this.slots.getActiveOffer();
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+ io.papermc.paper.event.player.PlayerPurchaseEvent event = null;
|
||||
+ if (merchantOffer != null && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ if (this.merchant instanceof net.minecraft.world.entity.npc.AbstractVillager abstractVillager) {
|
||||
+ event = new io.papermc.paper.event.player.PlayerTradeEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.AbstractVillager) abstractVillager.getBukkitEntity(), merchantOffer.asBukkit(), true, true);
|
||||
+ } else if (this.merchant instanceof org.bukkit.craftbukkit.inventory.CraftMerchantCustom.MinecraftMerchant) {
|
||||
+ event = new io.papermc.paper.event.player.PlayerPurchaseEvent(serverPlayer.getBukkitEntity(), merchantOffer.asBukkit(), false, true);
|
||||
+ }
|
||||
+ if (event != null) {
|
||||
+ if (!event.callEvent()) {
|
||||
+ stack.setCount(0);
|
||||
+ event.getPlayer().updateInventory();
|
||||
+ return;
|
||||
+ }
|
||||
+ merchantOffer = org.bukkit.craftbukkit.inventory.CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft();
|
||||
+ }
|
||||
+ }
|
||||
+ this.checkTakeAchievements(stack);
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
if (merchantOffer != null) {
|
||||
ItemStack itemStack = this.slots.getItem(0);
|
||||
ItemStack itemStack2 = this.slots.getItem(1);
|
||||
if (merchantOffer.take(itemStack, itemStack2) || merchantOffer.take(itemStack2, itemStack)) {
|
||||
- this.merchant.notifyTrade(merchantOffer);
|
||||
+ this.merchant.processTrade(merchantOffer, event); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
player.awardStat(Stats.TRADED_WITH_VILLAGER);
|
||||
this.slots.setItem(0, itemStack);
|
||||
this.slots.setItem(1, itemStack2);
|
||||
diff --git a/src/main/java/net/minecraft/world/item/trading/Merchant.java b/src/main/java/net/minecraft/world/item/trading/Merchant.java
|
||||
index 5a350948a4735902f5c612592bc9d100445a0c8a..716b30dcd7e63c66736c448dd136c9f74dc7fe43 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/trading/Merchant.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/trading/Merchant.java
|
||||
@@ -20,6 +20,7 @@ public interface Merchant {
|
||||
|
||||
void overrideOffers(MerchantOffers offers);
|
||||
|
||||
+ default void processTrade(MerchantOffer merchantRecipe, @Nullable io.papermc.paper.event.player.PlayerPurchaseEvent event) { this.notifyTrade(merchantRecipe); } // Paper
|
||||
void notifyTrade(MerchantOffer offer);
|
||||
|
||||
void notifyTradeUpdated(ItemStack stack);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
|
||||
index adf22ce4f0bcd3bd57dc2030c6c92d3df96566e3..e33ddcd967a427abfda9e6692338da4996a81c6c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
|
||||
@@ -74,10 +74,25 @@ public class CraftMerchantCustom extends CraftMerchant {
|
||||
return this.trades;
|
||||
}
|
||||
|
||||
+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
+ @Override
|
||||
+ public void processTrade(MerchantOffer merchantRecipe, @javax.annotation.Nullable io.papermc.paper.event.player.PlayerPurchaseEvent event) { // The MerchantRecipe passed in here is the one set by the PlayerPurchaseEvent
|
||||
+ /** Based on {@link net.minecraft.world.entity.npc.AbstractVillager#processTrade(MerchantOffer, io.papermc.paper.event.player.PlayerPurchaseEvent)} */
|
||||
+ if (getTradingPlayer() instanceof net.minecraft.server.level.ServerPlayer) {
|
||||
+ if (event == null || event.willIncreaseTradeUses()) {
|
||||
+ merchantRecipe.increaseUses();
|
||||
+ }
|
||||
+ if (event == null || event.isRewardingExp()) {
|
||||
+ this.tradingPlayer.level().addFreshEntity(new net.minecraft.world.entity.ExperienceOrb(this.tradingPlayer.level(), this.tradingPlayer.getX(), this.tradingPlayer.getY(), this.tradingPlayer.getZ(), merchantRecipe.getXp(), org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.tradingPlayer, null));
|
||||
+ }
|
||||
+ }
|
||||
+ this.notifyTrade(merchantRecipe);
|
||||
+ }
|
||||
+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
|
||||
@Override
|
||||
public void notifyTrade(MerchantOffer offer) {
|
||||
// increase recipe's uses
|
||||
- offer.increaseUses();
|
||||
+ // offer.increaseUses(); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; handled above in processTrade
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chase Henderson <henderson.chase@gmail.com>
|
||||
Date: Fri, 5 Jan 2024 03:50:10 -0500
|
||||
Subject: [PATCH] Add ShulkerDuplicateEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
||||
index bd6171d75fbf4a0debef3892d6f67356dc811b4d..e03119f88719c8d6d44793a6b3706ae97b2da307 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
||||
@@ -491,6 +491,11 @@ public class Shulker extends AbstractGolem implements VariantHolder<Optional<Dye
|
||||
if (entityshulker != null) {
|
||||
entityshulker.setVariant(this.getVariant());
|
||||
entityshulker.moveTo(vec3d);
|
||||
+ // Paper start - Shulker duplicate event
|
||||
+ if (!new io.papermc.paper.event.entity.ShulkerDuplicateEvent((org.bukkit.entity.Shulker) entityshulker.getBukkitEntity(), (org.bukkit.entity.Shulker) this.getBukkitEntity()).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Shulker duplicate event
|
||||
this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Luis <luisc99@icloud.com>
|
||||
Date: Thu, 11 Jan 2024 19:58:23 +0100
|
||||
Subject: [PATCH] Add api for spawn egg texture colors
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index b5abf9c7e5e09c670ae2435c23587e0482fbe917..b485a14a11f468e16d1da672f981e678c7a1522e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -654,6 +654,15 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);
|
||||
}
|
||||
|
||||
+ // Paper start - spawn egg color visibility
|
||||
+ @Override
|
||||
+ public org.bukkit.Color getSpawnEggLayerColor(final EntityType entityType, final int layer) {
|
||||
+ final net.minecraft.world.entity.EntityType<?> nmsType = org.bukkit.craftbukkit.entity.CraftEntityType.bukkitToMinecraft(entityType);
|
||||
+ final net.minecraft.world.item.SpawnEggItem eggItem = net.minecraft.world.item.SpawnEggItem.byId(nmsType);
|
||||
+ return eggItem == null ? null : org.bukkit.Color.fromRGB(eggItem.getColor(layer));
|
||||
+ }
|
||||
+ // Paper end - spawn egg color visibility
|
||||
+
|
||||
/**
|
||||
* This helper class represents the different NBT Tags.
|
||||
* <p>
|
|
@ -1,781 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 18 Jul 2023 17:49:38 -0700
|
||||
Subject: [PATCH] Add Lifecycle Event system
|
||||
|
||||
This event system is separate from Bukkit's event system and is
|
||||
meant for managing resources across reloads and from points in the
|
||||
PluginBootstrap.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java
|
||||
index 30b50e6294c6eaade5e17cfaf34600d122e6251c..0bb7694188d5fb75bb756ce75d0060ea980027ee 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.papermc.paper.plugin.bootstrap;
|
||||
|
||||
import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEventManager;
|
||||
import io.papermc.paper.plugin.provider.PluginProvider;
|
||||
import java.nio.file.Path;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
@@ -12,6 +14,10 @@ public final class PluginBootstrapContextImpl implements BootstrapContext {
|
||||
private final Path dataFolder;
|
||||
private final ComponentLogger logger;
|
||||
private final Path pluginSource;
|
||||
+ // Paper start - lifecycle events
|
||||
+ private boolean allowsLifecycleRegistration = true;
|
||||
+ private final PaperLifecycleEventManager<BootstrapContext> lifecycleEventManager = new PaperLifecycleEventManager<>(this, () -> this.allowsLifecycleRegistration); // Paper - lifecycle events
|
||||
+ // Paper end - lifecycle events
|
||||
|
||||
public PluginBootstrapContextImpl(PluginMeta config, Path dataFolder, ComponentLogger logger, Path pluginSource) {
|
||||
this.config = config;
|
||||
@@ -45,4 +51,20 @@ public final class PluginBootstrapContextImpl implements BootstrapContext {
|
||||
public @NotNull Path getPluginSource() {
|
||||
return this.pluginSource;
|
||||
}
|
||||
+
|
||||
+ // Paper start - lifecycle event system
|
||||
+ @Override
|
||||
+ public @NotNull PluginMeta getPluginMeta() {
|
||||
+ return this.config;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public LifecycleEventManager<BootstrapContext> getLifecycleManager() {
|
||||
+ return this.lifecycleEventManager;
|
||||
+ }
|
||||
+
|
||||
+ public void lockLifecycleEventRegistration() {
|
||||
+ this.allowsLifecycleRegistration = false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f84c9c80e701231e5c33ac3c5573f1093e80f38b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
||||
@@ -0,0 +1,110 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event;
|
||||
+
|
||||
+import com.google.common.base.Suppliers;
|
||||
+import com.mojang.logging.LogUtils;
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.RegistrarEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.RegistrarEventImpl;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.OwnerAwareLifecycleEvent;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.Set;
|
||||
+import java.util.function.Predicate;
|
||||
+import java.util.function.Supplier;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+import org.slf4j.Logger;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class LifecycleEventRunner {
|
||||
+
|
||||
+ private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||
+ private static final Supplier<Set<LifecycleEventType<?, ?, ?>>> BLOCKS_RELOADING = Suppliers.memoize(() -> Set.of( // lazy due to cyclic initialization
|
||||
+ ));
|
||||
+ public static final LifecycleEventRunner INSTANCE = new LifecycleEventRunner();
|
||||
+
|
||||
+ private final List<LifecycleEventType<?, ?, ?>> lifecycleEventTypes = new ArrayList<>();
|
||||
+ private boolean blockPluginReloading = false;
|
||||
+
|
||||
+ public void checkRegisteredHandler(final LifecycleEventOwner owner, final LifecycleEventType<?, ?, ?> eventType) {
|
||||
+ /*
|
||||
+ Lifecycle event handlers for reloadable events that are registered from the BootstrapContext prevent
|
||||
+ the server from reloading plugins. This is because reloading plugins requires disabling all the plugins,
|
||||
+ running the reload logic (which would include places where these events should fire) and then re-enabling plugins.
|
||||
+ */
|
||||
+ if (owner instanceof BootstrapContext && BLOCKS_RELOADING.get().contains(eventType)) {
|
||||
+ this.blockPluginReloading = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public boolean blocksPluginReloading() {
|
||||
+ return this.blockPluginReloading;
|
||||
+ }
|
||||
+
|
||||
+ public <O extends LifecycleEventOwner, E extends LifecycleEvent, ET extends LifecycleEventType<O, E, ?>> ET addEventType(final ET eventType) {
|
||||
+ this.lifecycleEventTypes.add(eventType);
|
||||
+ return eventType;
|
||||
+ }
|
||||
+
|
||||
+ public <O extends LifecycleEventOwner, E extends PaperLifecycleEvent> void callEvent(final LifecycleEventType<O, ? super E, ?> eventType, final E event) {
|
||||
+ this.callEvent(eventType, event, $ -> true);
|
||||
+ }
|
||||
+
|
||||
+ public <O extends LifecycleEventOwner, E extends PaperLifecycleEvent> void callEvent(final LifecycleEventType<O, ? super E, ?> eventType, final E event, final Predicate<? super O> ownerPredicate) {
|
||||
+ final AbstractLifecycleEventType<O, ? super E, ?, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ? super E, ?, ?>) eventType;
|
||||
+ lifecycleEventType.forEachHandler(registeredHandler -> {
|
||||
+ try {
|
||||
+ if (event instanceof final OwnerAwareLifecycleEvent<?> ownerAwareEvent) {
|
||||
+ ownerAwareGenericHelper(ownerAwareEvent, registeredHandler.owner());
|
||||
+ }
|
||||
+ registeredHandler.lifecycleEventHandler().run(event);
|
||||
+ } catch (final Throwable ex) {
|
||||
+ LOGGER.error("Could not run '{}' lifecycle event handler from {}", lifecycleEventType.name(), registeredHandler.owner().getPluginMeta().getDisplayName(), ex);
|
||||
+ } finally {
|
||||
+ if (event instanceof final OwnerAwareLifecycleEvent<?> ownerAwareEvent) {
|
||||
+ ownerAwareEvent.setOwner(null);
|
||||
+ }
|
||||
+ }
|
||||
+ }, handler -> ownerPredicate.test(handler.owner()));
|
||||
+ event.invalidate();
|
||||
+ }
|
||||
+
|
||||
+ private static <O extends LifecycleEventOwner> void ownerAwareGenericHelper(final OwnerAwareLifecycleEvent<O> event, final LifecycleEventOwner possibleOwner) {
|
||||
+ final @Nullable O owner = event.castOwner(possibleOwner);
|
||||
+ if (owner != null) {
|
||||
+ event.setOwner(owner);
|
||||
+ } else {
|
||||
+ throw new IllegalStateException("Found invalid owner " + possibleOwner + " for event " + event);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void unregisterAllEventHandlersFor(final Plugin plugin) {
|
||||
+ for (final LifecycleEventType<?, ?, ?> lifecycleEventType : this.lifecycleEventTypes) {
|
||||
+ this.removeEventHandlersOwnedBy(lifecycleEventType, plugin);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private <O extends LifecycleEventOwner> void removeEventHandlersOwnedBy(final LifecycleEventType<O, ?, ?> eventType, final Plugin possibleOwner) {
|
||||
+ final AbstractLifecycleEventType<O, ?, ?, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ?, ?, ?>) eventType;
|
||||
+ lifecycleEventType.removeMatching(registeredHandler -> registeredHandler.owner().getPluginMeta().getName().equals(possibleOwner.getPluginMeta().getName()));
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public <O extends LifecycleEventOwner, R extends PaperRegistrar<? super O>> void callStaticRegistrarEvent(final LifecycleEventType<O, ? extends RegistrarEvent<? super R>, ?> lifecycleEventType, final R registrar, final Class<? extends O> ownerClass) {
|
||||
+ this.callEvent((LifecycleEventType<O, RegistrarEvent<? super R>, ?>) lifecycleEventType, new RegistrarEventImpl<>(registrar, ownerClass), ownerClass::isInstance);
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public <O extends LifecycleEventOwner, R extends PaperRegistrar<? super O>> void callReloadableRegistrarEvent(final LifecycleEventType<O, ? extends ReloadableRegistrarEvent<? super R>, ?> lifecycleEventType, final R registrar, final Class<? extends O> ownerClass, final ReloadableRegistrarEvent.Cause cause) {
|
||||
+ this.callEvent((LifecycleEventType<O, ReloadableRegistrarEvent<? super R>, ?>) lifecycleEventType, new RegistrarEventImpl.ReloadableImpl<>(registrar, ownerClass, cause), ownerClass::isInstance);
|
||||
+ }
|
||||
+
|
||||
+ private LifecycleEventRunner() {
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e941405269a773e8a77e26ffd1afd84f53fadff5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEvent.java
|
||||
@@ -0,0 +1,10 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event;
|
||||
+
|
||||
+public interface PaperLifecycleEvent extends LifecycleEvent {
|
||||
+
|
||||
+ // called after all handlers have been run. Can be
|
||||
+ // used to invalid various contexts to plugins can't
|
||||
+ // try to re-use them by storing them from the event
|
||||
+ default void invalidate() {
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f1be5b9a29435bae0afd2bd951bfe88d1669e7eb
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration;
|
||||
+import java.util.function.BooleanSupplier;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class PaperLifecycleEventManager<O extends LifecycleEventOwner> implements LifecycleEventManager<O> {
|
||||
+
|
||||
+ private final O owner;
|
||||
+ public final BooleanSupplier registrationCheck;
|
||||
+
|
||||
+ public PaperLifecycleEventManager(final O owner, final BooleanSupplier registrationCheck) {
|
||||
+ this.owner = owner;
|
||||
+ this.registrationCheck = registrationCheck;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void registerEventHandler(final LifecycleEventHandlerConfiguration<? super O> handlerConfiguration) {
|
||||
+ Preconditions.checkState(this.registrationCheck.getAsBoolean(), "Cannot register lifecycle event handlers");
|
||||
+ ((AbstractLifecycleEventHandlerConfiguration<? super O, ?, ?>) handlerConfiguration).registerFrom(this.owner);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6a85a4f581612efff04c1a955493aa2e32476277
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.handler.configuration;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public abstract class AbstractLifecycleEventHandlerConfiguration<O extends LifecycleEventOwner, E extends LifecycleEvent, CI extends AbstractLifecycleEventHandlerConfiguration<O, E, CI>> implements LifecycleEventHandlerConfiguration<O> {
|
||||
+
|
||||
+ private final LifecycleEventHandler<? super E> handler;
|
||||
+ private final AbstractLifecycleEventType<O, E, ?, CI> type;
|
||||
+
|
||||
+ protected AbstractLifecycleEventHandlerConfiguration(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?, CI> type) {
|
||||
+ this.handler = handler;
|
||||
+ this.type = type;
|
||||
+ }
|
||||
+
|
||||
+ public abstract CI config();
|
||||
+
|
||||
+ public final void registerFrom(final O owner) {
|
||||
+ this.type.tryRegister(owner, this.handler, this.config());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e0699fcd0a098abc5e1206e7c0fa80b96eca7884
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java
|
||||
@@ -0,0 +1,33 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.handler.configuration;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class MonitorLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventHandlerConfiguration<O, E, MonitorLifecycleEventHandlerConfigurationImpl<O, E>> implements MonitorLifecycleEventHandlerConfiguration<O> {
|
||||
+
|
||||
+ private boolean monitor = false;
|
||||
+
|
||||
+ public MonitorLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?, MonitorLifecycleEventHandlerConfigurationImpl<O, E>> eventType) {
|
||||
+ super(handler, eventType);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public MonitorLifecycleEventHandlerConfigurationImpl<O, E> config() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isMonitor() {
|
||||
+ return this.monitor;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public MonitorLifecycleEventHandlerConfiguration<O> monitor() {
|
||||
+ this.monitor = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c1d0070fc1594f7a7c29d7dc679da7b347a7140b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.handler.configuration;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
||||
+import java.util.OptionalInt;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PrioritizedLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventHandlerConfiguration<O, E, PrioritizedLifecycleEventHandlerConfigurationImpl<O, E>> implements PrioritizedLifecycleEventHandlerConfiguration<O> {
|
||||
+
|
||||
+ private static final OptionalInt DEFAULT_PRIORITY = OptionalInt.of(0);
|
||||
+ private static final OptionalInt MONITOR_PRIORITY = OptionalInt.empty();
|
||||
+
|
||||
+ private OptionalInt priority = DEFAULT_PRIORITY;
|
||||
+
|
||||
+ public PrioritizedLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?, PrioritizedLifecycleEventHandlerConfigurationImpl<O, E>> eventType) {
|
||||
+ super(handler, eventType);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PrioritizedLifecycleEventHandlerConfigurationImpl<O, E> config() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public OptionalInt priority() {
|
||||
+ return this.priority;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PrioritizedLifecycleEventHandlerConfiguration<O> priority(final int priority) {
|
||||
+ this.priority = OptionalInt.of(priority);
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PrioritizedLifecycleEventHandlerConfiguration<O> monitor() {
|
||||
+ this.priority = MONITOR_PRIORITY;
|
||||
+ return this;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/PaperRegistrar.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/PaperRegistrar.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b2586c881988fbabe07eef1b43eb1b55f2d3fa52
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/PaperRegistrar.java
|
||||
@@ -0,0 +1,15 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.registrar;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public interface PaperRegistrar<O extends LifecycleEventOwner> extends Registrar {
|
||||
+
|
||||
+ void setCurrentContext(@Nullable O owner);
|
||||
+
|
||||
+ default void invalidate() {
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEventImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEventImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6d530c52aaf0dc2cdfe3bd56af557274a7f44256
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEventImpl.java
|
||||
@@ -0,0 +1,70 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.registrar;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.OwnerAwareLifecycleEvent;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class RegistrarEventImpl<R extends PaperRegistrar<? super O>, O extends LifecycleEventOwner> implements PaperLifecycleEvent, OwnerAwareLifecycleEvent<O>, RegistrarEvent<R> {
|
||||
+
|
||||
+ private final R registrar;
|
||||
+ private final Class<? extends O> ownerClass;
|
||||
+
|
||||
+ public RegistrarEventImpl(final R registrar, final Class<? extends O> ownerClass) {
|
||||
+ this.registrar = registrar;
|
||||
+ this.ownerClass = ownerClass;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public R registrar() {
|
||||
+ return this.registrar;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final void setOwner(final @Nullable O owner) {
|
||||
+ this.registrar.setCurrentContext(owner);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final @Nullable O castOwner(final LifecycleEventOwner owner) {
|
||||
+ return this.ownerClass.isInstance(owner) ? this.ownerClass.cast(owner) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void invalidate() {
|
||||
+ this.registrar.invalidate();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "RegistrarEventImpl{" +
|
||||
+ "registrar=" + this.registrar +
|
||||
+ ", ownerClass=" + this.ownerClass +
|
||||
+ '}';
|
||||
+ }
|
||||
+
|
||||
+ public static class ReloadableImpl<R extends PaperRegistrar<? super O>, O extends LifecycleEventOwner> extends RegistrarEventImpl<R, O> implements ReloadableRegistrarEvent<R> {
|
||||
+
|
||||
+ private final ReloadableRegistrarEvent.Cause cause;
|
||||
+
|
||||
+ public ReloadableImpl(final R registrar, final Class<? extends O> ownerClass, final Cause cause) {
|
||||
+ super(registrar, ownerClass);
|
||||
+ this.cause = cause;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Cause cause() {
|
||||
+ return this.cause;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "ReloadableImpl{" +
|
||||
+ "cause=" + this.cause +
|
||||
+ "} " + super.toString();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a65fb37f4a729e2fe9fb81af822db626ec7e6d7b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java
|
||||
@@ -0,0 +1,50 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration;
|
||||
+import java.util.function.Consumer;
|
||||
+import java.util.function.Predicate;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public abstract class AbstractLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent, C extends LifecycleEventHandlerConfiguration<O>, CI extends AbstractLifecycleEventHandlerConfiguration<O, E, CI>> implements LifecycleEventType<O, E, C> {
|
||||
+
|
||||
+ private final String name;
|
||||
+ private final Class<? extends O> ownerType;
|
||||
+
|
||||
+ protected AbstractLifecycleEventType(final String name, final Class<? extends O> ownerType) {
|
||||
+ this.name = name;
|
||||
+ this.ownerType = ownerType;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String name() {
|
||||
+ return this.name;
|
||||
+ }
|
||||
+
|
||||
+ private void verifyOwner(final O owner) {
|
||||
+ if (!this.ownerType.isInstance(owner)) {
|
||||
+ throw new IllegalArgumentException("You cannot register the lifecycle event '" + this.name + "' on " + owner);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public abstract void forEachHandler(Consumer<? super RegisteredHandler<O, E>> consumer, Predicate<? super RegisteredHandler<O, E>> predicate);
|
||||
+
|
||||
+ public abstract void removeMatching(Predicate<? super RegisteredHandler<O, E>> predicate);
|
||||
+
|
||||
+ protected abstract void register(O owner, LifecycleEventHandler<? super E> handler, CI config);
|
||||
+
|
||||
+ public final void tryRegister(final O owner, final LifecycleEventHandler<? super E> handler, final CI config) {
|
||||
+ this.verifyOwner(owner);
|
||||
+ LifecycleEventRunner.INSTANCE.checkRegisteredHandler(owner, this);
|
||||
+ this.register(owner, handler, config);
|
||||
+ }
|
||||
+
|
||||
+ public record RegisteredHandler<O, E extends LifecycleEvent>(O owner, LifecycleEventHandler<? super E> lifecycleEventHandler) {
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0886edad92b40276f268bd745b31bac359fd28af
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
||||
@@ -0,0 +1,25 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeProvider {
|
||||
+
|
||||
+ public static LifecycleEventTypeProviderImpl instance() {
|
||||
+ return (LifecycleEventTypeProviderImpl) LifecycleEventTypeProvider.PROVIDER;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Monitorable<O, E> monitor(final String name, final Class<? extends O> ownerType) {
|
||||
+ return LifecycleEventRunner.INSTANCE.addEventType(new MonitorableLifecycleEventType<>(name, ownerType));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) {
|
||||
+ return LifecycleEventRunner.INSTANCE.addEventType(new PrioritizableLifecycleEventType<>(name, ownerType));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6d92c1d3adf220154dfe7cba3a3f8158356c3e3c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java
|
||||
@@ -0,0 +1,54 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfiguration;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfigurationImpl;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.function.Consumer;
|
||||
+import java.util.function.Predicate;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventType<O, E, MonitorLifecycleEventHandlerConfiguration<O>, MonitorLifecycleEventHandlerConfigurationImpl<O, E>> implements LifecycleEventType.Monitorable<O, E> {
|
||||
+
|
||||
+ final List<RegisteredHandler<O, E>> handlers = new ArrayList<>();
|
||||
+ int nonMonitorIdx = 0;
|
||||
+
|
||||
+ public MonitorableLifecycleEventType(final String name, final Class<? extends O> ownerType) {
|
||||
+ super(name, ownerType);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public MonitorLifecycleEventHandlerConfigurationImpl<O, E> newHandler(final LifecycleEventHandler<? super E> handler) {
|
||||
+ return new MonitorLifecycleEventHandlerConfigurationImpl<>(handler, this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void register(final O owner, final LifecycleEventHandler<? super E> handler, final MonitorLifecycleEventHandlerConfigurationImpl<O, E> config) {
|
||||
+ final RegisteredHandler<O, E> registeredHandler = new RegisteredHandler<>(owner, handler);
|
||||
+ if (!config.isMonitor()) {
|
||||
+ this.handlers.add(this.nonMonitorIdx, registeredHandler);
|
||||
+ this.nonMonitorIdx++;
|
||||
+ } else {
|
||||
+ this.handlers.add(registeredHandler);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void forEachHandler(final Consumer<? super RegisteredHandler<O, E>> consumer, final Predicate<? super RegisteredHandler<O, E>> predicate) {
|
||||
+ for (final RegisteredHandler<O, E> handler : this.handlers) {
|
||||
+ if (predicate.test(handler)) {
|
||||
+ consumer.accept(handler);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeMatching(final Predicate<? super RegisteredHandler<O, E>> predicate) {
|
||||
+ this.handlers.removeIf(predicate);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/OwnerAwareLifecycleEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/OwnerAwareLifecycleEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3e7e7474f301c0725fa2bcd6e19e476fc35f2d5a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/OwnerAwareLifecycleEvent.java
|
||||
@@ -0,0 +1,15 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public interface OwnerAwareLifecycleEvent<O extends LifecycleEventOwner> extends LifecycleEvent {
|
||||
+
|
||||
+ void setOwner(@Nullable O owner);
|
||||
+
|
||||
+ @Nullable O castOwner(LifecycleEventOwner owner);
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6629f7fabf66ce761024268043cc30076ba8a3f1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfigurationImpl;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Comparator;
|
||||
+import java.util.List;
|
||||
+import java.util.OptionalInt;
|
||||
+import java.util.function.Consumer;
|
||||
+import java.util.function.Predicate;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PrioritizableLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventType<O, E, PrioritizedLifecycleEventHandlerConfiguration<O>, PrioritizedLifecycleEventHandlerConfigurationImpl<O, E>> implements LifecycleEventType.Prioritizable<O, E> {
|
||||
+
|
||||
+ private static final Comparator<PrioritizedHandler<?, ?>> COMPARATOR = Comparator.comparing(PrioritizedHandler::priority, (o1, o2) -> {
|
||||
+ if (o1.equals(o2)) {
|
||||
+ return 0;
|
||||
+ } else if (o1.isEmpty()) {
|
||||
+ return 1;
|
||||
+ } else if (o2.isEmpty()) {
|
||||
+ return -1;
|
||||
+ } else {
|
||||
+ return Integer.compare(o1.getAsInt(), o2.getAsInt());
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ private final List<PrioritizedHandler<O, E>> handlers = new ArrayList<>();
|
||||
+
|
||||
+ public PrioritizableLifecycleEventType(final String name, final Class<? extends O> ownerType) {
|
||||
+ super(name, ownerType);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PrioritizedLifecycleEventHandlerConfiguration<O> newHandler(final LifecycleEventHandler<? super E> handler) {
|
||||
+ return new PrioritizedLifecycleEventHandlerConfigurationImpl<>(handler, this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void register(final O owner, final LifecycleEventHandler<? super E> handler, final PrioritizedLifecycleEventHandlerConfigurationImpl<O, E> config) {
|
||||
+ this.handlers.add(new PrioritizedHandler<>(new RegisteredHandler<>(owner, handler), config.priority()));
|
||||
+ this.handlers.sort(COMPARATOR);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void forEachHandler(final Consumer<? super RegisteredHandler<O, E>> consumer, final Predicate<? super RegisteredHandler<O, E>> predicate) {
|
||||
+ for (final PrioritizedHandler<O, E> handler : this.handlers) {
|
||||
+ if (predicate.test(handler.handler())) {
|
||||
+ consumer.accept(handler.handler());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeMatching(final Predicate<? super RegisteredHandler<O, E>> predicate) {
|
||||
+ this.handlers.removeIf(prioritizedHandler -> predicate.test(prioritizedHandler.handler()));
|
||||
+ }
|
||||
+
|
||||
+ private record PrioritizedHandler<O extends LifecycleEventOwner, E extends LifecycleEvent>(RegisteredHandler<O, E> handler, OptionalInt priority) {}
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java
|
||||
index 834b85f24df023642f8abf7213fe578ac8c17a3e..3e82ea07ca4194844c5528446e2c4a46ff4acee5 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java
|
||||
@@ -293,6 +293,15 @@ class PaperPluginInstanceManager {
|
||||
+ pluginName + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
+ // Paper start - lifecycle event system
|
||||
+ try {
|
||||
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.unregisterAllEventHandlersFor(plugin);
|
||||
+ } catch (Throwable ex) {
|
||||
+ this.handlePluginException("Error occurred (in the plugin loader) while unregistering lifecycle event handlers for "
|
||||
+ + pluginName + " (Is it up to date?)", ex, plugin);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
try {
|
||||
this.server.getMessenger().unregisterIncomingPluginChannel(plugin);
|
||||
this.server.getMessenger().unregisterOutgoingPluginChannel(plugin);
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java
|
||||
index 2e96308696e131f3f013469a395e5ddda2c5d529..65a66e484c1c39c5f41d97db52f31c67b4479d20 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java
|
||||
@@ -32,8 +32,9 @@ public class BootstrapProviderStorage extends SimpleProviderStorage<PluginBootst
|
||||
@Override
|
||||
public boolean load(PluginProvider<PluginBootstrap> provider, PluginBootstrap provided) {
|
||||
try {
|
||||
- BootstrapContext context = PluginBootstrapContextImpl.create(provider, PluginInitializerManager.instance().pluginDirectoryPath());
|
||||
+ PluginBootstrapContextImpl context = PluginBootstrapContextImpl.create(provider, PluginInitializerManager.instance().pluginDirectoryPath()); // Paper - lifecycle events
|
||||
provided.bootstrap(context);
|
||||
+ context.lockLifecycleEventRegistration(); // Paper - lifecycle events
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Failed to run bootstrapper for %s. This plugin will not be loaded.".formatted(provider.getSource()), e);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index cce628673b6173f17ac81bce5469a7dbd8a2c648..fd4417e2863fb028a1b22b4f5c00d585dd127ad1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1035,6 +1035,11 @@ public final class CraftServer implements Server {
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
+ // Paper start - lifecycle events
|
||||
+ if (io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.blocksPluginReloading()) {
|
||||
+ throw new IllegalStateException("A lifecycle event handler has been registered which makes reloading plugins not possible");
|
||||
+ }
|
||||
+ // Paper end - lifecycle events
|
||||
org.spigotmc.WatchdogThread.hasStarted = false; // Paper - Disable watchdog early timeout on reload
|
||||
this.reloadCount++;
|
||||
this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java
|
||||
index d96399e9bf1a58db5a4a22e58abb99e7660e0694..66bdac50130f523f9dc4379b103b7a469f9ca36b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java
|
||||
@@ -143,4 +143,11 @@ public class MinecraftInternalPlugin extends PluginBase {
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
+
|
||||
+ // Paper start - lifecycle events
|
||||
+ @Override
|
||||
+ public @NotNull io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> getLifecycleManager() {
|
||||
+ throw new UnsupportedOperationException("Not supported.");
|
||||
+ }
|
||||
+ // Paper end - lifecycle events
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index b485a14a11f468e16d1da672f981e678c7a1522e..5143b8f81ce31e5d88f5de6b2856c3b7e3676048 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -663,6 +663,13 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
}
|
||||
// Paper end - spawn egg color visibility
|
||||
|
||||
+ // Paper start - lifecycle event API
|
||||
+ @Override
|
||||
+ public io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> createPluginLifecycleEventManager(final org.bukkit.plugin.java.JavaPlugin plugin, final java.util.function.BooleanSupplier registrationCheck) {
|
||||
+ return new io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEventManager<>(plugin, registrationCheck);
|
||||
+ }
|
||||
+ // Paper end - lifecycle event API
|
||||
+
|
||||
/**
|
||||
* This helper class represents the different NBT Tags.
|
||||
* <p>
|
||||
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProvider b/src/main/resources/META-INF/services/io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProvider
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..808b1192b60348ad05f0bfbdeda6f94df4876743
|
||||
--- /dev/null
|
||||
+++ b/src/main/resources/META-INF/services/io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProvider
|
||||
@@ -0,0 +1 @@
|
||||
+io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProviderImpl
|
||||
diff --git a/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java b/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java
|
||||
index 1d14f530ef888102e47eeeaf0d1a6076e51871c4..90cf0c702ca2ff9de64d9718ecba5f2d128953a6 100644
|
||||
--- a/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java
|
||||
+++ b/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java
|
||||
@@ -143,4 +143,11 @@ public class PaperTestPlugin extends PluginBase {
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
+
|
||||
+ // Paper start - lifecycle events
|
||||
+ @Override
|
||||
+ public io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> getLifecycleManager() {
|
||||
+ throw new UnsupportedOperationException("Not supported.");
|
||||
+ }
|
||||
+ // Paper end - lifecycle events
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yannick Lamprecht <yannicklamprecht@live.de>
|
||||
Date: Mon, 22 Jan 2024 13:27:30 +0100
|
||||
Subject: [PATCH] ItemStack Tooltip API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 5143b8f81ce31e5d88f5de6b2856c3b7e3676048..f6c33a9e2900890e4f6cb19784e01ff438cce83d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -639,6 +639,21 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
}
|
||||
// Paper end - fix custom stats criteria creation
|
||||
|
||||
+ // Paper start - expose itemstack tooltip lines
|
||||
+ @Override
|
||||
+ public java.util.List<net.kyori.adventure.text.Component> computeTooltipLines(final ItemStack itemStack, final io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, final org.bukkit.entity.Player player) {
|
||||
+ Preconditions.checkArgument(tooltipContext != null, "tooltipContext cannot be null");
|
||||
+ net.minecraft.world.item.TooltipFlag.Default flag = tooltipContext.isAdvanced() ? net.minecraft.world.item.TooltipFlag.ADVANCED : net.minecraft.world.item.TooltipFlag.NORMAL;
|
||||
+ if (tooltipContext.isCreative()) {
|
||||
+ flag = flag.asCreative();
|
||||
+ }
|
||||
+ final java.util.List<net.minecraft.network.chat.Component> lines = CraftItemStack.asNMSCopy(itemStack).getTooltipLines(
|
||||
+ net.minecraft.world.item.Item.TooltipContext.of(player == null ? net.minecraft.server.MinecraftServer.getServer().registryAccess() : ((org.bukkit.craftbukkit.entity.CraftPlayer) player).getHandle().level().registryAccess()),
|
||||
+ player == null ? null : ((org.bukkit.craftbukkit.entity.CraftPlayer) player).getHandle(), flag);
|
||||
+ return lines.stream().map(io.papermc.paper.adventure.PaperAdventure::asAdventure).toList();
|
||||
+ }
|
||||
+ // Paper end - expose itemstack tooltip lines
|
||||
+
|
||||
@Override
|
||||
public String get(Class<?> aClass, String s) {
|
||||
if (aClass == Enchantment.class) {
|
|
@ -1,70 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
|
||||
Date: Sat, 10 Feb 2024 10:03:48 +0100
|
||||
Subject: [PATCH] Add getChunkSnapshot includeLightData parameter
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
index f8c2d91958d6e4a1452fcf32c16fa8b97ea271a2..36a611d06131be00197c915871b8323544bb4972 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
@@ -328,12 +328,21 @@ public class CraftChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain) {
|
||||
+ // Paper start - Add getChunkSnapshot includeLightData parameter
|
||||
+ return getChunkSnapshot(includeMaxBlockY, includeBiome, includeBiomeTempRain, true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain, boolean includeLightData) {
|
||||
+ // Paper end - Add getChunkSnapshot includeLightData parameter
|
||||
ChunkAccess chunk = this.getHandle(ChunkStatus.FULL);
|
||||
|
||||
LevelChunkSection[] cs = chunk.getSections();
|
||||
PalettedContainer[] sectionBlockIDs = new PalettedContainer[cs.length];
|
||||
- byte[][] sectionSkyLights = new byte[cs.length][];
|
||||
- byte[][] sectionEmitLights = new byte[cs.length][];
|
||||
+ // Paper start - Add getChunkSnapshot includeLightData parameter
|
||||
+ byte[][] sectionSkyLights = includeLightData ? new byte[cs.length][] : null;
|
||||
+ byte[][] sectionEmitLights = includeLightData ? new byte[cs.length][] : null;
|
||||
+ // Paper end - Add getChunkSnapshot includeLightData parameter
|
||||
boolean[] sectionEmpty = new boolean[cs.length];
|
||||
PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
|
||||
|
||||
@@ -350,6 +359,7 @@ public class CraftChunk implements Chunk {
|
||||
}
|
||||
// Paper end - Fix ChunkSnapshot#isSectionEmpty(int)
|
||||
|
||||
+ if (includeLightData) { // Paper - Add getChunkSnapshot includeLightData parameter
|
||||
LevelLightEngine lightengine = this.worldServer.getLightEngine();
|
||||
DataLayer skyLightArray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(this.x, chunk.getSectionYFromSectionIndex(i), this.z)); // SPIGOT-7498: Convert section index
|
||||
if (skyLightArray == null) {
|
||||
@@ -365,6 +375,7 @@ public class CraftChunk implements Chunk {
|
||||
sectionEmitLights[i] = new byte[2048];
|
||||
System.arraycopy(emitLightArray.getData(), 0, sectionEmitLights[i], 0, 2048);
|
||||
}
|
||||
+ } // Paper - Add getChunkSnapshot includeLightData parameter
|
||||
|
||||
if (biome != null) {
|
||||
biome[i] = ((PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>) cs[i].getBiomes()).copy(); // Paper - Perf: use copy instead of round tripping with codecs
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
|
||||
index 85029f1acfdbb411d9ebdf95838d6db3898f4e58..0756b5adb3039997feadeb94afb10b596abd9424 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
|
||||
@@ -118,6 +118,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
||||
|
||||
@Override
|
||||
public final int getBlockSkyLight(int x, int y, int z) {
|
||||
+ Preconditions.checkState(this.skylight != null, "ChunkSnapshot created without light data. Please call getSnapshot with includeLightData=true"); // Paper - Add getChunkSnapshot includeLightData parameter
|
||||
this.validateChunkCoordinates(x, y, z);
|
||||
|
||||
int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1);
|
||||
@@ -126,6 +127,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
||||
|
||||
@Override
|
||||
public final int getBlockEmittedLight(int x, int y, int z) {
|
||||
+ Preconditions.checkState(this.emitlight != null, "ChunkSnapshot created without light data. Please call getSnapshot with includeLightData=true"); // Paper - Add getChunkSnapshot includeLightData parameter
|
||||
this.validateChunkCoordinates(x, y, z);
|
||||
|
||||
int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1);
|
|
@ -1,208 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: vicisacat <victor.branchu@gmail.com>
|
||||
Date: Fri, 17 Nov 2023 20:22:43 +0100
|
||||
Subject: [PATCH] Add FluidState API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/block/fluid/PaperFluidData.java b/src/main/java/io/papermc/paper/block/fluid/PaperFluidData.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..479bc32241ebadf8bbc1080b601f61391ad37fa4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/block/fluid/PaperFluidData.java
|
||||
@@ -0,0 +1,110 @@
|
||||
+package io.papermc.paper.block.fluid;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import io.papermc.paper.block.fluid.type.PaperFallingFluidData;
|
||||
+import io.papermc.paper.block.fluid.type.PaperFlowingFluidData;
|
||||
+import io.papermc.paper.util.MCUtil;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Map;
|
||||
+import java.util.function.Function;
|
||||
+import net.minecraft.world.level.material.FluidState;
|
||||
+import net.minecraft.world.level.material.LavaFluid;
|
||||
+import net.minecraft.world.level.material.WaterFluid;
|
||||
+import org.bukkit.Fluid;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.CraftFluid;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.craftbukkit.util.CraftVector;
|
||||
+import org.bukkit.util.Vector;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class PaperFluidData implements FluidData {
|
||||
+
|
||||
+ private final FluidState state;
|
||||
+
|
||||
+ protected PaperFluidData(final FluidState state) {
|
||||
+ this.state = state;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Provides the internal server representation of this fluid data.
|
||||
+ * @return the fluid state.
|
||||
+ */
|
||||
+ public FluidState getState() {
|
||||
+ return this.state;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final @NotNull Fluid getFluidType() {
|
||||
+ return CraftFluid.minecraftToBukkit(this.state.getType());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull PaperFluidData clone() {
|
||||
+ try {
|
||||
+ return (PaperFluidData) super.clone();
|
||||
+ } catch (final CloneNotSupportedException ex) {
|
||||
+ throw new AssertionError("Clone not supported", ex);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Vector computeFlowDirection(final Location location) {
|
||||
+ Preconditions.checkArgument(location.getWorld() != null, "Cannot compute flow direction on world-less location");
|
||||
+ return CraftVector.toBukkit(this.state.getFlow(
|
||||
+ ((CraftWorld) location.getWorld()).getHandle(),
|
||||
+ MCUtil.toBlockPosition(location)
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getLevel() {
|
||||
+ return this.state.getAmount();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float computeHeight(@NotNull final Location location) {
|
||||
+ Preconditions.checkArgument(location.getWorld() != null, "Cannot compute height on world-less location");
|
||||
+ return this.state.getHeight(((CraftWorld) location.getWorld()).getHandle(), MCUtil.toBlockPos(location));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isSource() {
|
||||
+ return this.state.isSource();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return this.state.hashCode();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final Object obj) {
|
||||
+ return obj instanceof final PaperFluidData paperFluidData && this.state.equals(paperFluidData.state);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "PaperFluidData{" + this.state + "}";
|
||||
+ }
|
||||
+
|
||||
+ /* Registry */
|
||||
+ private static final Map<Class<? extends net.minecraft.world.level.material.Fluid>, Function<FluidState, PaperFluidData>> MAP = new HashMap<>();
|
||||
+ static {
|
||||
+ //<editor-fold desc="PaperFluidData Registration" defaultstate="collapsed">
|
||||
+ register(LavaFluid.Source.class, PaperFallingFluidData::new);
|
||||
+ register(WaterFluid.Source.class, PaperFallingFluidData::new);
|
||||
+ register(LavaFluid.Flowing.class, PaperFlowingFluidData::new);
|
||||
+ register(WaterFluid.Flowing.class, PaperFlowingFluidData::new);
|
||||
+ //</editor-fold>
|
||||
+ }
|
||||
+
|
||||
+ static void register(final Class<? extends net.minecraft.world.level.material.Fluid> fluid, final Function<FluidState, PaperFluidData> creator) {
|
||||
+ Preconditions.checkState(MAP.put(fluid, creator) == null, "Duplicate mapping %s->%s", fluid, creator);
|
||||
+ MAP.put(fluid, creator);
|
||||
+ }
|
||||
+
|
||||
+ public static PaperFluidData createData(final FluidState state) {
|
||||
+ return MAP.getOrDefault(state.getType().getClass(), PaperFluidData::new).apply(state);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/block/fluid/package-info.java b/src/main/java/io/papermc/paper/block/fluid/package-info.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..cfabb814ebd281aab299c6c655266ff357e08806
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/block/fluid/package-info.java
|
||||
@@ -0,0 +1,5 @@
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+package io.papermc.paper.block.fluid;
|
||||
+
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
diff --git a/src/main/java/io/papermc/paper/block/fluid/type/PaperFallingFluidData.java b/src/main/java/io/papermc/paper/block/fluid/type/PaperFallingFluidData.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..655dbd83ff4e632f1168b75e9b402b05aa9d8edf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/block/fluid/type/PaperFallingFluidData.java
|
||||
@@ -0,0 +1,18 @@
|
||||
+
|
||||
+package io.papermc.paper.block.fluid.type;
|
||||
+
|
||||
+import io.papermc.paper.block.fluid.PaperFluidData;
|
||||
+import net.minecraft.world.level.material.FlowingFluid;
|
||||
+import net.minecraft.world.level.material.FluidState;
|
||||
+
|
||||
+public class PaperFallingFluidData extends PaperFluidData implements FallingFluidData {
|
||||
+
|
||||
+ public PaperFallingFluidData(final FluidState state) {
|
||||
+ super(state);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isFalling() {
|
||||
+ return this.getState().getValue(FlowingFluid.FALLING);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/block/fluid/type/PaperFlowingFluidData.java b/src/main/java/io/papermc/paper/block/fluid/type/PaperFlowingFluidData.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c0c2805cb045cdd835b402776a6923fe2ecc2a99
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/block/fluid/type/PaperFlowingFluidData.java
|
||||
@@ -0,0 +1,11 @@
|
||||
+package io.papermc.paper.block.fluid.type;
|
||||
+
|
||||
+import net.minecraft.world.level.material.FluidState;
|
||||
+
|
||||
+public class PaperFlowingFluidData extends PaperFallingFluidData implements FlowingFluidData {
|
||||
+
|
||||
+ public PaperFlowingFluidData(final FluidState state) {
|
||||
+ super(state);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
index 5cdc44c73b536f2ed2dcd49dbeccf0f69f614dba..ef1bfab74e93f48c621e7b4a3a54f59b84bdd064 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
@@ -107,6 +107,13 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
|
||||
return CraftBlock.at(this.getHandle(), new BlockPos(x, y, z)).getState();
|
||||
}
|
||||
|
||||
+ // Paper start - FluidState API
|
||||
+ @Override
|
||||
+ public io.papermc.paper.block.fluid.FluidData getFluidData(final int x, final int y, final int z) {
|
||||
+ return io.papermc.paper.block.fluid.PaperFluidData.createData(getHandle().getFluidState(new BlockPos(x, y, z)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public BlockData getBlockData(Location location) {
|
||||
return this.getBlockData(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
||||
index eaa9ba70b0b80d86eb376a0641420093a7c9dfdb..25598df0bb0d4347b2c17b6ec0afbfe4ecf808b9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java
|
||||
@@ -303,4 +303,11 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe
|
||||
return centerChunkZ;
|
||||
}
|
||||
// Paper end - Add more LimitedRegion API
|
||||
+ // Paper start - Fluid API
|
||||
+ @Override
|
||||
+ public io.papermc.paper.block.fluid.FluidData getFluidData(int x, int y, int z) {
|
||||
+ Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z);
|
||||
+ return super.getFluidData(x, y, z);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Mayr <davidliebtkekse@gmail.com>
|
||||
Date: Sat, 16 Dec 2023 10:40:29 +0100
|
||||
Subject: [PATCH] add number format api
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.network.chat.numbers.FixedFormat value
|
||||
public net.minecraft.network.chat.numbers.StyledFormat style
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/PaperScoreboardFormat.java b/src/main/java/io/papermc/paper/util/PaperScoreboardFormat.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6064086cc76ef0df999c7057121d0ac22bd4df65
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/PaperScoreboardFormat.java
|
||||
@@ -0,0 +1,38 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import io.papermc.paper.scoreboard.numbers.NumberFormat;
|
||||
+
|
||||
+public final class PaperScoreboardFormat {
|
||||
+
|
||||
+ private PaperScoreboardFormat() {
|
||||
+ }
|
||||
+
|
||||
+ public static net.minecraft.network.chat.numbers.NumberFormat asVanilla(final NumberFormat format) {
|
||||
+ final net.minecraft.network.chat.numbers.NumberFormat vanilla;
|
||||
+ if (format instanceof final io.papermc.paper.scoreboard.numbers.StyledFormat styled) {
|
||||
+ vanilla = new net.minecraft.network.chat.numbers.StyledFormat(PaperAdventure.asVanilla(styled.style()));
|
||||
+ } else if (format instanceof final io.papermc.paper.scoreboard.numbers.FixedFormat fixed) {
|
||||
+ vanilla = new net.minecraft.network.chat.numbers.FixedFormat(io.papermc.paper.adventure.PaperAdventure
|
||||
+ .asVanilla(fixed.component()));
|
||||
+ } else if (format.equals(NumberFormat.blank())) {
|
||||
+ vanilla = net.minecraft.network.chat.numbers.BlankFormat.INSTANCE;
|
||||
+ } else {
|
||||
+ throw new IllegalArgumentException("Unknown format type " + format.getClass());
|
||||
+ }
|
||||
+
|
||||
+ return vanilla;
|
||||
+ }
|
||||
+
|
||||
+ public static NumberFormat asPaper(final net.minecraft.network.chat.numbers.NumberFormat vanilla) {
|
||||
+ if (vanilla instanceof final net.minecraft.network.chat.numbers.StyledFormat styled) {
|
||||
+ return NumberFormat.styled(PaperAdventure.asAdventure(styled.style));
|
||||
+ } else if (vanilla instanceof final net.minecraft.network.chat.numbers.FixedFormat fixed) {
|
||||
+ return NumberFormat.fixed(io.papermc.paper.adventure.PaperAdventure.asAdventure(fixed.value));
|
||||
+ } else if (vanilla instanceof net.minecraft.network.chat.numbers.BlankFormat) {
|
||||
+ return NumberFormat.blank();
|
||||
+ }
|
||||
+
|
||||
+ throw new IllegalArgumentException("Unknown format type " + vanilla.getClass());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
index 2d3abf2a1da487ead74d698cc5ea4eb729c35c8d..1fec80c4f02aab3770c05bac8bfa2b622625e630 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
@@ -153,6 +153,34 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - add number format
|
||||
+ @Override
|
||||
+ public io.papermc.paper.scoreboard.numbers.NumberFormat numberFormat() {
|
||||
+ this.checkState();
|
||||
+
|
||||
+ net.minecraft.network.chat.numbers.NumberFormat vanilla = this.objective.numberFormat();
|
||||
+
|
||||
+ if (vanilla == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return io.papermc.paper.util.PaperScoreboardFormat.asPaper(vanilla);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ @Override
|
||||
+ public void numberFormat(io.papermc.paper.scoreboard.numbers.NumberFormat format) {
|
||||
+ this.checkState();
|
||||
+
|
||||
+ if (format == null) {
|
||||
+ this.objective.setNumberFormat(null);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.objective.setNumberFormat(io.papermc.paper.util.PaperScoreboardFormat.asVanilla(format));
|
||||
+ }
|
||||
+ // Paper end - add number format
|
||||
+
|
||||
@Override
|
||||
public void unregister() {
|
||||
CraftScoreboard scoreboard = this.checkState();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
index 74d9c407e971804bed420370f7b684d8658eb5aa..e307e897d6e1ba4cb21883dfeaf334bfbf56cfc4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java
|
||||
@@ -55,6 +55,41 @@ final class CraftScore implements Score {
|
||||
this.objective.checkState().board.getOrCreatePlayerScore(this.entry, this.objective.getHandle()).set(score);
|
||||
}
|
||||
|
||||
+
|
||||
+ // Paper start - add number format
|
||||
+ @Override
|
||||
+ public io.papermc.paper.scoreboard.numbers.NumberFormat numberFormat() {
|
||||
+ ReadOnlyScoreInfo scoreInfo = this.objective.checkState().board
|
||||
+ .getPlayerScoreInfo(this.entry, this.objective.getHandle());
|
||||
+
|
||||
+ if (scoreInfo == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.network.chat.numbers.NumberFormat vanilla = scoreInfo.numberFormat();
|
||||
+
|
||||
+ if (vanilla == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return io.papermc.paper.util.PaperScoreboardFormat.asPaper(vanilla);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ @Override
|
||||
+ public void numberFormat(io.papermc.paper.scoreboard.numbers.NumberFormat format) {
|
||||
+ final net.minecraft.world.scores.ScoreAccess access = this.objective.checkState()
|
||||
+ .board.getOrCreatePlayerScore(this.entry, this.objective.getHandle());
|
||||
+
|
||||
+ if (format == null) {
|
||||
+ access.numberFormatOverride(null);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ access.numberFormatOverride(io.papermc.paper.util.PaperScoreboardFormat.asVanilla(format));
|
||||
+ }
|
||||
+ // Paper end - add number format
|
||||
+
|
||||
@Override
|
||||
public boolean isScoreSet() {
|
||||
Scoreboard board = this.objective.checkState().board;
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yannick Lamprecht <yannicklamprecht@live.de>
|
||||
Date: Sat, 10 Feb 2024 20:50:01 +0100
|
||||
Subject: [PATCH] improve BanList types
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index fd4417e2863fb028a1b22b4f5c00d585dd127ad1..16a736e8327450712630b1659b156da879a57352 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2242,6 +2242,21 @@ public final class CraftServer implements Server {
|
||||
};
|
||||
}
|
||||
|
||||
+ // Paper start - add BanListType (which has a generic)
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ @Override
|
||||
+ public <B extends BanList<E>, E> B getBanList(final io.papermc.paper.ban.BanListType<B> type) {
|
||||
+ Preconditions.checkArgument(type != null, "BanList.BanType cannot be null");
|
||||
+ if (type == io.papermc.paper.ban.BanListType.IP) {
|
||||
+ return (B) new CraftIpBanList(this.playerList.getIpBans());
|
||||
+ } else if (type == io.papermc.paper.ban.BanListType.PROFILE) {
|
||||
+ return (B) new CraftProfileBanList(this.playerList.getBans());
|
||||
+ } else {
|
||||
+ throw new IllegalArgumentException("Unknown BanListType: " + type);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - add BanListType (which has a generic)
|
||||
+
|
||||
@Override
|
||||
public void setWhitelist(boolean value) {
|
||||
this.playerList.setUsingWhiteList(value);
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: vicisacat <victor.branchu@gmail.com>
|
||||
Date: Fri, 15 Mar 2024 17:35:40 +0100
|
||||
Subject: [PATCH] Expanded Hopper API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.block.entity.HopperBlockEntity setCooldown(I)V
|
||||
public net.minecraft.world.level.block.entity.HopperBlockEntity cooldownTime
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
||||
index 2995b407415c77288a54c3f4eb8cb93e1a289283..f3c4d3835a18475e2cd2f519ac3dd9d9b59c454d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
||||
@@ -40,4 +40,17 @@ public class CraftHopper extends CraftLootable<HopperBlockEntity> implements Hop
|
||||
public CraftHopper copy(Location location) {
|
||||
return new CraftHopper(this, location);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Expanded Hopper API
|
||||
+ @Override
|
||||
+ public void setTransferCooldown(final int cooldown) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(cooldown >= 0, "Hooper transfer cooldown cannot be negative (" + cooldown + ")");
|
||||
+ getSnapshot().setCooldown(cooldown);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getTransferCooldown() {
|
||||
+ return getSnapshot().cooldownTime;
|
||||
+ }
|
||||
+ // Paper end - Expanded Hopper API
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Badbird5907 <50347938+Badbird5907@users.noreply.github.com>
|
||||
Date: Mon, 4 Mar 2024 22:18:28 -0500
|
||||
Subject: [PATCH] Add BlockBreakProgressUpdateEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 39cf7ae086108d8077121829368b81605d046fab..4616672c4be74421e2acbc9df96f7c8ff2782e55 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1322,6 +1322,17 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
if (entity instanceof Player) entityhuman = (Player) entity;
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Paper start - Add BlockBreakProgressUpdateEvent
|
||||
+ // If a plugin is using this method to send destroy packets for a client-side only entity id, no block progress occurred on the server.
|
||||
+ // Hence, do not call the event.
|
||||
+ if (entity != null) {
|
||||
+ float progressFloat = Mth.clamp(progress, 0, 10) / 10.0f;
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this, pos);
|
||||
+ new io.papermc.paper.event.block.BlockBreakProgressUpdateEvent(bukkitBlock, progressFloat, entity.getBukkitEntity())
|
||||
+ .callEvent();
|
||||
+ }
|
||||
+ // Paper end - Add BlockBreakProgressUpdateEvent
|
||||
+
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Tue, 26 Mar 2024 21:42:23 -0400
|
||||
Subject: [PATCH] Deprecate ItemStack#setType
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index 520b637e0f281d3d3018681ec7b48b06c47f621e..7249ff939dfa786395595f687338315b779e0931 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -711,4 +711,24 @@ public final class CraftItemStack extends ItemStack {
|
||||
static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) {
|
||||
return !(item == null || item.getComponentsPatch().isEmpty());
|
||||
}
|
||||
+ // Paper start - with type
|
||||
+ @Override
|
||||
+ public ItemStack withType(final Material type) {
|
||||
+ if (type == Material.AIR) {
|
||||
+ return CraftItemStack.asCraftMirror(null);
|
||||
+ }
|
||||
+
|
||||
+ final net.minecraft.world.item.ItemStack copy = new net.minecraft.world.item.ItemStack(
|
||||
+ CraftItemType.bukkitToMinecraft(type), this.getAmount()
|
||||
+ );
|
||||
+
|
||||
+ if (this.handle != null) {
|
||||
+ copy.applyComponents(this.handle.getComponentsPatch());
|
||||
+ }
|
||||
+
|
||||
+ final CraftItemStack mirrored = CraftItemStack.asCraftMirror(copy);
|
||||
+ mirrored.setItemMeta(mirrored.getItemMeta());
|
||||
+ return mirrored;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Janet Blackquill <uhhadd@gmail.com>
|
||||
Date: Sun, 7 Apr 2024 16:52:42 -0400
|
||||
Subject: [PATCH] Add CartographyItemEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index e13097ceba283fdf165d7e6327fe78590252fe94..bead9625a04a9c1139c54d6a56f055b80eb2d701 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3092,6 +3092,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - cartography item event
|
||||
+ if (packet.getSlotNum() == net.minecraft.world.inventory.CartographyTableMenu.RESULT_SLOT && top instanceof org.bukkit.inventory.CartographyInventory cartographyInventory) {
|
||||
+ org.bukkit.inventory.ItemStack result = cartographyInventory.getResult();
|
||||
+ if (result != null && !result.isEmpty()) {
|
||||
+ if (click == ClickType.NUMBER_KEY) {
|
||||
+ event = new io.papermc.paper.event.player.CartographyItemEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum());
|
||||
+ } else {
|
||||
+ event = new io.papermc.paper.event.player.CartographyItemEvent(inventory, type, packet.getSlotNum(), click, action);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - cartography item event
|
||||
+
|
||||
event.setCancelled(cancelled);
|
||||
AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
|
||||
index ab98637bf967ac19f0bc06e8cb7f18a8b13ec809..a90e2c56c54797b2fec40eb3865835c5f640a544 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
|
||||
@@ -71,7 +71,7 @@ public class CartographyTableMenu extends AbstractContainerMenu {
|
||||
this.resultContainer = new ResultContainer(this.createBlockHolder(context)) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
- CartographyTableMenu.this.slotsChanged(this);
|
||||
+ // CartographyTableMenu.this.slotsChanged(this); // Paper - Add CatographyItemEvent - do not recompute results if the result slot changes - allows to set the result slot via api
|
||||
super.setChanged();
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 4 Mar 2022 09:46:33 -0800
|
||||
Subject: [PATCH] More Raid API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.raid.Raid raidEvent
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java
|
||||
index 364d233ca318bbf8c1bc3acfbaf2d2420fdf922f..fdff9788eaf663be79214b2ca491f0f0444f6136 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -110,6 +110,11 @@ public class Raid {
|
||||
private Raid.RaidStatus status;
|
||||
private int celebrationTicks;
|
||||
private Optional<BlockPos> waveSpawnPos;
|
||||
+ // Paper start
|
||||
+ private static final String PDC_NBT_KEY = "BukkitValues";
|
||||
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry PDC_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
+ public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(PDC_TYPE_REGISTRY);
|
||||
+ // Paper end
|
||||
|
||||
public Raid(int id, ServerLevel world, BlockPos pos) {
|
||||
this.raidEvent = new ServerBossEvent(Raid.RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10);
|
||||
@@ -153,6 +158,11 @@ public class Raid {
|
||||
this.heroesOfTheVillage.add(NbtUtils.loadUUID(nbtbase));
|
||||
}
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (nbt.contains(PDC_NBT_KEY, net.minecraft.nbt.Tag.TAG_COMPOUND)) {
|
||||
+ this.persistentDataContainer.putAll(nbt.getCompound(PDC_NBT_KEY));
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
}
|
||||
|
||||
@@ -870,6 +880,11 @@ public class Raid {
|
||||
}
|
||||
|
||||
nbt.put("HeroesOfTheVillage", nbttaglist);
|
||||
+ // Paper start
|
||||
+ if (!this.persistentDataContainer.isEmpty()) {
|
||||
+ nbt.put(PDC_NBT_KEY, this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // Paper end
|
||||
return nbt;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRaid.java b/src/main/java/org/bukkit/craftbukkit/CraftRaid.java
|
||||
index b8ce1c1c2447f9cff1717bfcfd6eb911ade0d4b3..51f21af9d75769abdcba713b9aa33392e994d9b0 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRaid.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRaid.java
|
||||
@@ -103,4 +103,34 @@ public final class CraftRaid implements Raid {
|
||||
public net.minecraft.world.entity.raid.Raid getHandle() {
|
||||
return this.handle;
|
||||
}
|
||||
+
|
||||
+ // Paper start - more Raid API
|
||||
+ @Override
|
||||
+ public int getId() {
|
||||
+ return this.handle.getId();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.boss.BossBar getBossBar() {
|
||||
+ return new org.bukkit.craftbukkit.boss.CraftBossBar(this.handle.raidEvent);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.persistence.PersistentDataContainer getPersistentDataContainer() {
|
||||
+ return this.handle.persistentDataContainer;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || this.getClass() != o.getClass()) return false;
|
||||
+ final org.bukkit.craftbukkit.CraftRaid craftRaid = (org.bukkit.craftbukkit.CraftRaid) o;
|
||||
+ return this.handle.equals(craftRaid.handle);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return this.handle.hashCode();
|
||||
+ }
|
||||
+ // Paper end - more Raid API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 2536a37ab9e5a7aa7373b1880f55cdb8c32a6f53..44ed6bd76fb9e81f6c0d99fe46173685dbbfe2a7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -2398,6 +2398,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
return (raid == null) ? null : new CraftRaid(raid);
|
||||
}
|
||||
|
||||
+ // Paper start - more Raid API
|
||||
+ @Override
|
||||
+ public @Nullable Raid getRaid(final int id) {
|
||||
+ final net.minecraft.world.entity.raid.@Nullable Raid nmsRaid = this.world.getRaids().raidMap.get(id);
|
||||
+ return nmsRaid != null ? new CraftRaid(nmsRaid) : null;
|
||||
+ }
|
||||
+ // Paper end - more Raid API
|
||||
+
|
||||
@Override
|
||||
public List<Raid> getRaids() {
|
||||
Raids persistentRaid = this.world.getRaids();
|
|
@ -1,103 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: leguan <longboard.noah@gmail.com>
|
||||
Date: Sun, 10 Mar 2024 20:10:41 +0100
|
||||
Subject: [PATCH] Add onboarding message for initial server start
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/configuration/Configurations.java b/src/main/java/io/papermc/paper/configuration/Configurations.java
|
||||
index 7684e71f802f3d19e5340713b45cc84860ce9495..96142deb42700f888ea08689ab62c27ef2b881fd 100644
|
||||
--- a/src/main/java/io/papermc/paper/configuration/Configurations.java
|
||||
+++ b/src/main/java/io/papermc/paper/configuration/Configurations.java
|
||||
@@ -129,6 +129,7 @@ public abstract class Configurations<G, W> {
|
||||
if (Files.notExists(configFile)) {
|
||||
node = CommentedConfigurationNode.root(loader.defaultOptions());
|
||||
node.node(Configuration.VERSION_FIELD).raw(this.globalConfigVersion());
|
||||
+ GlobalConfiguration.isFirstStart = true;
|
||||
} else {
|
||||
node = loader.load();
|
||||
this.verifyGlobalConfigVersion(node);
|
||||
diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
|
||||
index ab5089781b8866cd6ad1b9570634ba84d936cfe7..4de88f74182bb596c6b5ad0351cc0dacefd0ce96 100644
|
||||
--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
|
||||
+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
|
||||
@@ -25,6 +25,7 @@ public class GlobalConfiguration extends ConfigurationPart {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
static final int CURRENT_VERSION = 29; // (when you change the version, change the comment, so it conflicts on rebases): <insert changes here>
|
||||
private static GlobalConfiguration instance;
|
||||
+ public static boolean isFirstStart = false;
|
||||
public static GlobalConfiguration get() {
|
||||
return instance;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 2a92268dfc8ee264e4ee6ffc56b40a87e334acc8..1a9e323659dcff12ce53919eb3d6d6f66f835292 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1129,6 +1129,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
long tickSection = Util.getNanos();
|
||||
long currentTime;
|
||||
// Paper end - further improve server tick loop
|
||||
+ // Paper start - Add onboarding message for initial server start
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.isFirstStart) {
|
||||
+ LOGGER.info("*************************************************************************************");
|
||||
+ LOGGER.info("This is the first time you're starting this server.");
|
||||
+ LOGGER.info("It's recommended you read our 'Getting Started' documentation for guidance.");
|
||||
+ LOGGER.info("View this and more helpful information here: https://docs.papermc.io/paper/next-steps");
|
||||
+ LOGGER.info("*************************************************************************************");
|
||||
+ }
|
||||
+ // Paper end - Add onboarding message for initial server start
|
||||
+
|
||||
while (this.running) {
|
||||
long i;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
index 4d3fe4f56e0b264fa030409919caf52d5f421d46..759062d219ff490a3cb19e710c4d18e3e08288e0 100644
|
||||
--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
+++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -90,6 +90,7 @@ public class MinecraftServerGui extends JComponent {
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
try {
|
||||
+ this.add(this.buildOnboardingPanel(), "North"); // Paper - Add onboarding message for initial server start
|
||||
this.add(this.buildChatPanel(), "Center");
|
||||
this.add(this.buildInfoPanel(), "West");
|
||||
} catch (Exception exception) {
|
||||
@@ -115,6 +116,39 @@ public class MinecraftServerGui extends JComponent {
|
||||
return jpanel;
|
||||
}
|
||||
|
||||
+ // Paper start - Add onboarding message for initial server start
|
||||
+ private JComponent buildOnboardingPanel() {
|
||||
+ String onboardingLink = "https://docs.papermc.io/paper/next-steps";
|
||||
+ JPanel jPanel = new JPanel();
|
||||
+
|
||||
+ javax.swing.JLabel jLabel = new javax.swing.JLabel("If you need help setting up your server you can visit:");
|
||||
+ jLabel.setFont(MinecraftServerGui.MONOSPACED);
|
||||
+
|
||||
+ javax.swing.JLabel link = new javax.swing.JLabel("<html><u> " + onboardingLink + "</u></html>");
|
||||
+ link.setFont(MinecraftServerGui.MONOSPACED);
|
||||
+ link.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
|
||||
+ link.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
+ @Override
|
||||
+ public void mouseClicked(final java.awt.event.MouseEvent e) {
|
||||
+ try {
|
||||
+ java.awt.Desktop.getDesktop().browse(java.net.URI.create(onboardingLink));
|
||||
+ } catch (java.io.IOException exception) {
|
||||
+ LOGGER.error("Unable to find a default browser. Please manually visit the website: " + onboardingLink, exception);
|
||||
+ } catch (UnsupportedOperationException exception) {
|
||||
+ LOGGER.error("This platform does not support the BROWSE action. Please manually visit the website: " + onboardingLink, exception);
|
||||
+ } catch (SecurityException exception) {
|
||||
+ LOGGER.error("This action has been denied by the security manager. Please manually visit the website: " + onboardingLink, exception);
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ jPanel.add(jLabel);
|
||||
+ jPanel.add(link);
|
||||
+
|
||||
+ return jPanel;
|
||||
+ }
|
||||
+ // Paper end - Add onboarding message for initial server start
|
||||
+
|
||||
private JComponent buildPlayerPanel() {
|
||||
JList<?> jlist = new PlayerListComponent(this.server);
|
||||
JScrollPane jscrollpane = new JScrollPane(jlist, 22, 30);
|
|
@ -1,22 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gero <gecam59@gmail.com>
|
||||
Date: Mon, 19 Feb 2024 17:39:59 +0100
|
||||
Subject: [PATCH] Configurable max block/fluid ticks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 4616672c4be74421e2acbc9df96f7c8ff2782e55..3a1ecdaebfd64f4703eafc92b5895e1dbddd8ee6 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -500,9 +500,9 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
if (!this.isDebug() && flag) {
|
||||
j = this.getGameTime();
|
||||
gameprofilerfiller.push("blockTicks");
|
||||
- this.blockTicks.tick(j, 65536, this::tickBlock);
|
||||
+ this.blockTicks.tick(j, paperConfig().environment.maxBlockTicks, this::tickBlock); // Paper - configurable max block ticks
|
||||
gameprofilerfiller.popPush("fluidTicks");
|
||||
- this.fluidTicks.tick(j, 65536, this::tickFluid);
|
||||
+ this.fluidTicks.tick(j, paperConfig().environment.maxFluidTicks, this::tickFluid); // Paper - configurable max fluid ticks
|
||||
gameprofilerfiller.pop();
|
||||
}
|
||||
this.timings.scheduledBlocks.stopTiming(); // Paper
|
|
@ -1,41 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 21 Aug 2021 21:54:16 -0700
|
||||
Subject: [PATCH] Fix bees aging inside hives
|
||||
|
||||
Fixes bees incorrectly being aged up due to upstream's
|
||||
resetting the ticks inside hive on a failed release
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
index 6fb7ec36f6f7a3021fac4b9e31fd333dfd5ea5e5..7b263fab4f0014400b3b8e7e33db32f9a125f6ba 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
@@ -314,7 +314,7 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
iterator.remove();
|
||||
// CraftBukkit start
|
||||
} else {
|
||||
- tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.occupant.minTicksInHive / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable
|
||||
+ tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.occupant.minTicksInHive / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - Fix bees aging inside hives; use exitTickCounter to keep actual bee life
|
||||
// CraftBukkit end
|
||||
}
|
||||
}
|
||||
@@ -474,15 +474,18 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
private static class BeeData {
|
||||
|
||||
private final BeehiveBlockEntity.Occupant occupant;
|
||||
+ private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
|
||||
private int ticksInHive;
|
||||
|
||||
BeeData(BeehiveBlockEntity.Occupant data) {
|
||||
this.occupant = data;
|
||||
this.ticksInHive = data.ticksInHive();
|
||||
+ this.exitTickCounter = this.ticksInHive; // Paper - Fix bees aging inside hives
|
||||
}
|
||||
|
||||
public boolean tick() {
|
||||
- return this.ticksInHive++ > this.occupant.minTicksInHive;
|
||||
+ this.ticksInHive++; // Paper - Fix bees aging inside hives
|
||||
+ return this.exitTickCounter++ > this.occupant.minTicksInHive; // Paper - Fix bees aging inside hives
|
||||
}
|
||||
|
||||
public BeehiveBlockEntity.Occupant toOccupant() {
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
|
||||
Date: Thu, 18 Jan 2024 23:25:09 +0100
|
||||
Subject: [PATCH] Disable memory reserve allocating
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java
|
||||
index 06c514b2d0674cd7df6692981f020437ea0f2f91..bcb6a3b3cd17ce5db9aaf6bd3ec7a0ec1b44b979 100644
|
||||
--- a/src/main/java/net/minecraft/CrashReport.java
|
||||
+++ b/src/main/java/net/minecraft/CrashReport.java
|
||||
@@ -250,7 +250,7 @@ public class CrashReport {
|
||||
}
|
||||
|
||||
public static void preload() {
|
||||
- MemoryReserve.allocate();
|
||||
+ // MemoryReserve.allocate(); // Paper - Disable memory reserve allocating
|
||||
(new CrashReport("Don't panic!", new Throwable())).getFriendlyReport();
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: RodneyMKay <36546810+RodneyMKay@users.noreply.github.com>
|
||||
Date: Sun, 11 Feb 2024 20:05:11 +0100
|
||||
Subject: [PATCH] Fire EntityDamageByEntityEvent for unowned wither skulls
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
||||
index 729aa0125479ab839792a3f35c981046899421b5..02931861de955352e71d6f5ffc720a17304815fe 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
||||
@@ -72,7 +72,7 @@ public class WitherSkull extends AbstractHurtingProjectile {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
- flag = entity.hurt(this.damageSources().magic(), 5.0F);
|
||||
+ flag = entity.hurt(this.damageSources().magic().customCausingEntity(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls
|
||||
}
|
||||
|
||||
if (flag && entity instanceof LivingEntity) {
|
|
@ -1,211 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 9 Mar 2024 14:13:04 -0800
|
||||
Subject: [PATCH] Fix DamageSource API
|
||||
|
||||
Uses the correct entity in the EntityDamageByEntity event
|
||||
Returns the correct entity for API's DamageSource#getCausingEntity
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
index 533ea6cbb813c8d1dc2bb3f65fd94d4fa5dd591e..dd9638bdb228a53e72820e0e7cf6fe6fcc08fe4b 100644
|
||||
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
@@ -29,7 +29,8 @@ public class DamageSource {
|
||||
private boolean sweep = false;
|
||||
private boolean melting = false;
|
||||
private boolean poison = false;
|
||||
- private Entity customEntityDamager = null; // This field is a helper for when causing entity damage is not set by vanilla
|
||||
+ @Nullable
|
||||
+ private Entity customEventDamager = null; // This field is a helper for when causing entity damage is not set by vanilla // Paper - fix DamageSource API
|
||||
|
||||
public DamageSource sweep() {
|
||||
this.sweep = true;
|
||||
@@ -58,18 +59,19 @@ public class DamageSource {
|
||||
return this.poison;
|
||||
}
|
||||
|
||||
- public Entity getDamager() {
|
||||
- return (this.customEntityDamager != null) ? this.customEntityDamager : this.directEntity;
|
||||
+ // Paper start - fix DamageSource API
|
||||
+ @Nullable
|
||||
+ public Entity getCustomEventDamager() {
|
||||
+ return (this.customEventDamager != null) ? this.customEventDamager : this.directEntity;
|
||||
}
|
||||
|
||||
- public DamageSource customEntityDamager(Entity entity) {
|
||||
- // This method is not intended for change the causing entity if is already set
|
||||
- // also is only necessary if the entity passed is not the direct entity or different from the current causingEntity
|
||||
- if (this.customEntityDamager != null || this.directEntity == entity || this.causingEntity == entity) {
|
||||
- return this;
|
||||
+ public DamageSource customEventDamager(Entity entity) {
|
||||
+ if (this.directEntity != null) {
|
||||
+ throw new IllegalStateException("Cannot set custom event damager when direct entity is already set (report a bug to Paper)");
|
||||
}
|
||||
DamageSource damageSource = this.cloneInstance();
|
||||
- damageSource.customEntityDamager = entity;
|
||||
+ damageSource.customEventDamager = entity;
|
||||
+ // Paper end - fix DamageSource API
|
||||
return damageSource;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSources.java b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
|
||||
index abda6094e02ebd2589ba0e4760e574fcf44dc8e4..5ec8cbd07a1830876f58e1fd33de6df4466d7e95 100644
|
||||
--- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java
|
||||
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
|
||||
@@ -258,13 +258,7 @@ public class DamageSources {
|
||||
}
|
||||
|
||||
public DamageSource explosion(@Nullable Entity source, @Nullable Entity attacker) {
|
||||
- // CraftBukkit start
|
||||
- return this.explosion(source, attacker, attacker != null && source != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION);
|
||||
- }
|
||||
-
|
||||
- public DamageSource explosion(@Nullable Entity entity, @Nullable Entity entity1, ResourceKey<DamageType> resourceKey) {
|
||||
- return this.source(resourceKey, entity, entity1);
|
||||
- // CraftBukkit end
|
||||
+ return this.source(attacker != null && source != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, source, attacker); // Paper - revert to vanilla
|
||||
}
|
||||
|
||||
public DamageSource sonicBoom(Entity attacker) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index d6ec2fe1a4a004a2d2f7d6e5bfd8fd45b27ebb7a..62363c09111aaa31220fb260940744c097af7b3c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3200,7 +3200,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
return;
|
||||
}
|
||||
|
||||
- if (!this.hurt(this.damageSources().lightningBolt().customEntityDamager(lightning), 5.0F)) {
|
||||
+ if (!this.hurt(this.damageSources().lightningBolt().customEventDamager(lightning), 5.0F)) { // Paper - fix DamageSource API
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
index b4d68a08ec1e4ec7bcc123bcb6c2dc90272430cf..ffffa53fcaa6ec8681b283fa20bb5a3320ad9c11 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -334,7 +334,7 @@ public class Turtle extends Animal {
|
||||
|
||||
@Override
|
||||
public void thunderHit(ServerLevel world, LightningBolt lightning) {
|
||||
- this.hurt(this.damageSources().lightningBolt().customEntityDamager(lightning), Float.MAX_VALUE); // CraftBukkit
|
||||
+ this.hurt(this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
|
||||
index 0ffff5329fa2c7833f9ec71528cb7f951cf78109..bf2d91bbb4bf401696f5f5d14a67e3920a179084 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
|
||||
@@ -203,7 +203,7 @@ public abstract class HangingEntity extends Entity {
|
||||
} else {
|
||||
if (!this.isRemoved() && !this.level().isClientSide) {
|
||||
// CraftBukkit start - fire break events
|
||||
- Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity();
|
||||
+ Entity damager = (source.isIndirect() && source.getEntity() != null) ? source.getEntity() : source.getDirectEntity(); // Paper - fix DamageSource API
|
||||
HangingBreakEvent event;
|
||||
if (damager != null) {
|
||||
event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
index 7db5de71b0353d9807978c0351870fd99b76ee67..0ae4ba060b2ce2c79e1235c939f3c1926eb6e33e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
@@ -271,7 +271,7 @@ public class Creeper extends Monster implements PowerableMob {
|
||||
if (!event.isCancelled()) {
|
||||
// CraftBukkit end
|
||||
this.dead = true;
|
||||
- this.level().explode(this, this.level().damageSources().explosion(this, this.entityIgniter, net.minecraft.world.damagesource.DamageTypes.EXPLOSION), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit
|
||||
+ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
|
||||
this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
|
||||
this.spawnLingeringCloud();
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java
|
||||
index edc5cfd3f3eab176df9080cf932dac3905f1b26d..f8aa723f18e28b02d4b7055404922ff8d7a73f8d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java
|
||||
@@ -133,7 +133,7 @@ public class EvokerFangs extends Entity implements TraceableEntity {
|
||||
|
||||
if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) {
|
||||
if (entityliving1 == null) {
|
||||
- target.hurt(this.damageSources().magic().customEntityDamager(this), 6.0F); // CraftBukkit
|
||||
+ target.hurt(this.damageSources().magic().customEventDamager(this), 6.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
} else {
|
||||
if (entityliving1.isAlliedTo((Entity) target)) {
|
||||
return;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
||||
index ced6bf2fc4556c9b2b32ac382058506e931c1475..519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
||||
@@ -85,7 +85,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
|
||||
|
||||
entityplayer.connection.teleport(teleEvent.getTo());
|
||||
entity.resetFallDistance();
|
||||
- entity.hurt(this.damageSources().fall().customEntityDamager(this), 5.0F); // CraftBukkit
|
||||
+ entity.hurt(this.damageSources().fall().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
}
|
||||
// CraftBukkit end
|
||||
this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
||||
index 02931861de955352e71d6f5ffc720a17304815fe..55b4b5ad5f084c9a271a716d076672478d6486ba 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
||||
@@ -72,7 +72,7 @@ public class WitherSkull extends AbstractHurtingProjectile {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
- flag = entity.hurt(this.damageSources().magic().customCausingEntity(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls
|
||||
+ flag = entity.hurt(this.damageSources().magic().customEventDamager(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
if (flag && entity instanceof LivingEntity) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java
|
||||
index ab67c5caaff6e8c7de293b528636f53254b805bd..6d92856b5089e946a85d519cadce080bc6c3574f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java
|
||||
@@ -47,7 +47,7 @@ public class CraftDamageSource implements DamageSource {
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.Entity getDirectEntity() {
|
||||
- net.minecraft.world.entity.Entity entity = this.getHandle().getDamager();
|
||||
+ net.minecraft.world.entity.Entity entity = this.getHandle().getDirectEntity(); // Paper - fix DamageSource API
|
||||
return (entity != null) ? entity.getBukkitEntity() : null;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class CraftDamageSource implements DamageSource {
|
||||
|
||||
@Override
|
||||
public boolean isIndirect() {
|
||||
- return this.getHandle().getEntity() != this.getHandle().getDamager();
|
||||
+ return this.getHandle().isIndirect(); // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java
|
||||
index 4c6e15535fa40aad8cf1920f392589404f9ba79c..35eb95ef6fb6a0f7ea63351e90741c489fdd15f9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java
|
||||
@@ -41,6 +41,11 @@ public class CraftDamageSourceBuilder implements DamageSource.Builder {
|
||||
|
||||
@Override
|
||||
public DamageSource build() {
|
||||
+ // Paper start - fix DamageCause API
|
||||
+ if (this.causingEntity != null && this.directEntity == null) {
|
||||
+ throw new IllegalArgumentException("Direct entity must be set if causing entity is set");
|
||||
+ }
|
||||
+ // Paper end - fix DamageCause API
|
||||
return CraftDamageSource.buildFromBukkit(this.damageType, this.causingEntity, this.directEntity, this.damageLocation);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index e20feab675d05ae5b5b19870546585936c757970..96070da795755f71e99979288e32b7d7e2d869fb 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1084,7 +1084,7 @@ public class CraftEventFactory {
|
||||
|
||||
private static EntityDamageEvent handleEntityDamageEvent(Entity entity, DamageSource source, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled) {
|
||||
CraftDamageSource bukkitDamageSource = new CraftDamageSource(source);
|
||||
- Entity damager = (source.getDamager() != null) ? source.getDamager() : source.getEntity();
|
||||
+ final Entity damager = source.getCustomEventDamager(); // Paper - fix DamageSource API
|
||||
if (source.is(DamageTypeTags.IS_EXPLOSION)) {
|
||||
if (damager == null) {
|
||||
return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
|
@ -1,59 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Pierpaolo Coletta <p.coletta@glyart.com>
|
||||
Date: Sat, 30 Mar 2024 21:06:10 +0100
|
||||
Subject: [PATCH] Fix creation of invalid block entity during world generation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
index a59eece9c7a8c33cb8ce963906e993c3462684fb..386fbf79afe91af445f54aeab7d1296d1407a4d8 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -323,7 +323,7 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
return false;
|
||||
} else {
|
||||
ChunkAccess ichunkaccess = this.getChunk(pos);
|
||||
- BlockState iblockdata1 = ichunkaccess.setBlockState(pos, state, false);
|
||||
+ BlockState iblockdata1 = ichunkaccess.setBlockState(pos, state, false); final BlockState previousBlockState = iblockdata1; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
|
||||
|
||||
if (iblockdata1 != null) {
|
||||
this.level.onBlockStateChange(pos, iblockdata1, state);
|
||||
@@ -339,6 +339,17 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
ichunkaccess.removeBlockEntity(pos);
|
||||
}
|
||||
} else {
|
||||
+ // Paper start - Clear block entity before setting up a DUMMY block entity
|
||||
+ // The concept of removing a block entity when the block itself changes is generally lifted
|
||||
+ // from LevelChunk#setBlockState.
|
||||
+ // It is however to note that this may only run if the block actually changes.
|
||||
+ // Otherwise a chest block entity generated by a structure template that is later "updated" to
|
||||
+ // be waterlogged would remove its existing block entity (see PaperMC/Paper#10750)
|
||||
+ // This logic is *also* found in LevelChunk#setBlockState.
|
||||
+ if (previousBlockState != null && !java.util.Objects.equals(previousBlockState.getBlock(), state.getBlock())) {
|
||||
+ ichunkaccess.removeBlockEntity(pos);
|
||||
+ }
|
||||
+ // Paper end - Clear block entity before setting up a DUMMY block entity
|
||||
CompoundTag nbttagcompound = new CompoundTag();
|
||||
|
||||
nbttagcompound.putInt("x", pos.getX());
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 744db9eec4f7bdeb32f83300960a7fce63b393d8..8de6ad8b131061b2dae440dff71e2e6e7af2de39 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -1071,9 +1071,14 @@ public class LevelChunk extends ChunkAccess {
|
||||
if (this.blockEntity.getType().isValid(iblockdata)) {
|
||||
this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), iblockdata, this.blockEntity);
|
||||
this.loggedInvalidBlockState = false;
|
||||
- } else if (!this.loggedInvalidBlockState) {
|
||||
- this.loggedInvalidBlockState = true;
|
||||
- LevelChunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new Object[]{LogUtils.defer(this::getType), LogUtils.defer(this::getPos), iblockdata});
|
||||
+ // Paper start - Remove the Block Entity if it's invalid
|
||||
+ } else {
|
||||
+ LevelChunk.this.removeBlockEntity(this.getPos());
|
||||
+ if (!this.loggedInvalidBlockState) {
|
||||
+ this.loggedInvalidBlockState = true;
|
||||
+ LevelChunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new Object[]{LogUtils.defer(this::getType), LogUtils.defer(this::getPos), iblockdata});
|
||||
+ }
|
||||
+ // Paper end - Remove the Block Entity if it's invalid
|
||||
}
|
||||
|
||||
gameprofilerfiller.pop();
|
|
@ -1,108 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 29 Oct 2022 17:02:42 -0700
|
||||
Subject: [PATCH] Fix possible StackOverflowError for some dispenses
|
||||
|
||||
For saddles, carpets, horse armor, and chests for horse-likes
|
||||
a BlockDispenseEvent handler that always mutated the item without
|
||||
changing the type would result in a SO error because when it went
|
||||
to find the replacement dispense behavior (since the item "changed")
|
||||
it didn't properly handle if the replacement was the same instance
|
||||
of dispense behavior.
|
||||
|
||||
Additionally equippable mob heads, wither skulls, and carved pumpkins
|
||||
are subject to the same possible error.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
index 4fa838bf97ede6e1c893ba64f53aa7af5db0405a..32084df594649d8da04052bbfa111896d8ea1f91 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -238,7 +238,7 @@ public interface DispenseItemBehavior {
|
||||
// Chain to handler for new item
|
||||
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
idispensebehavior.dispense(pointer, eventStack);
|
||||
return stack;
|
||||
}
|
||||
@@ -294,7 +294,7 @@ public interface DispenseItemBehavior {
|
||||
// Chain to handler for new item
|
||||
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
idispensebehavior.dispense(pointer, eventStack);
|
||||
return stack;
|
||||
}
|
||||
@@ -368,7 +368,7 @@ public interface DispenseItemBehavior {
|
||||
// Chain to handler for new item
|
||||
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
idispensebehavior.dispense(pointer, eventStack);
|
||||
return stack;
|
||||
}
|
||||
@@ -710,7 +710,7 @@ public interface DispenseItemBehavior {
|
||||
OptionalDispenseItemBehavior dispensebehaviormaybe1 = new OptionalDispenseItemBehavior() {
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
|
||||
- this.setSuccess(ArmorItem.dispenseArmor(pointer, stack));
|
||||
+ this.setSuccess(ArmorItem.dispenseArmor(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
return stack;
|
||||
}
|
||||
};
|
||||
@@ -764,7 +764,7 @@ public interface DispenseItemBehavior {
|
||||
stack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(ArmorItem.dispenseArmor(pointer, stack));
|
||||
+ this.setSuccess(ArmorItem.dispenseArmor(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -810,7 +810,7 @@ public interface DispenseItemBehavior {
|
||||
stack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(ArmorItem.dispenseArmor(pointer, stack));
|
||||
+ this.setSuccess(ArmorItem.dispenseArmor(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return stack;
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java
|
||||
index e766397aae3f73548b290b0809b9d1ca0967ea39..786e4a8700cb84b16dd9b8892a0d1d5803924d81 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ArmorItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ArmorItem.java
|
||||
@@ -48,14 +48,20 @@ public class ArmorItem extends Item implements Equipable {
|
||||
public static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() {
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
|
||||
- return ArmorItem.dispenseArmor(pointer, stack) ? stack : super.execute(pointer, stack);
|
||||
+ return ArmorItem.dispenseArmor(pointer, stack, this) ? stack : super.execute(pointer, stack); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
};
|
||||
protected final ArmorItem.Type type;
|
||||
protected final Holder<ArmorMaterial> material;
|
||||
private final Supplier<ItemAttributeModifiers> defaultModifiers;
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
|
||||
public static boolean dispenseArmor(BlockSource pointer, ItemStack armor) {
|
||||
+ // Paper start
|
||||
+ return dispenseArmor(pointer, armor, null);
|
||||
+ }
|
||||
+ public static boolean dispenseArmor(BlockSource pointer, ItemStack armor, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) {
|
||||
+ // Paper end
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
List<LivingEntity> list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(armor)));
|
||||
|
||||
@@ -86,7 +92,7 @@ public class ArmorItem extends Item implements Equipable {
|
||||
// Chain to handler for new item
|
||||
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || idispensebehavior != currentBehavior)) { // Paper - fix possible StackOverflowError
|
||||
idispensebehavior.dispense(pointer, eventStack);
|
||||
return true;
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Mon, 5 Feb 2024 11:54:04 +0100
|
||||
Subject: [PATCH] Improve tag parser handling
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
index 92848b64a78fce7a92e1657c2da6fc5ee53eea44..4b4f812eb13d5f03bcf3f8724d8aa8dbbc724e8b 100644
|
||||
--- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
+++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
@@ -304,9 +304,15 @@ public class CommandDispatcher<S> {
|
||||
}
|
||||
final CommandContextBuilder<S> context = contextSoFar.copy();
|
||||
final StringReader reader = new StringReader(originalReader);
|
||||
+ boolean stop = false; // Paper - Handle non-recoverable exceptions
|
||||
try {
|
||||
try {
|
||||
child.parse(reader, context);
|
||||
+ // Paper start - Handle non-recoverable exceptions
|
||||
+ } catch (final io.papermc.paper.brigadier.TagParseCommandSyntaxException e) {
|
||||
+ stop = true;
|
||||
+ throw e;
|
||||
+ // Paper end - Handle non-recoverable exceptions
|
||||
} catch (final RuntimeException ex) {
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().createWithContext(reader, ex.getMessage());
|
||||
}
|
||||
@@ -321,6 +327,7 @@ public class CommandDispatcher<S> {
|
||||
}
|
||||
errors.put(child, ex);
|
||||
reader.setCursor(cursor);
|
||||
+ if (stop) return new ParseResults<>(contextSoFar, originalReader, errors); // Paper - Handle non-recoverable exceptions
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/brigadier/TagParseCommandSyntaxException.java b/src/main/java/io/papermc/paper/brigadier/TagParseCommandSyntaxException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a375ad4ba9db990b24a2b9ff366fcba66b753815
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/brigadier/TagParseCommandSyntaxException.java
|
||||
@@ -0,0 +1,15 @@
|
||||
+package io.papermc.paper.brigadier;
|
||||
+
|
||||
+import com.mojang.brigadier.LiteralMessage;
|
||||
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
+import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
+import net.minecraft.network.chat.Component;
|
||||
+
|
||||
+public final class TagParseCommandSyntaxException extends CommandSyntaxException {
|
||||
+
|
||||
+ private static final SimpleCommandExceptionType EXCEPTION_TYPE = new SimpleCommandExceptionType(new LiteralMessage("Error parsing NBT"));
|
||||
+
|
||||
+ public TagParseCommandSyntaxException(final String message) {
|
||||
+ super(EXCEPTION_TYPE, Component.literal(message));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/nbt/TagParser.java b/src/main/java/net/minecraft/nbt/TagParser.java
|
||||
index da101bca71f4710812621b98f0a0d8cab180346a..3cd112584accb8e8f050ac99738eed11c902e60e 100644
|
||||
--- a/src/main/java/net/minecraft/nbt/TagParser.java
|
||||
+++ b/src/main/java/net/minecraft/nbt/TagParser.java
|
||||
@@ -49,6 +49,7 @@ public class TagParser {
|
||||
}, CompoundTag::toString);
|
||||
public static final Codec<CompoundTag> LENIENT_CODEC = Codec.withAlternative(AS_CODEC, CompoundTag.CODEC);
|
||||
private final StringReader reader;
|
||||
+ private int depth; // Paper
|
||||
|
||||
public static CompoundTag parseTag(String string) throws CommandSyntaxException {
|
||||
return new TagParser(new StringReader(string)).readSingleStruct();
|
||||
@@ -159,6 +160,7 @@ public class TagParser {
|
||||
|
||||
public CompoundTag readStruct() throws CommandSyntaxException {
|
||||
this.expect('{');
|
||||
+ this.increaseDepth(); // Paper
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
this.reader.skipWhitespace();
|
||||
|
||||
@@ -182,6 +184,7 @@ public class TagParser {
|
||||
}
|
||||
|
||||
this.expect('}');
|
||||
+ this.depth--; // Paper
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
@@ -191,6 +194,7 @@ public class TagParser {
|
||||
if (!this.reader.canRead()) {
|
||||
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
|
||||
} else {
|
||||
+ this.increaseDepth(); // Paper
|
||||
ListTag listTag = new ListTag();
|
||||
TagType<?> tagType = null;
|
||||
|
||||
@@ -216,6 +220,7 @@ public class TagParser {
|
||||
}
|
||||
|
||||
this.expect(']');
|
||||
+ this.depth--; // Paper
|
||||
return listTag;
|
||||
}
|
||||
}
|
||||
@@ -288,4 +293,11 @@ public class TagParser {
|
||||
this.reader.skipWhitespace();
|
||||
this.reader.expect(c);
|
||||
}
|
||||
+
|
||||
+ private void increaseDepth() throws CommandSyntaxException {
|
||||
+ this.depth++;
|
||||
+ if (this.depth > 512) {
|
||||
+ throw new io.papermc.paper.brigadier.TagParseCommandSyntaxException("NBT tag is too complex, depth > 512");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java b/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java
|
||||
index 56e641bc5f6edc657647993ea2efbb7bb9c2f732..4aa6232bf0f72fcde32d257100bd15b1c5192aaa 100644
|
||||
--- a/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java
|
||||
+++ b/src/main/java/net/minecraft/network/chat/contents/TranslatableContents.java
|
||||
@@ -181,6 +181,15 @@ public class TranslatableContents implements ComponentContents {
|
||||
|
||||
@Override
|
||||
public <T> Optional<T> visit(FormattedText.ContentConsumer<T> visitor) {
|
||||
+ // Paper start - Count visited parts
|
||||
+ try {
|
||||
+ return this.visit(new TranslatableContentConsumer<>(visitor));
|
||||
+ } catch (IllegalArgumentException ignored) {
|
||||
+ return visitor.accept("...");
|
||||
+ }
|
||||
+ }
|
||||
+ private <T> Optional<T> visit(TranslatableContentConsumer<T> visitor) {
|
||||
+ // Paper end - Count visited parts
|
||||
this.decompose();
|
||||
|
||||
for (FormattedText formattedText : this.decomposedParts) {
|
||||
@@ -192,6 +201,25 @@ public class TranslatableContents implements ComponentContents {
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
+ // Paper start - Count visited parts
|
||||
+ private static final class TranslatableContentConsumer<T> implements FormattedText.ContentConsumer<T> {
|
||||
+ private static final IllegalArgumentException EX = new IllegalArgumentException("Too long");
|
||||
+ private final FormattedText.ContentConsumer<T> visitor;
|
||||
+ private int visited;
|
||||
+
|
||||
+ private TranslatableContentConsumer(FormattedText.ContentConsumer<T> visitor) {
|
||||
+ this.visitor = visitor;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Optional<T> accept(final String asString) {
|
||||
+ if (visited++ > 32) {
|
||||
+ throw EX;
|
||||
+ }
|
||||
+ return this.visitor.accept(asString);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Count visited parts
|
||||
|
||||
@Override
|
||||
public MutableComponent resolve(@Nullable CommandSourceStack source, @Nullable Entity sender, int depth) throws CommandSyntaxException {
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java
|
||||
index 898b19887ed34c87003fc63cb5905df2ba6234a5..b47eeb23055b135d5567552ba983bfbc3e1fab67 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java
|
||||
@@ -19,7 +19,7 @@ public class ServerboundCommandSuggestionPacket implements Packet<ServerGamePack
|
||||
|
||||
private ServerboundCommandSuggestionPacket(FriendlyByteBuf buf) {
|
||||
this.id = buf.readVarInt();
|
||||
- this.command = buf.readUtf(32500);
|
||||
+ this.command = buf.readUtf(2048); // Paper
|
||||
}
|
||||
|
||||
private void write(FriendlyByteBuf buf) {
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index bead9625a04a9c1139c54d6a56f055b80eb2d701..34d4243fb5198e36ea3291ffe8ed2480bc960cdb 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -763,6 +763,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// Paper end - Don't suggest if tab-complete is disabled
|
||||
+ // Paper start
|
||||
+ final int index;
|
||||
+ if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) {
|
||||
+ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
// Paper start - AsyncTabCompleteEvent
|
||||
TAB_COMPLETE_EXECUTOR.execute(() -> this.handleCustomCommandSuggestions0(packet));
|
||||
}
|
||||
@@ -815,6 +822,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
private void sendServerSuggestions(final ServerboundCommandSuggestionPacket packet, final StringReader stringreader) {
|
||||
// Paper end - AsyncTabCompleteEvent
|
||||
ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
|
||||
+ // Paper start - Handle non-recoverable exceptions
|
||||
+ if (!parseresults.getExceptions().isEmpty()
|
||||
+ && parseresults.getExceptions().values().stream().anyMatch(e -> e instanceof io.papermc.paper.brigadier.TagParseCommandSyntaxException)) {
|
||||
+ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Handle non-recoverable exceptions
|
||||
|
||||
this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
|
||||
// Paper start - Don't tab-complete namespaced commands if send-namespaced is false
|
|
@ -1,38 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Wed, 20 Mar 2024 20:41:35 -0400
|
||||
Subject: [PATCH] Item Mutation Fixes
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
index 2f62957e061f513e01ec617f22791a7f27d65f02..480d093105073edfd3acdd7b079b4ca5aa5fdc6d 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
@@ -228,7 +228,7 @@ public class EnchantmentMenu extends AbstractContainerMenu {
|
||||
return false;
|
||||
} else if (this.costs[id] > 0 && !itemstack.isEmpty() && (player.experienceLevel >= j && player.experienceLevel >= this.costs[id] || player.getAbilities().instabuild)) {
|
||||
this.access.execute((world, blockposition) -> {
|
||||
- ItemStack itemstack2 = itemstack;
|
||||
+ ItemStack itemstack2 = itemstack; // Paper - diff on change
|
||||
List<EnchantmentInstance> list = this.getEnchantmentList(world.enabledFeatures(), itemstack, id, this.costs[id]);
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -250,10 +250,16 @@ public class EnchantmentMenu extends AbstractContainerMenu {
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- if (itemstack.is(Items.BOOK)) {
|
||||
- itemstack2 = itemstack.transmuteCopy(Items.ENCHANTED_BOOK, 1);
|
||||
+ // Paper start
|
||||
+ itemstack2 = org.bukkit.craftbukkit.inventory.CraftItemStack.getOrCloneOnMutation(item, event.getItem());
|
||||
+ if (itemstack2 != itemstack) {
|
||||
this.enchantSlots.setItem(0, itemstack2);
|
||||
}
|
||||
+ if (itemstack2.is(Items.BOOK)) {
|
||||
+ itemstack2 = itemstack2.transmuteCopy(Items.ENCHANTED_BOOK, 1);
|
||||
+ this.enchantSlots.setItem(0, itemstack2);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
for (Map.Entry<org.bukkit.enchantments.Enchantment, Integer> entry : event.getEnchantsToAdd().entrySet()) {
|
Loading…
Add table
Add a link
Reference in a new issue