Patch me this, patch me that
This commit is contained in:
parent
457d03534d
commit
80de05ff33
73 changed files with 762 additions and 786 deletions
|
@ -1,91 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 18 Dec 2022 13:40:05 -0800
|
||||
Subject: [PATCH] More DragonBattle API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.dimension.end.EndDragonFight GATEWAY_COUNT
|
||||
public net.minecraft.world.level.dimension.end.EndDragonFight gateways
|
||||
public net.minecraft.world.level.dimension.end.EndDragonFight respawnCrystals
|
||||
public net.minecraft.world.level.dimension.end.EndDragonFight spawnNewGateway(Lnet/minecraft/core/BlockPos;)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
index bf39f006efef529db697ed4dccbd1657a2673b79..4a0479fcff94bf6a1f239c1f694202345cdea1d4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
@@ -441,6 +441,24 @@ public class EndDragonFight {
|
||||
this.gateways.clear();
|
||||
}
|
||||
|
||||
+ // Paper start - More DragonBattle API
|
||||
+ public boolean spawnNewGatewayIfPossible() {
|
||||
+ if (!this.gateways.isEmpty()) {
|
||||
+ this.spawnNewGateway();
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public List<EndCrystal> getSpikeCrystals() {
|
||||
+ final List<EndCrystal> endCrystals = new java.util.ArrayList<>();
|
||||
+ for (final SpikeFeature.EndSpike spike : SpikeFeature.getSpikesForLevel(this.level)) {
|
||||
+ endCrystals.addAll(this.level.getEntitiesOfClass(EndCrystal.class, spike.getTopBoundingBox()));
|
||||
+ }
|
||||
+ return endCrystals;
|
||||
+ }
|
||||
+ // Paper end - More DragonBattle API
|
||||
+
|
||||
private void spawnNewGateway() {
|
||||
if (!this.gateways.isEmpty()) {
|
||||
int i = (Integer) this.gateways.remove(this.gateways.size() - 1);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
|
||||
index dc7fdc120f4317ee1b7935ef226eddb0406aee6e..6bfabb38b51115beb2a65a165f235347838b6006 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
|
||||
@@ -137,4 +137,46 @@ public class CraftDragonBattle implements DragonBattle {
|
||||
private DragonRespawnAnimation toNMSRespawnPhase(RespawnPhase phase) {
|
||||
return (phase != RespawnPhase.NONE) ? DragonRespawnAnimation.values()[phase.ordinal()] : null;
|
||||
}
|
||||
+ // Paper start - More DragonBattle API
|
||||
+ @Override
|
||||
+ public int getGatewayCount() {
|
||||
+ return EndDragonFight.GATEWAY_COUNT - this.handle.gateways.size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean spawnNewGateway() {
|
||||
+ return this.handle.spawnNewGatewayIfPossible();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void spawnNewGateway(final io.papermc.paper.math.Position position) {
|
||||
+ this.handle.spawnNewGateway(io.papermc.paper.util.MCUtil.toBlockPos(position));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.EnderCrystal> getRespawnCrystals() {
|
||||
+ if (this.handle.respawnCrystals == null) {
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ final java.util.List<org.bukkit.entity.EnderCrystal> enderCrystals = new java.util.ArrayList<>();
|
||||
+ for (final net.minecraft.world.entity.boss.enderdragon.EndCrystal endCrystal : this.handle.respawnCrystals) {
|
||||
+ if (!endCrystal.isRemoved() && endCrystal.isAlive() && endCrystal.valid) {
|
||||
+ enderCrystals.add(((org.bukkit.entity.EnderCrystal) endCrystal.getBukkitEntity()));
|
||||
+ }
|
||||
+ }
|
||||
+ return java.util.Collections.unmodifiableList(enderCrystals);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.EnderCrystal> getHealingCrystals() {
|
||||
+ final java.util.List<org.bukkit.entity.EnderCrystal> enderCrystals = new java.util.ArrayList<>();
|
||||
+ for (final net.minecraft.world.entity.boss.enderdragon.EndCrystal endCrystal : this.handle.getSpikeCrystals()) {
|
||||
+ if (!endCrystal.isRemoved() && endCrystal.isAlive() && endCrystal.valid) {
|
||||
+ enderCrystals.add(((org.bukkit.entity.EnderCrystal) endCrystal.getBukkitEntity()));
|
||||
+ }
|
||||
+ }
|
||||
+ return java.util.Collections.unmodifiableList(enderCrystals);
|
||||
+ }
|
||||
+ // Paper end - More DragonBattle API
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: RodneyMKay <36546810+RodneyMKay@users.noreply.github.com>
|
||||
Date: Wed, 8 Sep 2021 21:34:01 +0200
|
||||
Subject: [PATCH] Add PlayerPickItemEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 7750660defe490bcdc24a3b4ad4f495c8a703fed..be0ce72bb493593a3d2eb7d7c37e3a650b7cc34b 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -935,8 +935,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
this.disconnect(Component.literal("Invalid hotbar selection (Hacking?)"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause
|
||||
return;
|
||||
}
|
||||
- this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed
|
||||
// Paper end - validate pick item position
|
||||
+ // Paper start - Add PlayerPickItemEvent
|
||||
+ Player bukkitPlayer = this.player.getBukkitEntity();
|
||||
+ int targetSlot = this.player.getInventory().getSuitableHotbarSlot();
|
||||
+ int sourceSlot = packet.getSlot();
|
||||
+
|
||||
+ io.papermc.paper.event.player.PlayerPickItemEvent event = new io.papermc.paper.event.player.PlayerPickItemEvent(bukkitPlayer, targetSlot, sourceSlot);
|
||||
+ if (!event.callEvent()) return;
|
||||
+
|
||||
+ this.player.getInventory().pickSlot(event.getSourceSlot(), event.getTargetSlot());
|
||||
+ // Paper end - Add PlayerPickItemEvent
|
||||
this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected)));
|
||||
this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot())));
|
||||
this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected));
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java
|
||||
index 688ed0c32b05b0135b94ec05738cdc6ff8dcb677..a62e7354bf67a66bdf9cd7c8f5d2e8f6bcacc74f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -171,7 +171,13 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
public void pickSlot(int slot) {
|
||||
- this.selected = this.getSuitableHotbarSlot();
|
||||
+ // Paper start - Add PlayerPickItemEvent
|
||||
+ pickSlot(slot, this.getSuitableHotbarSlot());
|
||||
+ }
|
||||
+
|
||||
+ public void pickSlot(int slot, int targetSlot) {
|
||||
+ this.selected = targetSlot;
|
||||
+ // Paper end - Add PlayerPickItemEvent
|
||||
ItemStack itemstack = (ItemStack) this.items.get(this.selected);
|
||||
|
||||
this.items.set(this.selected, (ItemStack) this.items.get(slot));
|
|
@ -1,39 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
Date: Tue, 12 Jul 2022 18:01:14 +0200
|
||||
Subject: [PATCH] Allow trident custom damage
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
|
||||
index e45c3a9805d9fac1fabe6d891c817743acd9969e..44c733c5b2c3e9942f28e882ad72306a24459c2c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
|
||||
@@ -36,16 +36,19 @@ public class ThrownTrident extends AbstractArrow {
|
||||
|
||||
public ThrownTrident(EntityType<? extends ThrownTrident> type, Level world) {
|
||||
super(type, world);
|
||||
+ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage
|
||||
}
|
||||
|
||||
public ThrownTrident(Level world, LivingEntity owner, ItemStack stack) {
|
||||
super(EntityType.TRIDENT, owner, world, stack, (ItemStack) null);
|
||||
+ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage
|
||||
this.entityData.set(ThrownTrident.ID_LOYALTY, this.getLoyaltyFromItem(stack));
|
||||
this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil());
|
||||
}
|
||||
|
||||
public ThrownTrident(Level world, double x, double y, double z, ItemStack stack) {
|
||||
super(EntityType.TRIDENT, x, y, z, world, stack, stack);
|
||||
+ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage
|
||||
this.entityData.set(ThrownTrident.ID_LOYALTY, this.getLoyaltyFromItem(stack));
|
||||
this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil());
|
||||
}
|
||||
@@ -129,7 +132,7 @@ public class ThrownTrident extends AbstractArrow {
|
||||
@Override
|
||||
protected void onHitEntity(EntityHitResult entityHitResult) {
|
||||
Entity entity = entityHitResult.getEntity();
|
||||
- float f = 8.0F;
|
||||
+ float f = (float) this.getBaseDamage(); // Paper - Allow trident custom damage
|
||||
Entity entity1 = this.getOwner();
|
||||
DamageSource damagesource = this.damageSources().trident(this, (Entity) (entity1 == null ? this : entity1));
|
||||
Level world = this.level();
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: The456gamer <the456gamer@the456gamer.dev>
|
||||
Date: Mon, 21 Aug 2023 14:13:42 +0100
|
||||
Subject: [PATCH] Expose hand in BlockCanBuildEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
index 7180996027f70aef7afe32fb2adfce6431429401..fc7d978f9e57814a933b9cb725c3af1e7d403795 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
@@ -191,7 +191,7 @@ public class BlockItem extends Item {
|
||||
boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper - Cancel hit for vanished players
|
||||
org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
|
||||
|
||||
- BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn);
|
||||
+ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
|
||||
context.getLevel().getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
return event.isBuildable();
|
||||
diff --git a/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java b/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
index 39b8b3675ac58409e05fac07e07c8016c5280d81..f8f909ebdad5e96379e8bd8c610164ef0697368e 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
@@ -59,7 +59,7 @@ public class StandingAndWallBlockItem extends BlockItem {
|
||||
boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty());
|
||||
org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
|
||||
|
||||
- BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn);
|
||||
+ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
|
||||
context.getLevel().getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
return (event.isBuildable()) ? iblockdata1 : null;
|
|
@ -1,39 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Muijsers <martijnmuijsers@live.nl>
|
||||
Date: Mon, 21 Aug 2023 21:05:09 +0200
|
||||
Subject: [PATCH] Optimize nearest structure border iteration
|
||||
|
||||
Getting the nearest generated structure contains a nested set of loops that
|
||||
iterates over all chunks at a specific chessboard distance. It does this by
|
||||
iterating over the entire square of chunks within that distance, and checking
|
||||
if the coordinates are at exactly the right distance to be on the border.
|
||||
|
||||
This patch optimizes the iteration by only iterating over the border chunks.
|
||||
This evaluated chunks are the same, and in the same order, as before, to
|
||||
ensure that the returned found structure (which may for example be a buried
|
||||
treasure that will be marked on a treasure map) is the same as in vanilla.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index 102de569415ef011dacdca9a6ea8134d0ef62454..29697fad32dad3377eebc82d280ba48d3c1ad516 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -265,12 +265,15 @@ public abstract class ChunkGenerator {
|
||||
int i1 = placement.spacing();
|
||||
|
||||
for (int j1 = -radius; j1 <= radius; ++j1) {
|
||||
- boolean flag1 = j1 == -radius || j1 == radius;
|
||||
+ // Paper start - Perf: iterate over border chunks instead of entire square chunk area
|
||||
+ boolean flag1 = j1 == -radius || j1 == radius; final boolean onBorderAlongZAxis = flag1; // Paper - OBFHELPER
|
||||
|
||||
- for (int k1 = -radius; k1 <= radius; ++k1) {
|
||||
- boolean flag2 = k1 == -radius || k1 == radius;
|
||||
+ for (int k1 = -radius; k1 <= radius; k1 += onBorderAlongZAxis ? 1 : radius * 2) {
|
||||
+ // boolean flag2 = k1 == -radius || k1 == radius;
|
||||
|
||||
- if (flag1 || flag2) {
|
||||
+ // if (flag1 || flag2) {
|
||||
+ if (true) {
|
||||
+ // Paper end - Perf: iterate over border chunks instead of entire square chunk area
|
||||
int l1 = centerChunkX + i1 * j1;
|
||||
int i2 = centerChunkZ + i1 * k1;
|
||||
ChunkPos chunkcoordintpair = placement.getPotentialStructureChunk(seed, l1, i2);
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aeltumn <daniel@goossens.ch>
|
||||
Date: Thu, 24 Aug 2023 13:05:30 +0200
|
||||
Subject: [PATCH] Implement OfflinePlayer#isConnected
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
index 2c2c4db31a746b4eb853dc04c6b3e5631bbfa034..4f4e3ee18d586f61706504218cddc06a38ca5580 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
@@ -54,6 +54,13 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
||||
return this.getPlayer() != null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isConnected() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public String getName() {
|
||||
Player player = this.getPlayer();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index a3912d4de96a6bb2b9b3977705fa3facb891f73d..a1b870fb3d1fd5d209474c47bf523d0d5d58ce39 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -256,6 +256,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
return this.server.getPlayer(this.getUniqueId()) != null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isConnected() {
|
||||
+ return !this.getHandle().hasDisconnected();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public InetSocketAddress getAddress() {
|
||||
if (this.getHandle().connection.protocol() == null) return null;
|
|
@ -1,129 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 23 Aug 2023 13:22:09 -0700
|
||||
Subject: [PATCH] Fix slot desync
|
||||
|
||||
General patch fixing slot desyncs between the server and client that
|
||||
result from cancelled events/paper introduced logic.
|
||||
|
||||
Co-authored-by: Minecrell <minecrell@minecrell.net>
|
||||
Co-authored-by: Newwind <support@newwindserver.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 7270b6fa96bae937663c0fea77887e21fbd0eb57..530728cd4b258444f6efe064903b521f4b23cd04 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -400,6 +400,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
|
||||
// Use method to resend items in hands in case of client desync, because the item use got cancelled.
|
||||
// For example, when cancelling the leash event
|
||||
+ @Deprecated // Paper - this shouldn't be used, use the regular sendAllDataToRemote call to resync all
|
||||
public void resendItemInHands() {
|
||||
this.containerMenu.findSlot(this.getInventory(), this.getInventory().selected).ifPresent(s -> {
|
||||
this.containerSynchronizer.sendSlotChange(this.containerMenu, s, this.getMainHandItem());
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index be0ce72bb493593a3d2eb7d7c37e3a650b7cc34b..0ffa95542a0ed49a3f83700841f7c76c0717ae22 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2729,10 +2729,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
// Refresh the current entity metadata
|
||||
entity.refreshEntityData(ServerGamePacketListenerImpl.this.player);
|
||||
// SPIGOT-7136 - Allays
|
||||
- if (entity instanceof Allay) {
|
||||
+ if (entity instanceof Allay || entity instanceof net.minecraft.world.entity.animal.horse.AbstractHorse) { // Paper - Fix horse armor desync
|
||||
ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList())));
|
||||
- ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote();
|
||||
}
|
||||
+
|
||||
+ ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote(); // Paper - fix slot desync - always refresh player inventory
|
||||
}
|
||||
|
||||
if (event.isCancelled()) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 84d283cd637b5c84a8682acec503b0e3831d1684..bd0e205c760414784ae483452fd02292939dcb5c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2638,8 +2638,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
if (!this.level().isClientSide()) {
|
||||
// CraftBukkit start - fire PlayerLeashEntityEvent
|
||||
if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) {
|
||||
- ((ServerPlayer) player).resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item
|
||||
+ // ((ServerPlayer) player).resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item // Paper - Fix inventory desync
|
||||
((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, leashable.getLeashHolder()));
|
||||
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java
|
||||
index 5a7b1be351834a6b8889b1380cede1be025cb302..e336934f37075a827843e4b1bb2b6b660d2c60c9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java
|
||||
@@ -101,6 +101,7 @@ public class Cow extends Animal {
|
||||
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
index 02e49c7ae5e120302b6479cf3e3934b9217eebf0..376bcbc189008464f4d518c1e07643431ba96306 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -234,6 +234,7 @@ public class Goat extends Animal {
|
||||
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java
|
||||
index 1634a7d5ff06583408cf2f02f2b5f90931b1e02a..066a6e5ed2632a55324ec0d10f2f8a6bf3f30a0f 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java
|
||||
@@ -55,6 +55,7 @@ public class ArmorStandItem extends Item {
|
||||
entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F);
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityarmorstand).isCancelled()) {
|
||||
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
index fc7d978f9e57814a933b9cb725c3af1e7d403795..96fb69ec6db2e7c8c728435f0c537b076259b2fb 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
@@ -114,7 +114,7 @@ public class BlockItem extends Item {
|
||||
if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
|
||||
blockstate.update(true, false);
|
||||
|
||||
- if (this instanceof SolidBucketItem) {
|
||||
+ if (true) { // Paper - if the event is called here, the inventory should be updated
|
||||
((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
|
||||
}
|
||||
return InteractionResult.FAIL;
|
||||
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
|
||||
index f9a940cdff3983d9d4de46bd5ddc1905f9254dcf..273bb38f14b8af08d123e02742d365fb5d91cdf5 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
|
||||
@@ -49,6 +49,7 @@ public class EndCrystalItem extends Item {
|
||||
entityendercrystal.setShowBottom(false);
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityendercrystal).isCancelled()) {
|
||||
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java
|
||||
index 66074445d3908b9bb1c8d70e1e27d057720ec8e5..d524fcc191cb95d6ec7f12ae7fceeb8077bb08fc 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/MinecartItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/MinecartItem.java
|
||||
@@ -137,6 +137,7 @@ public class MinecartItem extends Item {
|
||||
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityminecartabstract).isCancelled()) {
|
||||
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
// CraftBukkit end
|
|
@ -1,120 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 4 Mar 2022 12:45:03 -0800
|
||||
Subject: [PATCH] Add titleOverride to InventoryOpenEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 530728cd4b258444f6efe064903b521f4b23cd04..b65d816bb9feb18ecf74e10e9728c302e5657587 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1656,12 +1656,17 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
this.nextContainerCounter();
|
||||
AbstractContainerMenu container = factory.createMenu(this.containerCounter, this.getInventory(), this);
|
||||
|
||||
+ Component title = null; // Paper - Add titleOverride to InventoryOpenEvent
|
||||
// CraftBukkit start - Inventory open hook
|
||||
if (container != null) {
|
||||
container.setTitle(factory.getDisplayName());
|
||||
|
||||
boolean cancelled = false;
|
||||
- container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled);
|
||||
+ // Paper start - Add titleOverride to InventoryOpenEvent
|
||||
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(this, container, cancelled);
|
||||
+ container = result.getSecond();
|
||||
+ title = PaperAdventure.asVanilla(result.getFirst());
|
||||
+ // Paper end - Add titleOverride to InventoryOpenEvent
|
||||
if (container == null && !cancelled) { // Let pre-cancelled events fall through
|
||||
// SPIGOT-5263 - close chest if cancelled
|
||||
if (factory instanceof Container) {
|
||||
@@ -1683,7 +1688,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
this.containerMenu = container;
|
||||
- if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - Prevent opening inventories when frozen
|
||||
+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper - Add titleOverride to InventoryOpenEvent
|
||||
// CraftBukkit end
|
||||
this.initMenu(container);
|
||||
return OptionalInt.of(this.containerCounter);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
index b782cc64426a058881947ed62316c1cb8d332037..7dcfb45c24d7743956be514c7d554e06aac77b3e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
@@ -366,12 +366,16 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
Preconditions.checkArgument(windowType != null, "Unknown windowType");
|
||||
AbstractContainerMenu container = new CraftContainer(inventory, player, player.nextContainerCounter());
|
||||
|
||||
- container = CraftEventFactory.callInventoryOpenEvent(player, container);
|
||||
+ // Paper start - Add titleOverride to InventoryOpenEvent
|
||||
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container);
|
||||
+ container = result.getSecond();
|
||||
+ // Paper end - Add titleOverride to InventoryOpenEvent
|
||||
if (container == null) return;
|
||||
|
||||
//String title = container.getBukkitView().getTitle(); // Paper - comment
|
||||
net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper
|
||||
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(container.getBukkitView().getTitle()); // Paper
|
||||
+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent
|
||||
|
||||
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
|
||||
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
|
||||
@@ -448,7 +452,10 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
}
|
||||
|
||||
// Trigger an INVENTORY_OPEN event
|
||||
- container = CraftEventFactory.callInventoryOpenEvent(player, container);
|
||||
+ // Paper start - Add titleOverride to InventoryOpenEvent
|
||||
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container);
|
||||
+ container = result.getSecond();
|
||||
+ // Paper end - Add titleOverride to InventoryOpenEvent
|
||||
if (container == null) {
|
||||
return;
|
||||
}
|
||||
@@ -459,6 +466,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
//String title = inventory.getTitle(); // Paper - comment
|
||||
net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper
|
||||
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper
|
||||
+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent
|
||||
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
|
||||
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
|
||||
player.containerMenu = container;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 6b241ec85f360ec79f18b911175d7092861024a4..2690c471b819f8308f6db44150025dfa323d4e0c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1403,10 +1403,21 @@ public class CraftEventFactory {
|
||||
}
|
||||
|
||||
public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container) {
|
||||
- return CraftEventFactory.callInventoryOpenEvent(player, container, false);
|
||||
+ // Paper start - Add titleOverride to InventoryOpenEvent
|
||||
+ return callInventoryOpenEventWithTitle(player, container).getSecond();
|
||||
+ }
|
||||
+ public static com.mojang.datafixers.util.Pair<net.kyori.adventure.text.@org.jetbrains.annotations.Nullable Component, @org.jetbrains.annotations.Nullable AbstractContainerMenu> callInventoryOpenEventWithTitle(ServerPlayer player, AbstractContainerMenu container) {
|
||||
+ return CraftEventFactory.callInventoryOpenEventWithTitle(player, container, false);
|
||||
+ // Paper end - Add titleOverride to InventoryOpenEvent
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - use method that acknowledges title overrides
|
||||
public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) {
|
||||
+ // Paper start - Add titleOverride to InventoryOpenEvent
|
||||
+ return callInventoryOpenEventWithTitle(player, container, cancelled).getSecond();
|
||||
+ }
|
||||
+ public static com.mojang.datafixers.util.Pair<net.kyori.adventure.text.@org.jetbrains.annotations.Nullable Component, @org.jetbrains.annotations.Nullable AbstractContainerMenu> callInventoryOpenEventWithTitle(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) {
|
||||
+ // Paper end - Add titleOverride to InventoryOpenEvent
|
||||
if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open
|
||||
player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - Inventory close reason
|
||||
}
|
||||
@@ -1421,10 +1432,10 @@ public class CraftEventFactory {
|
||||
|
||||
if (event.isCancelled()) {
|
||||
container.transferTo(player.containerMenu, craftPlayer);
|
||||
- return null;
|
||||
+ return com.mojang.datafixers.util.Pair.of(null, null); // Paper - Add titleOverride to InventoryOpenEvent
|
||||
}
|
||||
|
||||
- return container;
|
||||
+ return com.mojang.datafixers.util.Pair.of(event.titleOverride(), container); // Paper - Add titleOverride to InventoryOpenEvent
|
||||
}
|
||||
|
||||
public static ItemStack callPreCraftEvent(CraftingContainer matrix, Container resultInventory, ItemStack result, InventoryView lastCraftView, boolean isRepair) {
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
Date: Tue, 27 Jun 2023 13:26:06 +0200
|
||||
Subject: [PATCH] Configure sniffer egg hatch time
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
|
||||
index b943384eb6a4612993556036f0d3beec6939a559..ffe5e14cf8190774c8935513ebeb041eda81f912 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
|
||||
@@ -62,7 +62,7 @@ public class SnifferEggBlock extends Block {
|
||||
|
||||
// Paper start - Call BlockFadeEvent
|
||||
private void rescheduleTick(ServerLevel world, BlockPos pos) {
|
||||
- int baseDelay = hatchBoost(world, pos) ? BOOSTED_HATCH_TIME_TICKS : REGULAR_HATCH_TIME_TICKS;
|
||||
+ int baseDelay = hatchBoost(world, pos) ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper - Configure sniffer egg hatch time
|
||||
world.scheduleTick(pos, this, (baseDelay / 3) + world.random.nextInt(RANDOM_HATCH_OFFSET_TICKS));
|
||||
// reschedule to avoid being stuck here and behave like the other calls (see #onPlace)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ public class SnifferEggBlock extends Block {
|
||||
world.levelEvent(3009, pos, 0);
|
||||
}
|
||||
|
||||
- int i = bl ? 12000 : 24000;
|
||||
+ int i = bl ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper
|
||||
int j = i / 3;
|
||||
world.gameEvent(GameEvent.BLOCK_PLACE, pos, GameEvent.Context.of(state));
|
||||
world.scheduleTick(pos, this, j + world.random.nextInt(300));
|
|
@ -1,75 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Muijsers <martijnmuijsers@live.nl>
|
||||
Date: Tue, 15 Aug 2023 21:04:55 +0200
|
||||
Subject: [PATCH] Do crystal-portal proximity check before entity lookup
|
||||
|
||||
This adds a very cheap distance check when an end crystal is placed.
|
||||
|
||||
Attempting to respawn the dragon, which involves looking up the end crystal
|
||||
entities near the portal, every time an end crystal is placed, can be slow on
|
||||
some servers that have players placing end crystals as a style of combat.
|
||||
|
||||
The very cheap distance check prevents running the entity lookup every time.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
|
||||
index 273bb38f14b8af08d123e02742d365fb5d91cdf5..5f51e64cb0611a4ba6bdcdcacbcba1063a7f3a5c 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
|
||||
@@ -30,7 +30,7 @@ public class EndCrystalItem extends Item {
|
||||
if (!iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) {
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
- BlockPos blockposition1 = blockposition.above();
|
||||
+ BlockPos blockposition1 = blockposition.above(); final BlockPos aboveBlockPosition = blockposition1; // Paper - OBFHELPER
|
||||
|
||||
if (!world.isEmptyBlock(blockposition1)) {
|
||||
return InteractionResult.FAIL;
|
||||
@@ -58,7 +58,7 @@ public class EndCrystalItem extends Item {
|
||||
EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight();
|
||||
|
||||
if (enderdragonbattle != null) {
|
||||
- enderdragonbattle.tryRespawn();
|
||||
+ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
index 4a0479fcff94bf6a1f239c1f694202345cdea1d4..84300f2f7b7be4f5281edd8e263646dbcbb3ba07 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
@@ -560,6 +560,12 @@ public class EndDragonFight {
|
||||
}
|
||||
|
||||
public boolean tryRespawn() { // CraftBukkit - return boolean
|
||||
+ // Paper start - Perf: Do crystal-portal proximity check before entity lookup
|
||||
+ return this.tryRespawn(null);
|
||||
+ }
|
||||
+
|
||||
+ public boolean tryRespawn(@Nullable BlockPos placedEndCrystalPos) { // placedEndCrystalPos is null if the tryRespawn() call was not caused by a placed end crystal
|
||||
+ // Paper end - Perf: Do crystal-portal proximity check before entity lookup
|
||||
if (this.dragonKilled && this.respawnStage == null) {
|
||||
BlockPos blockposition = this.portalLocation;
|
||||
|
||||
@@ -577,6 +583,22 @@ public class EndDragonFight {
|
||||
blockposition = this.portalLocation;
|
||||
}
|
||||
|
||||
+ // Paper start - Perf: Do crystal-portal proximity check before entity lookup
|
||||
+ if (placedEndCrystalPos != null) {
|
||||
+ // The end crystal must be 0 or 1 higher than the portal origin
|
||||
+ int dy = placedEndCrystalPos.getY() - blockposition.getY();
|
||||
+ if (dy != 0 && dy != 1) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // The end crystal must be within a distance of 1 in one planar direction, and 3 in the other
|
||||
+ int dx = placedEndCrystalPos.getX() - blockposition.getX();
|
||||
+ int dz = placedEndCrystalPos.getZ() - blockposition.getZ();
|
||||
+ if (!((dx >= -1 && dx <= 1 && dz >= -3 && dz <= 3) || (dx >= -3 && dx <= 3 && dz >= -1 && dz <= 1))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Perf: Do crystal-portal proximity check before entity lookup
|
||||
+
|
||||
List<EndCrystal> list = Lists.newArrayList();
|
||||
BlockPos blockposition1 = blockposition.above(1);
|
||||
Iterator iterator = Direction.Plane.HORIZONTAL.iterator();
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Sauve <paul@technove.co>
|
||||
Date: Thu, 18 Feb 2021 13:13:27 -0600
|
||||
Subject: [PATCH] Skip POI finding if stuck in vehicle
|
||||
|
||||
Copyright (C) 2020 Technove LLC
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
index 21e50342598f7cd9efa1a39e70bd72d152d98812..e8aa27547e3fa1a42720889c7038d4fb0273e7b5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
@@ -57,6 +57,7 @@ public class AcquirePoi {
|
||||
return false;
|
||||
} else {
|
||||
mutableLong.setValue(time + 20L + (long)world.getRandom().nextInt(20));
|
||||
+ if (entity.getNavigation().isStuck()) mutableLong.add(200); // Paper - Perf: Wait an additional 10s to check again if they're stuck
|
||||
PoiManager poiManager = world.getPoiManager();
|
||||
long2ObjectMap.long2ObjectEntrySet().removeIf(entry -> !entry.getValue().isStillValid(time));
|
||||
Predicate<BlockPos> predicate2 = pos -> {
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Mon, 11 Sep 2023 12:01:57 +1000
|
||||
Subject: [PATCH] Add slot sanity checks in container clicks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0ffa95542a0ed49a3f83700841f7c76c0717ae22..d377804026f3f5cf80a623228d24e09c56ef0dae 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2986,6 +2986,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
break;
|
||||
case SWAP:
|
||||
if ((packet.getButtonNum() >= 0 && packet.getButtonNum() < 9) || packet.getButtonNum() == 40) {
|
||||
+ // Paper start - Add slot sanity checks to container clicks
|
||||
+ if (packet.getSlotNum() < 0) {
|
||||
+ action = InventoryAction.NOTHING;
|
||||
+ break;
|
||||
+ }
|
||||
+ // Paper end - Add slot sanity checks to container clicks
|
||||
click = (packet.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY;
|
||||
Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum());
|
||||
if (clickedSlot.mayPickup(this.player)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 0e380151b038e2133013eb7d73621cf247b5b954..afd8f48bd41d2cac413c292f7988c903da1dc700 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -423,6 +423,7 @@ public abstract class AbstractContainerMenu {
|
||||
this.resetQuickCraft();
|
||||
}
|
||||
} else if (this.quickcraftStatus == 1) {
|
||||
+ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks
|
||||
slot = (Slot) this.slots.get(slotIndex);
|
||||
itemstack = this.getCarried();
|
||||
if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) {
|
||||
@@ -597,6 +598,7 @@ public abstract class AbstractContainerMenu {
|
||||
int j2;
|
||||
|
||||
if (actionType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) {
|
||||
+ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks
|
||||
ItemStack itemstack4 = playerinventory.getItem(button);
|
||||
|
||||
slot = (Slot) this.slots.get(slotIndex);
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
|
||||
Date: Wed, 13 Sep 2023 05:46:10 +0200
|
||||
Subject: [PATCH] Call BlockRedstoneEvents for lecterns
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LecternBlock.java b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
index 751ff3d51f8ae57f847c3acf7a7cd663a6ae1c68..0c52e1f8bc233bb66e53f4c69e1d8757382bbe81 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
@@ -179,6 +179,16 @@ public class LecternBlock extends BaseEntityBlock {
|
||||
}
|
||||
|
||||
private static void changePowered(Level world, BlockPos pos, BlockState state, boolean powered) {
|
||||
+ // Paper start - call BlockRedstoneEvents for lecterns
|
||||
+ final int currentRedstoneLevel = state.getValue(LecternBlock.POWERED) ? 15 : 0, targetRedstoneLevel = powered ? 15 : 0;
|
||||
+ if (currentRedstoneLevel != targetRedstoneLevel) {
|
||||
+ final org.bukkit.event.block.BlockRedstoneEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, pos, currentRedstoneLevel, targetRedstoneLevel);
|
||||
+
|
||||
+ if (event.getNewCurrent() != targetRedstoneLevel) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - call BlockRedstoneEvents for lecterns
|
||||
world.setBlock(pos, (BlockState) state.setValue(LecternBlock.POWERED, powered), 3);
|
||||
LecternBlock.updateBelow(world, pos, state);
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aeltumn <daniel@goossens.ch>
|
||||
Date: Mon, 28 Aug 2023 13:44:09 +0200
|
||||
Subject: [PATCH] Allow proper checking of empty item stacks
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index 4d29c34e221b749b6972c7ed79ac1f86da999ed7..c5a09f086d35f84c0a30266f78e06e2dfb5603e6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -40,12 +40,19 @@ public final class CraftItemStack extends ItemStack {
|
||||
}
|
||||
// Paper end - MC Utils
|
||||
|
||||
+ // Paper start - override isEmpty to use vanilla's impl
|
||||
+ @Override
|
||||
+ public boolean isEmpty() {
|
||||
+ return handle == null || handle.isEmpty();
|
||||
+ }
|
||||
+ // Paper end - override isEmpty to use vanilla's impl
|
||||
+
|
||||
public static net.minecraft.world.item.ItemStack asNMSCopy(ItemStack original) {
|
||||
if (original instanceof CraftItemStack) {
|
||||
CraftItemStack stack = (CraftItemStack) original;
|
||||
return stack.handle == null ? net.minecraft.world.item.ItemStack.EMPTY : stack.handle.copy();
|
||||
}
|
||||
- if (original == null || original.getType() == Material.AIR) {
|
||||
+ if (original == null || original.isEmpty()) { // Paper - override isEmpty to use vanilla's impl; use isEmpty
|
||||
return net.minecraft.world.item.ItemStack.EMPTY;
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
Date: Thu, 31 Aug 2023 17:32:48 +0200
|
||||
Subject: [PATCH] Fix silent equipment change for mobs
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index e87360e21e6eb7b0161c34a3ac6cb83d18bcd1e8..cf1f6a0081f0dbcf43842ec23accf6c3ae9b79d8 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -1106,19 +1106,26 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
|
||||
@Override
|
||||
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
|
||||
+ // Paper start - Fix silent equipment change
|
||||
+ setItemSlot(slot, stack, false);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
|
||||
+ // Paper end - Fix silent equipment change
|
||||
this.verifyEquippedItem(stack);
|
||||
switch (slot.getType()) {
|
||||
case HAND:
|
||||
- this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack);
|
||||
+ this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
|
||||
break;
|
||||
case HUMANOID_ARMOR:
|
||||
- this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack);
|
||||
+ this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
|
||||
break;
|
||||
case ANIMAL_ARMOR:
|
||||
ItemStack itemstack1 = this.bodyArmorItem;
|
||||
|
||||
this.bodyArmorItem = stack;
|
||||
- this.onEquipItem(slot, itemstack1, stack);
|
||||
+ this.onEquipItem(slot, itemstack1, stack, silent); // Paper - Fix silent equipment change
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
index 6627126ab02dbd5e9d1de6b186d75d850ef11280..3b5cf6ffb74d11bea5eb21bd66d679734ff5000c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
@@ -254,8 +254,8 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
||||
// Paper end - shouldBurnInDay API
|
||||
|
||||
@Override
|
||||
- public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
|
||||
- super.setItemSlot(slot, stack);
|
||||
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) { // Paper - Fix silent equipment change
|
||||
+ super.setItemSlot(slot, stack, silent); // Paper - Fix silent equipment change
|
||||
if (!this.level().isClientSide) {
|
||||
this.reassessWeaponGoal();
|
||||
}
|
||||
diff --git a/src/test/java/io/papermc/paper/entity/EntitySetItemSlotSilentOverrideTest.java b/src/test/java/io/papermc/paper/entity/EntitySetItemSlotSilentOverrideTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..18e0ae815528f3b2f944febc01df48f346b3a4f6
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/entity/EntitySetItemSlotSilentOverrideTest.java
|
||||
@@ -0,0 +1,52 @@
|
||||
+package io.papermc.paper.entity;
|
||||
+
|
||||
+import io.github.classgraph.ClassGraph;
|
||||
+import io.github.classgraph.ClassInfo;
|
||||
+import io.github.classgraph.MethodInfo;
|
||||
+import io.github.classgraph.MethodInfoList;
|
||||
+import io.github.classgraph.MethodParameterInfo;
|
||||
+import io.github.classgraph.ScanResult;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.stream.Stream;
|
||||
+import org.bukkit.support.environment.Normal;
|
||||
+import org.junit.jupiter.params.ParameterizedTest;
|
||||
+import org.junit.jupiter.params.provider.MethodSource;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.fail;
|
||||
+
|
||||
+@Normal
|
||||
+public class EntitySetItemSlotSilentOverrideTest {
|
||||
+
|
||||
+ public static Stream<ClassInfo> parameters() {
|
||||
+ final List<ClassInfo> classInfo = new ArrayList<>();
|
||||
+ try (ScanResult scanResult = new ClassGraph()
|
||||
+ .enableClassInfo()
|
||||
+ .enableMethodInfo()
|
||||
+ .whitelistPackages("net.minecraft")
|
||||
+ .scan()
|
||||
+ ) {
|
||||
+ for (final ClassInfo subclass : scanResult.getSubclasses("net.minecraft.world.entity.LivingEntity")) {
|
||||
+ final MethodInfoList setItemSlot = subclass.getDeclaredMethodInfo("setItemSlot");
|
||||
+ if (!setItemSlot.isEmpty()) {
|
||||
+ classInfo.add(subclass);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return classInfo.stream();
|
||||
+ }
|
||||
+
|
||||
+ @ParameterizedTest
|
||||
+ @MethodSource("parameters")
|
||||
+ public void checkSetItemSlotSilentOverrides(ClassInfo overridesSetItemSlot) {
|
||||
+ final MethodInfoList setItemSlot = overridesSetItemSlot.getDeclaredMethodInfo("setItemSlot");
|
||||
+ for (final MethodInfo methodInfo : setItemSlot) {
|
||||
+ for (final MethodParameterInfo methodParameterInfo : methodInfo.getParameterInfo()) {
|
||||
+ if ("boolean".equals(methodParameterInfo.getTypeDescriptor().toStringWithSimpleNames())) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ fail(overridesSetItemSlot.getName() + " needs to override setItemSlot with the boolean silent parameter as well");
|
||||
+ }
|
||||
+}
|
|
@ -1,54 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: The456gamer <the456gamer@the456gamer.dev>
|
||||
Date: Mon, 28 Aug 2023 01:32:39 +0100
|
||||
Subject: [PATCH] Fix spigot's Forced-Stats
|
||||
|
||||
moves the loading after vanilla loading, so it overrides the values.
|
||||
disables saving any forced stats, so it stays at the same value (without enabling disableStatSaving)
|
||||
fixes stat initialization to not cause a NullPointerException
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java
|
||||
index ec437644adff6a6ec1e3fe2dd3a6354edafde1db..fb7342f7a5008a283c3400c6313c637de8210dfa 100644
|
||||
--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java
|
||||
+++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java
|
||||
@@ -48,13 +48,6 @@ public class ServerStatsCounter extends StatsCounter {
|
||||
public ServerStatsCounter(MinecraftServer server, File file) {
|
||||
this.server = server;
|
||||
this.file = file;
|
||||
- // Spigot start
|
||||
- for ( Map.Entry<ResourceLocation, Integer> entry : org.spigotmc.SpigotConfig.forcedStats.entrySet() )
|
||||
- {
|
||||
- Stat<ResourceLocation> wrapper = Stats.CUSTOM.get( entry.getKey() );
|
||||
- this.stats.put( wrapper, entry.getValue().intValue() );
|
||||
- }
|
||||
- // Spigot end
|
||||
if (file.isFile()) {
|
||||
try {
|
||||
this.parseLocal(server.getFixerUpper(), FileUtils.readFileToString(file));
|
||||
@@ -65,6 +58,18 @@ public class ServerStatsCounter extends StatsCounter {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Moved after stat fetching for player state file
|
||||
+ // Moves the loading after vanilla loading, so it overrides the values.
|
||||
+ // Disables saving any forced stats, so it stays at the same value (without enabling disableStatSaving)
|
||||
+ // Fixes stat initialization to not cause a NullPointerException
|
||||
+ // Spigot start
|
||||
+ for ( Map.Entry<ResourceLocation, Integer> entry : org.spigotmc.SpigotConfig.forcedStats.entrySet() )
|
||||
+ {
|
||||
+ Stat<ResourceLocation> wrapper = Stats.CUSTOM.get(java.util.Objects.requireNonNull(BuiltInRegistries.CUSTOM_STAT.get(entry.getKey()))); // Paper - ensured by SpigotConfig#stats
|
||||
+ this.stats.put( wrapper, entry.getValue().intValue() );
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+ // Paper end - Moved after stat fetching for player state file
|
||||
}
|
||||
|
||||
public void save() {
|
||||
@@ -80,6 +85,7 @@ public class ServerStatsCounter extends StatsCounter {
|
||||
@Override
|
||||
public void setValue(Player player, Stat<?> stat, int value) {
|
||||
if ( org.spigotmc.SpigotConfig.disableStatSaving ) return; // Spigot
|
||||
+ if (stat.getType() == Stats.CUSTOM && stat.getValue() instanceof final ResourceLocation resourceLocation && org.spigotmc.SpigotConfig.forcedStats.get(resourceLocation) != null) return; // Paper - disable saving forced stats
|
||||
super.setValue(player, stat, value);
|
||||
this.dirty.add(stat);
|
||||
}
|
|
@ -1,302 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 24 Jan 2022 00:09:02 -0800
|
||||
Subject: [PATCH] Add missing InventoryHolders to inventories
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/Container.java b/src/main/java/net/minecraft/world/Container.java
|
||||
index db41ffbd24adccd78edf3368ba1f7a3ab9f6072c..5db5ba026462ca642dcee718af732f80fadabef5 100644
|
||||
--- a/src/main/java/net/minecraft/world/Container.java
|
||||
+++ b/src/main/java/net/minecraft/world/Container.java
|
||||
@@ -103,7 +103,7 @@ public interface Container extends Clearable {
|
||||
|
||||
java.util.List<org.bukkit.entity.HumanEntity> getViewers();
|
||||
|
||||
- org.bukkit.inventory.InventoryHolder getOwner();
|
||||
+ org.bukkit.inventory.@org.jetbrains.annotations.Nullable InventoryHolder getOwner(); // Paper - annotation
|
||||
|
||||
void setMaxStackSize(int size);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java
|
||||
index 6632cf24ebe6d147950a1fdb876660937da86b73..d04bf7d06855022c973073fb84c5d3d65f2553e1 100644
|
||||
--- a/src/main/java/net/minecraft/world/SimpleContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/SimpleContainer.java
|
||||
@@ -30,7 +30,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
// CraftBukkit start - add fields and methods
|
||||
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
private int maxStack = MAX_STACK;
|
||||
- protected org.bukkit.inventory.InventoryHolder bukkitOwner;
|
||||
+ protected @Nullable org.bukkit.inventory.InventoryHolder bukkitOwner; // Paper - annotation
|
||||
|
||||
public List<ItemStack> getContents() {
|
||||
return this.items;
|
||||
@@ -58,6 +58,11 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
}
|
||||
|
||||
public org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ if (this.bukkitOwner == null && this.bukkitOwnerCreator != null) {
|
||||
+ this.bukkitOwner = this.bukkitOwnerCreator.get();
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
return this.bukkitOwner;
|
||||
}
|
||||
|
||||
@@ -86,6 +91,13 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
public SimpleContainer(int size) {
|
||||
this(size, null);
|
||||
}
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ private @Nullable java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> bukkitOwnerCreator;
|
||||
+ public SimpleContainer(java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> bukkitOwnerCreator, int size) {
|
||||
+ this(size);
|
||||
+ this.bukkitOwnerCreator = bukkitOwnerCreator;
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
|
||||
public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) {
|
||||
this.bukkitOwner = owner;
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index afd8f48bd41d2cac413c292f7988c903da1dc700..8a1035c0aa859f67a6806c183d96a88ddf760baa 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -991,4 +991,15 @@ public abstract class AbstractContainerMenu {
|
||||
this.stateId = this.stateId + 1 & 32767;
|
||||
return this.stateId;
|
||||
}
|
||||
+
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ // The reason this is a supplier, is that the createHolder method uses the bukkit InventoryView#getTopInventory to get the inventory in question
|
||||
+ // and that can't be obtained safely until the AbstractContainerMenu has been fully constructed. Using a supplier lazily
|
||||
+ // initializes the InventoryHolder safely.
|
||||
+ protected final Supplier<org.bukkit.inventory.BlockInventoryHolder> createBlockHolder(final ContainerLevelAccess context) {
|
||||
+ //noinspection ConstantValue
|
||||
+ Preconditions.checkArgument(context != null, "context was null");
|
||||
+ return () -> context.createBlockHolder(this);
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
|
||||
index a735aeeb59f79154ce797c6e2f5600305f46d217..b93c118d957f0a2f40e2f31fd6400bd69438cf72 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
|
||||
@@ -42,7 +42,7 @@ public class BeaconMenu extends AbstractContainerMenu {
|
||||
public BeaconMenu(int syncId, Container inventory, ContainerData propertyDelegate, ContainerLevelAccess context) {
|
||||
super(MenuType.BEACON, syncId);
|
||||
this.player = (Inventory) inventory; // CraftBukkit - TODO: check this
|
||||
- this.beacon = new SimpleContainer(1) { // CraftBukkit - decompile error
|
||||
+ this.beacon = new SimpleContainer(this.createBlockHolder(context), 1) { // CraftBukkit - decompile error // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public boolean canPlaceItem(int slot, ItemStack stack) {
|
||||
return stack.is(ItemTags.BEACON_PAYMENT_ITEMS);
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
|
||||
index c52c4c4210bc6ae082443318d9795c48c816aba6..ab98637bf967ac19f0bc06e8cb7f18a8b13ec809 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
|
||||
@@ -54,7 +54,7 @@ public class CartographyTableMenu extends AbstractContainerMenu {
|
||||
|
||||
public CartographyTableMenu(int syncId, Inventory inventory, final ContainerLevelAccess context) {
|
||||
super(MenuType.CARTOGRAPHY_TABLE, syncId);
|
||||
- this.container = new SimpleContainer(2) {
|
||||
+ this.container = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
CartographyTableMenu.this.slotsChanged(this);
|
||||
@@ -68,7 +68,7 @@ public class CartographyTableMenu extends AbstractContainerMenu {
|
||||
}
|
||||
// CraftBukkit end
|
||||
};
|
||||
- this.resultContainer = new ResultContainer() {
|
||||
+ this.resultContainer = new ResultContainer(this.createBlockHolder(context)) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
CartographyTableMenu.this.slotsChanged(this);
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
index 85e336637db8643fc5aca1dba724c9b341cbf46f..12b466ccb7c36021cf807c4f3fd2bcb037943abc 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
@@ -21,6 +21,18 @@ public interface ContainerLevelAccess {
|
||||
return new org.bukkit.Location(this.getWorld().getWorld(), this.getPosition().getX(), this.getPosition().getY(), this.getPosition().getZ());
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ default boolean isBlock() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ default org.bukkit.inventory.@org.jetbrains.annotations.Nullable BlockInventoryHolder createBlockHolder(AbstractContainerMenu menu) {
|
||||
+ if (!this.isBlock()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(this, menu.getBukkitView().getTopInventory());
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
|
||||
ContainerLevelAccess NULL = new ContainerLevelAccess() {
|
||||
@Override
|
||||
@@ -48,6 +60,12 @@ public interface ContainerLevelAccess {
|
||||
return pos;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ @Override
|
||||
+ public boolean isBlock() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
|
||||
@Override
|
||||
public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) {
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
index 2fa009b33bccd6aeee30f23f9207ab039740d95d..fff1c39920e7d7051dfe3dd39c77865d3bdf113e 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
@@ -63,7 +63,7 @@ public class EnchantmentMenu extends AbstractContainerMenu {
|
||||
|
||||
public EnchantmentMenu(int syncId, Inventory playerInventory, ContainerLevelAccess context) {
|
||||
super(MenuType.ENCHANTMENT, syncId);
|
||||
- this.enchantSlots = new SimpleContainer(2) {
|
||||
+ this.enchantSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
index 15ec798e149d80aace186f84b9236ddeaba690c3..1678f6c8b2c7db761783e53043169bf12bc2cb29 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
@@ -60,8 +60,8 @@ public class GrindstoneMenu extends AbstractContainerMenu {
|
||||
|
||||
public GrindstoneMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) {
|
||||
super(MenuType.GRINDSTONE, syncId);
|
||||
- this.resultSlots = new ResultContainer();
|
||||
- this.repairSlots = new SimpleContainer(2) {
|
||||
+ this.resultSlots = new ResultContainer(this.createBlockHolder(context)); // Paper - Add missing InventoryHolders
|
||||
+ this.repairSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
|
||||
index be840717e180b6b5abd14db6cc9263349737f9a3..7de5e47f9a54263734eeef855a2dc07ef64d30ea 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
|
||||
@@ -18,7 +18,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
|
||||
protected final Player player;
|
||||
protected final Container inputSlots;
|
||||
private final List<Integer> inputSlotIndexes;
|
||||
- protected final ResultContainer resultSlots = new ResultContainer();
|
||||
+ protected final ResultContainer resultSlots; // Paper - Add missing InventoryHolders; delay field init
|
||||
private final int resultSlotIndex;
|
||||
|
||||
protected abstract boolean mayPickup(Player player, boolean present);
|
||||
@@ -30,6 +30,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
|
||||
public ItemCombinerMenu(@Nullable MenuType<?> type, int syncId, Inventory playerInventory, ContainerLevelAccess context) {
|
||||
super(type, syncId);
|
||||
this.access = context;
|
||||
+ this.resultSlots = new ResultContainer(this.createBlockHolder(this.access)); // Paper - Add missing InventoryHolders; delay field init
|
||||
this.player = playerInventory.player;
|
||||
ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition = this.createInputSlotDefinitions();
|
||||
|
||||
@@ -96,7 +97,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
|
||||
protected abstract ItemCombinerMenuSlotDefinition createInputSlotDefinitions();
|
||||
|
||||
private SimpleContainer createContainer(int size) {
|
||||
- return new SimpleContainer(size) {
|
||||
+ return new SimpleContainer(this.createBlockHolder(this.access), size) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
|
||||
index dc23b646e55bb66e0aa584d82b75b4b3d233276a..2c0e182f7b03ed0f87c259af4df9c4e52106220d 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
|
||||
@@ -73,7 +73,7 @@ public class LoomMenu extends AbstractContainerMenu {
|
||||
this.selectablePatterns = List.of();
|
||||
this.slotUpdateListener = () -> {
|
||||
};
|
||||
- this.inputContainer = new SimpleContainer(3) {
|
||||
+ this.inputContainer = new SimpleContainer(this.createBlockHolder(context), 3) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
@@ -88,7 +88,7 @@ public class LoomMenu extends AbstractContainerMenu {
|
||||
}
|
||||
// CraftBukkit end
|
||||
};
|
||||
- this.outputContainer = new SimpleContainer(1) {
|
||||
+ this.outputContainer = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/ResultContainer.java b/src/main/java/net/minecraft/world/inventory/ResultContainer.java
|
||||
index d4592218d761eb38402e3d95c642e80a708cb333..4c4266a85c38e41e6c7e6144a68624f4daa50c54 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/ResultContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/ResultContainer.java
|
||||
@@ -29,7 +29,12 @@ public class ResultContainer implements Container, RecipeCraftingHolder {
|
||||
}
|
||||
|
||||
public org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
- return null; // Result slots don't get an owner
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ if (this.holder == null && this.holderCreator != null) {
|
||||
+ this.holder = this.holderCreator.get();
|
||||
+ }
|
||||
+ return this.holder; // Result slots don't get an owner
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
}
|
||||
|
||||
// Don't need a transaction; the InventoryCrafting keeps track of it for us
|
||||
@@ -53,6 +58,14 @@ public class ResultContainer implements Container, RecipeCraftingHolder {
|
||||
return null;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ private @Nullable java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> holderCreator;
|
||||
+ private @Nullable org.bukkit.inventory.InventoryHolder holder;
|
||||
+ public ResultContainer(java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> holderCreator) {
|
||||
+ this();
|
||||
+ this.holderCreator = holderCreator;
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
|
||||
public ResultContainer() {
|
||||
this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY);
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
|
||||
index 37e75c02c374314372630f4bda0b92519809f2a4..5a0015f761f6a25d7bb7b9cfe7a9b4771a6a37ec 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
|
||||
@@ -69,7 +69,7 @@ public class StonecutterMenu extends AbstractContainerMenu {
|
||||
this.input = ItemStack.EMPTY;
|
||||
this.slotUpdateListener = () -> {
|
||||
};
|
||||
- this.container = new SimpleContainer(1) {
|
||||
+ this.container = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper - Add missing InventoryHolders
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
@@ -84,7 +84,7 @@ public class StonecutterMenu extends AbstractContainerMenu {
|
||||
}
|
||||
// CraftBukkit end
|
||||
};
|
||||
- this.resultContainer = new ResultContainer();
|
||||
+ this.resultContainer = new ResultContainer(this.createBlockHolder(context)); // Paper - Add missing InventoryHolders
|
||||
this.access = context;
|
||||
this.level = playerInventory.player.level();
|
||||
this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33));
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java
|
||||
index 7ae484b0fa5bf5494c6ead15f7f1c0fa840ae270..7129eb5f5cea39992b4c690cb421004004a952ea 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java
|
||||
@@ -17,6 +17,13 @@ public class CraftBlockInventoryHolder implements BlockInventoryHolder {
|
||||
this.block = CraftBlock.at(world, pos);
|
||||
this.inventory = new CraftInventory(inv);
|
||||
}
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ public CraftBlockInventoryHolder(net.minecraft.world.inventory.ContainerLevelAccess levelAccess, Inventory inventory) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(levelAccess.isBlock());
|
||||
+ this.block = CraftBlock.at(levelAccess.getWorld(), levelAccess.getPosition());
|
||||
+ this.inventory = inventory;
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
|
||||
@Override
|
||||
public Block getBlock() {
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 18 Jun 2023 23:04:46 -0700
|
||||
Subject: [PATCH] Do not read tile entities in chunks that are positioned
|
||||
outside of the chunk
|
||||
|
||||
The tile entities are not accessible and so should not be loaded.
|
||||
This can happen as a result of users moving regionfiles around,
|
||||
which would cause a crash on Folia but would appear to function
|
||||
fine on Paper.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
index 5e1a68e3a920aab10a459b9b54f6abd59e7855e0..d42585bccb03f8ee1be5e37cfbe8520af4cc5454 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
@@ -303,6 +303,13 @@ public class ChunkSerializer {
|
||||
for (int k1 = 0; k1 < nbttaglist3.size(); ++k1) {
|
||||
CompoundTag nbttagcompound4 = nbttaglist3.getCompound(k1);
|
||||
|
||||
+ // Paper start - do not read tile entities positioned outside the chunk
|
||||
+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound4);
|
||||
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
|
||||
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end - do not read tile entities positioned outside the chunk
|
||||
((ChunkAccess) object1).setBlockEntityNbt(nbttagcompound4);
|
||||
}
|
||||
|
||||
@@ -507,10 +514,19 @@ public class ChunkSerializer {
|
||||
CompoundTag nbttagcompound1 = nbttaglist1.getCompound(i);
|
||||
boolean flag = nbttagcompound1.getBoolean("keepPacked");
|
||||
|
||||
+ // Paper start - do not read tile entities positioned outside the chunk
|
||||
+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); // moved up
|
||||
+ ChunkPos chunkPos = chunk.getPos();
|
||||
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
|
||||
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end - do not read tile entities positioned outside the chunk
|
||||
+
|
||||
if (flag) {
|
||||
chunk.setBlockEntityNbt(nbttagcompound1);
|
||||
} else {
|
||||
- BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1);
|
||||
+ // Paper - do not read tile entities positioned outside the chunk; move up
|
||||
BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound1, world.registryAccess());
|
||||
|
||||
if (tileentity != null) {
|
|
@ -1,37 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sat, 23 Sep 2023 01:49:39 -0400
|
||||
Subject: [PATCH] Add missing logs for log-ips config option
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
|
||||
index d4f5a98a0b1ca9f2a8baa6e0b27353df94d1f333..569516822319c885e76be1aa92580bdf0bc932f5 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
|
||||
@@ -50,7 +50,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
|
||||
com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper
|
||||
|
||||
if (i == 0) {
|
||||
- LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress);
|
||||
+ LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? socketaddress: "<ip address withheld>"); // Paper - Respect logIPs option
|
||||
|
||||
// Paper start - Call PaperServerListPingEvent and use results
|
||||
event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(net.minecraft.server.MinecraftServer.getServer(), (java.net.InetSocketAddress) socketaddress, 39, null);
|
||||
@@ -83,7 +83,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
|
||||
// LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}", socketaddress);
|
||||
// Paper end
|
||||
} else {
|
||||
- LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress);
|
||||
+ LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? socketaddress: "<ip address withheld>"); // Paper - Respect logIPs option
|
||||
}
|
||||
|
||||
if (s == null) {
|
||||
@@ -207,7 +207,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
|
||||
buf.release();
|
||||
this.buf = null;
|
||||
|
||||
- LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress());
|
||||
+ LOGGER.debug("Ping: (1.6) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? ctx.channel().remoteAddress(): "<ip address withheld>"); // Paper - Respect logIPs option
|
||||
|
||||
java.net.InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port);
|
||||
com.destroystokyo.paper.event.server.PaperServerListPingEvent event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 8 Aug 2023 17:29:33 -0700
|
||||
Subject: [PATCH] Fix race condition on UpgradeData.BlockFixers class init
|
||||
|
||||
The CHUNKY_FIXERS field is modified during the constructors
|
||||
of the BlockFixers, but the code that uses CHUNKY_FIXERS does
|
||||
not properly ensure that BlockFixers has been initialised before
|
||||
using it, leading to a possible race condition where instances of
|
||||
BlockFixers are accessed before they have initialised correctly.
|
||||
|
||||
We can force the class to initialise fully before accessing the
|
||||
field by calling any method on the class, and for convenience
|
||||
we use values().
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
|
||||
index 22b6d0851a51da180cd8fbbe6554c5370f5ac5bd..cd9b65f278a750a0177a3252271015d43172b2e9 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
|
||||
@@ -140,6 +140,7 @@ public class UpgradeData {
|
||||
Fluid fluid = tick.type() == Fluids.EMPTY ? level.getFluidState(tick.pos()).getType() : tick.type();
|
||||
level.scheduleTick(tick.pos(), fluid, tick.delay(), tick.priority());
|
||||
});
|
||||
+ UpgradeData.BlockFixers.values(); // Paper - force the class init so that we don't access CHUNKY_FIXERS before all BlockFixers are initialised
|
||||
CHUNKY_FIXERS.forEach(logic -> logic.processChunk(level));
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 23 Sep 2023 22:07:15 -0700
|
||||
Subject: [PATCH] Fix NPE in AdvancementProgress#getDateAwarded
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java
|
||||
index aeb04a65a1201f05fd02151fce5756d797c63615..ec3b9cb901913b093c3eb0bda8dc0dbb738c165e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java
|
||||
@@ -44,7 +44,7 @@ public class CraftAdvancementProgress implements AdvancementProgress {
|
||||
@Override
|
||||
public Date getDateAwarded(String criteria) {
|
||||
CriterionProgress criterion = this.handle.getCriterion(criteria);
|
||||
- return (criterion == null) ? null : Date.from(criterion.getObtained());
|
||||
+ return (criterion == null) ? null : criterion.getObtained() == null ? null : Date.from(criterion.getObtained()); // Paper - fix NPE if criterion isn't obtained
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,25 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 23 Sep 2023 22:31:54 -0700
|
||||
Subject: [PATCH] Fix team sidebar objectives not being cleared
|
||||
|
||||
Objectives displayed in team sidebars were not cleared when switching
|
||||
scoreboards. If a player's scoreboard has a displayed objective for the
|
||||
'gold' sidebar, and their scoreboard was switched to one where they
|
||||
still had a 'gold' team, it would still be displayed
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
index cad42a0f3c016bf65181e50d139ae4e2fb9158a5..b3e1adeb932da9b3bed16acd94e2f16da48a7c72 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
@@ -87,8 +87,8 @@ public final class CraftScoreboardManager implements ScoreboardManager {
|
||||
|
||||
// Old objective tracking
|
||||
HashSet<Objective> removed = new HashSet<>();
|
||||
- for (int i = 0; i < 3; ++i) {
|
||||
- Objective scoreboardobjective = oldboard.getDisplayObjective(net.minecraft.world.scores.DisplaySlot.BY_ID.apply(i));
|
||||
+ for (net.minecraft.world.scores.DisplaySlot slot : net.minecraft.world.scores.DisplaySlot.values()) { // Paper - clear all display slots
|
||||
+ Objective scoreboardobjective = oldboard.getDisplayObjective(slot); // Paper - clear all display slots
|
||||
if (scoreboardobjective != null && !removed.contains(scoreboardobjective)) {
|
||||
entityplayer.connection.send(new ClientboundSetObjectivePacket(scoreboardobjective, 1));
|
||||
removed.add(scoreboardobjective);
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
|
||||
Date: Sun, 24 Sep 2023 18:35:28 +0200
|
||||
Subject: [PATCH] Fix missing map initialize event call
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.storage.DimensionDataStorage readSavedData(Ljava/util/function/Function;Lnet/minecraft/util/datafix/DataFixTypes;Ljava/lang/String;)Lnet/minecraft/world/level/saveddata/SavedData;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 1ed6002501b501e72bfff81ae9abc506133a10d0..c13652fccf08ff9235f22e89941a37b283f92f03 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1664,13 +1664,24 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
@Nullable
|
||||
@Override
|
||||
public MapItemSavedData getMapData(MapId id) {
|
||||
- // CraftBukkit start
|
||||
- MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key());
|
||||
- if (worldmap != null) {
|
||||
- worldmap.id = id;
|
||||
+ // Paper start - Call missing map initialize event and set id
|
||||
+ final DimensionDataStorage storage = this.getServer().overworld().getDataStorage();
|
||||
+
|
||||
+ final net.minecraft.world.level.saveddata.SavedData existing = storage.cache.get(id.key());
|
||||
+ if (existing == null && !storage.cache.containsKey(id.key())) {
|
||||
+ final MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key());
|
||||
+ storage.cache.put(id.key(), worldmap);
|
||||
+ if (worldmap != null) {
|
||||
+ worldmap.id = id;
|
||||
+ new MapInitializeEvent(worldmap.mapView).callEvent();
|
||||
+ return worldmap;
|
||||
+ }
|
||||
+ } else if (existing instanceof MapItemSavedData mapItemSavedData) {
|
||||
+ mapItemSavedData.id = id;
|
||||
}
|
||||
- return worldmap;
|
||||
- // CraftBukkit end
|
||||
+
|
||||
+ return existing instanceof MapItemSavedData data ? data : null;
|
||||
+ // Paper end - Call missing map initialize event and set id
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: booky10 <boooky10@gmail.com>
|
||||
Date: Sun, 27 Aug 2023 16:11:31 +0200
|
||||
Subject: [PATCH] Update entity data when attaching firework to entity
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.projectile.FireworkRocketEntity DATA_ATTACHED_TO_TARGET
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
index 2d54cf6f3d9696c55335f0a2057025e2034d4e13..759b6e54db93792c9862b1f1625118ac6fa49d7a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
@@ -69,6 +69,10 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
||||
}
|
||||
|
||||
this.getHandle().attachedToEntity = (entity != null) ? ((CraftLivingEntity) entity).getHandle() : null;
|
||||
+ // Paper start - update entity data
|
||||
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET,
|
||||
+ entity != null ? java.util.OptionalInt.of(entity.getEntityId()) : java.util.OptionalInt.empty());
|
||||
+ // Paper end - update entity data
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: LemonCaramel <admin@caramel.moe>
|
||||
Date: Sun, 24 Sep 2023 20:19:44 +0900
|
||||
Subject: [PATCH] Fix UnsafeValues#loadAdvancement
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 23ed0a130525a0b3a1b41330685476463c81f183..b07c8111daa010dee2bb8be52162aafa4c267f1f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -308,9 +308,30 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
ResourceLocation minecraftkey = CraftNamespacedKey.toMinecraft(key);
|
||||
|
||||
JsonElement jsonelement = ServerAdvancementManager.GSON.fromJson(advancement, JsonElement.class);
|
||||
- net.minecraft.advancements.Advancement nms = net.minecraft.advancements.Advancement.CODEC.parse(JsonOps.INSTANCE, jsonelement).getOrThrow(JsonParseException::new);
|
||||
+ final net.minecraft.resources.RegistryOps<JsonElement> ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE); // Paper - use RegistryOps
|
||||
+ final net.minecraft.advancements.Advancement nms = net.minecraft.advancements.Advancement.CODEC.parse(ops, jsonelement).getOrThrow(JsonParseException::new); // Paper - use RegistryOps
|
||||
if (nms != null) {
|
||||
- MinecraftServer.getServer().getAdvancements().advancements.put(minecraftkey, new AdvancementHolder(minecraftkey, nms));
|
||||
+ // Paper start - Fix throw UnsupportedOperationException
|
||||
+ //MinecraftServer.getServer().getAdvancements().advancements.put(minecraftkey, new AdvancementHolder(minecraftkey, nms));
|
||||
+ final com.google.common.collect.ImmutableMap.Builder<ResourceLocation, AdvancementHolder> mapBuilder = com.google.common.collect.ImmutableMap.builder();
|
||||
+ mapBuilder.putAll(MinecraftServer.getServer().getAdvancements().advancements);
|
||||
+
|
||||
+ final AdvancementHolder holder = new AdvancementHolder(minecraftkey, nms);
|
||||
+ mapBuilder.put(minecraftkey, holder);
|
||||
+
|
||||
+ MinecraftServer.getServer().getAdvancements().advancements = mapBuilder.build();
|
||||
+ final net.minecraft.advancements.AdvancementTree tree = MinecraftServer.getServer().getAdvancements().tree();
|
||||
+ tree.addAll(java.util.List.of(holder));
|
||||
+
|
||||
+ // recalculate advancement position
|
||||
+ final net.minecraft.advancements.AdvancementNode node = tree.get(minecraftkey);
|
||||
+ if (node != null) {
|
||||
+ final net.minecraft.advancements.AdvancementNode root = node.root();
|
||||
+ if (root.holder().value().display().isPresent()) {
|
||||
+ net.minecraft.advancements.TreeNodePosition.run(root);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Fix throw UnsupportedOperationException
|
||||
Advancement bukkit = Bukkit.getAdvancement(key);
|
||||
|
||||
if (bukkit != null) {
|
|
@ -1,30 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: booky10 <boooky10@gmail.com>
|
||||
Date: Sat, 14 Oct 2023 03:11:11 +0200
|
||||
Subject: [PATCH] Add player idle duration API
|
||||
|
||||
Implements API for getting and resetting a player's idle duration.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index a1b870fb3d1fd5d209474c47bf523d0d5d58ce39..1d79bacbfb24442573245550263141ad56332971 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -3419,6 +3419,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Duration getIdleDuration() {
|
||||
+ return Duration.ofMillis(net.minecraft.Util.getMillis() - this.getHandle().getLastActionTime());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetIdleDuration() {
|
||||
+ this.getHandle().resetLastActionTime();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public Player.Spigot spigot()
|
||||
{
|
||||
return this.spigot;
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brokkonaut <hannos17@gmx.de>
|
||||
Date: Sat, 21 Oct 2023 20:52:57 +0100
|
||||
Subject: [PATCH] Don't check if we can see non-visible entities
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 57af5d1986021c9a135599c6f55b091aebd3bab7..6c667823c2ef15766f3afc1a9c819cb6c24b0912 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1537,7 +1537,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper end - Configurable entity tracking range by Y
|
||||
|
||||
// CraftBukkit start - respect vanish API
|
||||
- if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {
|
||||
+ if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
|
||||
flag = false;
|
||||
}
|
||||
// CraftBukkit end
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
Date: Fri, 20 Oct 2023 19:50:22 +0200
|
||||
Subject: [PATCH] Fix NPE in SculkBloomEvent world access
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
|
||||
index 8d95d129cae03af9ded699047742324807186994..a74732902c0494c67e6acf2fc04581ff9c46b832 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
|
||||
@@ -35,9 +35,16 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
|
||||
public SculkCatalystBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.SCULK_CATALYST, pos, state);
|
||||
this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(state, new BlockPositionSource(pos));
|
||||
- this.catalystListener.level = this.level; // CraftBukkit
|
||||
}
|
||||
|
||||
+ // Paper start - Fix NPE in SculkBloomEvent world access
|
||||
+ @Override
|
||||
+ public void setLevel(Level level) {
|
||||
+ super.setLevel(level);
|
||||
+ this.catalystListener.sculkSpreader.level = level;
|
||||
+ }
|
||||
+ // Paper end - Fix NPE in SculkBloomEvent world access
|
||||
+
|
||||
public static void serverTick(Level world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) {
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = blockEntity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep.
|
||||
blockEntity.catalystListener.getSculkSpreader().updateCursors(world, pos, world.getRandom(), true);
|
||||
@@ -67,13 +74,12 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
|
||||
final SculkSpreader sculkSpreader;
|
||||
private final BlockState blockState;
|
||||
private final PositionSource positionSource;
|
||||
- private Level level; // CraftBukkit
|
||||
|
||||
public CatalystListener(BlockState state, PositionSource positionSource) {
|
||||
this.blockState = state;
|
||||
this.positionSource = positionSource;
|
||||
this.sculkSpreader = SculkSpreader.createLevelSpreader();
|
||||
- this.sculkSpreader.level = this.level; // CraftBukkit
|
||||
+ // this.sculkSpreader.level = this.level; // CraftBukkit // Paper - Fix NPE in SculkBloomEvent world access
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Scandurra <david.scandurra@check24.de>
|
||||
Date: Wed, 25 Oct 2023 20:36:25 +0200
|
||||
Subject: [PATCH] Allow null itemstack for Player#sendEquipmentChange
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 1d79bacbfb24442573245550263141ad56332971..b2abaf6b535da13cdeeb99c568b91c585ac2ed20 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -1127,7 +1127,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
@Override
|
||||
public void sendEquipmentChange(LivingEntity entity, EquipmentSlot slot, ItemStack item) {
|
||||
- this.sendEquipmentChange(entity, Map.of(slot, item));
|
||||
+ this.sendEquipmentChange(entity, java.util.Collections.singletonMap(slot, item)); // Paper - replace Map.of to allow null values
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: astei <andrew@steinborn.me>
|
||||
Date: Sat, 28 Oct 2023 19:46:21 -0400
|
||||
Subject: [PATCH] Optimize VarInts
|
||||
|
||||
https://github.com/PaperMC/Paper/pull/6957#issuecomment-985250854
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/VarInt.java b/src/main/java/net/minecraft/network/VarInt.java
|
||||
index 49a8ddc269d53458cfbd639b7de838c2e5765748..74ed47659d3e615c2dae7da98d5a8cf1559625bf 100644
|
||||
--- a/src/main/java/net/minecraft/network/VarInt.java
|
||||
+++ b/src/main/java/net/minecraft/network/VarInt.java
|
||||
@@ -9,6 +9,18 @@ public class VarInt {
|
||||
private static final int DATA_BITS_PER_BYTE = 7;
|
||||
|
||||
public static int getByteSize(int i) {
|
||||
+ // Paper start - Optimize VarInts
|
||||
+ return VARINT_EXACT_BYTE_LENGTHS[Integer.numberOfLeadingZeros(i)];
|
||||
+ }
|
||||
+ private static final int[] VARINT_EXACT_BYTE_LENGTHS = new int[33];
|
||||
+ static {
|
||||
+ for (int i = 0; i <= 32; ++i) {
|
||||
+ VARINT_EXACT_BYTE_LENGTHS[i] = (int) Math.ceil((31d - (i - 1)) / 7d);
|
||||
+ }
|
||||
+ VARINT_EXACT_BYTE_LENGTHS[32] = 1; // Special case for the number 0.
|
||||
+ }
|
||||
+ public static int getByteSizeOld(int i) {
|
||||
+ // Paper end - Optimize VarInts
|
||||
for (int j = 1; j < 5; j++) {
|
||||
if ((i & -1 << j * 7) == 0) {
|
||||
return j;
|
||||
@@ -39,6 +51,21 @@ public class VarInt {
|
||||
}
|
||||
|
||||
public static ByteBuf write(ByteBuf buf, int i) {
|
||||
+ // Paper start - Optimize VarInts
|
||||
+ // Peel the one and two byte count cases explicitly as they are the most common VarInt sizes
|
||||
+ // that the proxy will write, to improve inlining.
|
||||
+ if ((i & (0xFFFFFFFF << 7)) == 0) {
|
||||
+ buf.writeByte(i);
|
||||
+ } else if ((i & (0xFFFFFFFF << 14)) == 0) {
|
||||
+ int w = (i & 0x7F | 0x80) << 8 | (i >>> 7);
|
||||
+ buf.writeShort(w);
|
||||
+ } else {
|
||||
+ writeOld(buf, i);
|
||||
+ }
|
||||
+ return buf;
|
||||
+ }
|
||||
+ public static ByteBuf writeOld(ByteBuf buf, int i) {
|
||||
+ // Paper end - Optimize VarInts
|
||||
while ((i & -128) != 0) {
|
||||
buf.writeByte(i & 127 | 128);
|
||||
i >>>= 7;
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: TrollyLoki <trollyloki@gmail.com>
|
||||
Date: Wed, 11 Oct 2023 00:45:53 -0400
|
||||
Subject: [PATCH] Add API to get the collision shape of a block before it's
|
||||
placed
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
index 64ddd6d1c40dc91b6e7fc3118403415bb4533d97..0daa0bf7e56aa7228d89867500cb780b37f06541 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
@@ -679,6 +679,20 @@ public class CraftBlockData implements BlockData {
|
||||
return this.state.isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CraftBlock.blockFaceToNotch(face), CraftBlockSupport.toNMS(support));
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public org.bukkit.util.VoxelShape getCollisionShape(Location location) {
|
||||
+ Preconditions.checkArgument(location != null, "location must not be null");
|
||||
+
|
||||
+ CraftWorld world = (CraftWorld) location.getWorld();
|
||||
+ Preconditions.checkArgument(world != null, "location must not have a null world");
|
||||
+
|
||||
+ BlockPos position = CraftLocation.toBlockPosition(location);
|
||||
+ net.minecraft.world.phys.shapes.VoxelShape shape = this.state.getCollisionShape(world.getHandle(), position);
|
||||
+ return new org.bukkit.craftbukkit.util.CraftVoxelShape(shape);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public Color getMapColor() {
|
||||
return Color.fromRGB(this.state.getMapColor(null, null).col);
|
|
@ -1,116 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: TonytheMacaroni <tonythemacaroni123@gmail.com>
|
||||
Date: Wed, 6 Sep 2023 19:24:16 -0400
|
||||
Subject: [PATCH] Add predicate for blocks when raytracing
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
index c978f3b2d42f512e982f289e76c2422e41b7eec6..bb8e962e63c7a2d931f9bd7f7c002aa35cfa5fd3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
@@ -70,6 +70,12 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
|
||||
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
|
||||
default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
|
||||
+ // Paper start - Add predicate for blocks when raytracing
|
||||
+ return clip(raytrace1, blockposition, null);
|
||||
+ }
|
||||
+
|
||||
+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
|
||||
+ // Paper end - Add predicate for blocks when raytracing
|
||||
// Paper start - Prevent raytrace from loading chunks
|
||||
BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
|
||||
if (iblockdata == null) {
|
||||
@@ -79,7 +85,7 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
|
||||
}
|
||||
// Paper end - Prevent raytrace from loading chunks
|
||||
- if (iblockdata.isAir()) return null; // Paper - Perf: optimise air cases
|
||||
+ if (iblockdata.isAir() || (canCollide != null && this instanceof LevelAccessor levelAccessor && !canCollide.test(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockposition)))) return null; // Paper - Perf: optimise air cases & check canCollide predicate
|
||||
FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: don't need to go to world state again
|
||||
Vec3 vec3d = raytrace1.getFrom();
|
||||
Vec3 vec3d1 = raytrace1.getTo();
|
||||
@@ -95,8 +101,14 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
// CraftBukkit end
|
||||
|
||||
default BlockHitResult clip(ClipContext context) {
|
||||
+ // Paper start - Add predicate for blocks when raytracing
|
||||
+ return clip(context, (java.util.function.Predicate<org.bukkit.block.Block>) null);
|
||||
+ }
|
||||
+
|
||||
+ default BlockHitResult clip(ClipContext context, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
|
||||
+ // Paper end - Add predicate for blocks when raytracing
|
||||
return (BlockHitResult) BlockGetter.traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> {
|
||||
- return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method
|
||||
+ return this.clip(raytrace1, blockposition, canCollide); // CraftBukkit - moved into separate method // Paper - Add predicate for blocks when raytracing
|
||||
}, (raytrace1) -> {
|
||||
Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index cb50fca4867688d2572e8ab5b7fef7243c5b8ba9..7ada46aa24e1bc15207a34c15b056e4e76238757 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1106,9 +1106,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> filter) {
|
||||
+ // Paper start - Add predicate for blocks when raytracing
|
||||
+ return rayTraceEntities((io.papermc.paper.math.Position) start, direction, maxDistance, raySize, filter);
|
||||
+ }
|
||||
+
|
||||
+ public RayTraceResult rayTraceEntities(io.papermc.paper.math.Position start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> filter) {
|
||||
Preconditions.checkArgument(start != null, "Location start cannot be null");
|
||||
- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
|
||||
- start.checkFinite();
|
||||
+ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
|
||||
+ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
|
||||
+ // Paper end - Add predicate for blocks when raytracing
|
||||
|
||||
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
|
||||
direction.checkFinite();
|
||||
@@ -1158,9 +1164,16 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks) {
|
||||
+ // Paper start - Add predicate for blocks when raytracing
|
||||
+ return this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate<? super Block> canCollide) {
|
||||
Preconditions.checkArgument(start != null, "Location start cannot be null");
|
||||
- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
|
||||
- start.checkFinite();
|
||||
+ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
|
||||
+ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
|
||||
+ // Paper end - Add predicate for blocks when raytracing
|
||||
|
||||
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
|
||||
direction.checkFinite();
|
||||
@@ -1173,16 +1186,23 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
|
||||
Vector dir = direction.clone().normalize().multiply(maxDistance);
|
||||
- Vec3 startPos = CraftLocation.toVec3D(start);
|
||||
+ Vec3 startPos = io.papermc.paper.util.MCUtil.toVec3(start); // Paper - Add predicate for blocks when raytracing
|
||||
Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
|
||||
- HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()));
|
||||
+ HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), canCollide); // Paper - Add predicate for blocks when raytracing
|
||||
|
||||
return CraftRayTraceResult.fromNMS(this, nmsHitResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<? super Entity> filter) {
|
||||
- RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks);
|
||||
+ // Paper start - Add predicate for blocks when raytracing
|
||||
+ return this.rayTrace(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, filter, null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<? super Entity> filter, Predicate<? super Block> canCollide) {
|
||||
+ RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, canCollide);
|
||||
+ // Paper end - Add predicate for blocks when raytracing
|
||||
Vector startVec = null;
|
||||
double blockHitDistance = maxDistance;
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: booky10 <boooky10@gmail.com>
|
||||
Date: Sun, 29 Oct 2023 02:36:10 +0100
|
||||
Subject: [PATCH] Broadcast take item packets with collector as source
|
||||
|
||||
This fixes players (which can't view the collector) seeing item pickups with themselves as the target.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 4e96a65396b687d2823f2229744f5d448ba87512..04232f281ebd46954ef2259962c7bfc43b8a8aeb 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3749,7 +3749,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
public void take(Entity item, int count) {
|
||||
if (!item.isRemoved() && !this.level().isClientSide && (item instanceof ItemEntity || item instanceof AbstractArrow || item instanceof ExperienceOrb)) {
|
||||
- ((ServerLevel) this.level()).getChunkSource().broadcast(item, new ClientboundTakeItemEntityPacket(item.getId(), this.getId(), count));
|
||||
+ ((ServerLevel) this.level()).getChunkSource().broadcastAndSend(this, new ClientboundTakeItemEntityPacket(item.getId(), this.getId(), count)); // Paper - broadcast with collector as source
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tamion <70228790+notTamion@users.noreply.github.com>
|
||||
Date: Sat, 4 Nov 2023 23:57:05 +0100
|
||||
Subject: [PATCH] Expand LingeringPotion API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
index 5c6cb752f61c3f3c2960a337173fb7dfe86cc1d3..86c4b593a97431efd062b8c9d86bf92269c00536 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
@@ -274,7 +274,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
|
||||
boolean noEffects = potioncontents.hasEffects(); // Paper - Fix potions splash events
|
||||
// CraftBukkit start
|
||||
org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud);
|
||||
- if (!(event.isCancelled() || entityareaeffectcloud.isRemoved() || (noEffects && !entityareaeffectcloud.potionContents.hasEffects()))) { // Paper - don't spawn area effect cloud if the effects were empty and not changed during the event handling
|
||||
+ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved() || (!event.allowsEmptyCreation() && (noEffects && !entityareaeffectcloud.potionContents.hasEffects())))) { // Paper - don't spawn area effect cloud if the effects were empty and not changed during the event handling
|
||||
this.level().addFreshEntity(entityareaeffectcloud);
|
||||
} else {
|
||||
entityareaeffectcloud.discard(null); // CraftBukkit - add Bukkit remove cause
|
|
@ -1,72 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tamion <70228790+notTamion@users.noreply.github.com>
|
||||
Date: Sat, 30 Sep 2023 12:36:14 +0200
|
||||
Subject: [PATCH] Fix strikeLightningEffect powers lightning rods and clears
|
||||
copper
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java
|
||||
index 0471d9c85af02133f99cca4e181b83b58a3f1abc..4f701788bd21b61cad251a3a88f9bc416fb99051 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java
|
||||
@@ -47,6 +47,7 @@ public class LightningBolt extends Entity {
|
||||
private ServerPlayer cause;
|
||||
private final Set<Entity> hitEntities = Sets.newHashSet();
|
||||
private int blocksSetOnFire;
|
||||
+ public boolean isEffect; // Paper - Properly handle lightning effects api
|
||||
|
||||
public LightningBolt(EntityType<? extends LightningBolt> type, Level world) {
|
||||
super(type, world);
|
||||
@@ -87,7 +88,7 @@ public class LightningBolt extends Entity {
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
- if (this.life == 2) {
|
||||
+ if (!this.isEffect && this.life == 2) { // Paper - Properly handle lightning effects api
|
||||
if (this.level().isClientSide()) {
|
||||
this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F, false);
|
||||
this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F, false);
|
||||
@@ -134,7 +135,7 @@ public class LightningBolt extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
- if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly
|
||||
+ if (this.life >= 0 && !this.isEffect) { // CraftBukkit - add !this.visualOnly // Paper - Properly handle lightning effects api
|
||||
if (!(this.level() instanceof ServerLevel)) {
|
||||
this.level().setSkyFlashTime(2);
|
||||
} else if (!this.visualOnly) {
|
||||
@@ -163,7 +164,7 @@ public class LightningBolt extends Entity {
|
||||
}
|
||||
|
||||
private void spawnFire(int spreadAttempts) {
|
||||
- if (!this.visualOnly && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
|
||||
+ if (!this.visualOnly && !this.isEffect && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { // Paper - Properly handle lightning effects api
|
||||
BlockPos blockposition = this.blockPosition();
|
||||
BlockState iblockdata = BaseFireBlock.getState(this.level(), blockposition);
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 166458785b507208caa7ecf8ee8b60650ca3523a..7200c336de27ffd4d37231768ff5192956ede972 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -736,7 +736,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
LightningBolt lightning = EntityType.LIGHTNING_BOLT.create(this.world);
|
||||
lightning.moveTo(loc.getX(), loc.getY(), loc.getZ());
|
||||
- lightning.setVisualOnly(isVisual);
|
||||
+ lightning.isEffect = isVisual; // Paper - Properly handle lightning effects api
|
||||
this.world.strikeLightning(lightning, LightningStrikeEvent.Cause.CUSTOM);
|
||||
return (LightningStrike) lightning.getBukkitEntity();
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
|
||||
index 6fed8075aa75e3852dc826a45ca44603c0446a56..e9f471e60af0725ec34e2985d63ae9ea9f88590a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
|
||||
@@ -13,7 +13,7 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike
|
||||
|
||||
@Override
|
||||
public boolean isEffect() {
|
||||
- return this.getHandle().visualOnly;
|
||||
+ return this.getHandle().isEffect; // Paper - Properly handle lightning effects api
|
||||
}
|
||||
|
||||
public int getFlashes() {
|
|
@ -1,75 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: booky10 <boooky10@gmail.com>
|
||||
Date: Mon, 3 Jul 2023 01:55:32 +0200
|
||||
Subject: [PATCH] Add hand to fish event for all player interactions
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index e70ca1b2e6fbbc1f20e65429298d01b4ebd2dd29..270f4c94912b16c7d4a2d62670847cbb5e011819 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -482,7 +482,15 @@ public class FishingHook extends Projectile {
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {}
|
||||
|
||||
+ // Paper start - Add hand parameter to PlayerFishEvent
|
||||
+ @Deprecated
|
||||
+ @io.papermc.paper.annotation.DoNotUse
|
||||
public int retrieve(ItemStack usedItem) {
|
||||
+ return this.retrieve(net.minecraft.world.InteractionHand.MAIN_HAND, usedItem);
|
||||
+ }
|
||||
+
|
||||
+ public int retrieve(net.minecraft.world.InteractionHand hand, ItemStack usedItem) {
|
||||
+ // Paper end - Add hand parameter to PlayerFishEvent
|
||||
net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner();
|
||||
|
||||
if (!this.level().isClientSide && entityhuman != null && !this.shouldStopFishing(entityhuman)) {
|
||||
@@ -490,7 +498,7 @@ public class FishingHook extends Projectile {
|
||||
|
||||
if (this.hookedIn != null) {
|
||||
// CraftBukkit start
|
||||
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY);
|
||||
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.CAUGHT_ENTITY); // Paper - Add hand parameter to PlayerFishEvent
|
||||
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
|
||||
|
||||
if (playerFishEvent.isCancelled()) {
|
||||
@@ -519,7 +527,7 @@ public class FishingHook extends Projectile {
|
||||
}
|
||||
// Paper end
|
||||
// CraftBukkit start
|
||||
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null
|
||||
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null // Paper - Add hand parameter to PlayerFishEvent
|
||||
playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1);
|
||||
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
|
||||
|
||||
@@ -553,7 +561,7 @@ public class FishingHook extends Projectile {
|
||||
|
||||
if (this.onGround()) {
|
||||
// CraftBukkit start
|
||||
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND);
|
||||
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.IN_GROUND); // Paper - Add hand parameter to PlayerFishEvent
|
||||
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
|
||||
|
||||
if (playerFishEvent.isCancelled()) {
|
||||
@@ -564,7 +572,7 @@ public class FishingHook extends Projectile {
|
||||
}
|
||||
// CraftBukkit start
|
||||
if (i == 0) {
|
||||
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN);
|
||||
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.REEL_IN); // Paper - Add hand parameter to PlayerFishEvent
|
||||
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
|
||||
if (playerFishEvent.isCancelled()) {
|
||||
return 0;
|
||||
diff --git a/src/main/java/net/minecraft/world/item/FishingRodItem.java b/src/main/java/net/minecraft/world/item/FishingRodItem.java
|
||||
index 364c3090057405f83130089d275baf1a61d8e0ca..efb21967fdd2c3b4cb35db6faf213d55da5fc30e 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/FishingRodItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/FishingRodItem.java
|
||||
@@ -30,7 +30,7 @@ public class FishingRodItem extends Item {
|
||||
|
||||
if (user.fishing != null) {
|
||||
if (!world.isClientSide) {
|
||||
- int i = user.fishing.retrieve(itemstack);
|
||||
+ int i = user.fishing.retrieve(hand, itemstack); // Paper - Add hand parameter to PlayerFishEvent
|
||||
|
||||
itemstack.hurtAndBreak(i, user, LivingEntity.getSlotForHand(hand));
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 15 Dec 2022 00:14:44 -0800
|
||||
Subject: [PATCH] Fix several issues with EntityBreedEvent
|
||||
|
||||
Upstream did not account for different hands when storing
|
||||
the breed item for later use in the event. Also they only
|
||||
stored a reference to the stack, not a copy so if the stack
|
||||
changed after love mode was started, the breed item in the event
|
||||
also changed. Also in several places, the breed item was stored after
|
||||
it was decreased by one to consume the item.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java
|
||||
index b46352b328178df2a48d1c9e895bed3fabd2c292..1808e1b01afa3041a54c9c9a7586d4d61960527a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java
|
||||
@@ -148,8 +148,9 @@ public abstract class Animal extends AgeableMob {
|
||||
int i = this.getAge();
|
||||
|
||||
if (!this.level().isClientSide && i == 0 && this.canFallInLove()) {
|
||||
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -175,10 +176,18 @@ public abstract class Animal extends AgeableMob {
|
||||
return this.inLove <= 0;
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Fix EntityBreedEvent copying
|
||||
public void setInLove(@Nullable Player player) {
|
||||
+ // Paper start - Fix EntityBreedEvent copying
|
||||
+ this.setInLove(player, null);
|
||||
+ }
|
||||
+ public void setInLove(@Nullable Player player, @Nullable ItemStack breedItemCopy) {
|
||||
+ if (breedItemCopy != null) this.breedItem = breedItemCopy;
|
||||
+ // Paper end - Fix EntityBreedEvent copying
|
||||
// CraftBukkit start
|
||||
EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600);
|
||||
if (entityEnterLoveModeEvent.isCancelled()) {
|
||||
+ this.breedItem = null; // Paper - Fix EntityBreedEvent copying; clear if cancelled
|
||||
return;
|
||||
}
|
||||
this.inLove = entityEnterLoveModeEvent.getTicksInLove();
|
||||
@@ -186,7 +195,7 @@ public abstract class Animal extends AgeableMob {
|
||||
if (player != null) {
|
||||
this.loveCause = player.getUUID();
|
||||
}
|
||||
- this.breedItem = player.getInventory().getSelected(); // CraftBukkit
|
||||
+ // Paper - Fix EntityBreedEvent copying; set breed item in better place
|
||||
|
||||
this.level().broadcastEntityEvent(this, (byte) 18);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
||||
index 293d6891948e99ac9bd741008f7dcbc5fc1a2e3d..e108f876d3f129c6287f13d68427aed2a6f0c5b1 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
||||
@@ -673,8 +673,9 @@ public class Panda extends Animal {
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
this.ageUp((int) ((float) (-this.getAge() / 20) * 0.1F), true);
|
||||
} else if (!this.level().isClientSide && this.getAge() == 0 && this.canFallInLove()) {
|
||||
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
|
||||
this.usePlayerItem(player, hand, itemstack);
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
|
||||
} else {
|
||||
if (this.level().isClientSide || this.isSitting() || this.isInWater()) {
|
||||
return InteractionResult.PASS;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
index 4eb305bc77767531efb6f9d299216248d4ee39d2..729fd2d52dd48e25ee7a077a3ffafc80ecef7c9f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
@@ -352,8 +352,8 @@ public class Armadillo extends Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void setInLove(@Nullable Player player) {
|
||||
- super.setInLove(player);
|
||||
+ public void setInLove(@Nullable Player player, @Nullable ItemStack breedItemCopy) { // Paper
|
||||
+ super.setInLove(player, breedItemCopy); // Paper
|
||||
this.makeSound(SoundEvents.ARMADILLO_EAT);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
index 0388b09e1c4f03958384680ed487792a54007463..8941752e4600ccd11b3fa1147b2e414785589eed 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
@@ -393,7 +393,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl
|
||||
boolean flag1 = this.isTamed() && this.getAge() == 0 && this.canFallInLove();
|
||||
|
||||
if (flag1) {
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
|
||||
}
|
||||
|
||||
boolean flag2 = this.isBaby();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
index f1e43254936feedfe0ffbf77071505f3a65e5053..1f5ed236fb7c0c1b0181675747d25d233f534284 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
@@ -572,7 +572,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
|
||||
b0 = 5;
|
||||
if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) {
|
||||
flag = true;
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
|
||||
}
|
||||
} else if (item.is(Items.GOLDEN_APPLE) || item.is(Items.ENCHANTED_GOLDEN_APPLE)) {
|
||||
f = 10.0F;
|
||||
@@ -580,7 +580,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
|
||||
b0 = 10;
|
||||
if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) {
|
||||
flag = true;
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
index 82c57124433cc033c99e609e8ad71e03d340bc5e..cf6a3a63b6f2b96943c0f399e8c82d293fee31ba 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
@@ -179,7 +179,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
|
||||
f = 10.0F;
|
||||
if (this.isTamed() && this.getAge() == 0 && this.canFallInLove()) {
|
||||
flag = true;
|
||||
- this.setInLove(player);
|
||||
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: TonytheMacaroni <tonythemacaroni123@gmail.com>
|
||||
Date: Thu, 9 Nov 2023 20:34:44 -0500
|
||||
Subject: [PATCH] Add UUID attribute modifier API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
|
||||
index 52439f4b959c74027eb191a3af960c70beb978e8..a2c057d92ea34368c7efc538b6e5b15ef342c54e 100644
|
||||
--- a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
|
||||
+++ b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
|
||||
@@ -5,6 +5,7 @@ import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
|
||||
|
||||
+import java.util.UUID;
|
||||
import java.util.Collection;
|
||||
|
||||
public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
|
||||
@@ -18,6 +19,11 @@ public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
|
||||
throw new UnsupportedOperationException("Cannot modify default attributes");
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public void removeModifier(UUID uuid) {
|
||||
+ throw new UnsupportedOperationException("Cannot modify default attributes");
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public void addModifier(AttributeModifier modifier) {
|
||||
throw new UnsupportedOperationException("Cannot modify default attributes");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/AttributeMappings.java b/src/main/java/org/bukkit/craftbukkit/attribute/AttributeMappings.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ce23ac9bcf5b043a07130da39cc8804f0d0be1e5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/AttributeMappings.java
|
||||
@@ -0,0 +1,68 @@
|
||||
+package org.bukkit.craftbukkit.attribute;
|
||||
+
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Map;
|
||||
+import java.util.UUID;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+final class AttributeMappings {
|
||||
+ private static final Map<UUID, NamespacedKey> ATTRIBUTE_MODIFIER_IDS = new HashMap<>();
|
||||
+
|
||||
+ static {
|
||||
+ add(-4483571535397864886L, -5989644940537681742L, "armor.body");
|
||||
+ add(8144722948526719024L, -7778190119041365872L, "effect.slowness");
|
||||
+ add(6967552254039378640L, -9116175396973475259L, "enchantment.aqua_affinity");
|
||||
+ add(5279725409867744698L, -5150363631200102632L, "attacking");
|
||||
+ add(148071211714102867L, -7685811609035173472L, "attacking");
|
||||
+ add(6196088217904236654L, -7493791321850887290L, "effect.minining_fatigue");
|
||||
+ add(-5084161844451524480L, -8859020046251006329L, "enchantment.soul_speed");
|
||||
+ add(-7907339078496465106L, -8112074600724210224L, "enchantment.swift_sneak");
|
||||
+ add(6688265815086220243L, -6545541163342161890L, "drinking");
|
||||
+ add(8315164243412860989L, -6631520853640075966L, "creative_mode_block_range");
|
||||
+ add(4389663563256579765L, -4827163546944004714L, "enchantment.efficiency");
|
||||
+ add(6732612758648800940L, -5145707699103688244L, "effect.health_boost");
|
||||
+ add(9079981369298536661L, -6728494925450710401L, "covered");
|
||||
+ add(-1521481167610687786L, -8630419745734927691L, "effect.absorption");
|
||||
+ add(-7473408062188862076L, -5872005994337939597L, "creative_mode_entity_range");
|
||||
+ add(-3721396875562958315L, -5317020504214661337L, "effect.unluck");
|
||||
+ add(-2861585646493481178L, -6113244764726669811L, "armor.leggings");
|
||||
+ add(6718535547217657911L, -5386630269401489641L, "enchantment.sweeping_edge");
|
||||
+ add(-7949229004988660584L, -7828611303000832459L, "effect.speed");
|
||||
+ add(-8650171790042118250L, -5749650997644763080L, "enchantment.soul_speed");
|
||||
+ add(551224288813600377L, -8734740027710371860L, "enchantment.respiration");
|
||||
+ add(-7046399332347654691L, -6723081531683397260L, "suffocating");
|
||||
+ add(7361814797886573596L, -8641397326606817395L, "sprinting");
|
||||
+ add(-6972338111383059132L, -8978659762232839026L, "armor.chestplate");
|
||||
+ add(-5371971015925809039L, -6062243582569928137L, "enchantment.fire_protection");
|
||||
+ add(7245570952092733273L, -8449101711440750679L, "effect.strength");
|
||||
+ add(-422425648963762075L, -5756800103171642205L, "base_attack_speed");
|
||||
+ add(-4607081316629330256L, -7008565754814018370L, "effect.jump_boost");
|
||||
+ add(271280981090454338L, -8746077033958322898L, "effect.luck");
|
||||
+ add(2211131075215181206L, -5513857709499300658L, "powder_snow");
|
||||
+ add(-8908768238899017377L, -8313820693701227669L, "armor.boots");
|
||||
+ add(-5797418877589107702L, -6181652684028920077L, "effect.haste");
|
||||
+ add(3086076556416732775L, -5150312587563650736L, "armor.helmet");
|
||||
+ add(-5082757096938257406L, -4891139119377885130L, "baby");
|
||||
+ add(2478452629826324956L, -7247530463494186011L, "effect.weakness");
|
||||
+ add(4659420831966187055L, -5191473055587376048L, "enchantment.blast_protection");
|
||||
+ add(7301951777949303281L, -6753860660653972126L, "evil");
|
||||
+ add(8533189226688352746L, -8254757081029716377L, "baby");
|
||||
+ add(1286946037536540352L, -5768092872487507967L, "enchantment.depth_strider");
|
||||
+ add(-3801225194067177672L, -6586624321849018929L, "base_attack_damage");
|
||||
+ }
|
||||
+
|
||||
+ public static @NotNull NamespacedKey uuidToKey(final UUID uuid) {
|
||||
+ final NamespacedKey key = ATTRIBUTE_MODIFIER_IDS.get(uuid);
|
||||
+ if (key != null) {
|
||||
+ return key;
|
||||
+ } else {
|
||||
+ return NamespacedKey.minecraft(uuid.toString());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void add(final long msb, final long lsb, final String id) {
|
||||
+ final UUID uuid = new UUID(msb, lsb);
|
||||
+ ATTRIBUTE_MODIFIER_IDS.put(uuid, NamespacedKey.minecraft(id));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
|
||||
index cd6a492f56b3dee5985c068e20009b6c833e143b..34b9d79fd1a4aa7395b3383fa721f5689494aa12 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
|
||||
@@ -45,6 +45,33 @@ public class CraftAttributeInstance implements AttributeInstance {
|
||||
return result;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public AttributeModifier getModifier(final net.kyori.adventure.key.Key key) {
|
||||
+ Preconditions.checkArgument(key != null, "Key cannot be null");
|
||||
+ net.minecraft.world.entity.ai.attributes.AttributeModifier modifier = this.handle.getModifier(io.papermc.paper.adventure.PaperAdventure.asVanilla(key));
|
||||
+ return modifier == null ? null : CraftAttributeInstance.convert(modifier);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeModifier(final net.kyori.adventure.key.Key key) {
|
||||
+ Preconditions.checkArgument(key != null, "Key cannot be null");
|
||||
+ this.handle.removeModifier(io.papermc.paper.adventure.PaperAdventure.asVanilla(key));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public AttributeModifier getModifier(java.util.UUID uuid) {
|
||||
+ Preconditions.checkArgument(uuid != null, "UUID cannot be null");
|
||||
+ return this.getModifier(AttributeMappings.uuidToKey(uuid));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeModifier(java.util.UUID uuid) {
|
||||
+ Preconditions.checkArgument(uuid != null, "UUID cannot be null");
|
||||
+ this.removeModifier(AttributeMappings.uuidToKey(uuid));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void addModifier(AttributeModifier modifier) {
|
||||
Preconditions.checkArgument(modifier != null, "modifier");
|
|
@ -1,28 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: booky10 <boooky10@gmail.com>
|
||||
Date: Sun, 12 Nov 2023 05:09:47 +0100
|
||||
Subject: [PATCH] Fix missing event call for entity teleport API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 580427bf1521ac9fef37f7464e12a7bfe4fbfb10..9ca1fee03bfa557f1df7388c6043c9ec6d02a79a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -258,6 +258,17 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // Paper start - fix teleport event not being called
|
||||
+ org.bukkit.event.entity.EntityTeleportEvent event = new org.bukkit.event.entity.EntityTeleportEvent(
|
||||
+ this, this.getLocation(), location);
|
||||
+ // cancelling the event is handled differently for players and entities,
|
||||
+ // entities just stop teleporting, players will still teleport to the "from" location of the event
|
||||
+ if (!event.callEvent() || event.getTo() == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ location = event.getTo();
|
||||
+ // Paper end
|
||||
+
|
||||
// If this entity is riding another entity, we must dismount before teleporting.
|
||||
if (dismount) this.entity.stopRiding(); // Paper - Teleport passenger API
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrPowerGamerBR <git@mrpowergamerbr.com>
|
||||
Date: Tue, 21 Nov 2023 12:16:39 -0300
|
||||
Subject: [PATCH] Lazily create LootContext for criterions
|
||||
|
||||
For each player on each tick, enter block triggers are invoked, and these create loot contexts that are promptly thrown away since the trigger doesn't pass the predicate
|
||||
|
||||
To avoid this, we now lazily create the LootContext if the criterion passes the predicate AND if any of the listener triggers require a loot context instance
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
||||
index f43053ba082f9772b6ec02828fa2d6f387c32d26..35772110e9318df46a2729dbc0b5879b290011b7 100644
|
||||
--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
||||
+++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
||||
@@ -42,14 +42,14 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
|
||||
PlayerAdvancements playerAdvancements = player.getAdvancements();
|
||||
Set<CriterionTrigger.Listener<T>> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak
|
||||
if (set != null && !set.isEmpty()) {
|
||||
- LootContext lootContext = EntityPredicate.createContext(player, player);
|
||||
+ LootContext lootContext = null; // EntityPredicate.createContext(player, player); // Paper - Perf: lazily create LootContext for criterions
|
||||
List<CriterionTrigger.Listener<T>> list = null;
|
||||
|
||||
for (CriterionTrigger.Listener<T> listener : set) {
|
||||
T simpleInstance = listener.trigger();
|
||||
if (predicate.test(simpleInstance)) {
|
||||
Optional<ContextAwarePredicate> optional = simpleInstance.player();
|
||||
- if (optional.isEmpty() || optional.get().matches(lootContext)) {
|
||||
+ if (optional.isEmpty() || optional.get().matches(lootContext = (lootContext == null ? EntityPredicate.createContext(player, player) : lootContext))) { // Paper - Perf: lazily create LootContext for criterions
|
||||
if (list == null) {
|
||||
list = Lists.newArrayList();
|
||||
}
|
|
@ -1,208 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 23 Nov 2023 10:33:25 -0800
|
||||
Subject: [PATCH] Don't fire sync events during worldgen
|
||||
|
||||
Fixes EntityPotionEffectEvent
|
||||
Fixes EntityPoseChangeEvent
|
||||
|
||||
Asynchronous chunk generation provides an opportunity for things
|
||||
to happen async that previously fired synchronous-only events. This
|
||||
patch is for mitigating those issues by various methods.
|
||||
|
||||
Also fixes correctly marking/clearing the entity generation flag.
|
||||
This patch sets the generation flag anytime an entity is created
|
||||
via StructureTemplate before loading from NBT to catch uses of
|
||||
the flag during the loading logic. This patch clears the generation
|
||||
flag from an entity when added to a ServerLevel for the situation
|
||||
where generation happened directly to a ServerLevel and the
|
||||
entity still has the flag set.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 60c75f7c4258efb26c2595ca7724b08d3c046c9d..34ece37aee68e4d8eeaa919e8bd489a672756049 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1224,6 +1224,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
// CraftBukkit start
|
||||
private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
||||
+ entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process
|
||||
// Paper start - extra debug info
|
||||
if (entity.valid) {
|
||||
MinecraftServer.LOGGER.error("Attempted Double World add on {}", entity, new Throwable());
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index bd0e205c760414784ae483452fd02292939dcb5c..f163cb3c75e90b96b3794a7e0c5b803268814c8c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -624,7 +624,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
if (pose == this.getPose()) {
|
||||
return;
|
||||
}
|
||||
- this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()]));
|
||||
+ // Paper start - Don't fire sync event during generation
|
||||
+ if (!this.generation) {
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()]));
|
||||
+ }
|
||||
+ // Paper end - Don't fire sync event during generation
|
||||
// CraftBukkit end
|
||||
this.entityData.set(Entity.DATA_POSE, pose);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
index 5fb3279342506611882b5780cfbee0371919c93c..b98f9246b60daf31460f41ce214dfa7c011f5684 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
@@ -592,9 +592,15 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
}
|
||||
|
||||
public static Optional<Entity> create(CompoundTag nbt, Level world) {
|
||||
+ // Paper start - Don't fire sync event during generation
|
||||
+ return create(nbt, world, false);
|
||||
+ }
|
||||
+ public static Optional<Entity> create(CompoundTag nbt, Level world, boolean generation) {
|
||||
+ // Paper end - Don't fire sync event during generation
|
||||
return Util.ifElse(EntityType.by(nbt).map((entitytypes) -> {
|
||||
return entitytypes.create(world);
|
||||
}), (entity) -> {
|
||||
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
|
||||
entity.load(nbt);
|
||||
}, () -> {
|
||||
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 04232f281ebd46954ef2259962c7bfc43b8a8aeb..0c67f04ae7eeaa10a90419031447ad5397c6b9e2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1138,6 +1138,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) {
|
||||
+ // Paper start - Don't fire sync event during generation
|
||||
+ return this.addEffect(mobeffect, entity, cause, true);
|
||||
+ }
|
||||
+ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
|
||||
+ // Paper end - Don't fire sync event during generation
|
||||
// org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
|
||||
if (this.isTickingEffects) {
|
||||
this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause));
|
||||
@@ -1157,10 +1162,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
override = new MobEffectInstance(mobeffect1).update(mobeffect);
|
||||
}
|
||||
|
||||
+ if (fireEvent) { // Paper - Don't fire sync event during generation
|
||||
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override);
|
||||
+ override = event.isOverride(); // Paper - Don't fire sync event during generation
|
||||
if (event.isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
+ } // Paper - Don't fire sync event during generation
|
||||
// CraftBukkit end
|
||||
|
||||
if (mobeffect1 == null) {
|
||||
@@ -1169,7 +1177,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
flag = true;
|
||||
mobeffect.onEffectAdded(this);
|
||||
// CraftBukkit start
|
||||
- } else if (event.isOverride()) {
|
||||
+ } else if (override) { // Paper - Don't fire sync event during generation
|
||||
mobeffect1.update(mobeffect);
|
||||
this.onEffectUpdated(mobeffect1, true, entity);
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
||||
index f91ea9ac5a0d0d3bae5d1eb0c409f4f9c4e5a62b..9045f18f49a5c6685597d0a77126d7cb35bc5e88 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
||||
@@ -172,7 +172,7 @@ public class Spider extends Monster {
|
||||
Holder<MobEffect> holder = entityspider_groupdataspider.effect;
|
||||
|
||||
if (holder != null) {
|
||||
- this.addEffect(new MobEffectInstance(holder, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit
|
||||
+ this.addEffect(new MobEffectInstance(holder, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, world instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index cf8258e8d46ca7286a66c38fa24af369bd9a279f..0555abfda468c343af8244a122ebe769e70a0292 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -525,7 +525,7 @@ public class StructureTemplate {
|
||||
private static Optional<Entity> createEntityIgnoreException(ServerLevelAccessor world, CompoundTag nbt) {
|
||||
// CraftBukkit start
|
||||
// try {
|
||||
- return EntityType.create(nbt, world.getLevel());
|
||||
+ return EntityType.create(nbt, world.getLevel(), true); // Paper - Don't fire sync event during generation
|
||||
// } catch (Exception exception) {
|
||||
// return Optional.empty();
|
||||
// }
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
|
||||
index 524b51a0ab808a0629c871ad813115abd4b49dbd..fceed3d08ee6f4c171685986bb19d2be592eedc6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
|
||||
@@ -92,15 +92,17 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel {
|
||||
return this.handle.getLevel();
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) {
|
||||
- this.handle.addFreshEntityWithPassengers(arg0, arg1);
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void addFreshEntityWithPassengers(Entity entity) {
|
||||
- this.handle.addFreshEntityWithPassengers(entity);
|
||||
- }
|
||||
+ // Paper start - Don't fire sync event during generation; don't override these methods so all entities are run through addFreshEntity
|
||||
+ // @Override
|
||||
+ // public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) {
|
||||
+ // this.handle.addFreshEntityWithPassengers(arg0, arg1);
|
||||
+ // }
|
||||
+ //
|
||||
+ // @Override
|
||||
+ // public void addFreshEntityWithPassengers(Entity entity) {
|
||||
+ // this.handle.addFreshEntityWithPassengers(entity);
|
||||
+ // }
|
||||
+ // Paper end - Don't fire sync event during generation; don't override these methods
|
||||
|
||||
@Override
|
||||
public ServerLevel getMinecraftWorld() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
|
||||
index 35ecf6f824aca56a20280dd683123df1d0c7d66e..1d1fdcf10498c421f106158254e052da6d68d8a5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
|
||||
@@ -39,21 +39,23 @@ public class TransformerGeneratorAccess extends DelegatedGeneratorAccess {
|
||||
return super.addFreshEntity(arg0, arg1);
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public void addFreshEntityWithPassengers(Entity entity) {
|
||||
- if (this.structureTransformer != null && !this.structureTransformer.transformEntity(entity)) {
|
||||
- return;
|
||||
- }
|
||||
- super.addFreshEntityWithPassengers(entity);
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) {
|
||||
- if (this.structureTransformer != null && !this.structureTransformer.transformEntity(arg0)) {
|
||||
- return;
|
||||
- }
|
||||
- super.addFreshEntityWithPassengers(arg0, arg1);
|
||||
- }
|
||||
+ // Paper start - Don't fire sync event during generation; don't override these methods so all entities are run through addFreshEntity
|
||||
+ // @Override
|
||||
+ // public void addFreshEntityWithPassengers(Entity entity) {
|
||||
+ // if (this.structureTransformer != null && !this.structureTransformer.transformEntity(entity)) {
|
||||
+ // return;
|
||||
+ // }
|
||||
+ // super.addFreshEntityWithPassengers(entity);
|
||||
+ // }
|
||||
+ //
|
||||
+ // @Override
|
||||
+ // public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) {
|
||||
+ // if (this.structureTransformer != null && !this.structureTransformer.transformEntity(arg0)) {
|
||||
+ // return;
|
||||
+ // }
|
||||
+ // super.addFreshEntityWithPassengers(arg0, arg1);
|
||||
+ // }
|
||||
+ // Paper end - Don't fire sync event during generation; don't override these methods
|
||||
|
||||
public boolean setCraftBlock(BlockPos position, CraftBlockState craftBlockState, int i, int j) {
|
||||
if (this.structureTransformer != null) {
|
|
@ -1,26 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 27 Mar 2023 10:20:00 -0700
|
||||
Subject: [PATCH] Add Structure check API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 7200c336de27ffd4d37231768ff5192956ede972..cb85180daaa2b40cba2474784548d650bc4d639b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -246,6 +246,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
};
|
||||
}
|
||||
// Paper end
|
||||
+ // Paper start - structure check API
|
||||
+ @Override
|
||||
+ public boolean hasStructureAt(final io.papermc.paper.math.Position position, final Structure structure) {
|
||||
+ return this.world.structureManager().getStructureWithPieceAt(
|
||||
+ io.papermc.paper.util.MCUtil.toBlockPos(position),
|
||||
+ CraftStructure.bukkitToMinecraft(structure)
|
||||
+ ).isValid();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
private static final Random rand = new Random();
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: hyper1423 <backup8822@gmail.com>
|
||||
Date: Sun, 3 Dec 2023 07:38:09 +0900
|
||||
Subject: [PATCH] Fix CraftMetaItem#getAttributeModifier duplication check
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index df34eba383c0d3035c8baed7fdd054ecdd681fa3..f15456b02cabbbe33d701450ef53a0561d91cb8c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
@@ -1414,7 +1414,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null");
|
||||
this.checkAttributeList();
|
||||
for (Map.Entry<Attribute, AttributeModifier> entry : this.attributeModifiers.entries()) {
|
||||
- Preconditions.checkArgument(!entry.getValue().getKey().equals(modifier.getKey()), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier);
|
||||
+ Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine
|
||||
}
|
||||
return this.attributeModifiers.put(attribute, modifier);
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 22 Mar 2022 09:34:41 -0700
|
||||
Subject: [PATCH] Restore vanilla entity drops behavior
|
||||
|
||||
Instead of just tracking the itemstacks, this tracks with it, the
|
||||
action to take with that itemstack to apply the correct logic
|
||||
on dropping the item instead of generalizing it for all dropped
|
||||
items like CB does.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index b65d816bb9feb18ecf74e10e9728c302e5657587..62ec627e80b87a92a2a51ba9fc3626a67636855f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -976,20 +976,20 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
if (this.isRemoved()) {
|
||||
return;
|
||||
}
|
||||
- java.util.List<org.bukkit.inventory.ItemStack> loot = new java.util.ArrayList<>(this.getInventory().getContainerSize());
|
||||
+ List<DefaultDrop> loot = new java.util.ArrayList<>(this.getInventory().getContainerSize()); // Paper - Restore vanilla drops behavior
|
||||
boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator();
|
||||
|
||||
if (!keepInventory) {
|
||||
for (ItemStack item : this.getInventory().getContents()) {
|
||||
if (!item.isEmpty() && !EnchantmentHelper.has(item, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) {
|
||||
- loot.add(CraftItemStack.asCraftMirror(item).markForInventoryDrop());
|
||||
+ loot.add(new DefaultDrop(item, stack -> this.drop(stack, true, false, false))); // Paper - Restore vanilla drops behavior; drop function taken from Inventory#dropAll (don't fire drop event)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false
|
||||
// SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule)
|
||||
this.dropFromLootTable(damageSource, this.lastHurtByPlayerTime > 0);
|
||||
- this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag);
|
||||
+ // Paper - Restore vanilla drops behaviour; custom death loot is a noop on server player, remove.
|
||||
|
||||
loot.addAll(this.drops);
|
||||
this.drops.clear(); // SPIGOT-5188: make sure to clear
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index f163cb3c75e90b96b3794a7e0c5b803268814c8c..e88c88b6f87dddda8e8e3ed215a8f2c166afa3ef 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -2562,6 +2562,25 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
|
||||
@Nullable
|
||||
public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) {
|
||||
+ // Paper start - Restore vanilla drops behavior
|
||||
+ return this.spawnAtLocation(stack, yOffset, null);
|
||||
+ }
|
||||
+ public record DefaultDrop(Item item, org.bukkit.inventory.ItemStack stack, @Nullable java.util.function.Consumer<ItemStack> dropConsumer) {
|
||||
+ public DefaultDrop(final ItemStack stack, final java.util.function.Consumer<ItemStack> dropConsumer) {
|
||||
+ this(stack.getItem(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), dropConsumer);
|
||||
+ }
|
||||
+
|
||||
+ public void runConsumer(final java.util.function.Consumer<org.bukkit.inventory.ItemStack> fallback) {
|
||||
+ if (this.dropConsumer == null || org.bukkit.craftbukkit.inventory.CraftItemType.bukkitToMinecraft(this.stack.getType()) != this.item) {
|
||||
+ fallback.accept(this.stack);
|
||||
+ } else {
|
||||
+ this.dropConsumer.accept(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(this.stack));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ public ItemEntity spawnAtLocation(ItemStack stack, float yOffset, @Nullable java.util.function.Consumer<? super ItemEntity> delayedAddConsumer) {
|
||||
+ // Paper end - Restore vanilla drops behavior
|
||||
if (stack.isEmpty()) {
|
||||
return null;
|
||||
} else if (this.level().isClientSide) {
|
||||
@@ -2569,14 +2588,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
} else {
|
||||
// CraftBukkit start - Capture drops for death event
|
||||
if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) {
|
||||
- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // Paper - mirror so we can destroy it later
|
||||
+ // Paper start - Restore vanilla drops behavior
|
||||
+ ((net.minecraft.world.entity.LivingEntity) this).drops.add(new net.minecraft.world.entity.Entity.DefaultDrop(stack, itemStack -> {
|
||||
+ ItemEntity itemEntity = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), itemStack); // stack is copied before consumer
|
||||
+ itemEntity.setDefaultPickUpDelay();
|
||||
+ this.level.addFreshEntity(itemEntity);
|
||||
+ if (delayedAddConsumer != null) delayedAddConsumer.accept(itemEntity);
|
||||
+ }));
|
||||
+ // Paper end - Restore vanilla drops behavior
|
||||
return null;
|
||||
}
|
||||
// CraftBukkit end
|
||||
ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - copy so we can destroy original
|
||||
stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe
|
||||
|
||||
- entityitem.setDefaultPickUpDelay();
|
||||
+ entityitem.setDefaultPickUpDelay(); // Paper - diff on change (in dropConsumer)
|
||||
// Paper start - Call EntityDropItemEvent
|
||||
return this.spawnAtLocation(entityitem);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 0c67f04ae7eeaa10a90419031447ad5397c6b9e2..6b2dc430126713e11658f94762035ff10bbe018c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -278,7 +278,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
protected float appliedScale;
|
||||
// CraftBukkit start
|
||||
public int expToDrop;
|
||||
- public ArrayList<org.bukkit.inventory.ItemStack> drops = new ArrayList<org.bukkit.inventory.ItemStack>();
|
||||
+ public ArrayList<DefaultDrop> drops = new ArrayList<>(); // Paper - Restore vanilla drops behavior
|
||||
public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
|
||||
public boolean collides = true;
|
||||
public Set<UUID> collidableExemptions = new HashSet<>();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
index 1b49090a466bc74d9e5f2815314955b6dfbb83dc..62271e74399a827a488159da234465ef18e15e6e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
@@ -538,10 +538,9 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
|
||||
@Override
|
||||
protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {
|
||||
super.dropCustomDeathLoot(world, source, causedByPlayer);
|
||||
- ItemEntity entityitem = this.spawnAtLocation((ItemLike) Items.NETHER_STAR);
|
||||
-
|
||||
+ ItemEntity entityitem = this.spawnAtLocation(new net.minecraft.world.item.ItemStack(Items.NETHER_STAR), 0, ItemEntity::setExtendedLifetime); // Paper - Restore vanilla drops behavior; spawnAtLocation returns null so modify the item entity with a consumer
|
||||
if (entityitem != null) {
|
||||
- entityitem.setExtendedLifetime();
|
||||
+ entityitem.setExtendedLifetime(); // Paper - diff on change
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 5bcb9a53ebebeef4bd6ec2458df4b63002ebd804..2f398750bfee5758ad8b1367b6fc14364e4de776 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -621,7 +621,7 @@ public class ArmorStand extends LivingEntity {
|
||||
ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
|
||||
|
||||
itemstack.set(DataComponents.CUSTOM_NAME, this.getCustomName());
|
||||
- this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
|
||||
+ this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior
|
||||
return this.brokenByAnything(world, damageSource); // Paper
|
||||
}
|
||||
|
||||
@@ -635,7 +635,7 @@ public class ArmorStand extends LivingEntity {
|
||||
for (i = 0; i < this.handItems.size(); ++i) {
|
||||
itemstack = (ItemStack) this.handItems.get(i);
|
||||
if (!itemstack.isEmpty()) {
|
||||
- this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
|
||||
+ this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
|
||||
this.handItems.set(i, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
@@ -643,7 +643,7 @@ public class ArmorStand extends LivingEntity {
|
||||
for (i = 0; i < this.armorItems.size(); ++i) {
|
||||
itemstack = (ItemStack) this.armorItems.get(i);
|
||||
if (!itemstack.isEmpty()) {
|
||||
- this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
|
||||
+ this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
|
||||
this.armorItems.set(i, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 2690c471b819f8308f6db44150025dfa323d4e0c..f529243852df8e193a604bb6d895333848b14a74 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -975,18 +975,24 @@ public class CraftEventFactory {
|
||||
}
|
||||
|
||||
public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource) {
|
||||
- return CraftEventFactory.callEntityDeathEvent(victim, damageSource, new ArrayList<org.bukkit.inventory.ItemStack>(0));
|
||||
+ return CraftEventFactory.callEntityDeathEvent(victim, damageSource, new ArrayList<>(0)); // Paper - Restore vanilla drops behavior
|
||||
}
|
||||
|
||||
- public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<org.bukkit.inventory.ItemStack> drops) {
|
||||
+ public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<Entity.DefaultDrop> drops) { // Paper - Restore vanilla drops behavior
|
||||
// Paper start
|
||||
return CraftEventFactory.callEntityDeathEvent(victim, damageSource, drops, com.google.common.util.concurrent.Runnables.doNothing());
|
||||
}
|
||||
- public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<org.bukkit.inventory.ItemStack> drops, Runnable lootCheck) {
|
||||
+
|
||||
+ private static final java.util.function.Function<org.bukkit.inventory.ItemStack, Entity.DefaultDrop> FROM_FUNCTION = stack -> {
|
||||
+ if (stack == null) return null;
|
||||
+ return new Entity.DefaultDrop(CraftItemType.bukkitToMinecraft(stack.getType()), stack, null);
|
||||
+ };
|
||||
+
|
||||
+ public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<Entity.DefaultDrop> drops, Runnable lootCheck) { // Paper
|
||||
// Paper end
|
||||
CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
|
||||
CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource);
|
||||
- EntityDeathEvent event = new EntityDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward(damageSource.getEntity()));
|
||||
+ EntityDeathEvent event = new EntityDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(damageSource.getEntity())); // Paper - Restore vanilla drops behavior
|
||||
populateFields(victim, event); // Paper - make cancellable
|
||||
CraftWorld world = (CraftWorld) entity.getWorld();
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
@@ -1000,20 +1006,24 @@ public class CraftEventFactory {
|
||||
victim.expToDrop = event.getDroppedExp();
|
||||
lootCheck.run(); // Paper - advancement triggers before destroying items
|
||||
|
||||
- for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
|
||||
+ // Paper start - Restore vanilla drops behavior
|
||||
+ for (Entity.DefaultDrop drop : drops) {
|
||||
+ if (drop == null) continue;
|
||||
+ final org.bukkit.inventory.ItemStack stack = drop.stack();
|
||||
+ // Paper end - Restore vanilla drops behavior
|
||||
if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue;
|
||||
|
||||
- world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS
|
||||
+ drop.runConsumer(s -> world.dropItem(entity.getLocation(), s)); // Paper - Restore vanilla drops behavior
|
||||
if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List<org.bukkit.inventory.ItemStack> drops, net.kyori.adventure.text.Component deathMessage, boolean keepInventory) { // Paper - Adventure
|
||||
+ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List<Entity.DefaultDrop> drops, net.kyori.adventure.text.Component deathMessage, boolean keepInventory) { // Paper - Adventure & Restore vanilla drops behavior
|
||||
CraftPlayer entity = victim.getBukkitEntity();
|
||||
CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource);
|
||||
- PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward(damageSource.getEntity()), 0, deathMessage);
|
||||
+ PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(damageSource.getEntity()), 0, deathMessage); // Paper - Restore vanilla drops behavior
|
||||
event.setKeepInventory(keepInventory);
|
||||
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
|
||||
populateFields(victim, event); // Paper - make cancellable
|
||||
@@ -1031,16 +1041,14 @@ public class CraftEventFactory {
|
||||
victim.expToDrop = event.getDroppedExp();
|
||||
victim.newExp = event.getNewExp();
|
||||
|
||||
- for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
|
||||
+ // Paper start - Restore vanilla drops behavior
|
||||
+ for (Entity.DefaultDrop drop : drops) {
|
||||
+ if (drop == null) continue;
|
||||
+ final org.bukkit.inventory.ItemStack stack = drop.stack();
|
||||
+ // Paper end - Restore vanilla drops behavior
|
||||
if (stack == null || stack.getType() == Material.AIR) continue;
|
||||
|
||||
- if (stack instanceof CraftItemStack craftItemStack && craftItemStack.isForInventoryDrop()) {
|
||||
- victim.drop(CraftItemStack.asNMSCopy(stack), true, false, false); // SPIGOT-7800, SPIGOT-7801: Vanilla Behaviour for Player Inventory dropped items
|
||||
- } else {
|
||||
- victim.forceDrops = true;
|
||||
- victim.spawnAtLocation(CraftItemStack.asNMSCopy(stack)); // SPIGOT-7806: Vanilla Behaviour for items not related to Player Inventory dropped items
|
||||
- victim.forceDrops = false;
|
||||
- }
|
||||
+ drop.runConsumer(s -> victim.drop(CraftItemStack.unwrap(s), true, false, false)); // Paper - Restore vanilla drops behavior
|
||||
}
|
||||
|
||||
return event;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index c5a09f086d35f84c0a30266f78e06e2dfb5603e6..f33742ee06e8443a5f5adaaa987d7523dc193b5a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -130,27 +130,6 @@ public final class CraftItemStack extends ItemStack {
|
||||
this.setItemMeta(itemMeta);
|
||||
}
|
||||
|
||||
- /**
|
||||
- * Gets if the item is marked as an inventory drop in death events.
|
||||
- *
|
||||
- * @return true if the item is marked as an inventory drop
|
||||
- */
|
||||
- @ApiStatus.Internal
|
||||
- public boolean isForInventoryDrop() {
|
||||
- return this.isForInventoryDrop;
|
||||
- }
|
||||
-
|
||||
- /**
|
||||
- * Marks this item as an inventory drop in death events.
|
||||
- *
|
||||
- * @return the ItemStack marked as an inventory drop
|
||||
- */
|
||||
- @ApiStatus.Internal
|
||||
- public ItemStack markForInventoryDrop() {
|
||||
- this.isForInventoryDrop = true;
|
||||
- return this;
|
||||
- }
|
||||
-
|
||||
@Override
|
||||
public MaterialData getData() {
|
||||
return this.handle != null ? CraftMagicNumbers.getMaterialData(this.handle.getItem()) : super.getData();
|
|
@ -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 d839f8df658c894f144ba4637d290ffbed77e132..415d9802ae4dd75b44055b8faf19672fa50c585f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -204,7 +204,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;
|
||||
@@ -219,7 +219,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
|
||||
@@ -237,15 +237,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()) {
|
||||
EnchantmentHelper.onHitBlock(this.level, this.player.getMainHandItem(), this.player, this.player, EquipmentSlot.MAINHAND, Vec3.atCenterOf(pos), iblockdata, (item) -> {
|
||||
this.player.onEquippedItemBroken(item, EquipmentSlot.MAINHAND);
|
||||
@@ -257,7 +259,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;
|
||||
}
|
||||
@@ -265,7 +267,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;
|
||||
}
|
||||
|
||||
@@ -356,7 +358,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);
|
||||
}
|
||||
@@ -382,13 +384,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
|
||||
@@ -537,16 +541,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 6caed156ed0cfe0017d578f58cb963ee68272d78..321188173918d0d60858a258400dfd682ccdb21c 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
@@ -79,7 +79,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);
|
||||
}
|
||||
@@ -187,7 +187,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 87cae96faf33fa0491b13add79e02fc225bd2f70..e9a9c89bd6a4ce7cb30c2fcf79a537fc18204aeb 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -500,10 +500,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 3dbdfc2fb973c3c9aecc6582451071e8a939f5f0..c410e2d94562afc6bdd5bb3c9c01995eac0bc3fc 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
||||
@@ -155,6 +155,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
|
||||
@@ -203,6 +204,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;
|
||||
}
|
||||
@@ -235,4 +237,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 18859eea522ff26cbefb5bbc5065b5369ed6c189..319e000519fd719cea0e6daf2ba9cfa67e6958a3 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 {
|
||||
|
||||
@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 {
|
||||
});
|
||||
}
|
||||
|
||||
- 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 6b2dc430126713e11658f94762035ff10bbe018c..13ef1ad250b56dbadba0244186e369d7ba9b5c0e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -4232,7 +4232,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/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
|
||||
index 87c669517baa923ffa7392e400e7344e81fc9406..9aee0569447d351729c26eedbe24d5defe620162 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
|
||||
@@ -303,7 +303,7 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this, (double) x + 0.5D, (double) y, (double) z + 0.5D);
|
||||
- if (event.isCancelled()) {
|
||||
+ if (event.isCancelled() || event.getTo() == null) { // Paper - prevent NP on null event to location
|
||||
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 632b74e84d6ee58da8806e30b75e16fb864afa64..bf58956379d0a5dbfdc34e8626847638b4111433 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 950ce40d268d89ff3c503116081db6c9ccd65329..454b29d8c9e42e328933aa578f49d28f1e77898a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1869,7 +1869,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 b2abaf6b535da13cdeeb99c568b91c585ac2ed20..6db4d21ee4dc97820943d3fd2aa55054cac95f50 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -1921,6 +1921,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,411 +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 f32f8d5cb22feb885a53d3b56c04ad4219d2bafa..44b79a7c2f8b95a484d1999fa2167ce588f7985b 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
@@ -103,11 +103,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 6b26af41423110bd982eb8c0eea0cba5e9fdc633..38ac2759894660be1ee7ba59b0bd1270158e9232 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
||||
@@ -256,11 +256,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;
|
||||
@@ -274,13 +281,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 dc6230458e09f7555eee7f6a567ff60ad454666b..9d50b9ac8084f3db1844cc7ad1ce9153614ff9d9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
||||
@@ -80,12 +80,19 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
||||
|
||||
if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
// CraftBukkit start
|
||||
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) {
|
||||
- this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients
|
||||
- return InteractionResult.PASS;
|
||||
+ // Paper start - expose drops in event
|
||||
+ java.util.List<net.minecraft.world.item.ItemStack> drops = generateDefaultDrops();
|
||||
+ final org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
||||
+ if (event != null) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ if (player instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) this.resendPossiblyDesyncedDataValues(java.util.List.of(Bogged.DATA_SHEARED), serverPlayer);
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
||||
+ // Paper end - expose drops in event
|
||||
}
|
||||
// CraftBukkit end
|
||||
- this.shear(SoundSource.PLAYERS);
|
||||
+ this.shear(SoundSource.PLAYERS, drops); // Paper - expose drops in event
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
if (!this.level().isClientSide) {
|
||||
itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
|
||||
@@ -140,12 +147,31 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
||||
|
||||
@Override
|
||||
public void shear(SoundSource shearedSoundCategory) {
|
||||
+ // Paper start - shear drop API
|
||||
+ this.shear(shearedSoundCategory, generateDefaultDrops());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void shear(SoundSource shearedSoundCategory, java.util.List<net.minecraft.world.item.ItemStack> drops) {
|
||||
+ // Paper end - shear drop API
|
||||
this.level().playSound((Player) null, (Entity) this, SoundEvents.BOGGED_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
|
||||
- this.spawnShearedMushrooms();
|
||||
+ this.spawnDrops(drops); // Paper - shear drop API
|
||||
this.setSheared(true);
|
||||
}
|
||||
|
||||
private void spawnShearedMushrooms() {
|
||||
+ // Paper start - shear drops API
|
||||
+ this.spawnDrops(generateDefaultDrops()); // Only here for people calling spawnSheardMushrooms. Not used otherwise.
|
||||
+ }
|
||||
+ private void spawnDrops(java.util.List<net.minecraft.world.item.ItemStack> drops) {
|
||||
+ drops.forEach(stack -> {
|
||||
+ this.forceDrops = true;
|
||||
+ this.spawnAtLocation(stack, this.getBbHeight());
|
||||
+ this.forceDrops = false;
|
||||
+ });
|
||||
+ }
|
||||
+ private void generateShearedMushrooms(java.util.function.Consumer<ItemStack> stackConsumer) {
|
||||
+ // Paper end - shear drops API
|
||||
Level world = this.level();
|
||||
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
@@ -156,12 +182,21 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
||||
while (objectlistiterator.hasNext()) {
|
||||
ItemStack itemstack = (ItemStack) objectlistiterator.next();
|
||||
|
||||
- this.spawnAtLocation(itemstack, this.getBbHeight());
|
||||
+ 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 f529243852df8e193a604bb6d895333848b14a74..d407e9e8f1b530f00e632e0249514fb68d48316b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1691,20 +1691,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 f33742ee06e8443a5f5adaaa987d7523dc193b5a..a1a32a77bda0560a7b7f30a5d1c1837ee96997d3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -69,6 +69,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..5e6dfc93c86ec369b686f15ca066478e1635dbc3
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/entity/ShearableDropsTest.java
|
||||
@@ -0,0 +1,35 @@
|
||||
+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.environment.Normal;
|
||||
+import org.junit.jupiter.params.ParameterizedTest;
|
||||
+import org.junit.jupiter.params.provider.MethodSource;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+
|
||||
+@Normal
|
||||
+class ShearableDropsTest {
|
||||
+
|
||||
+ 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");
|
||||
+ }
|
||||
+}
|
Loading…
Add table
Add a link
Reference in a new issue