Patches!!!!!!!

This commit is contained in:
Owen1212055 2024-04-24 18:36:49 -04:00
parent 051855997e
commit e0a245d2ea
No known key found for this signature in database
GPG key ID: 2133292072886A30
133 changed files with 631 additions and 700 deletions

View file

@ -0,0 +1,457 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 11 Dec 2022 23:47:22 -0800
Subject: [PATCH] Fix inconsistencies in dispense events regarding stack size
The javadocs for BlockDispenseEvent suggest the ItemStack is a single
item which is being dispensed. Before this fix, sometimes it was the whole
stack before a single item had been taken. This fixes that so the stack size
is always 1.
diff --git a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
index 90e1914599b43c8bf813596b3b428d8be3bac1b5..6df0db8b4cdab23494ea34236949ece4989110a3 100644
--- a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
@@ -58,7 +58,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
// Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3);
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink at end and single item in event
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -68,12 +68,13 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -89,8 +90,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
EntityType.createDefaultStackConfig(worldserver, stack, (Player) null).accept(object);
((Boat) object).setVariant(this.type);
((Boat) object).setYRot(enumdirection.toYRot());
- if (!worldserver.addFreshEntity((Entity) object)) stack.grow(1); // CraftBukkit
- // itemstack.shrink(1); // CraftBukkit - handled during event processing
+ if (worldserver.addFreshEntity((Entity) object) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
return stack;
}
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 2bb3d1f0b89ef5b9b1f9f8da1070d21168830645..9507dbbb4b490149b9248c384be5adaccae40c41 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -109,7 +109,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
ServerLevel worldserver = pointer.level();
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -119,12 +119,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -141,7 +142,7 @@ public interface DispenseItemBehavior {
return ItemStack.EMPTY;
}
- // itemstack.shrink(1); // Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
// CraftBukkit end
pointer.level().gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, pointer.pos());
return stack;
@@ -163,7 +164,7 @@ public interface DispenseItemBehavior {
ServerLevel worldserver = pointer.level();
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -173,12 +174,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -195,7 +197,7 @@ public interface DispenseItemBehavior {
ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, consumer, blockposition, MobSpawnType.DISPENSER, false, false);
if (entityarmorstand != null) {
- // itemstack.shrink(1); // CraftBukkit - Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
}
return stack;
@@ -215,7 +217,7 @@ public interface DispenseItemBehavior {
if (!list.isEmpty()) {
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
ServerLevel world = pointer.level();
org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -226,12 +228,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -242,7 +245,7 @@ public interface DispenseItemBehavior {
}
// CraftBukkit end
((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS, CraftItemStack.asNMSCopy(event.getItem())); // Paper - Fix saddles losing nbt data - MC-191591
- // itemstack.shrink(1); // CraftBukkit - handled above
+ if (shrink) stack.shrink(1); // Paper - actually handle here
this.setSuccess(true);
return stack;
} else {
@@ -270,7 +273,7 @@ public interface DispenseItemBehavior {
} while (!entityhorseabstract.isBodyArmorItem(stack) || entityhorseabstract.isWearingBodyArmor() || !entityhorseabstract.isTamed());
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
ServerLevel world = pointer.level();
org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -281,12 +284,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -296,6 +300,7 @@ public interface DispenseItemBehavior {
}
}
+ if (shrink) stack.shrink(1); // Paper - shrink here
entityhorseabstract.setBodyArmorItem(CraftItemStack.asNMSCopy(event.getItem()));
// CraftBukkit end
this.setSuccess(true);
@@ -342,7 +347,7 @@ public interface DispenseItemBehavior {
entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next();
// CraftBukkit start
} while (!entityhorsechestedabstract.isTamed());
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below
ServerLevel world = pointer.level();
org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -353,10 +358,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
+ // stack.grow(1); // Paper - shrink below (this was actually missing and should be here, added it commented out to be consistent)
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -368,7 +376,7 @@ public interface DispenseItemBehavior {
entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem()));
// CraftBukkit end
- // itemstack.shrink(1); // CraftBukkit - handled above
+ if (shrink) stack.shrink(1); // Paper - actually handle here
this.setSuccess(true);
return stack;
}
@@ -413,7 +421,7 @@ public interface DispenseItemBehavior {
if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) {
// Paper end - correctly check if the bucket place will succeed
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
if (!DispenserBlock.eventFired) {
@@ -486,7 +494,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
@@ -533,7 +541,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!DispenserBlock.eventFired) {
@@ -596,7 +604,7 @@ public interface DispenseItemBehavior {
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
// CraftBukkit start
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!DispenserBlock.eventFired) {
@@ -662,7 +670,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
// EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null);
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink at end and single item in event
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -672,12 +680,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -693,7 +702,7 @@ public interface DispenseItemBehavior {
worldserver.addFreshEntity(entitytntprimed);
worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
worldserver.gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, blockposition);
- // itemstack.shrink(1); // CraftBukkit - handled above
+ if (shrink) stack.shrink(1); // Paper - actually handle here
return stack;
}
});
@@ -720,7 +729,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
@@ -769,7 +778,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
@@ -842,7 +851,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - only single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
diff --git a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
index 1b1c54ce8f187b968352d4aad05821ece182e20b..985954030654d521291cccbfc3ca49b67ee4357d 100644
--- a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
@@ -40,7 +40,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior {
// CraftBukkit start
// this.projectileItem.shoot(iprojectile, (double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty());
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper
org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -50,12 +50,13 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -69,7 +70,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior {
((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.blockEntity());
// CraftBukkit end
worldserver.addFreshEntity(iprojectile);
- // itemstack.shrink(1); // CraftBukkit - Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
return stack;
}
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
index 4924926327787e7564116e9d6e20d2c2e98b2229..fbed5d57db0c0e79996f85571b9af0071fa953c7 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
@@ -38,7 +38,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
ServerLevel worldserver = pointer.level();
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!DispenserBlock.eventFired) {
diff --git a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
index f84987c36a16df19286d6f1badfb1ffb9cc7e770..6f2adf2334e35e8a617a4ced0c1af2abf32bbd8d 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
@@ -34,7 +34,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = CraftBlock.at(pointer.level(), pointer.pos());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java
index f1cee3266e95094dd1afd501c96e4beaa3d71796..e766397aae3f73548b290b0809b9d1ca0967ea39 100644
--- a/src/main/java/net/minecraft/world/item/ArmorItem.java
+++ b/src/main/java/net/minecraft/world/item/ArmorItem.java
@@ -64,7 +64,7 @@ public class ArmorItem extends Item implements Equipable {
} else {
LivingEntity entityliving = (LivingEntity) list.get(0);
EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(armor);
- ItemStack itemstack1 = armor.split(1);
+ ItemStack itemstack1 = armor.copyWithCount(1); // Paper - shrink below and single item in event
// CraftBukkit start
Level world = pointer.level();
org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
@@ -76,12 +76,13 @@ public class ArmorItem extends Item implements Equipable {
}
if (event.isCancelled()) {
- armor.grow(1);
+ // armor.grow(1); // Paper - shrink below
return false;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- armor.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -98,6 +99,7 @@ public class ArmorItem extends Item implements Equipable {
((Mob) entityliving).setPersistenceRequired();
}
+ if (shrink) armor.shrink(1); // Paper
return true;
}
}
diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java
index 727319e86aa77b5a67b4c4f03b1e9aba9fe6bcde..66074445d3908b9bb1c8d70e1e27d057720ec8e5 100644
--- a/src/main/java/net/minecraft/world/item/MinecartItem.java
+++ b/src/main/java/net/minecraft/world/item/MinecartItem.java
@@ -66,7 +66,7 @@ public class MinecartItem extends Item {
// CraftBukkit start
// EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type);
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block2 = CraftBlock.at(worldserver, pointer.pos());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -76,12 +76,13 @@ public class MinecartItem extends Item {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -94,8 +95,7 @@ public class MinecartItem extends Item {
itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((MinecartItem) itemstack1.getItem()).type, itemstack1, (Player) null);
- if (!worldserver.addFreshEntity(entityminecartabstract)) stack.grow(1);
- // itemstack.shrink(1); // CraftBukkit - handled during event processing
+ if (worldserver.addFreshEntity(entityminecartabstract) && shrink) stack.shrink(1); // Paper - actually handle here
// CraftBukkit end
return stack;
}

View file

@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 21 May 2022 20:59:45 -0700
Subject: [PATCH] Add BlockLockCheckEvent
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
index ff3f26c31bd11b48f48e354ea6b33aa55dcbff5d..02675f15e157ce68506c813b19cf5472bf67bc00 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
@@ -73,17 +73,44 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
protected abstract Component getDefaultName();
public boolean canOpen(Player player) {
- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName());
+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this); // Paper - Add BlockLockCheckEvent
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add BlockLockCheckEvent
public static boolean canUnlock(Player player, LockCode lock, Component containerName) {
+ // Paper start - Add BlockLockCheckEvent
+ return canUnlock(player, lock, containerName, null);
+ }
+ public static boolean canUnlock(Player player, LockCode lock, Component containerName, @Nullable BlockEntity blockEntity) {
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != null && blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity) {
+ final org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos());
+ net.kyori.adventure.text.Component lockedMessage = net.kyori.adventure.text.Component.translatable("container.isLocked", io.papermc.paper.adventure.PaperAdventure.asAdventure(containerName));
+ net.kyori.adventure.sound.Sound lockedSound = net.kyori.adventure.sound.Sound.sound(org.bukkit.Sound.BLOCK_CHEST_LOCKED, net.kyori.adventure.sound.Sound.Source.BLOCK, 1.0F, 1.0F);
+ final io.papermc.paper.event.block.BlockLockCheckEvent event = new io.papermc.paper.event.block.BlockLockCheckEvent(block, (io.papermc.paper.block.LockableTileState) block.getState(), serverPlayer.getBukkitEntity(), lockedMessage, lockedSound);
+ event.callEvent();
+ if (event.getResult() == org.bukkit.event.Event.Result.ALLOW) {
+ return true;
+ } else if (event.getResult() == org.bukkit.event.Event.Result.DENY || (!player.isSpectator() && !lock.unlocksWith(event.isUsingCustomKeyItemStack() ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getKeyItem()) : player.getMainHandItem()))) {
+ if (event.getLockedMessage() != null) {
+ event.getPlayer().sendActionBar(event.getLockedMessage());
+ }
+ if (event.getLockedSound() != null) {
+ event.getPlayer().playSound(event.getLockedSound());
+ }
+ return false;
+ } else {
+ return true;
+ }
+ } else { // logic below is replaced by logic above
+ // Paper end - Add BlockLockCheckEvent
if (!player.isSpectator() && !lock.unlocksWith(player.getMainHandItem())) {
- player.displayClientMessage(Component.translatable("container.isLocked", containerName), true);
+ player.displayClientMessage(Component.translatable("container.isLocked", containerName), true); // Paper - diff on change
player.playNotifySound(SoundEvents.CHEST_LOCKED, SoundSource.BLOCKS, 1.0F, 1.0F);
return false;
} else {
return true;
}
+ } // Paper - Add BlockLockCheckEvent
}
protected abstract NonNullList<ItemStack> getItems();
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 35c7d05b1898adf6b193d0b0b53f3c3be186d4ce..2e3d89ca35b513340cd1ebefa875280b32e1756e 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -472,7 +472,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
@Nullable
@Override
public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null;
+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; // Paper - Add BlockLockCheckEvent
}
@Override

View file

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dawon <dawon@dawon.eu>
Date: Wed, 19 Oct 2022 23:31:53 +0200
Subject: [PATCH] Add Sneaking API for Entities
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 92c80776273f6be43b40686c7ab7dd7371b1c06f..365281dfc0308c5db0c72b56208d9b87be0e955e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -872,6 +872,18 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return Pose.values()[this.getHandle().getPose().ordinal()];
}
+ // Paper start
+ @Override
+ public void setSneaking(boolean sneak) {
+ this.getHandle().setShiftKeyDown(sneak);
+ }
+
+ @Override
+ public boolean isSneaking() {
+ return this.getHandle().isShiftKeyDown();
+ }
+ // Paper end
+
@Override
public SpawnCategory getSpawnCategory() {
return CraftSpawnCategory.toBukkit(this.getHandle().getType().getCategory());

View file

@ -0,0 +1,117 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 14 Dec 2022 15:52:11 -0800
Subject: [PATCH] Improve logging and errors
Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
diff --git a/src/main/java/net/minecraft/advancements/AdvancementTree.java b/src/main/java/net/minecraft/advancements/AdvancementTree.java
index 2665170b8391a77d6b3fb7ae7b5ccfc0be65acd7..e00d4e0896c0163c43d79af63338de67c7cb0dc4 100644
--- a/src/main/java/net/minecraft/advancements/AdvancementTree.java
+++ b/src/main/java/net/minecraft/advancements/AdvancementTree.java
@@ -35,7 +35,7 @@ public class AdvancementTree {
this.remove(advancementnode1);
}
- AdvancementTree.LOGGER.info("Forgot about advancement {}", advancement.holder());
+ AdvancementTree.LOGGER.debug("Forgot about advancement {}", advancement.holder()); // Paper - Improve logging and errors
this.nodes.remove(advancement.holder().id());
if (advancement.parent() == null) {
this.roots.remove(advancement);
@@ -77,7 +77,7 @@ public class AdvancementTree {
}
}
- // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload
+ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload // Paper - Improve logging and errors; you say it was moved... but it wasn't :) it should be moved however, since this is called when the API creates an advancement
}
private boolean tryInsert(AdvancementHolder advancement) {
diff --git a/src/main/java/net/minecraft/server/ServerAdvancementManager.java b/src/main/java/net/minecraft/server/ServerAdvancementManager.java
index 4fa6abfe79ab7ff0e7643975351ab1a10efdc278..b4f15c51faae544bc0a4fcc33760df66e1397f87 100644
--- a/src/main/java/net/minecraft/server/ServerAdvancementManager.java
+++ b/src/main/java/net/minecraft/server/ServerAdvancementManager.java
@@ -67,6 +67,7 @@ public class ServerAdvancementManager extends SimpleJsonResourceReloadListener {
AdvancementTree advancementtree = new AdvancementTree();
advancementtree.addAll(this.advancements.values());
+ LOGGER.info("Loaded {} advancements", advancementtree.nodes().size()); // Paper - Improve logging and errors; moved from AdvancementTree#addAll
Iterator iterator = advancementtree.roots().iterator();
while (iterator.hasNext()) {
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index fdff82ed5dbf5176d470b9b6c41acfe6b98c7039..00679b76715fde4b90a999fd11cca40d048b1349 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -278,6 +278,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!");
DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString());
DedicatedServer.LOGGER.warn("Perhaps a server is already running on that port?");
+ if (true) throw new IllegalStateException("Failed to bind to port", ioexception); // Paper - Propagate failed to bind to port error
return false;
}
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index d20baa57c5367861fb5b3b6ea746a6391b6115cc..c9b4960d9818b71ca2af5e2e23755545ca7da55a 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3393,7 +3393,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator));
} catch (ProfilePublicKey.ValidationException profilepublickey_b) {
- ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage());
+ // ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); // Paper - Improve logging and errors
this.disconnect(profilepublickey_b.getComponent(), profilepublickey_b.kickCause); // Paper - kick event causes
}
diff --git a/src/main/java/net/minecraft/server/packs/PathPackResources.java b/src/main/java/net/minecraft/server/packs/PathPackResources.java
index ed1d3d30404dfc6303e746f31295b6b1aa40f204..8d7565eda4536e8aa42dd3dcbcfac38cbf16020a 100644
--- a/src/main/java/net/minecraft/server/packs/PathPackResources.java
+++ b/src/main/java/net/minecraft/server/packs/PathPackResources.java
@@ -103,6 +103,12 @@ public class PathPackResources extends AbstractPackResources {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
for (Path path2 : directoryStream) {
String string = path2.getFileName().toString();
+ // Paper start - Improve logging and errors
+ if (!Files.isDirectory(path2)) {
+ LOGGER.error("Invalid directory entry: {} in {}.", string, this.root, new java.nio.file.NotDirectoryException(string));
+ continue;
+ }
+ // Paper end - Improve logging and errors
if (ResourceLocation.isValidNamespace(string)) {
set.add(string);
} else {
diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
index 9ae23dbf076e977c9d9b98a02c5925e9a8f68f7f..0126b88f60904dfbf1e29eb3b89a985061d91f91 100644
--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
@@ -79,7 +79,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
this.byType = LinkedHashMultimap.create(builder.build());
this.byName = Maps.newHashMap(com_google_common_collect_immutablemap_builder.build());
// CraftBukkit end
- RecipeManager.LOGGER.info("Loaded {} recipes", this.byType.size());
+ RecipeManager.LOGGER.info("Loaded {} recipes", this.byName.size()); // Paper - Improve logging and errors; log correct number of recipes
}
// CraftBukkit start
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
index 1f82491fc885e3c349fca779ce98798a5c6efde5..71d057dc8c7362f8e7aaca5e31c9f02b2bf3f281 100644
--- a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
@@ -44,6 +44,7 @@ import org.bukkit.material.MaterialData;
*/
@Deprecated
public final class CraftLegacy {
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper - Improve logging and errors
private static final Map<Byte, Material> SPAWN_EGGS = new HashMap<>();
private static final Set<String> whitelistedStates = new HashSet<>(Arrays.asList("explode", "check_decay", "decayable", "facing"));
@@ -255,7 +256,7 @@ public final class CraftLegacy {
}
static {
- System.err.println("Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!");
+ LOGGER.warn("Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!"); // Paper - Improve logging and errors; doesn't need to be an error
if (MinecraftServer.getServer() != null && MinecraftServer.getServer().isDebugging()) {
new Exception().printStackTrace();
}

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 15 Dec 2022 10:33:39 -0800
Subject: [PATCH] Improve PortalEvents
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 63e4fa54c6931a3fc33b081662823f5b736d8496..48103cefacf75a51619f7a3ebeb7731956a65a4f 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3513,7 +3513,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
Location enter = bukkitEntity.getLocation();
Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld());
- EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius);
+ // Paper start
+ final org.bukkit.PortalType portalType = switch (cause) {
+ case END_PORTAL -> org.bukkit.PortalType.ENDER;
+ case NETHER_PORTAL -> org.bukkit.PortalType.NETHER;
+ default -> org.bukkit.PortalType.CUSTOM;
+ };
+ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius, portalType);
+ // Paper end
event.getEntity().getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) {
return null;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 27 Oct 2022 15:35:47 +0200
Subject: [PATCH] Add config option for spider worldborder climbing
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 c80019f0c9f814c5259b4d3ec2d8a85669dc728f..6006480d9f6d60bb7b5628eabe6740013066cde4 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
@@ -82,7 +82,7 @@ public class Spider extends Monster {
public void tick() {
super.tick();
if (!this.level().isClientSide) {
- this.setClimbing(this.horizontalCollision);
+ this.setClimbing(this.horizontalCollision && (this.level().paperConfig().entities.behavior.allowSpiderWorldBorderClimbing)); // Paper - Add config option for spider worldborder climbing
}
}

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NonSwag <mrminecraft00@gmail.com>
Date: Thu, 8 Dec 2022 20:25:05 +0100
Subject: [PATCH] Add missing SpigotConfig logCommands check
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index c9b4960d9818b71ca2af5e2e23755545ca7da55a..6e6024d9c397894903130a4b91a621ae1844a4b5 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2087,7 +2087,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private void performSignedChatCommand(ServerboundChatCommandSignedPacket packet, LastSeenMessages lastSeenMessages) {
// CraftBukkit start
String command = "/" + packet.command();
+ if (org.spigotmc.SpigotConfig.logCommands) { // Paper - Add missing SpigotConfig logCommands check
ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command);
+ } // Paper - Add missing SpigotConfig logCommands check
PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command, new LazyPlayerSet(this.server));
this.cserver.getPluginManager().callEvent(event);

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NonSwag <mrminecraft00@gmail.com>
Date: Tue, 6 Dec 2022 23:04:21 +0100
Subject: [PATCH] Fix NPE on Allay#stopDancing while not dancing
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java
index 1d04df8752af74ae73231922041d09df9d7492bb..c64918175ec08d20cde2bda9e0cac8b474385fe0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java
@@ -78,7 +78,7 @@ public class CraftAllay extends CraftCreature implements org.bukkit.entity.Allay
public void stopDancing() {
this.getHandle().forceDancing = false;
this.getHandle().jukeboxPos = null;
- this.getHandle().setJukeboxPlaying(null, false);
+ this.getHandle().setDancing(false); // Paper - Directly modify set dancing to avoid NPE
}
@Override

View file

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TreyRuffy <TreyRuffy@users.noreply.github.com>
Date: Fri, 27 May 2022 02:26:08 -0600
Subject: [PATCH] Flying Fall Damage
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 761e8a0c4e1db465c18892999e86885f27ca8075..230ffd3c4541ef8979605d733b6463e39cd00206 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -194,6 +194,7 @@ public abstract class Player extends LivingEntity {
public Entity currentExplosionCause;
public boolean ignoreFallDamageFromCurrentImpulse;
public boolean affectsSpawning = true; // Paper - Affects Spawning API
+ public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
// CraftBukkit start
public boolean fauxSleeping;
@@ -1693,7 +1694,7 @@ public abstract class Player extends LivingEntity {
@Override
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
- if (this.abilities.mayfly) {
+ if (this.abilities.mayfly && !this.flyingFallDamage.toBooleanOrElse(false)) { // Paper - flying fall damage
return false;
} else {
if (fallDistance >= 2.0F) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index af6713dc949cce945f3625092a01f04ad41120e7..1925d55ffb0fbf554fc3d6f6d75f119146f60dca 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2566,6 +2566,19 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().onUpdateAbilities();
}
+ // Paper start - flying fall damage
+ @Override
+ public void setFlyingFallDamage(@NotNull net.kyori.adventure.util.TriState flyingFallDamage) {
+ getHandle().flyingFallDamage = flyingFallDamage;
+ }
+
+ @NotNull
+ @Override
+ public net.kyori.adventure.util.TriState hasFlyingFallDamage() {
+ return getHandle().flyingFallDamage;
+ }
+ // Paper end - flying fall damage
+
@Override
public int getNoDamageTicks() {
if (this.getHandle().spawnInvulnerableTime > 0) {

View file

@ -0,0 +1,177 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 22 Oct 2021 16:25:07 -0700
Subject: [PATCH] Add exploded block state to BlockExplodeEvent and
EntityDamageByBlockEvent
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index ec52c7a75d9988475fbb4fe12ef7f4489ef3d894..a78fd4f9ce97ebece45979908382de8f5fc14c1b 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -21,6 +21,7 @@ public class DamageSource {
private final Entity directEntity;
@Nullable
private final Vec3 damageSourcePosition;
+ public org.bukkit.block.BlockState explodedBlockState; // Paper - add exploded state
// CraftBukkit start
@Nullable
private org.bukkit.block.Block directBlock; // The block that caused the damage. damageSourcePosition is not used for all block damages
@@ -94,6 +95,7 @@ public class DamageSource {
private DamageSource cloneInstance() {
DamageSource damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition);
+ damageSource.explodedBlockState = this.explodedBlockState; // Paper - Include explodedBlockState when clone this instance of DamageSource
damageSource.directBlock = this.getDirectBlock();
damageSource.withSweep = this.isSweep();
damageSource.poison = this.isPoison();
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSources.java b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
index 2f5591aa232b834bb9b69a2a349ce93d1a9c63fa..8ba60de95845f4d56f299c5f1b2b5163461ba38d 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
@@ -265,8 +265,17 @@ public class DamageSources {
return this.source(DamageTypes.SONIC_BOOM, attacker);
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - add exploded state
public DamageSource badRespawnPointExplosion(Vec3 position) {
- return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position);
+ // Paper start - add exploded state
+ return this.badRespawnPointExplosion(position, null);
+ }
+
+ public DamageSource badRespawnPointExplosion(Vec3 position, @Nullable org.bukkit.block.BlockState explodedBlockState) {
+ DamageSource source = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position);
+ source.explodedBlockState = explodedBlockState;
+ return source;
+ // Paper end - add exploded state
}
public DamageSource outOfBorder() {
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index aa81144975fa66bcdb3d107e2a461b6d62d8e59e..fbd1f4f3a8c94a4842f91b7cc6c21f0cf7edd7ac 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -386,7 +386,7 @@ public class Explosion {
bukkitBlocks = event.blockList();
this.yield = event.getYield();
} else {
- BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield);
+ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield, this.damageSource.explodedBlockState); // Paper - add exploded state
this.level.getCraftServer().getPluginManager().callEvent(event);
this.wasCanceled = event.isCancelled();
bukkitBlocks = event.blockList();
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index 03035ed3df2f32e14a8eb9bc3d536ef64b5d87ba..872bec4c366c86177334452315cc4a8097dae3c0 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -95,6 +95,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
// CraftBukkit - moved world and biome check into EntityHuman
if (false && !BedBlock.canSetSpawn(world)) {
+ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, pos, state); // Paper - add exploded state (this won't be called due to the false, but it's good for reference)
world.removeBlock(pos, false);
BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite());
@@ -104,7 +105,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
Vec3 vec3d = pos.getCenter();
- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
return InteractionResult.SUCCESS;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
if (!this.kickVillagerOutOfBed(world, pos)) {
@@ -146,6 +147,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition) {
{
{
+ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, blockposition, iblockdata); // Paper - add exploded state
world.removeBlock(blockposition, false);
BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite());
@@ -155,7 +157,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
Vec3 vec3d = blockposition.getCenter();
- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
return InteractionResult.SUCCESS;
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
index a4a90df0b500fb440226b07462faaa87594b12a5..c389e2f891655bd8c9f307057dc1ad62dfcbc79e 100644
--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -133,6 +133,7 @@ public class RespawnAnchorBlock extends Block {
}
private void explode(BlockState state, Level world, final BlockPos explodedPos) {
+ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(explodedPos, state, null); // Paper - add exploded state
world.removeBlock(explodedPos, false);
Stream<Direction> stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error
@@ -149,7 +150,7 @@ public class RespawnAnchorBlock extends Block {
};
Vec3 vec3d = explodedPos.getCenter();
- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
}
public static boolean canSetSpawn(Level world) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
index c38b7148a3bbe7d29adea19d08dde4d9c8e29704..30b40d3715f98eff90d16aad491f5be5162be9e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
@@ -291,6 +291,12 @@ public final class CraftBlockStates {
BlockEntity tileEntity = (blockEntityTag == null) ? null : BlockEntity.loadStatic(blockPosition, blockData, blockEntityTag, registry);
return CraftBlockStates.getBlockState(null, blockPosition, blockData, tileEntity);
}
+ // Paper start - add exploded state
+ public static BlockState getUnplacedBlockState(net.minecraft.world.level.BlockGetter levelAccessor, BlockPos blockPos, net.minecraft.world.level.block.state.BlockState blockData) {
+ BlockEntity tileEntity = levelAccessor.getBlockEntity(blockPos);
+ return CraftBlockStates.getBlockState(null, blockPos, blockData, tileEntity);
+ }
+ // Paper end - add exploded state
// See BlockStateFactory#createBlockState(World, BlockPosition, IBlockData, TileEntity)
private static CraftBlockState getBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index c52cb55cd1da988ec646e4e1484ec1a72513291d..a226b7cdc9c63ef09d7d48269c287af1ab6dbdc4 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1070,7 +1070,7 @@ public class CraftEventFactory {
Entity damager = (bukkitDamageSource.isIndirect() && source.getDirectEntity() != null) ? source.getDirectEntity() : source.getCausingEntity();
if (source.is(DamageTypeTags.IS_EXPLOSION)) {
if (damager == null) {
- return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
+ return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.explodedBlockState); // Paper - Include BlockState for damage
}
DamageCause damageCause = (damager.getBukkitEntity() instanceof org.bukkit.entity.TNTPrimed) ? DamageCause.BLOCK_EXPLOSION : DamageCause.ENTITY_EXPLOSION;
return CraftEventFactory.callEntityDamageEvent(damager, entity, damageCause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API
@@ -1117,7 +1117,7 @@ public class CraftEventFactory {
} else {
throw new IllegalStateException(String.format("Unhandled damage of %s by %s from %s", entity, source.getDirectBlock(), source.getMsgId()));
}
- return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
+ return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.explodedBlockState); // Paper - Include BlockState for damage
}
DamageCause cause;
@@ -1170,8 +1170,13 @@ public class CraftEventFactory {
return CraftEventFactory.callEntityDamageEvent(event, damagee, cancelled);
}
- private static EntityDamageEvent callEntityDamageEvent(Block damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled) {
- EntityDamageByBlockEvent event = new EntityDamageByBlockEvent(damager, damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions);
+ // Paper start
+ private static EntityDamageEvent callEntityDamageEvent(Block damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled) { // Paper
+ return callEntityDamageEvent(damager, damagee, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, null);
+ }
+ private static EntityDamageEvent callEntityDamageEvent(Block damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled, @Nullable org.bukkit.block.BlockState explodedBlockState) {
+ EntityDamageByBlockEvent event = new EntityDamageByBlockEvent(damager, damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, explodedBlockState);
+ // Paper end
return CraftEventFactory.callEntityDamageEvent(event, damagee, cancelled);
}

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Tue, 11 Oct 2022 23:30:32 +0300
Subject: [PATCH] Expose pre-collision moving velocity to
VehicleBlockCollisionEvent
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 48103cefacf75a51619f7a3ebeb7731956a65a4f..09defe4a20c7b0794cba358c177e787f1c0273c1 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -968,6 +968,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public void move(MoverType movementType, Vec3 movement) {
+ final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity
if (this.noPhysics) {
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
@@ -1052,7 +1053,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
if (!bl.getType().isAir()) {
- VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl);
+ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl, org.bukkit.craftbukkit.util.CraftVector.toBukkit(originalMovement)); // Paper - Expose pre-collision velocity
this.level.getCraftServer().getPluginManager().callEvent(event);
}
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 15 Sep 2021 14:52:42 -0700
Subject: [PATCH] config for disabling entity tag tags
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index 3ac31c869d0e53410558ddeb79c21d3f5a3decb6..c36b5aa3cf7ecff839f7115bf9be4776bcee13c3 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -502,6 +502,16 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
if (minecraftserver != null && entity != null) {
if (world.isClientSide || !entity.onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) {
+ // Paper start - filter out protected tags
+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
+ nbt = nbt.update((compound) -> {
+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : world.paperConfig().entities.spawning.filteredEntityTagNbtPaths) {
+ tag.remove(compound);
+ }
+ });
+ }
+ // Paper end - filter out protected tags
+
nbt.loadInto(entity);
}
}

View file

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 8 Jan 2023 17:38:28 -0800
Subject: [PATCH] Use single player info update packet on join
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 6e6024d9c397894903130a4b91a621ae1844a4b5..c3beef7d81e43466d99dbc6a42150a4ae9fa7f54 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3429,7 +3429,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.signedMessageDecoder = session.createMessageDecoder(this.player.getUUID());
this.chatMessageChain.append(() -> {
this.player.setChatSession(session);
- this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)));
+ this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)), this.player); // Paper - Use single player info update packet on join
});
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index b2634bdedfe8359da602cf600a2bdddbd762e7c2..eef1fb3265a088a2f6718631c1728f3e32014c14 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -361,6 +361,7 @@ public abstract class PlayerList {
// CraftBukkit start - sendAll above replaced with this loop
ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player));
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
for (int i = 0; i < this.players.size(); ++i) {
ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
@@ -368,12 +369,17 @@ public abstract class PlayerList {
entityplayer1.connection.send(packet);
}
- if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) {
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
continue;
}
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1)));
+ onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join
}
+ // Paper start - Use single player info update packet on join
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers));
+ }
+ // Paper end - Use single player info update packet on join
player.sentListPacket = true;
player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now

View file

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <lynxplay101@gmail.com>
Date: Tue, 10 Jan 2023 21:06:42 +0100
Subject: [PATCH] Correctly shrink items during EntityResurrectEvent
The EntityResurrectEvent logic is supposed to locate a totem of undying
in any of the interaction slots of the player inventory and then, if the
called EntityResurrectEvent is not cancelled, shrink that item by 1,
usually reducing it to zero.
For this, the logic iterates over the items in the interaction slots and
breaks out the loop if a totem of undying was found.
However, even if no totem of undying was found, the iteration item stack
variable remains as a refernce to the last interaction slot probed.
Plugins uncancelling a EntityResurrectEvent, which is published
pre-cancelled to listeners if no totem of undying could be found,
would hence cause the server logic to shrink completely unrelated items
found in, at the writing of this patch, the players off hand slot.
This patch corrects this behaviour by only shrinking the item if a totem
of undying was found and the event was called uncancelled.
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 6ac6848fe27336a96a813c84d7d797cc9bc4c297..810e94674acff08eda6d98e91546a2338706ef42 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1638,7 +1638,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.level().getCraftServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
- if (!itemstack1.isEmpty()) {
+ if (!itemstack1.isEmpty() && itemstack != null) { // Paper - only reduce item if actual totem was found
itemstack1.shrink(1);
}
if (itemstack != null && this instanceof ServerPlayer) {

View file

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lama06 <andreasprues36@gmail.com>
Date: Sat, 21 Jan 2023 13:53:23 +0100
Subject: [PATCH] Win Screen API
== AT ==
public net.minecraft.server.level.ServerPlayer seenCredits
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 1925d55ffb0fbf554fc3d6f6d75f119146f60dca..1519220d02dfeb14fded5687b77a85306faf6dcd 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1292,6 +1292,25 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().connection.send(packet);
}
+ // Paper start
+ @Override
+ public void showWinScreen() {
+ if (getHandle().connection == null) return;
+ var packet = new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, 1);
+ getHandle().connection.send(packet);
+ }
+
+ @Override
+ public boolean hasSeenWinScreen() {
+ return getHandle().seenCredits;
+ }
+
+ @Override
+ public void setHasSeenWinScreen(boolean hasSeenWinScreen) {
+ getHandle().seenCredits = hasSeenWinScreen;
+ }
+ // Paper end
+
@Override
public void setRotation(float yaw, float pitch) {
// Paper start - Teleport API

View file

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Josh Roy <joshroy126@gmail.com>
Date: Mon, 23 Jan 2023 19:19:01 -0500
Subject: [PATCH] Remove CraftItemStack#setAmount null assignment
This creates a problem with Paper's item serialization
api where deserialized items, which are internally
created as a CraftItemStack, will be completely lost if
#setAmount(0) is invoked (since the underlying handle
is set to null), while a regular Bukkit ItemStack
simply sets the amount field to zero, retaining the
item's data.
Vanilla treats items with zero amounts the same as items
with less than zero amounts, so this code doesn't create
a problem with operations on the vanilla ItemStack.
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 79529a5208810d25aeab537eac70ed9c6583ef18..be2b7c2b412a1d64466c25c1b19b10a869cd288d 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -160,7 +160,7 @@ public final class CraftItemStack extends ItemStack {
}
this.handle.setCount(amount);
- if (amount == 0) {
+ if (false && amount == 0) { // Paper - remove CraftItemStack#setAmount null assignment
this.handle = null;
}
}

View file

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 26 Jan 2023 16:19:26 -0800
Subject: [PATCH] Fix force-opening enchantment tables
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 79faf3c64891899bf5d6d119154aba02d4665b3b..e1150d36de56466ad9fdd5f2cdb4c30855d4af70 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -403,7 +403,18 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
// If there isn't an enchant table we can force create one, won't be very useful though.
BlockPos pos = CraftLocation.toBlockPosition(location);
- this.getHandle().openMenu(Blocks.ENCHANTING_TABLE.defaultBlockState().getMenuProvider(this.getHandle().level(), pos));
+ // Paper start
+ MenuProvider menuProvider = Blocks.ENCHANTING_TABLE.defaultBlockState().getMenuProvider(this.getHandle().level(), pos);
+ if (menuProvider == null) {
+ if (!force) {
+ return null;
+ }
+ menuProvider = new net.minecraft.world.SimpleMenuProvider((syncId, inventory, player) -> {
+ return new net.minecraft.world.inventory.EnchantmentMenu(syncId, inventory, net.minecraft.world.inventory.ContainerLevelAccess.create(this.getHandle().level(), pos));
+ }, Component.translatable("container.enchant"));
+ }
+ this.getHandle().openMenu(menuProvider);
+ // Paper end
if (force) {
this.getHandle().containerMenu.checkReachable = false;

View file

@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TheTuso <piotrekpasztor@gmail.com>
Date: Thu, 2 Feb 2023 16:40:41 +0100
Subject: [PATCH] Add Entity Body Yaw API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 365281dfc0308c5db0c72b56208d9b87be0e955e..991b94ff1186b1071a94b2662873dc071255e2e6 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1164,6 +1164,33 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
// Paper end - entity powdered snow API
+ // Paper start - entity body yaw API
+ @Override
+ public double getX() {
+ return this.entity.getX();
+ }
+
+ @Override
+ public double getY() {
+ return this.entity.getY();
+ }
+
+ @Override
+ public double getZ() {
+ return this.entity.getZ();
+ }
+
+ @Override
+ public float getPitch() {
+ return this.entity.getXRot();
+ }
+
+ @Override
+ public float getYaw() {
+ return this.entity.getBukkitYaw();
+ }
+ // Paper end - entity body yaw API
+
// Paper start - missing entity api
@Override
public boolean isInvisible() { // Paper - moved up from LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 51e9b9f7460ec4f8b14d570356026d433351806d..4f31bf6f51a72b010b850e1e62a06b455eac906c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1176,4 +1176,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
this.getHandle().frictionState = state;
}
// Paper end - friction API
+
+ // Paper start - body yaw API
+ @Override
+ public float getBodyYaw() {
+ return this.getHandle().getVisualRotationYInDegrees();
+ }
+
+ @Override
+ public void setBodyYaw(final float bodyYaw) {
+ this.getHandle().setYBodyRot(bodyYaw);
+ }
+ // Paper end - body yaw API
}

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Mon, 27 Feb 2023 19:16:07 +0100
Subject: [PATCH] Fix MC-157464 Prevent sleeping villagers moving towards food
Fixes sleeping villagers moving to nearby food by adding an !isSleeping predicate
Relevant links:
https://bugs.mojang.com/browse/MC-157464
https://github.com/PaperMC/Paper/issues/8569
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
index 5a18bf854792339fcd54e32f8053d014f3d195a5..f000a6c1e61198e6dd06ae5f084d12fdf309f50a 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
@@ -38,7 +38,7 @@ public class VillagerGoalPackages {
Pair.of(1, new MoveToTargetSink()),
Pair.of(2, PoiCompetitorScan.create()),
Pair.of(3, new LookAndFollowTradingPlayerSink(speed)),
- Pair.of(5, GoToWantedItem.create(speed, false, 4)),
+ Pair.of(5, GoToWantedItem.create(villager -> !villager.isSleeping(), speed, false, 4)), // Paper - Fix MC-157464
Pair.of(
6, AcquirePoi.create(profession.acquirableJobSite(), MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, true, Optional.empty())
),

View file

@ -0,0 +1,103 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Fri, 24 Jun 2022 12:39:34 +0200
Subject: [PATCH] Add EntityFertilizeEggEvent
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
index b550befd7bd05951be160f81600200b0b31bae5b..3eabf1e94c0a1086f471e30bf523581907169c58 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
@@ -441,6 +441,10 @@ public class Turtle extends Animal {
if (entityplayer == null && this.partner.getLoveCause() != null) {
entityplayer = this.partner.getLoveCause();
}
+ // Paper start - Add EntityFertilizeEggEvent event
+ io.papermc.paper.event.entity.EntityFertilizeEggEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this.animal, this.partner);
+ if (event.isCancelled()) return;
+ // Paper end - Add EntityFertilizeEggEvent event
if (entityplayer != null) {
entityplayer.awardStat(Stats.ANIMALS_BRED);
@@ -455,7 +459,7 @@ public class Turtle extends Animal {
RandomSource randomsource = this.animal.getRandom();
if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper;
+ if (event.getExperience() > 0) this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), event.getExperience(), org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper - Add EntityFertilizeEggEvent event
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
index a7af50ebc17abd829a7254c03785206da9624060..816977990639ec0559b652fc9666afd5046f0a5d 100644
--- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
@@ -261,7 +261,12 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
@Override
public void spawnChildFromBreeding(ServerLevel world, Animal other) {
- this.finalizeSpawnChildFromBreeding(world, other, null);
+ // Paper start - Add EntityFertilizeEggEvent event
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
+ if (result.isCancelled()) return;
+
+ this.finalizeSpawnChildFromBreeding(world, other, null, result.getExperience()); // Paper - use craftbukkit call that takes experience amount
+ // Paper end - Add EntityFertilizeEggEvent event
this.getBrain().setMemory(MemoryModuleType.IS_PREGNANT, Unit.INSTANCE);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
index a0c52ce65d4035d135b1536c7408a6867a553447..dc035bf94c5f6574ed8ad369b327b7f7a145e1d6 100644
--- a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
+++ b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
@@ -345,11 +345,16 @@ public class Sniffer extends Animal {
@Override
public void spawnChildFromBreeding(ServerLevel world, Animal other) {
+ // Paper start - Add EntityFertilizeEggEvent event
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
+ if (result.isCancelled()) return;
+ // Paper end - Add EntityFertilizeEggEvent event
+
ItemStack itemstack = new ItemStack(Items.SNIFFER_EGG);
ItemEntity entityitem = new ItemEntity(world, this.position().x(), this.position().y(), this.position().z(), itemstack);
entityitem.setDefaultPickUpDelay();
- this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null);
+ this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null, result.getExperience()); // Paper - Add EntityFertilizeEggEvent event
if (this.spawnAtLocation(entityitem) != null) { // Paper - Call EntityDropItemEvent
this.playSound(SoundEvents.SNIFFER_EGG_PLOP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 0.5F);
} // Paper - Call EntityDropItemEvent
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index a226b7cdc9c63ef09d7d48269c287af1ab6dbdc4..e9a70547324dabd97dc90820515a11d2b630a704 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -2109,4 +2109,28 @@ public class CraftEventFactory {
return event.callEvent();
}
// Paper end
+
+ // Paper start - add EntityFertilizeEggEvent
+ /**
+ * Calls the {@link io.papermc.paper.event.entity.EntityFertilizeEggEvent}.
+ * If the event is cancelled, this method also resets the love on both the {@code breeding} and {@code other} entity.
+ *
+ * @param breeding the entity on which #spawnChildFromBreeding was called.
+ * @param other the partner of the entity.
+ * @return the event after it was called. The instance may be used to retrieve the experience of the event.
+ */
+ public static io.papermc.paper.event.entity.EntityFertilizeEggEvent callEntityFertilizeEggEvent(Animal breeding, Animal other) {
+ ServerPlayer serverPlayer = breeding.getLoveCause();
+ if (serverPlayer == null) serverPlayer = other.getLoveCause();
+ final int experience = breeding.getRandom().nextInt(7) + 1; // From Animal#spawnChildFromBreeding(ServerLevel, Animal)
+
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent event = new io.papermc.paper.event.entity.EntityFertilizeEggEvent((LivingEntity) breeding.getBukkitEntity(), (LivingEntity) other.getBukkitEntity(), serverPlayer == null ? null : serverPlayer.getBukkitEntity(), breeding.breedItem == null ? null : CraftItemStack.asCraftMirror(breeding.breedItem).clone(), experience);
+ if (!event.callEvent()) {
+ breeding.resetLove();
+ other.resetLove(); // stop the pathfinding to avoid infinite loop
+ }
+
+ return event;
+ }
+ // Paper end - add EntityFertilizeEggEvent
}

View file

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 10 Oct 2021 18:18:01 -0700
Subject: [PATCH] Fix HumanEntity#drop not updating the client inv
== AT ==
public net.minecraft.server.level.ServerPlayer containerSynchronizer
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index e1150d36de56466ad9fdd5f2cdb4c30855d4af70..3d36d79a4e7f16f6face3465cdf54656984f3ebc 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -750,8 +750,15 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
// Paper end
@Override
public boolean dropItem(boolean dropAll) {
- if (!(this.getHandle() instanceof ServerPlayer)) return false;
- return ((ServerPlayer) this.getHandle()).drop(dropAll);
+ // Paper start - Fix HumanEntity#drop not updating the client inv
+ if (!(this.getHandle() instanceof ServerPlayer player)) return false;
+ boolean success = player.drop(dropAll);
+ if (!success) return false;
+ final net.minecraft.world.entity.player.Inventory inv = player.getInventory();
+ final java.util.OptionalInt optionalSlot = player.containerMenu.findSlot(inv, inv.selected);
+ optionalSlot.ifPresent(slot -> player.containerSynchronizer.sendSlotChange(player.containerMenu, slot, inv.getSelected()));
+ return true;
+ // Paper end - Fix HumanEntity#drop not updating the client inv
}
@Override

View file

@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Sun, 8 Aug 2021 19:56:02 +0200
Subject: [PATCH] Add CompostItemEvent and EntityCompostItemEvent
diff --git a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
index fcd8a977eaa52cd478507c3b44fa72b194df9540..0af05d6f046368af5a5a600288b8329c17f278c7 100644
--- a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
@@ -336,7 +336,21 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
int i = (Integer) iblockdata.getValue(ComposterBlock.LEVEL);
float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem());
- if ((i != 0 || f <= 0.0F) && rand >= (double) f) {
+ // Paper start - Add CompostItemEvent and EntityCompostItemEvent
+ boolean willRaiseLevel = !((i != 0 || f <= 0.0F) && rand >= (double) f);
+ final io.papermc.paper.event.block.CompostItemEvent event;
+ if (entity == null) {
+ event = new io.papermc.paper.event.block.CompostItemEvent(org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, blockposition), itemstack.getBukkitStack(), willRaiseLevel);
+ } else {
+ event = new io.papermc.paper.event.entity.EntityCompostItemEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, blockposition), itemstack.getBukkitStack(), willRaiseLevel);
+ }
+ if (!event.callEvent()) { // check for cancellation of entity event (non entity event can't be cancelled cause of hoppers)
+ return null;
+ }
+ willRaiseLevel = event.willRaiseLevel();
+
+ if (!willRaiseLevel) {
+ // Paper end - Add CompostItemEvent and EntityCompostItemEvent
return iblockdata;
} else {
int j = i + 1;
@@ -485,6 +499,11 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
if (!itemstack.isEmpty()) {
this.changed = true;
BlockState iblockdata = ComposterBlock.addItem((Entity) null, this.state, this.level, this.pos, itemstack);
+ // Paper start - Add CompostItemEvent and EntityCompostItemEvent
+ if (iblockdata == null) {
+ return;
+ }
+ // Paper end - Add CompostItemEvent and EntityCompostItemEvent
this.level.levelEvent(1500, this.pos, iblockdata != this.state ? 1 : 0);
this.removeItemNoUpdate(0);

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 5 Mar 2023 14:38:21 -0800
Subject: [PATCH] Correctly handle ArmorStand invisibility
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
index 2c16cedf8cb2e4047415e056c419ed9c33c80e93..ccda0d7a96c201905f0f62dcb0e5b278a51dee9f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
@@ -152,6 +152,14 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
this.getHandle().noPhysics = !gravity;
}
+ // Paper start - Armor Stand has its own invisible field
+ @Override
+ public void setInvisible(final boolean invisible) {
+ this.getHandle().setInvisible(invisible);
+ super.setInvisible(invisible);
+ }
+ // Paper end
+
@Override
public boolean isVisible() {
return !this.getHandle().isInvisible();

View file

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 16 Mar 2023 10:04:17 +0100
Subject: [PATCH] Fix advancement triggers for entity damage
Changes the Interaction entity's trigger to use the vanilla
generic damage source
Fixes a couple places where the original damage and modified damage
were passed in the reverse order to the advancement triggers
diff --git a/src/main/java/net/minecraft/world/entity/Interaction.java b/src/main/java/net/minecraft/world/entity/Interaction.java
index 2ebbf7954dc5e0d6c9d53327d05b725eec310086..c5bd2e90ad74ba08910f65a2e07b6f76435df10f 100644
--- a/src/main/java/net/minecraft/world/entity/Interaction.java
+++ b/src/main/java/net/minecraft/world/entity/Interaction.java
@@ -156,7 +156,7 @@ public class Interaction extends Entity implements Attackable, Targeting {
// CraftBukkit end
this.attack = new Interaction.PlayerAction(entityhuman.getUUID(), this.level().getGameTime());
if (entityhuman instanceof ServerPlayer entityplayer) {
- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, source, (float) event.getFinalDamage(), 1.0F, false); // CraftBukkit
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, entityhuman.damageSources().generic(), 1.0F, (float) event.getFinalDamage(), false); // CraftBukkit // Paper - use correct source and fix taken/dealt param order
}
return !this.getResponse();
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 810e94674acff08eda6d98e91546a2338706ef42..a356d0476e6ff9389809e8db1f584ac4bffe8be9 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -2369,7 +2369,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
// Duplicate triggers if blocking
if (event.getDamage(DamageModifier.BLOCKING) < 0) {
if (this instanceof ServerPlayer) {
- CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true);
+ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, originalDamage, f, true); // Paper - fix taken/dealt param order
f2 = (float) -event.getDamage(DamageModifier.BLOCKING);
if (f2 > 0.0F && f2 < 3.4028235E37F) {
((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F));
@@ -2377,7 +2377,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
if (damagesource.getEntity() instanceof ServerPlayer) {
- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true);
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, originalDamage, f, true); // Paper - fix taken/dealt param order
}
return false;

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Thu, 16 Mar 2023 16:27:50 +0100
Subject: [PATCH] Fix text display error on spawn
diff --git a/src/main/java/net/minecraft/world/entity/Display.java b/src/main/java/net/minecraft/world/entity/Display.java
index bd56721485b3b4ac81c97d60fc2a83bfc20977c0..a658943669cdfd49f66ba713505d11b33306ed86 100644
--- a/src/main/java/net/minecraft/world/entity/Display.java
+++ b/src/main/java/net/minecraft/world/entity/Display.java
@@ -892,7 +892,7 @@ public abstract class Display extends Entity {
b = loadFlag(b, nbt, "default_background", (byte)4);
Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC
.decode(NbtOps.INSTANCE, nbt.get("alignment"))
- .resultOrPartial(Util.prefix("Display entity", Display.LOGGER::error))
+ .result() // Paper - Hide text display error on spawn
.map(Pair::getFirst);
if (optional.isPresent()) {
b = switch ((Display.TextDisplay.Align)optional.get()) {

View file

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 15 Mar 2023 18:29:45 -0700
Subject: [PATCH] Fix inventories returning null Locations
Wandering Trader, AbstractHorse, Beacon and Composter inventories returned null locations
when a block or entity location is readily available
Co-authored-by: Lukas Planz <lukas.planz@web.de>
diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java
index c26161784359ea167e11de8aa58eda3b4851059c..6632cf24ebe6d147950a1fdb876660937da86b73 100644
--- a/src/main/java/net/minecraft/world/SimpleContainer.java
+++ b/src/main/java/net/minecraft/world/SimpleContainer.java
@@ -63,6 +63,16 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
@Override
public Location getLocation() {
+ // Paper start - Fix inventories returning null Locations
+ // When the block inventory does not have a tile state that implements getLocation, e. g. composters
+ if (this.bukkitOwner instanceof org.bukkit.inventory.BlockInventoryHolder blockInventoryHolder) {
+ return blockInventoryHolder.getBlock().getLocation();
+ }
+ // When the bukkit owner is a bukkit entity, but does not implement Container itself, e. g. horses
+ if (this.bukkitOwner instanceof org.bukkit.entity.Entity entity) {
+ return entity.getLocation();
+ }
+ // Paper end - Fix inventories returning null Locations
return null;
}
diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
index 580e5714c62aef5a5fdd16606712b96f3d41c938..37735417e2a3df96eea88aa0a3f2d7faeb823a2e 100644
--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
@@ -52,6 +52,12 @@ public class BeaconMenu extends AbstractContainerMenu {
public int getMaxStackSize() {
return 1;
}
+ // Paper start - Fix inventories returning null Locations
+ @Override
+ public org.bukkit.Location getLocation() {
+ return context.getLocation();
+ }
+ // Paper end - Fix inventories returning null Locations
};
checkContainerDataCount(propertyDelegate, 3);
this.beaconData = propertyDelegate;
diff --git a/src/main/java/net/minecraft/world/inventory/MerchantContainer.java b/src/main/java/net/minecraft/world/inventory/MerchantContainer.java
index 7cc96b62f6bacdb44a37d74db214bd0e11c4d503..9140fab07aab32065f7a3b5d13dd17d61dc6d646 100644
--- a/src/main/java/net/minecraft/world/inventory/MerchantContainer.java
+++ b/src/main/java/net/minecraft/world/inventory/MerchantContainer.java
@@ -65,7 +65,7 @@ public class MerchantContainer implements Container {
@Override
public Location getLocation() {
- return (this.merchant instanceof Villager) ? ((Villager) this.merchant).getBukkitEntity().getLocation() : null;
+ return (this.merchant instanceof AbstractVillager) ? ((AbstractVillager) this.merchant).getBukkitEntity().getLocation() : null; // Paper - Fix inventories returning null Locations
}
// CraftBukkit end

View file

@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 17 Oct 2021 15:39:48 -0400
Subject: [PATCH] Add Shearable API
diff --git a/src/main/java/io/papermc/paper/entity/PaperShearable.java b/src/main/java/io/papermc/paper/entity/PaperShearable.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcf254e3c81cf1e401bddc850fb24ad29dcc127c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/entity/PaperShearable.java
@@ -0,0 +1,21 @@
+package io.papermc.paper.entity;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.sound.Sound;
+import net.minecraft.world.entity.Shearable;
+import org.jetbrains.annotations.NotNull;
+
+public interface PaperShearable extends io.papermc.paper.entity.Shearable {
+
+ Shearable getHandle();
+
+ @Override
+ default boolean readyToBeSheared() {
+ return this.getHandle().readyForShearing();
+ }
+
+ @Override
+ default void shear(@NotNull Sound.Source source) {
+ this.getHandle().shear(PaperAdventure.asVanilla(source));
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
index 986f7b18112ef183de3bbff269a92bf6ac945477..9cc81bcccbf1141f66fedada1359b7c0dfa8e22a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
@@ -14,7 +14,7 @@ import org.bukkit.entity.MushroomCow;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-public class CraftMushroomCow extends CraftCow implements MushroomCow {
+public class CraftMushroomCow extends CraftCow implements MushroomCow, io.papermc.paper.entity.PaperShearable { // Paper
public CraftMushroomCow(CraftServer server, net.minecraft.world.entity.animal.MushroomCow entity) {
super(server, entity);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java
index 030bf7b6312799231d0b614ba5c84fec23c276e3..37291d7ad9fdf0fe78894f82a418f40bb581f58b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java
@@ -4,7 +4,7 @@ import org.bukkit.DyeColor;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Sheep;
-public class CraftSheep extends CraftAnimals implements Sheep {
+public class CraftSheep extends CraftAnimals implements Sheep, io.papermc.paper.entity.PaperShearable { // Paper
public CraftSheep(CraftServer server, net.minecraft.world.entity.animal.Sheep entity) {
super(server, entity);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
index 1e9807b8f468742d208f817e22d7625106fc1b58..4ce2373ff71c3c1b8951646e057587a3ab09e145 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
@@ -4,7 +4,7 @@ import net.minecraft.world.entity.animal.SnowGolem;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Snowman;
-public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity<SnowGolem> { // Paper
+public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity<SnowGolem>, io.papermc.paper.entity.PaperShearable { // Paper
public CraftSnowman(CraftServer server, SnowGolem entity) {
super(server, entity);
}

View file

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 23 Feb 2023 13:19:13 -0800
Subject: [PATCH] Fix SpawnEggMeta#get/setSpawnedType
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java
index c36c004156d3a89dc2209423c57a2ce230d686dc..a6d2370113eb44c0863b7837362dbb350f5057c6 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java
@@ -224,6 +224,30 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
public void setSpawnedType(EntityType type) {
throw new UnsupportedOperationException("Must change item type to set spawned type");
}
+ // Paper start
+ @Override
+ public EntityType getCustomSpawnedType() {
+ return java.util.Optional.ofNullable(this.entityTag)
+ .map(tag -> tag.getString(ENTITY_ID.NBT))
+ .flatMap(net.minecraft.world.entity.EntityType::byString)
+ .map(org.bukkit.craftbukkit.util.CraftMagicNumbers::getEntityType)
+ .orElse(null);
+ }
+
+ @Override
+ public void setCustomSpawnedType(final EntityType type) {
+ if (type == null) {
+ if (this.entityTag != null) {
+ this.entityTag.remove(ENTITY_ID.NBT);
+ }
+ } else {
+ if (this.entityTag == null) {
+ this.entityTag = new CompoundTag();
+ }
+ this.entityTag.putString(ENTITY_ID.NBT, type.key().toString());
+ }
+ }
+ // Paper end
@Override
public EntitySnapshot getSpawnedEntity() {

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 19 Mar 2023 20:36:22 -0700
Subject: [PATCH] Fix crash relating to bad recipes in furnace-like tile
entities
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index d19e799491f790ca967a0731ef95a06993a7ab9a..f40b2582d9087f9dbb5cab950304698f33fdd879 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -613,6 +613,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
Entry<ResourceLocation> entry = (Entry) objectiterator.next();
worldserver.getRecipeManager().byKey((ResourceLocation) entry.getKey()).ifPresent((recipeholder) -> {
+ if (!(recipeholder.value() instanceof AbstractCookingRecipe)) return; // Paper - don't process non-cooking recipes
list.add(recipeholder);
AbstractFurnaceBlockEntity.createExperience(worldserver, vec3d, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit
});

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 30 Mar 2023 03:13:58 +0100
Subject: [PATCH] Treat sequence violations like they should be
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index c3beef7d81e43466d99dbc6a42150a4ae9fa7f54..e351ed77fbe1ea9de2dd5600d61524eb39c17899 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1966,6 +1966,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
public void ackBlockChangesUpTo(int sequence) {
if (sequence < 0) {
+ this.disconnect("Expected packet sequence nr >= 0", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - Treat sequence violations like they should be
throw new IllegalArgumentException("Expected packet sequence nr >= 0");
} else {
this.ackBlockChangesUpTo = Math.max(sequence, this.ackBlockChangesUpTo);

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 1 Dec 2022 12:42:18 -0800
Subject: [PATCH] remove duplicate animate packet for records
diff --git a/src/main/java/net/minecraft/world/item/RecordItem.java b/src/main/java/net/minecraft/world/item/RecordItem.java
index 115ac21ea743d30fe8ba62b206da4f5a1bd56cc4..815220924753e87a8f485c2c928222561c726855 100644
--- a/src/main/java/net/minecraft/world/item/RecordItem.java
+++ b/src/main/java/net/minecraft/world/item/RecordItem.java
@@ -47,7 +47,7 @@ public class RecordItem extends Item {
ItemStack itemstack = context.getItemInHand();
if (!world.isClientSide) {
- if (true) return InteractionResult.SUCCESS; // CraftBukkit - handled in ItemStack
+ if (true) return InteractionResult.sidedSuccess(world.isClientSide); // CraftBukkit - handled in ItemStack // Paper - fix duplicate animate packet
Player entityhuman = context.getPlayer();
BlockEntity tileentity = world.getBlockEntity(blockposition);

View file

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 3 Apr 2023 08:55:52 +0100
Subject: [PATCH] Prevent causing expired keys from impacting new joins
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
index 68c062cbaa030d62d97c9c003651f8fc17a00a6b..6247a21c9c391abf1f6db3482c659593e4f29355 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
@@ -113,7 +113,15 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
}),
INITIALIZE_CHAT(
(serialized, buf) -> serialized.chatSession = buf.readNullable(RemoteChatSession.Data::read),
- (buf, entry) -> buf.writeNullable(entry.chatSession, RemoteChatSession.Data::write)
+ // Paper start - Prevent causing expired keys from impacting new joins
+ (buf, entry) -> {
+ RemoteChatSession.Data chatSession = entry.chatSession;
+ if (chatSession != null && chatSession.profilePublicKey().hasExpired()) {
+ chatSession = null;
+ }
+ buf.writeNullable(chatSession, RemoteChatSession.Data::write);
+ }
+ // Paper end - Prevent causing expired keys from impacting new joins
),
UPDATE_GAME_MODE((serialized, buf) -> serialized.gameMode = GameType.byId(buf.readVarInt()), (buf, entry) -> buf.writeVarInt(entry.gameMode().getId())),
UPDATE_LISTED((serialized, buf) -> serialized.listed = buf.readBoolean(), (buf, entry) -> buf.writeBoolean(entry.listed())),
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index e351ed77fbe1ea9de2dd5600d61524eb39c17899..1a0245c798107d2d4239e07262f5cc89490a3b08 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -296,6 +296,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private int knownMovePacketCount;
@Nullable
private RemoteChatSession chatSession;
+ private boolean hasLoggedExpiry = false; // Paper - Prevent causing expired keys from impacting new joins
private SignedMessageChain.Decoder signedMessageDecoder;
private final LastSeenMessagesValidator lastSeenMessages = new LastSeenMessagesValidator(20);
private final MessageSignatureCache messageSignatureCache = MessageSignatureCache.createDefault();
@@ -408,6 +409,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
}
+ // Paper start - Prevent causing expired keys from impacting new joins
+ if (!hasLoggedExpiry && this.chatSession != null && this.chatSession.profilePublicKey().data().hasExpired()) {
+ LOGGER.info("Player profile key for {} has expired!", this.player.getName().getString());
+ hasLoggedExpiry = true;
+ }
+ // Paper end - Prevent causing expired keys from impacting new joins
+
}
private int getMaximumFlyingTicks(Entity vehicle) {
@@ -3427,6 +3435,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private void resetPlayerChatState(RemoteChatSession session) {
this.chatSession = session;
+ this.hasLoggedExpiry = false; // Paper - Prevent causing expired keys from impacting new joins
this.signedMessageDecoder = session.createMessageDecoder(this.player.getUUID());
this.chatMessageChain.append(() -> {
this.player.setChatSession(session);

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 5 Apr 2023 20:15:47 +0100
Subject: [PATCH] Prevent GameEvents being fired from unloaded chunks
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 2eda55a09632a6c5668600251a8c491c501fbe2b..80c927c906d1b6119c1b32b8982d879fbbd4d257 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1374,6 +1374,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
@Override
public void gameEvent(Holder<GameEvent> event, Vec3 emitterPos, GameEvent.Context emitter) {
+ // Paper start - Prevent GameEvents being fired from unloaded chunks
+ if (this.getChunkIfLoadedImmediately((Mth.floor(emitterPos.x) >> 4), (Mth.floor(emitterPos.z) >> 4)) == null) {
+ return;
+ }
+ // Paper end - Prevent GameEvents being fired from unloaded chunks
this.gameEventDispatcher.post(event, emitterPos, emitter);
}

View file

@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sun, 9 May 2021 16:49:49 -0500
Subject: [PATCH] Use array for gamerule storage
diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java
index 51e560d7856f230c5aa2dc32706c3a4996720aa5..89e327bc3a45879fe68887c7aadb077f31a770eb 100644
--- a/src/main/java/net/minecraft/world/level/GameRules.java
+++ b/src/main/java/net/minecraft/world/level/GameRules.java
@@ -122,6 +122,7 @@ public class GameRules {
worldserver.setDefaultSpawnPos(worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle());
}));
private final Map<GameRules.Key<?>, GameRules.Value<?>> rules;
+ private final GameRules.Value<?>[] gameruleArray; // Paper - Perf: Use array for gamerule storage
private static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
GameRules.Key<T> gamerules_gamerulekey = new GameRules.Key<>(name, category);
@@ -140,17 +141,30 @@ public class GameRules {
}
public GameRules() {
- this.rules = (Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> {
+ // Paper start - Perf: Use array for gamerule storage
+ this((Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> {
return ((GameRules.Type) entry.getValue()).createRule();
- }));
+ })));
+ // Paper end - Perf: Use array for gamerule storage
}
private GameRules(Map<GameRules.Key<?>, GameRules.Value<?>> rules) {
this.rules = rules;
+
+ // Paper start - Perf: Use array for gamerule storage
+ int arraySize = rules.keySet().stream().mapToInt(key -> key.gameRuleIndex).max().orElse(-1) + 1;
+ GameRules.Value<?>[] values = new GameRules.Value[arraySize];
+
+ for (Entry<GameRules.Key<?>, GameRules.Value<?>> entry : rules.entrySet()) {
+ values[entry.getKey().gameRuleIndex] = entry.getValue();
+ }
+
+ this.gameruleArray = values;
+ // Paper end - Perf: Use array for gamerule storage
}
public <T extends GameRules.Value<T>> T getRule(GameRules.Key<T> key) {
- return (T) this.rules.get(key); // CraftBukkit - decompile error
+ return key == null ? null : (T) this.gameruleArray[key.gameRuleIndex]; // Paper - Perf: Use array for gamerule storage
}
public CompoundTag createTag() {
@@ -209,6 +223,10 @@ public class GameRules {
}
public static final class Key<T extends GameRules.Value<T>> {
+ // Paper start - Perf: Use array for gamerule storage
+ private static int lastGameRuleIndex = 0;
+ public final int gameRuleIndex = lastGameRuleIndex++;
+ // Paper end - Perf: Use array for gamerule storage
final String id;
private final GameRules.Category category;

View file

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 9 Apr 2023 21:11:58 -0700
Subject: [PATCH] Fix a couple of upstream bed issues
Upstream incorrectly skipped explosion logic if
the bed was occupied and added a "feature" where
if you set your spawn in a respawn anchor world
but then replaced it with a bed, you could respawn
at the bed in that world.
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index 872bec4c366c86177334452315cc4a8097dae3c0..e9f8949267208b93f0c56c36ada38274ed4280f5 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -108,6 +108,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
return InteractionResult.SUCCESS;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
+ if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first
if (!this.kickVillagerOutOfBed(world, pos)) {
player.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true);
}
@@ -165,8 +166,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
// CraftBukkit end
public static boolean canSetSpawn(Level world) {
- // CraftBukkit - moved world and biome check into EntityHuman
- return true || world.dimensionType().bedWorks();
+ return world.dimensionType().bedWorks(); // Paper - actually check if the bed works
}
private boolean kickVillagerOutOfBed(Level world, BlockPos pos) {

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Fri, 7 Apr 2023 20:11:17 +0200
Subject: [PATCH] Fix demo flag not enabling demo mode
https://github.com/PaperMC/Paper/issues/9046
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 13e1a914d4523f1c192db2a9a1ee6522e0ee27da..c33f85b570f159ab465b5a10a8044a81f2797f43 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -325,7 +325,9 @@ public class Main {
/*
dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec11));
- dedicatedserver1.setDemo(optionset.has(optionspec2));
+ */
+ dedicatedserver1.setDemo(optionset.has("demo")); // Paper
+ /*
dedicatedserver1.setId((String) optionset.valueOf(optionspec12));
*/
boolean flag2 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui");

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: GodOfPro <1387ilia@gmail.com>
Date: Tue, 11 Apr 2023 16:31:39 +0430
Subject: [PATCH] Add Mob Experience reward API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
index 921594a78ea511337434b29b5bc1a037eb30992c..e155501fb3a88edf3ddac3aa0aae1b6a5a84962e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
@@ -167,4 +167,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
this.getHandle().setAggressive(aggressive);
}
// Paper end
+
+ // Paper start
+ @Override
+ public int getPossibleExperienceReward() {
+ return getHandle().getExperienceReward();
+ }
+ // Paper end
}

View file

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 1 May 2023 18:31:26 -0700
Subject: [PATCH] Break redstone on top of trap doors early
This logic hooks into the neighbour update which should be invoked
as a result of redstone powering the trap door.
diff --git a/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java b/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java
index 26096c28f654118b0d541f33c659fbc43b34509b..2b5fdcb12dcd8730df24113b9a6d295f000dd9f6 100644
--- a/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -153,7 +153,26 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
flag1 = eventRedstone.getNewCurrent() > 0;
}
// CraftBukkit end
- if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) {
+ // Paper start - break redstone on trapdoors early
+ boolean open = (Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1;
+ // note: this must run before any state for this block/its neighborus are written to the world
+ // we allow the redstone event to fire so that plugins can block
+ if (flag1 && open) { // if we are now powered and it caused the trap door to open
+ // in this case, first check for the redstone on top first
+ BlockPos abovePos = pos.above();
+ BlockState above = world.getBlockState(abovePos);
+ if (above.getBlock() instanceof RedStoneWireBlock) {
+ world.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
+ Block.popResource(world, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
+ // now check that this didn't change our state
+ if (world.getBlockState(pos) != state) {
+ // our state was changed, so we cannot propagate this update
+ return;
+ }
+ }
+ }
+ if (open) {
+ // Paper end - break redstone on trapdoors early
state = (BlockState) state.setValue(TrapDoorBlock.OPEN, flag1);
this.playSound((Player) null, world, pos, flag1);
}

View file

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 14 May 2023 00:47:28 -0400
Subject: [PATCH] Avoid Lazy Initialization for Enum Fields
This patch is meant to get rid of any instances of lazy initialization that Minecraft introduces for enums.
This has the possibility to create race condition issues, and generally don't make sense to be lazily done anyways.
diff --git a/src/main/java/com/mojang/math/OctahedralGroup.java b/src/main/java/com/mojang/math/OctahedralGroup.java
index 0a3b6b8e250bd35530c05a1cdaf2eb8a9af4c72b..9aa82fc757c67a9456b2bdec744c0cb474d64df6 100644
--- a/src/main/java/com/mojang/math/OctahedralGroup.java
+++ b/src/main/java/com/mojang/math/OctahedralGroup.java
@@ -110,6 +110,7 @@ public enum OctahedralGroup implements StringRepresentable {
this.permutation = axisTransformation;
this.transformation = new Matrix3f().scaling(flipX ? -1.0F : 1.0F, flipY ? -1.0F : 1.0F, flipZ ? -1.0F : 1.0F);
this.transformation.mul(axisTransformation.transformation());
+ this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
}
private BooleanList packInversions() {
@@ -138,7 +139,7 @@ public enum OctahedralGroup implements StringRepresentable {
return this.name;
}
- public Direction rotate(Direction direction) {
+ public void initializeRotationDirections() { // Paper - Avoid Lazy Initialization for Enum Fields
if (this.rotatedDirections == null) {
this.rotatedDirections = Maps.newEnumMap(Direction.class);
Direction.Axis[] axiss = Direction.Axis.values();
@@ -153,6 +154,10 @@ public enum OctahedralGroup implements StringRepresentable {
}
}
+ // Paper start - Avoid Lazy Initialization for Enum Fields
+ }
+ public Direction rotate(Direction direction) {
+ // Paper end - Avoid Lazy Initialization for Enum Fields
return this.rotatedDirections.get(direction);
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Sun, 7 May 2023 22:33:50 +0200
Subject: [PATCH] More accurate isInOpenWater impl
For fishing hooks, the openWater field is true by default, and only calculated when a "fish" is approaching the bobber.
This patch changes the API impl to calculate the open water state itself instead of returning this field.
Relevant link: https://github.com/PaperMC/Paper/issues/9131
== AT ==
public net.minecraft.world.entity.projectile.FishingHook calculateOpenWater(Lnet/minecraft/core/BlockPos;)Z
public net.minecraft.world.entity.projectile.FishingHook outOfWaterTime
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
index ad1aeea80877f2cdb9e8ad9c5b46f95dd76b3335..116f23a3ee9fa409d7bc34c3769b94ed2bb07183 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
@@ -164,7 +164,7 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
@Override
public boolean isInOpenWater() {
- return this.getHandle().isOpenWaterFishing();
+ return this.getHandle().outOfWaterTime < 10 && this.getHandle().calculateOpenWater(this.getHandle().blockPosition()); // Paper - isOpenWaterFishing is only calculated when a "fish" is approaching the hook
}
@Override

View file

@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 20 Jan 2022 18:11:20 -0800
Subject: [PATCH] Expand PlayerItemMendEvent
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
index adc3e6298a1946fdea029c82a9954fb5b6e24497..a207a31d80a302dbdfe80f8727222542d3a78da2 100644
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
@@ -344,7 +344,7 @@ public class ExperienceOrb extends Entity {
ItemStack itemstack = (ItemStack) entry.getValue();
int j = Math.min(this.xpToDurability(amount), itemstack.getDamageValue());
// CraftBukkit start
- org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j);
+ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j, this::durabilityToXp); // Paper - Expand PlayerItemMendEvent
j = event.getRepairAmount();
if (event.isCancelled()) {
return amount;
@@ -352,8 +352,13 @@ public class ExperienceOrb extends Entity {
// CraftBukkit end
itemstack.setDamageValue(itemstack.getDamageValue() - j);
- int k = amount - this.durabilityToXp(j);
+ int k = amount - event.getDurabilityToXpOperation().applyAsInt(j); // Paper - Expand PlayerItemMendEvent
this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls
+ // Paper start - Expand PlayerItemMendEvent
+ if (j == 0 && amount == k) { // if repair amount is 0 and no xp was removed, don't do recursion; treat as cancelled
+ return k;
+ }
+ // Paper end - Expand PlayerItemMendEvent
return k > 0 ? this.repairPlayerItems(player, k) : 0;
} else {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 1519220d02dfeb14fded5687b77a85306faf6dcd..722c69e0149a9bf35159a7ffbb338fbc42600f0e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1835,11 +1835,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ());
int i = Math.min(orb.xpToDurability(amount), itemstack.getDamageValue());
- org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i);
+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i, orb::durabilityToXp); // Paper - Expand PlayerItemMendEvent
i = event.getRepairAmount();
orb.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN);
if (!event.isCancelled()) {
- amount -= orb.durabilityToXp(i);
+ amount -= event.getDurabilityToXpOperation().applyAsInt(i); // Paper - Expand PlayerItemMendEvent
itemstack.setDamageValue(itemstack.getDamageValue() - i);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e9a70547324dabd97dc90820515a11d2b630a704..c1b5d9713cb301dc06b74d97dca4fd5562c539e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1267,10 +1267,10 @@ public class CraftEventFactory {
return event;
}
- public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount) {
+ public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount, java.util.function.IntUnaryOperator durabilityToXpOp) { // Paper - Expand PlayerItemMendEvent
Player player = (Player) entity.getBukkitEntity();
org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asCraftMirror(nmsMendedItem);
- PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount);
+ PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount, durabilityToXpOp); // Paper - Expand PlayerItemMendEvent
Bukkit.getPluginManager().callEvent(event);
return event;
}

View file

@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 30 May 2023 12:59:10 -0700
Subject: [PATCH] Refresh ProjectileSource for projectiles
Makes sure the value returned by Projectile#getShooter in
the API matches the owner UUID specified in the entity nbt.
Previously, after the entity reloaded, Projectile#getShooter
would return null, while the entity still had an owner.
Also fixes setting the shooter/owner to null actually
clearing the owner.
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 09defe4a20c7b0794cba358c177e787f1c0273c1..b2e2bd4d7e3b373a92d3a4a13446f27fbf652c0a 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -386,6 +386,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean inWorld = false;
public boolean generation;
public int maxAirTicks = this.getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
+ @Nullable // Paper - Refresh ProjectileSource for projectiles
public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only
public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled
public boolean persistentInvisibility = false;
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
index 734e00caf72a694654319f69f793dcbf616f1784..64f7ae4d9e37daf2d48231f44f686008953ad39b 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
@@ -51,14 +51,31 @@ public abstract class Projectile extends Entity implements TraceableEntity {
this.ownerUUID = entity.getUUID();
this.cachedOwner = entity;
}
- this.projectileSource = (entity != null && entity.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) entity.getBukkitEntity() : null; // CraftBukkit
-
+ // Paper start - Refresh ProjectileSource for projectiles
+ else {
+ this.ownerUUID = null;
+ this.cachedOwner = null;
+ this.projectileSource = null;
+ }
+ // Paper end - Refresh ProjectileSource for projectiles
+ this.refreshProjectileSource(false); // Paper
+ }
+ // Paper start - Refresh ProjectileSource for projectiles
+ public void refreshProjectileSource(boolean fillCache) {
+ if (fillCache) {
+ this.getOwner();
+ }
+ if (this.cachedOwner != null && !this.cachedOwner.isRemoved() && this.projectileSource == null && this.cachedOwner.getBukkitEntity() instanceof ProjectileSource projSource) {
+ this.projectileSource = projSource;
+ }
}
+ // Paper end - Refresh ProjectileSource for projectiles
@Nullable
@Override
public Entity getOwner() {
if (this.cachedOwner != null && !this.cachedOwner.isRemoved()) {
+ this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles
return this.cachedOwner;
} else {
if (this.ownerUUID != null) {
@@ -68,6 +85,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
ServerLevel worldserver = (ServerLevel) world;
this.cachedOwner = worldserver.getEntity(this.ownerUUID);
+ this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles
return this.cachedOwner;
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
index c1c52f4fc5f900fac4098e5e37c52dfc4e82b8bb..236f94348ff8da661e23e3e17b7fc1b143680da9 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
@@ -60,6 +60,7 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
@Override
public final org.bukkit.projectiles.ProjectileSource getShooter() {
+ this.getHandle().refreshProjectileSource(true); // Paper - Refresh ProjectileSource for projectiles
return this.getHandle().projectileSource;
}

View file

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Malfrador <malfrador@gmail.com>
Date: Wed, 31 May 2023 23:30:00 +0200
Subject: [PATCH] Add transient 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 12135ffeacd648f6bc4d7d327059ea1a7e8c79c4..52439f4b959c74027eb191a3af960c70beb978e8 100644
--- a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
+++ b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
@@ -23,6 +23,11 @@ public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
throw new UnsupportedOperationException("Cannot modify default attributes");
}
+ @Override
+ public void addTransientModifier(AttributeModifier modifier) {
+ throw new UnsupportedOperationException("Cannot modify default attributes");
+ }
+
@Override
public void removeModifier(AttributeModifier modifier) {
throw new UnsupportedOperationException("Cannot modify default attributes");
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
index 8afbb8e0cb368e95f23bb78c1261f9aa9b8abd86..c0fb6da6bc3c5b4f37601d898fa421d430417d97 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
@@ -50,6 +50,14 @@ public class CraftAttributeInstance implements AttributeInstance {
this.handle.addPermanentModifier(CraftAttributeInstance.convert(modifier));
}
+ // Paper start - Transient modifier API
+ @Override
+ public void addTransientModifier(AttributeModifier modifier) {
+ Preconditions.checkArgument(modifier != null, "modifier");
+ this.handle.addTransientModifier(CraftAttributeInstance.convert(modifier));
+ }
+ // Paper end
+
@Override
public void removeModifier(AttributeModifier modifier) {
Preconditions.checkArgument(modifier != null, "modifier");

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Mon, 3 Apr 2023 18:46:49 +0200
Subject: [PATCH] Fix block place logic
Fix several issues when a player interact with a block:
* the place sound isn't played for the dispensed shulker block
* desync of the jukebox blocks between bukkit handler and the vanilla interaction
* poi can desync when the BlockPhysicsEvent is cancelled
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 7d76cdc59984b156628273c8357485eb10046007..7180996027f70aef7afe32fb2adfce6431429401 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -128,7 +128,7 @@ public class BlockItem extends Item {
SoundType soundeffecttype = iblockdata1.getSoundType();
- // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F);
+ if (entityhuman == null) world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), net.minecraft.sounds.SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); // Paper - Fix block place logic; reintroduce this for the dispenser (i.e the shulker)
world.gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1));
itemstack.consume(1, entityhuman);
return InteractionResult.sidedSuccess(world.isClientSide);
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index a80d225a7a4206acc4b93e328c96adf4411dad1d..1e104a724a327b98963ef2f23c10c426de6113a5 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -507,13 +507,7 @@ public final class ItemStack implements DataComponentHolder {
if (tileentity instanceof JukeboxBlockEntity) {
JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity;
- // There can only be one
- ItemStack record = this.copy();
- if (!record.isEmpty()) {
- record.setCount(1);
- }
-
- tileentityjukebox.setTheItem(record);
+ tileentityjukebox.setTheItem(this.copy()); // Paper - Fix block place logic; sync this with record item, jukebox has now an inventory
world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition)));
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 37c81d6c95efaab12a05075e6397ab2548c76722..19a177041e6e9621b0e35ca4f4ceb79b72448680 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -554,17 +554,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// CraftBukkit start
iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam
CraftWorld world = ((ServerLevel) this).getWorld();
+ boolean cancelledUpdates = false; // Paper - Fix block place logic
if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent
BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata));
this.getCraftServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) {
- return;
- }
+ cancelledUpdates = event.isCancelled(); // Paper - Fix block place logic
}
// CraftBukkit end
+ if (!cancelledUpdates) { // Paper - Fix block place logic
iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1);
iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1);
+ } // Paper - Fix block place logic
}
// CraftBukkit start - SPIGOT-5710

View file

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Thu, 8 Jun 2023 20:23:13 -0400
Subject: [PATCH] Fix spigot sound playing for BlockItem ItemStacks
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 1e104a724a327b98963ef2f23c10c426de6113a5..735a56648a783a618891b391418a8fd0d2968f4f 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -558,7 +558,11 @@ public final class ItemStack implements DataComponentHolder {
// SPIGOT-1288 - play sound stripped from ItemBlock
if (this.item instanceof BlockItem) {
- SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots
+ // Paper start - Fix spigot sound playing for BlockItem ItemStacks
+ BlockPos position = new net.minecraft.world.item.context.BlockPlaceContext(context).getClickedPos();
+ net.minecraft.world.level.block.state.BlockState blockData = world.getBlockState(position);
+ SoundType soundeffecttype = blockData.getSoundType();
+ // Paper end - Fix spigot sound playing for BlockItem ItemStacks
world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F);
}

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Fri, 9 Jun 2023 13:04:42 +0200
Subject: [PATCH] Call BlockGrowEvent for missing blocks
Call the event for pitcher crops and sniffer egg
diff --git a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
index d06e3892cf42723f8e3f621b5497c5348fa1a715..5f1ec3f69295760b7b8097916c82cbf9ddd49700 100644
--- a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
@@ -133,7 +133,7 @@ public class PitcherCropBlock extends DoublePlantBlock implements BonemealableBl
int i = Math.min(state.getValue(AGE) + amount, 4);
if (this.canGrow(world, pos, state, i)) {
BlockState blockState = state.setValue(AGE, Integer.valueOf(i));
- world.setBlock(pos, blockState, 2);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, blockState, 2)) return; // Paper
if (isDouble(i)) {
world.setBlock(pos.above(), blockState.setValue(HALF, DoubleBlockHalf.UPPER), 3);
}
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 f53808e200bd83ab80954ec5c1e9c14250302be8..b943384eb6a4612993556036f0d3beec6939a559 100644
--- a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
@@ -71,8 +71,13 @@ public class SnifferEggBlock extends Block {
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!this.isReadyToHatch(state)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2)) {
+ this.rescheduleTick(world, pos);
+ return;
+ }
+ // Paper end
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- world.setBlock(pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2);
} else {
// Paper start - Call BlockFadeEvent
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, state.getFluidState().createLegacyBlock()).isCancelled()) {

View file

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TheMeinerLP <p.glanz@madfix.me>
Date: Tue, 13 Jun 2023 16:10:59 +0200
Subject: [PATCH] Don't enforce icanhasbukkit default if alias block exists
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index d5575fcc1458fe3083821792f09f9ed53c12e825..29a11dc69b64ddc6022812757b2839931e271ac2 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -354,7 +354,11 @@ public final class CraftServer implements Server {
}
this.commandsConfiguration = YamlConfiguration.loadConfiguration(this.getCommandsConfigFile());
this.commandsConfiguration.options().copyDefaults(true);
- this.commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8)));
+ // Paper start - don't enforce icanhasbukkit default if alias block exists
+ final YamlConfiguration commandsDefaults = YamlConfiguration.loadConfiguration(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8));
+ if (this.commandsConfiguration.contains("aliases")) commandsDefaults.set("aliases", null);
+ this.commandsConfiguration.setDefaults(commandsDefaults);
+ // Paper end - don't enforce icanhasbukkit default if alias block exists
this.saveCommandsConfig();
// Migrate aliases from old file and add previously implicit $1- to pass all arguments

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 14 Jun 2023 13:17:40 -0700
Subject: [PATCH] fix MapLike spam for missing key 'selector'
diff --git a/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java b/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java
index 8c8c16ce53f5bdf88274cb80767decf0a2612637..d4288ae84c08ff6cb2f6763eeb9c358d5bf38f55 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java
@@ -353,7 +353,7 @@ public interface VibrationSystem {
public static Codec<VibrationSystem.Data> CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(VibrationInfo.CODEC.lenientOptionalFieldOf("event").forGetter((vibrationsystem_a) -> {
return Optional.ofNullable(vibrationsystem_a.currentVibration);
- }), VibrationSelector.CODEC.fieldOf("selector").forGetter(VibrationSystem.Data::getSelectionStrategy), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(VibrationSystem.Data::getTravelTimeInTicks)).apply(instance, (optional, vibrationselector, integer) -> {
+ }), Codec.optionalField("selector", VibrationSelector.CODEC).xmap(o -> o.orElseGet(VibrationSelector::new), Optional::of).forGetter(VibrationSystem.Data::getSelectionStrategy), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(VibrationSystem.Data::getTravelTimeInTicks)).apply(instance, (optional, vibrationselector, integer) -> { // Paper - fix MapLike spam for missing "selector" in 1.19.2
return new VibrationSystem.Data((VibrationInfo) optional.orElse(null), vibrationselector, integer, true); // CraftBukkit - decompile error
});
});

View file

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sun, 11 Jun 2023 19:02:46 +0200
Subject: [PATCH] Fix sniffer removeExploredLocation
Add support to remove explored location in different world
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java
index 60251107371ef876d29fc9aa578835250715c4bc..555337018fe218ac5a296a5e6a1d82720fee05e1 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java
@@ -34,12 +34,13 @@ public class CraftSniffer extends CraftAnimals implements Sniffer {
@Override
public void removeExploredLocation(Location location) {
Preconditions.checkArgument(location != null, "location cannot be null");
- if (location.getWorld() != this.getWorld()) {
- return;
- }
BlockPos blockPosition = CraftLocation.toBlockPosition(location);
- this.getHandle().getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, this.getHandle().getExploredPositions().filter(blockPositionExplored -> !blockPositionExplored.equals(blockPosition)).collect(Collectors.toList()));
+ // Paper start
+ net.minecraft.world.level.Level level = location.getWorld() != null ? ((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle() : this.getHandle().level();
+ net.minecraft.core.GlobalPos globalPos = net.minecraft.core.GlobalPos.of(level.dimension(), blockPosition);
+ this.getHandle().getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, this.getHandle().getExploredPositions().filter(blockPositionExplored -> !blockPositionExplored.equals(globalPos)).collect(Collectors.toList()));
+ // Paper end
}
@Override

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 17 Jun 2023 13:17:25 -0700
Subject: [PATCH] Add method to remove all active potion effects
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 4f31bf6f51a72b010b850e1e62a06b455eac906c..eca55d45e1529fffbfcf5d6b8fd23935385e8bcd 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -555,6 +555,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return effects;
}
+ // Paper start - LivingEntity#clearActivePotionEffects();
+ @Override
+ public boolean clearActivePotionEffects() {
+ return this.getHandle().removeAllEffects(EntityPotionEffectEvent.Cause.PLUGIN);
+ }
+ // Paper end
+
@Override
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile) {
return this.launchProjectile(projectile, null);

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Redned <redned235@gmail.com>
Date: Mon, 12 Jun 2023 11:54:12 -0500
Subject: [PATCH] Fix incorrect crafting result amount for fireworks
Although vanilla does not specifically call this method anywhere, this fixes a bug where the result using the Bukkit API returns the wrong amount.
diff --git a/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java b/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java
index da924bb34354b1a8b3db3ad63b5705253d942514..56c8900c8771919d5e0e62b4d165ae6f00042872 100644
--- a/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java
+++ b/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java
@@ -78,7 +78,7 @@ public class FireworkRocketRecipe extends CustomRecipe {
@Override
public ItemStack getResultItem(HolderLookup.Provider registriesLookup) {
- return new ItemStack(Items.FIREWORK_ROCKET);
+ return new ItemStack(Items.FIREWORK_ROCKET, 3); // Paper - Fix incorrect crafting result amount
}
@Override

View file

@ -0,0 +1,93 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: by77er <by77er@gmail.com>
Date: Mon, 12 Jun 2023 12:56:46 -0400
Subject: [PATCH] Add event for player editing sign
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 735a56648a783a618891b391418a8fd0d2968f4f..31f67c83416031079569375e5f69738dd639b93f 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -537,7 +537,7 @@ public final class ItemStack implements DataComponentHolder {
try {
if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) {
if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) {
- blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit
+ blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Paper - Add PlayerOpenSignEvent
}
}
} finally {
diff --git a/src/main/java/net/minecraft/world/level/block/SignBlock.java b/src/main/java/net/minecraft/world/level/block/SignBlock.java
index e602c58bc14036d78a00ad548a821650b92e29df..f7bae8060d993176799ff3ff4653d760a137faba 100644
--- a/src/main/java/net/minecraft/world/level/block/SignBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SignBlock.java
@@ -142,7 +142,7 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
} else if (flag1) {
return InteractionResult.SUCCESS;
} else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag)) {
- this.openTextEdit(player, tileentitysign, flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit
+ this.openTextEdit(player, tileentitysign, flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper - Add PlayerOpenSignEvent
return InteractionResult.SUCCESS;
} else {
return InteractionResult.PASS;
@@ -187,16 +187,33 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
return blockpropertywood;
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - Add PlayerOpenSignEvent
public void openTextEdit(Player player, SignBlockEntity blockEntity, boolean front) {
- // Craftbukkit start
- this.openTextEdit(player, blockEntity, front, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN);
- }
-
- public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) {
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) {
+ // Paper start - Add PlayerOpenSignEvent
+ this.openTextEdit(player, blockEntity, front, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.UNKNOWN);
+ }
+ public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) {
+ org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(tileentitysign.getLevel(), tileentitysign.getBlockPos());
+ org.bukkit.craftbukkit.block.CraftSign<?> bukkitSign = (org.bukkit.craftbukkit.block.CraftSign<?>) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(bukkitBlock);
+ io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent(
+ bukkitPlayer,
+ bukkitSign,
+ flag ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
+ cause);
+ if (!event.callEvent()) return;
+ if (org.bukkit.event.player.PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ final org.bukkit.event.player.PlayerSignOpenEvent.Cause legacyCause = switch (cause) {
+ case PLACE -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE;
+ case PLUGIN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLUGIN;
+ case INTERACT -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT;
+ case UNKNOWN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN;
+ };
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, legacyCause)) {
+ // Paper end - Add PlayerOpenSignEvent
return;
}
- // Craftbukkit end
+ } // Paper - Add PlayerOpenSignEvent
tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID());
entityhuman.openTextEdit(tileentitysign, flag);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
index a12702cdf36c75572e661b5b5758270f5058c181..8303343ecca91076839f4436d6b3a3bf4739c2fd 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
@@ -168,9 +168,15 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
Preconditions.checkArgument(sign.isPlaced(), "Sign must be placed");
Preconditions.checkArgument(sign.getWorld() == player.getWorld(), "Sign must be in same world as Player");
+ // Paper start - Add PlayerOpenSignEvent
+ io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent((Player) player, sign, side, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLUGIN);
+ if (!event.callEvent()) return;
+ if (PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ // Paper end - Add PlayerOpenSignEvent
if (!CraftEventFactory.callPlayerSignOpenEvent(player, sign, side, PlayerSignOpenEvent.Cause.PLUGIN)) {
return;
}
+ } // Paper - Add PlayerOpenSignEvent
SignBlockEntity handle = ((CraftSign<?>) sign).getTileEntity();
handle.setAllowedPlayerEditor(player.getUniqueId());

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Redned <redned235@gmail.com>
Date: Mon, 19 Jun 2023 15:45:53 -0500
Subject: [PATCH] Only tick item frames if players can see it
In the event that an item frame cannot be seen by any players, ticking the item frame every tick is unnecessary. This can be a very hot section of the entity tracker when lots of item frames are present on a server, so this reduces the logic which speeds it up.
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index f355dd986bf861da3edb90d7e05f901e19686fef..b195de05371e9762654b69365f0e722443425d33 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -113,7 +113,7 @@ public class ServerEntity {
Entity entity = this.entity;
- if (entity instanceof ItemFrame entityitemframe) {
+ if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame) { // Paper - Perf: Only tick item frames if players can see it
if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block
ItemStack itemstack = entityitemframe.getItem();

View file

@ -0,0 +1,90 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 24 Jan 2022 15:32:02 -0800
Subject: [PATCH] Fix cmd permission levels for command blocks
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
index f3c83bb20a73b489f1fb6bacb69388902b1b6fe7..3c0d2332207ba638faaaa4280bce18c334a01271 100644
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
@@ -204,10 +204,29 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
return this.permissionLevel >= level;
}
+ // Paper start - Fix permission levels for command blocks
+ private boolean forceRespectPermissionLevel() {
+ return this.source == CommandSource.NULL || (this.source instanceof final net.minecraft.world.level.BaseCommandBlock commandBlock && commandBlock.getLevel().paperConfig().commandBlocks.forceFollowPermLevel);
+ }
+ // Paper end - Fix permission levels for command blocks
+
// CraftBukkit start
public boolean hasPermission(int i, String bukkitPermission) {
- // World is null when loading functions
- return ((this.getLevel() == null || !this.getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || this.getBukkitSender().hasPermission(bukkitPermission);
+ // Paper start - Fix permission levels for command blocks
+ final java.util.function.BooleanSupplier hasBukkitPerm = () -> this.source == CommandSource.NULL /*treat NULL as having all bukkit perms*/ || this.getBukkitSender().hasPermission(bukkitPermission); // lazily check bukkit perms to the benefit of custom permission setups
+ // if the server is null, we must check the vanilla perm level system
+ // if ignoreVanillaPermissions is true, we can skip vanilla perms and just run the bukkit perm check
+ //noinspection ConstantValue
+ if (this.getServer() == null || !this.getServer().server.ignoreVanillaPermissions) { // server & level are null for command function loading
+ final boolean hasPermLevel = this.permissionLevel >= i;
+ if (this.forceRespectPermissionLevel()) { // NULL CommandSource and command blocks (if setting is enabled) should always pass the vanilla perm check
+ return hasPermLevel && hasBukkitPerm.getAsBoolean();
+ } else { // otherwise check vanilla perm first then bukkit perm, matching upstream behavior
+ return hasPermLevel || hasBukkitPerm.getAsBoolean();
+ }
+ }
+ return hasBukkitPerm.getAsBoolean();
+ // Paper end - Fix permission levels for command blocks
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 4114e2b148baf9ddc489eed11fed4aacd0eab401..60406cb01c5a409ba6fe98677a5cc332effaebea 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -299,16 +299,7 @@ public class Commands {
String[] args = command.split(" ");
if (args.length == 0) return; // Paper - empty commands shall not be dispatched
- String cmd = args[0];
- if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length());
- if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length());
-
- // Block disallowed commands
- if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op")
- || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip")
- || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) {
- return;
- }
+ // Paper - Fix permission levels for command blocks
// Handle vanilla commands;
if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) {
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
index c671b26d7dc70bac1f4bf9a68a264b25865cf7da..83ef2c3e7b06152b9e68f90002c35e77f148347d 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
@@ -136,7 +136,7 @@ public class MinecartCommandBlock extends AbstractMinecart {
@Override
public CommandSourceStack createCommandSourceStack() {
- return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), 2, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this);
+ return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this); // Paper - configurable command block perm level
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java
index 4c7d142dc653f3aca82e0563b6ba2e020721eb9b..6c484f3f8f37a19992ebbfe30aba399cac21acfe 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java
@@ -58,7 +58,7 @@ public class CommandBlockEntity extends BlockEntity {
public CommandSourceStack createCommandSourceStack() {
Direction enumdirection = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING);
- return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null);
+ return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); // Paper - configurable command block perm level
}
@Override

View file

@ -0,0 +1,179 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Boy <sivertpaulsen2@gmail.com>
Date: Sun, 18 Jun 2023 17:45:33 +0200
Subject: [PATCH] Add option to disable block updates
diff --git a/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java b/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java
index 06f0e5afdab6274154213d82ab3278e08c4ba1b7..8569ad43985fa60d5196ae4bc21646406d8b2adc 100644
--- a/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java
@@ -38,6 +38,7 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
return getStateWithConnections(ctx.getLevel(), ctx.getClickedPos(), this.defaultBlockState());
}
@@ -59,6 +60,7 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return state; // Paper - add option to disable block updates
if (!state.canSurvive(world, pos)) {
world.scheduleTick(pos, this, 1);
return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -70,6 +72,7 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return; // Paper - add option to disable block updates
if (!state.canSurvive(world, pos)) {
world.destroyBlock(pos, true);
}
@@ -77,6 +80,7 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
protected boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return true; // Paper - add option to disable block updates
BlockState blockState = world.getBlockState(pos.below());
boolean bl = !world.getBlockState(pos.above()).isAir() && !blockState.isAir();
diff --git a/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java b/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java
index 3f45058eee0c78f50c119da5da4c7d2af0251a27..d16aad72c90bbde158b845759eef227546d12e24 100644
--- a/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java
@@ -43,6 +43,7 @@ public class HugeMushroomBlock extends Block {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
BlockGetter blockGetter = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState()
@@ -56,6 +57,7 @@ public class HugeMushroomBlock extends Block {
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return neighborState.is(this)
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(false))
: super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -63,6 +65,7 @@ public class HugeMushroomBlock extends Block {
@Override
protected BlockState rotate(BlockState state, Rotation rotation) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.EAST)), state.getValue(EAST))
@@ -73,6 +76,7 @@ public class HugeMushroomBlock extends Block {
@Override
protected BlockState mirror(BlockState state, Mirror mirror) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.EAST)), state.getValue(EAST))
diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
index f77d51d10e01fc4eaf5516c05c8be0ef7a425893..1d82cfe7af0dc42f88901fb0c44896771fdf8a93 100644
--- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
@@ -66,11 +66,13 @@ public class NoteBlock extends Block {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return this.defaultBlockState(); // Paper - place without considering instrument
return this.setInstrument(ctx.getLevel(), ctx.getClickedPos(), this.defaultBlockState());
}
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return state; // Paper - prevent noteblock instrument from updating
boolean flag = direction.getAxis() == Direction.Axis.Y;
return flag ? this.setInstrument(world, pos, state) : super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -78,6 +80,7 @@ public class NoteBlock extends Block {
@Override
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return; // Paper - prevent noteblock powered-state from updating
boolean flag1 = world.hasNeighborSignal(pos);
if (flag1 != (Boolean) state.getValue(NoteBlock.POWERED)) {
@@ -116,7 +119,7 @@ public class NoteBlock extends Block {
if (world.isClientSide) {
return InteractionResult.SUCCESS;
} else {
- state = (BlockState) state.cycle(NoteBlock.NOTE);
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) state = (BlockState) state.cycle(NoteBlock.NOTE); // Paper - prevent noteblock note from updating
world.setBlock(pos, state, 3);
this.playNote(player, state, world, pos);
player.awardStat(Stats.TUNE_NOTEBLOCK);
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
index e032d8907045c653c3dd449f65e93e40fd0bb6be..6fe5be785423a35b6ff4e6206ca281b66845b979 100644
--- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
@@ -67,6 +67,7 @@ public class TripWireBlock extends Block {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return this.defaultBlockState(); // Paper - place tripwire without updating
Level world = ctx.getLevel();
BlockPos blockposition = ctx.getClickedPos();
@@ -75,11 +76,13 @@ public class TripWireBlock extends Block {
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent tripwire from updating
return direction.getAxis().isHorizontal() ? (BlockState) state.setValue((Property) TripWireBlock.PROPERTY_BY_DIRECTION.get(direction), this.shouldConnectTo(neighborState, direction)) : super.updateShape(state, direction, neighborState, world, pos, neighborPos);
}
@Override
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!oldState.is(state.getBlock())) {
this.updateSource(world, pos, state);
}
@@ -87,6 +90,7 @@ public class TripWireBlock extends Block {
@Override
protected void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!moved && !state.is(newState.getBlock())) {
this.updateSource(world, pos, (BlockState) state.setValue(TripWireBlock.POWERED, true));
}
@@ -94,6 +98,7 @@ public class TripWireBlock extends Block {
@Override
public BlockState playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent disarming tripwires
if (!world.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) {
world.setBlock(pos, (BlockState) state.setValue(TripWireBlock.DISARMED, true), 4);
world.gameEvent((Entity) player, (Holder) GameEvent.SHEAR, pos);
@@ -103,6 +108,7 @@ public class TripWireBlock extends Block {
}
private void updateSource(Level world, BlockPos pos, BlockState state) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
Direction[] aenumdirection = new Direction[]{Direction.SOUTH, Direction.WEST};
int i = aenumdirection.length;
int j = 0;
@@ -135,6 +141,7 @@ public class TripWireBlock extends Block {
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwires from detecting collision
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide) {
if (!(Boolean) state.getValue(TripWireBlock.POWERED)) {
@@ -145,6 +152,7 @@ public class TripWireBlock extends Block {
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwire pressed check
if ((Boolean) world.getBlockState(pos).getValue(TripWireBlock.POWERED)) {
this.checkPressed(world, pos);
}

View file

@ -0,0 +1,88 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sat, 29 Oct 2022 15:41:56 +0200
Subject: [PATCH] Call missing BlockDispenseEvent
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 9507dbbb4b490149b9248c384be5adaccae40c41..5bbadc890a72f1cb22c6881ebcc163b0c06a367a 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -898,6 +898,13 @@ public interface DispenseItemBehavior {
this.setSuccess(true);
if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) {
if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) {
+ // Paper start - Call missing BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata);
stack.shrink(1);
} else {
@@ -977,6 +984,13 @@ public interface DispenseItemBehavior {
Optional<BlockState> optional = HoneycombItem.getWaxed(iblockdata);
if (optional.isPresent()) {
+ // Paper start - Call missing BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get());
worldserver.levelEvent(3003, blockposition, 0);
stack.shrink(1);
@@ -1004,6 +1018,12 @@ public interface DispenseItemBehavior {
if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) {
return this.defaultDispenseItemBehavior.dispense(pointer, stack);
} else {
+ // Paper start - Call missing BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition1, stack, this);
+ if (result != null) {
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
if (!worldserver.isClientSide) {
for (int k = 0; k < 5; ++k) {
worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + worldserver.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + worldserver.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D);
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index c1b5d9713cb301dc06b74d97dca4fd5562c539e2..27bafd5349805171399dbd141f5c568ec35286f4 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -2110,6 +2110,32 @@ public class CraftEventFactory {
}
// Paper end
+ // Paper start - Call missing BlockDispenseEvent
+ @Nullable
+ public static ItemStack handleBlockDispenseEvent(net.minecraft.core.dispenser.BlockSource pointer, BlockPos to, ItemStack itemStack, net.minecraft.core.dispenser.DispenseItemBehavior instance) {
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(pointer.level(), pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1));
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to));
+ if (!net.minecraft.world.level.block.DispenserBlock.eventFired) {
+ if (!event.callEvent()) {
+ return itemStack;
+ }
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ net.minecraft.core.dispenser.DispenseItemBehavior itemBehavior = net.minecraft.world.level.block.DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+ if (itemBehavior != net.minecraft.core.dispenser.DispenseItemBehavior.NOOP && itemBehavior != instance) {
+ itemBehavior.dispense(pointer, eventStack);
+ return itemStack;
+ }
+ }
+ return null;
+ }
+ // Paper end - Call missing BlockDispenseEvent
+
// Paper start - add EntityFertilizeEggEvent
/**
* Calls the {@link io.papermc.paper.event.entity.EntityFertilizeEggEvent}.

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 5 Jul 2023 23:11:53 +0100
Subject: [PATCH] Don't load chunks for supporting block checks
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index b2e2bd4d7e3b373a92d3a4a13446f27fbf652c0a..16f36d1bfe6458f9aa935cdc63066c082bc83f8e 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1211,7 +1211,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
protected BlockPos getOnPos(float offset) {
- if (this.mainSupportingBlockPos.isPresent()) {
+ if (this.mainSupportingBlockPos.isPresent() && this.level().getChunkIfLoadedImmediately(this.mainSupportingBlockPos.get()) != null) { // Paper - ensure no loads
BlockPos blockposition = (BlockPos) this.mainSupportingBlockPos.get();
if (offset <= 1.0E-5F) {

View file

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 6 Jul 2023 20:17:37 -0700
Subject: [PATCH] Optimize player lookups for beacons
For larger ranges, it's better to iterate over the player list
than the entity slices.
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 2e3d89ca35b513340cd1ebefa875280b32e1756e..8a89ba2f50b0032b9db854d2c8cb6493f58dbe34 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -333,7 +333,22 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10); // Paper - Custom beacon ranges
AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
- List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
+ // Paper start - Perf: optimize player lookup for beacons
+ List<Player> list;
+ if (d0 <= 128.0) {
+ list = world.getEntitiesOfClass(Player.class, axisalignedbb);
+ } else {
+ list = new java.util.ArrayList<>();
+ for (Player player : world.players()) {
+ if (player.isSpectator()) {
+ continue;
+ }
+ if (player.getBoundingBox().intersects(axisalignedbb)) {
+ list.add(player);
+ }
+ }
+ }
+ // Paper end - Perf: optimize player lookup for beacons
return list;
}

View file

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 23 Jun 2023 12:16:28 -0700
Subject: [PATCH] Add Sign#getInteractableSideFor
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
index a55a2db66d8c8482c5b4107b21bb82d7e8ff4288..749b24cdc0cc2f04fe7fa29da7ea2ffd4ee153e5 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
@@ -68,12 +68,17 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
}
public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) {
+ // Paper start - Add Sign#getInteractableSideFor
+ return this.isFacingFrontText(player.getX(), player.getZ());
+ }
+ public boolean isFacingFrontText(double x, double z) {
+ // Paper end - Add Sign#getInteractableSideFor
Block block = this.getBlockState().getBlock();
if (block instanceof SignBlock blocksign) {
Vec3 vec3d = blocksign.getSignHitboxCenterPosition(this.getBlockState());
- double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3d.x);
- double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3d.z);
+ double d0 = x - ((double) this.getBlockPos().getX() + vec3d.x); // Paper - Add Sign#getInteractableSideFor
+ double d1 = z - ((double) this.getBlockPos().getZ() + vec3d.z); // Paper - Add Sign#getInteractableSideFor
float f = blocksign.getYRotationDegrees(this.getBlockState());
float f1 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
index 8303343ecca91076839f4436d6b3a3bf4739c2fd..cefbb015a77b9e3cab56e5ed4fe35fba91641632 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
@@ -198,6 +198,14 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
}
// Paper end
+ // Paper start - side facing API
+ @Override
+ public Side getInteractableSideFor(final double x, final double z) {
+ this.requirePlaced();
+ return this.getSnapshot().isFacingFrontText(x, z) ? Side.FRONT : Side.BACK;
+ }
+ // Paper end
+
public static Component[] sanitizeLines(String[] lines) {
Component[] components = new Component[4];

View file

@ -0,0 +1,74 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 11 Jul 2023 11:22:30 -0700
Subject: [PATCH] fix item meta for tadpole buckets
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
index 071f4fe53fbea333b5db52ac719c5e6b833ffe19..4cc5f39ee20948e2369b21041b663a7e50d15ac1 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -364,6 +364,7 @@ public final class CraftItemFactory implements ItemFactory {
case COD_BUCKET:
case PUFFERFISH_BUCKET:
case SALMON_BUCKET:
+ case TADPOLE_BUCKET: // Paper
case ITEM_FRAME:
case GLOW_ITEM_FRAME:
case PAINTING:
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index be2b7c2b412a1d64466c25c1b19b10a869cd288d..d544a4e4d88b51cf6ca53e048c411aa23c64d78f 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -600,6 +600,7 @@ public final class CraftItemStack extends ItemStack {
case COD_BUCKET:
case PUFFERFISH_BUCKET:
case SALMON_BUCKET:
+ case TADPOLE_BUCKET: // Paper
case ITEM_FRAME:
case GLOW_ITEM_FRAME:
case PAINTING:
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java
index 27af7ca9d62bdb4a24be5af139c181d7bc271ba5..3ff0340c40e9dc9a6e690de15ccade7a0c4e8f02 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java
@@ -19,6 +19,7 @@ public class CraftMetaEntityTag extends CraftMetaItem {
Material.COD_BUCKET,
Material.PUFFERFISH_BUCKET,
Material.SALMON_BUCKET,
+ Material.TADPOLE_BUCKET, // Paper
Material.ITEM_FRAME,
Material.GLOW_ITEM_FRAME,
Material.PAINTING
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
index 7237e24686885c754c87e7eec53c6400fd0b47bf..f071968be481a164192085a3e405bea2d26062b6 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
@@ -234,6 +234,27 @@ public class ItemMetaTest extends AbstractTestingBase {
}
}
+ // Paper start - check entity tag metas
+ private static final java.util.Set<Class<?>> ENTITY_TAG_METAS = java.util.Set.of(
+ CraftMetaEntityTag.class,
+ CraftMetaTropicalFishBucket.class,
+ CraftMetaAxolotlBucket.class
+ );
+ @Test
+ public void testEntityTagMeta() {
+ for (final Item item : BuiltInRegistries.ITEM) {
+ if (item instanceof net.minecraft.world.item.HangingEntityItem || item instanceof net.minecraft.world.item.MobBucketItem) {
+ ItemStack stack = new ItemStack(CraftItemType.minecraftToBukkit(item));
+ assertTrue(ENTITY_TAG_METAS.contains(stack.getItemMeta().getClass()), "missing entity tag meta handling for " + item);
+ stack = CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.STONE);
+ stack.editMeta(meta -> meta.displayName(net.kyori.adventure.text.Component.text("hello")));
+ stack.setType(CraftItemType.minecraftToBukkit(item));
+ assertTrue(ENTITY_TAG_METAS.contains(stack.getItemMeta().getClass()), "missing entity tag meta handling for " + item);
+ }
+ }
+ }
+ // Paper end
+
@Test
public void testEachExtraData() {
final List<StackProvider> providers = Arrays.asList(

View file

@ -0,0 +1,351 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 4 Jul 2023 11:27:10 -0700
Subject: [PATCH] Fix BanList API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
index 8caee0181f256e2ffd4e880274859eaf5f81ae96..4d654c4f0b6210a9841427789ba70ce5d1d308be 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
@@ -115,17 +115,17 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper - fix ban list API
return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Instant expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant expires, String source) { // Paper - fix ban list API
return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source) { // Paper - fix ban list API
return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, duration, source);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
index 13e5e44b069121e51b9486c445902937f1d6c6d8..4a37c8172b42b10472bb90c9310c7ae3eeaa3481 100644
--- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
+++ b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
@@ -9,7 +9,7 @@ import org.bukkit.BanEntry;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.profile.PlayerProfile;
-public final class CraftProfileBanEntry implements BanEntry<PlayerProfile> {
+public final class CraftProfileBanEntry implements BanEntry<com.destroystokyo.paper.profile.PlayerProfile> { // Paper
private static final Date minorDate = Date.from(Instant.parse("1899-12-31T04:00:00Z"));
private final UserBanList list;
private final GameProfile profile;
@@ -33,8 +33,8 @@ public final class CraftProfileBanEntry implements BanEntry<PlayerProfile> {
}
@Override
- public PlayerProfile getBanTarget() {
- return new CraftPlayerProfile(this.profile);
+ public com.destroystokyo.paper.profile.PlayerProfile getBanTarget() { // Paper
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this.profile); // Paper
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
index 172202accf4448a933fcf1ff820316c7910dd7f7..50ee7656580d386db473c054f5c5ec57bb2b1424 100644
--- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
+++ b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
@@ -24,42 +24,80 @@ public class CraftProfileBanList implements ProfileBanList {
}
@Override
- public BanEntry<PlayerProfile> getBanEntry(String target) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(String target) { // Paper
Preconditions.checkArgument(target != null, "Target cannot be null");
return this.getBanEntry(CraftProfileBanList.getProfile(target));
}
@Override
- public BanEntry<PlayerProfile> getBanEntry(PlayerProfile target) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(PlayerProfile target) { // Paper
Preconditions.checkArgument(target != null, "Target cannot be null");
- return this.getBanEntry(((CraftPlayerProfile) target).buildGameProfile());
+ return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile()); // Paper
+ }
+ // Paper start - fix ban list API
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(final com.destroystokyo.paper.profile.PlayerProfile target) {
+ Preconditions.checkArgument(target != null, "target cannot be null");
+
+ return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile());
+ }
+
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Date expires, final String source) {
+ Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
+ Preconditions.checkArgument(target.getId() != null, "The PlayerProfile UUID cannot be null");
+
+ return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source);
+ }
+
+ @Override
+ public boolean isBanned(final com.destroystokyo.paper.profile.PlayerProfile target) {
+ return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+ }
+
+ @Override
+ public void pardon(final com.destroystokyo.paper.profile.PlayerProfile target) {
+ this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
}
@Override
- public BanEntry<PlayerProfile> addBan(String target, String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Instant expires, final String source) {
+ Date date = expires != null ? Date.from(expires) : null;
+ return this.addBan(target, reason, date, source);
+ }
+
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Duration duration, final String source) {
+ Instant instant = duration != null ? Instant.now().plus(duration) : null;
+ return this.addBan(target, reason, instant, source);
+ }
+ // Paper end - fix ban list API
+
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(String target, String reason, Date expires, String source) { // Paper - fix ban list API
Preconditions.checkArgument(target != null, "Ban target cannot be null");
return this.addBan(CraftProfileBanList.getProfileByName(target), reason, expires, source);
}
@Override
- public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) { // Paper - fix ban list API
Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
Preconditions.checkArgument(target.getUniqueId() != null, "The PlayerProfile UUID cannot be null");
- return this.addBan(((CraftPlayerProfile) target).buildGameProfile(), reason, expires, source);
+ return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source); // Paper
}
@Override
- public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Instant expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Instant expires, String source) { // Paper - fix ban list API
Date date = expires != null ? Date.from(expires) : null;
return this.addBan(target, reason, date, source);
}
@Override
- public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Duration duration, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Duration duration, String source) { // Paper - fix ban list API
Instant instant = duration != null ? Instant.now().plus(duration) : null;
return this.addBan(target, reason, instant, source);
}
@@ -76,8 +114,8 @@ public class CraftProfileBanList implements ProfileBanList {
}
@Override
- public Set<BanEntry<PlayerProfile>> getEntries() {
- ImmutableSet.Builder<BanEntry<PlayerProfile>> builder = ImmutableSet.builder();
+ public Set<BanEntry<com.destroystokyo.paper.profile.PlayerProfile>> getEntries() { // Paper
+ ImmutableSet.Builder<BanEntry<com.destroystokyo.paper.profile.PlayerProfile>> builder = ImmutableSet.builder(); // Paper
for (UserBanListEntry entry : this.list.getEntries()) {
GameProfile profile = entry.getUser();
builder.add(new CraftProfileBanEntry(profile, entry, this.list));
@@ -88,9 +126,14 @@ public class CraftProfileBanList implements ProfileBanList {
@Override
public boolean isBanned(PlayerProfile target) {
+ // Paper start
+ return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+ }
+ private boolean isBanned(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
+ // Paper end
Preconditions.checkArgument(target != null, "Target cannot be null");
- return this.isBanned(((CraftPlayerProfile) target).buildGameProfile());
+ return this.isBanned(target.buildGameProfile()); // Paper
}
@Override
@@ -102,9 +145,14 @@ public class CraftProfileBanList implements ProfileBanList {
@Override
public void pardon(PlayerProfile target) {
+ // Paper start
+ this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+ }
+ private void pardon(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
+ // Paper end
Preconditions.checkArgument(target != null, "Target cannot be null");
- this.pardon(((CraftPlayerProfile) target).buildGameProfile());
+ this.pardon(target.buildGameProfile()); // Paper
}
@Override
@@ -114,7 +162,7 @@ public class CraftProfileBanList implements ProfileBanList {
this.pardon(CraftProfileBanList.getProfile(target));
}
- public BanEntry<PlayerProfile> getBanEntry(GameProfile profile) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(GameProfile profile) { // Paper
if (profile == null) {
return null;
}
@@ -127,7 +175,7 @@ public class CraftProfileBanList implements ProfileBanList {
return new CraftProfileBanEntry(profile, entry, this.list);
}
- public BanEntry<PlayerProfile> addBan(GameProfile profile, String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(GameProfile profile, String reason, Date expires, String source) { // Paper
if (profile == null) {
return null;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 722c69e0149a9bf35159a7ffbb338fbc42600f0e..1c6fdad145d81a25ccd2b1193ebe4b5ad96bfb9c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1733,23 +1733,23 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper - fix ban list API
return this.ban(reason, expires, source, true);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Instant expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant expires, String source) { // Paper - fix ban list API
return this.ban(reason, expires != null ? Date.from(expires) : null, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source) { // Paper - fix ban list API
return this.ban(reason, duration != null ? Instant.now().plus(duration) : null, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) {
- BanEntry<PlayerProfile> banEntry = ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) { // Paper - fix ban list API
+ BanEntry<com.destroystokyo.paper.profile.PlayerProfile> banEntry = ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source); // Paper - fix ban list API
if (kickPlayer) {
this.kickPlayer(reason);
}
@@ -1757,12 +1757,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Instant instant, String source, boolean kickPlayer) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant instant, String source, boolean kickPlayer) { // Paper - fix ban list API
return this.ban(reason, instant != null ? Date.from(instant) : null, source, kickPlayer);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source, boolean kickPlayer) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source, boolean kickPlayer) { // Paper - fix ban list API
return this.ban(reason, duration != null ? Instant.now().plus(duration) : null, source, kickPlayer);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
index 6f779c6f4422c5b5dc22f66e3e702c714d0e052b..41336821d4e0430e19f2fc021f09430d7a1302f6 100644
--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
+++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
@@ -28,7 +28,7 @@ import org.bukkit.profile.PlayerProfile;
import org.bukkit.profile.PlayerTextures;
@SerializableAs("PlayerProfile")
-public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile { // Paper
+public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile, com.destroystokyo.paper.profile.PlayerProfile { // Paper
@Nonnull
public static GameProfile validateSkullProfile(@Nonnull GameProfile gameProfile) {
@@ -123,7 +123,7 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
}
@Override
- public CompletableFuture<PlayerProfile> update() {
+ public CompletableFuture update() { // Paper - have to remove generic to avoid clashing between bukkit.PlayerProfile and paper.PlayerProfile
return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.PROFILE_EXECUTOR); // Paper - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
}
@@ -277,4 +277,71 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
// Paper - diff on change
return profile;
}
+
+ // Paper start - This must implement our PlayerProfile so generic casts succeed from cb.CraftPlayerProfile to paper.PlayerProfile
+ // The methods don't actually have to be implemented, because the profile should immediately be cast to SharedPlayerProfile
+ @Override
+ public String setName(final String name) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public UUID getId() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public UUID setId(final UUID uuid) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public java.util.Set<com.destroystokyo.paper.profile.ProfileProperty> getProperties() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean hasProperty(final String property) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public void setProperty(final com.destroystokyo.paper.profile.ProfileProperty property) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public void setProperties(final java.util.Collection<com.destroystokyo.paper.profile.ProfileProperty> properties) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public void clearProperties() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean completeFromCache() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean completeFromCache(final boolean onlineMode) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean completeFromCache(final boolean lookupUUID, final boolean onlineMode) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean complete(final boolean textures) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean complete(final boolean textures, final boolean onlineMode) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
}

View file

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: galacticwarrior9 <zareef1@yahoo.com>
Date: Thu, 13 Jul 2023 21:32:13 +0100
Subject: [PATCH] Determine lava and water fluid explosion resistance by their
block explosion resistance
When selecting which explosion resistance to use for lava and water, vanilla selects the highest value between their block explosion resistance and fluid explosion resistance.
Problems emerge when we want to reduce the explosion resistance of water or lava, since the fluid explosion resistance is hardcoded to return 100.0F and can't be changed by a plugin. This simply makes the fluid explosion resistance the same as the block explosion resistance, which allows plugin to change the value. Since both are the same in vanilla, this has no side effects on servers that do not need to do this.
diff --git a/src/main/java/net/minecraft/world/level/material/LavaFluid.java b/src/main/java/net/minecraft/world/level/material/LavaFluid.java
index 72f8b72c6436ca3b8eaeb39c7d3efe2c1462ae1d..3bb4a9a1a6249e8ba2de237f801210e7f4fd5825 100644
--- a/src/main/java/net/minecraft/world/level/material/LavaFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/LavaFluid.java
@@ -232,7 +232,7 @@ public abstract class LavaFluid extends FlowingFluid {
@Override
protected float getExplosionResistance() {
- return 100.0F;
+ return Blocks.LAVA.getExplosionResistance(); // Paper - Get explosion resistance from actual block
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/material/WaterFluid.java b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
index 21b4afd053e01073eb514264d4960f0f3b1ee3d8..109f71401c65f476ccf6813137386fc9fef10254 100644
--- a/src/main/java/net/minecraft/world/level/material/WaterFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
@@ -125,7 +125,7 @@ public abstract class WaterFluid extends FlowingFluid {
@Override
protected float getExplosionResistance() {
- return 100.0F;
+ return Blocks.WATER.getExplosionResistance(); // Paper - Get explosion resistance from actual block
}
@Override

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 24 Jun 2023 09:42:53 -0700
Subject: [PATCH] Fix possible NPE on painting creation
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 7ba6302ecb72fa6e523054e7e3223d79eedf6589..63f9852de5b557351793ba3aebdd7e752caf2417 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -325,8 +325,13 @@ public final class CraftEntityTypes {
// Hanging
register(new EntityTypeData<>(EntityType.PAINTING, Painting.class, CraftPainting::new, createHanging(Painting.class, (spawnData, hangingData) -> {
if (spawnData.normalWorld && hangingData.randomize()) {
- return net.minecraft.world.entity.decoration.Painting.create(spawnData.minecraftWorld(), hangingData.position(), hangingData.direction()).orElse(null);
- } else {
+ // Paper start - if randomizeData fails, force it
+ final net.minecraft.world.entity.decoration.Painting entity = net.minecraft.world.entity.decoration.Painting.create(spawnData.minecraftWorld(), hangingData.position(), hangingData.direction()).orElse(null);
+ if (entity != null) {
+ return entity;
+ }
+ } /*else*/ {
+ // Paper end - if randomizeData fails, force it
net.minecraft.world.entity.decoration.Painting entity = new net.minecraft.world.entity.decoration.Painting(net.minecraft.world.entity.EntityType.PAINTING, spawnData.minecraftWorld());
entity.absMoveTo(spawnData.x(), spawnData.y(), spawnData.z(), spawnData.yaw(), spawnData.pitch());
entity.setDirection(hangingData.direction());
@@ -465,6 +470,7 @@ public final class CraftEntityTypes {
AABB bb = (ItemFrame.class.isAssignableFrom(clazz))
? net.minecraft.world.entity.decoration.ItemFrame.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).getOpposite(), width, height)
: HangingEntity.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).getOpposite(), width, height);
+ if (!spawnData.world.noCollision(bb)) continue; // Paper - add collision check
List<net.minecraft.world.entity.Entity> list = spawnData.world().getEntities(null, bb);
for (Iterator<net.minecraft.world.entity.Entity> it = list.iterator(); !taken && it.hasNext(); ) {
net.minecraft.world.entity.Entity e = it.next();

View file

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Fri, 19 Mar 2021 16:07:21 -0700
Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by
WanderingTraderSpawner
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
index 63189d6325173a42b619907b44a426848fbc6988..0854e9b7ee2e6b23b6c1ee6a324a5a253c9d4679 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
@@ -68,7 +68,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
public WanderingTrader(EntityType<? extends WanderingTrader> type, Level world) {
super(type, world);
- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader
+ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set.
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
index d5d27b0d352ca3fd57a26605cb35c499e88b57fc..f4cdb97ed6c0850da980760c0c2df69480485940 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
@@ -120,7 +120,7 @@ public class WanderingTraderSpawner implements CustomSpawner {
return false;
}
- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(world, blockposition2, MobSpawnType.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
+ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(world, null, trader -> trader.setDespawnDelay(48000), blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit // Paper - set despawnTimer before spawn events called
if (entityvillagertrader != null) {
for (int i = 0; i < 2; ++i) {

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Golfing8 <atroo@me.com>
Date: Mon, 8 May 2023 09:18:17 -0400
Subject: [PATCH] ExperienceOrb should call EntitySpawnEvent
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 27bafd5349805171399dbd141f5c568ec35286f4..5af62603415865068ca4b79a7e68d8eb813596b1 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -735,7 +735,8 @@ public class CraftEventFactory {
// Spigot start - SPIGOT-7523: Merge after spawn event and only merge if the event was not cancelled (gets checked above)
if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) {
double radius = world.spigotConfig.expMerge;
- if (radius > 0) {
+ event = CraftEventFactory.callEntitySpawnEvent(entity); // Call spawn event for ExperienceOrb entities
+ if (radius > 0 && !event.isCancelled() && !entity.isRemoved()) {
// Paper start - Maximum exp value when merging; Whole section has been tweaked, see comments for specifics
final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue;
final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0;

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jacob Litewski <jacob.litewski@gmail.com>
Date: Tue, 13 Jun 2023 19:16:39 -0400
Subject: [PATCH] Make Amethyst throw both Spread and Grow Events
diff --git a/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java b/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java
index 6c402bfd9bed54cbb9b337d3528fdcffbd3d87c0..8920855b07a31715327b8102c7faafc9f916825d 100644
--- a/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java
@@ -45,7 +45,13 @@ public class BuddingAmethystBlock extends AmethystBlock {
if (block != null) {
BlockState iblockdata2 = (BlockState) ((BlockState) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == Fluids.WATER);
+ // Paper start - Have Amethyst throw both spread and grow events
+ if (block == Blocks.SMALL_AMETHYST_BUD) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, iblockdata2); // CraftBukkit
+ } else {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, blockposition1, iblockdata2);
+ }
+ // Paper end - Have Amethyst throw both spread and grow events
}
}

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Sun, 14 May 2023 12:57:15 +0200
Subject: [PATCH] Add whitelist events
diff --git a/src/main/java/net/minecraft/server/players/UserWhiteList.java b/src/main/java/net/minecraft/server/players/UserWhiteList.java
index 3226a3b69453fb5e13003e941ccbc2d941e047b0..aaa3d5769e0e184e19d01109a76a65be634f830d 100644
--- a/src/main/java/net/minecraft/server/players/UserWhiteList.java
+++ b/src/main/java/net/minecraft/server/players/UserWhiteList.java
@@ -28,4 +28,23 @@ public class UserWhiteList extends StoredUserList<GameProfile, UserWhiteListEntr
protected String getKeyForUser(GameProfile gameProfile) {
return gameProfile.getId().toString();
}
+ // Paper start - Add whitelist events
+ @Override
+ public void add(UserWhiteListEntry entry) {
+ if (!new io.papermc.paper.event.server.WhitelistStateUpdateEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(entry.getUser()), io.papermc.paper.event.server.WhitelistStateUpdateEvent.WhitelistStatus.ADDED).callEvent()) {
+ return;
+ }
+
+ super.add(entry);
+ }
+
+ @Override
+ public void remove(GameProfile profile) {
+ if (!new io.papermc.paper.event.server.WhitelistStateUpdateEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(profile), io.papermc.paper.event.server.WhitelistStateUpdateEvent.WhitelistStatus.REMOVED).callEvent()) {
+ return;
+ }
+
+ super.remove(profile);
+ }
+ // Paper end - Add whitelist events
}

View file

@ -0,0 +1,111 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Moulberry <james.jenour@protonmail.com>
Date: Wed, 26 Jul 2023 20:13:31 +0800
Subject: [PATCH] Implement PlayerFailMoveEvent
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 1a0245c798107d2d4239e07262f5cc89490a3b08..8085e59bf16d3a5c85bd9d328126f226c026f163 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1272,8 +1272,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
double d0 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX(this.player.getX())); final double toX = d0; // Paper - OBFHELPER
double d1 = ServerGamePacketListenerImpl.clampVertical(packet.getY(this.player.getY())); final double toY = d1; // Paper - OBFHELPER
double d2 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ(this.player.getZ())); final double toZ = d2; // Paper - OBFHELPER
- float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot()));
- float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot()));
+ float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot())); final float toYaw = f; // Paper - OBFHELPER
+ float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot())); final float toPitch = f1; // Paper - OBFHELPER
if (this.player.isPassenger()) {
this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1);
@@ -1340,8 +1340,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
// Paper start - Prevent moving into unloaded chunks
if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position())))) {
- this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet());
- return;
+ // Paper start - Add fail move event
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_INTO_UNLOADED_CHUNK,
+ toX, toY, toZ, toYaw, toPitch, false);
+ if (!event.isAllowed()) {
+ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet());
+ return;
+ }
+ // Paper end - Add fail move event
}
// Paper end - Prevent moving into unloaded chunks
@@ -1350,9 +1356,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
if (d10 - d9 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
// CraftBukkit end
- ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8});
- this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
- return;
+ // Paper start - Add fail move event
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
+ toX, toY, toZ, toYaw, toPitch, true);
+ if (!event.isAllowed()) {
+ if (event.getLogWarning())
+ ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8});
+ this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
+ return;
+ }
+ // Paper end - Add fail move event
}
}
}
@@ -1414,14 +1427,31 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
d8 = d2 - this.player.getZ();
d10 = d6 * d6 + d7 * d7 + d8 * d8;
- boolean flag3 = false;
+ boolean movedWrongly = false; // Paper - Add fail move event; rename
if (!this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
- flag3 = true;
+ // Paper start - Add fail move event
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY,
+ toX, toY, toZ, toYaw, toPitch, true);
+ if (!event.isAllowed()) {
+ movedWrongly = true;
+ if (event.getLogWarning())
+ // Paper end
ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
+ } // Paper
}
- if (!this.player.noPhysics && !this.player.isSleeping() && (flag3 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) {
+ // Paper start - Add fail move event
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2));
+ if (teleportBack) {
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
+ toX, toY, toZ, toYaw, toPitch, false);
+ if (event.isAllowed()) {
+ teleportBack = false;
+ }
+ }
+ if (teleportBack) {
+ // Paper end - Add fail move event
this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet.
this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround());
} else {
@@ -3456,4 +3486,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
}
+
+ // Paper start - Add fail move event
+ private io.papermc.paper.event.player.PlayerFailMoveEvent fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason failReason,
+ double toX, double toY, double toZ, float toYaw, float toPitch, boolean logWarning) {
+ Player player = this.getCraftPlayer();
+ Location from = new Location(player.getWorld(), this.lastPosX, this.lastPosY, this.lastPosZ, this.lastYaw, this.lastPitch);
+ Location to = new Location(player.getWorld(), toX, toY, toZ, toYaw, toPitch);
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = new io.papermc.paper.event.player.PlayerFailMoveEvent(player, failReason,
+ false, logWarning, from, to);
+ event.callEvent();
+ return event;
+ }
+ // Paper end - Add fail move event
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <lynxplay101@gmail.com>
Date: Fri, 4 Aug 2023 15:53:36 +0200
Subject: [PATCH] Only erase allay memory on non-item targets
Spigot incorrectly instanceOf checks the EntityTargetEvent#getTarget
against the internal ItemEntity type and removes the nearest wanted item
memory if said instanceOf check fails, (which is always the case)
causing allays to behave differently as they constantly loose their
target item.
This commit fixes the faulty behaviour by instance performing a check
against the CraftItem type.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
index bd9aa4a5443da862be3403c1941113373741a87c..2f92eb39cde7b30a894db347ca85a506d880411e 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
@@ -35,8 +35,9 @@ public class GoToWantedItem {
if (event.isCancelled()) {
return false;
}
- if (!(event.getTarget() instanceof ItemEntity)) {
+ if (!(event.getTarget() instanceof org.bukkit.craftbukkit.entity.CraftItem)) { // Paper - only erase allay memory on non-item targets
memoryaccessor2.erase();
+ return false; // Paper - only erase allay memory on non-item targets
}
entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle();

View file

@ -0,0 +1,114 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 21 Aug 2021 17:25:38 -0700
Subject: [PATCH] API for updating recipes on clients
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index b00da578cb4ba037a540584738b3f866acfa9f88..2f62af670441d422133b18d00d9e5e5e58e4afe7 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1530,6 +1530,13 @@ public abstract class PlayerList {
}
public void reloadResources() {
+ // Paper start - API for updating recipes on clients
+ this.reloadAdvancementData();
+ this.reloadTagData();
+ this.reloadRecipeData();
+ }
+ public void reloadAdvancementData() {
+ // Paper end - API for updating recipes on clients
// CraftBukkit start
/*Iterator iterator = this.advancements.values().iterator();
@@ -1545,7 +1552,15 @@ public abstract class PlayerList {
}
// CraftBukkit end
+ // Paper start - API for updating recipes on clients
+ }
+ public void reloadTagData() {
+ // Paper end - API for updating recipes on clients
this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries)));
+ // Paper start - API for updating recipes on clients
+ }
+ public void reloadRecipeData() {
+ // Paper end - API for updating recipes on clients
ClientboundUpdateRecipesPacket packetplayoutrecipeupdate = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getOrderedRecipes());
Iterator iterator1 = this.players.iterator();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 233dc26b6698887e5b2ab179a67364eca389ed86..810ffd7cd1a8a7facc63e10e9eb5fed0504737e3 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1142,6 +1142,18 @@ public final class CraftServer implements Server {
ReloadCommand.reload(this.console);
}
+ // Paper start - API for updating recipes on clients
+ @Override
+ public void updateResources() {
+ this.playerList.reloadResources();
+ }
+
+ @Override
+ public void updateRecipes() {
+ this.playerList.reloadRecipeData();
+ }
+ // Paper end - API for updating recipes on clients
+
private void loadIcon() {
this.icon = new CraftIconCache(null);
try {
@@ -1529,6 +1541,13 @@ public final class CraftServer implements Server {
@Override
public boolean addRecipe(Recipe recipe) {
+ // Paper start - API for updating recipes on clients
+ return this.addRecipe(recipe, false);
+ }
+
+ @Override
+ public boolean addRecipe(Recipe recipe, boolean resendRecipes) {
+ // Paper end - API for updating recipes on clients
CraftRecipe toAdd;
if (recipe instanceof CraftRecipe) {
toAdd = (CraftRecipe) recipe;
@@ -1558,6 +1577,11 @@ public final class CraftServer implements Server {
}
}
toAdd.addToCraftingManager();
+ // Paper start - API for updating recipes on clients
+ if (resendRecipes) {
+ this.playerList.reloadRecipeData();
+ }
+ // Paper end - API for updating recipes on clients
return true;
}
@@ -1738,10 +1762,23 @@ public final class CraftServer implements Server {
@Override
public boolean removeRecipe(NamespacedKey recipeKey) {
+ // Paper start - API for updating recipes on clients
+ return this.removeRecipe(recipeKey, false);
+ }
+
+ @Override
+ public boolean removeRecipe(NamespacedKey recipeKey, boolean resendRecipes) {
+ // Paper end - API for updating recipes on clients
Preconditions.checkArgument(recipeKey != null, "recipeKey == null");
ResourceLocation mcKey = CraftNamespacedKey.toMinecraft(recipeKey);
- return this.getServer().getRecipeManager().removeRecipe(mcKey);
+ // Paper start - resend recipes on successful removal
+ boolean removed = this.getServer().getRecipeManager().removeRecipe(mcKey);
+ if (removed && resendRecipes) {
+ this.playerList.reloadRecipeData();
+ }
+ return removed;
+ // Paper end
}
@Override

View file

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Gameoholic <viner.atmic@gmail.com>
Date: Sun, 30 Jul 2023 13:30:34 +0300
Subject: [PATCH] Fix rotation when spawning display entities
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 63f9852de5b557351793ba3aebdd7e752caf2417..2c44056065b75efecdf7bc835d1e899d1b50ccfe 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -220,6 +220,7 @@ public final class CraftEntityTypes {
Vector direction = spawnData.location().getDirection().multiply(10);
entity.assignPower(direction.getX(), direction.getY(), direction.getZ());
};
+ private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> ROT = (spawnData, entity) -> entity.setRot(spawnData.yaw(), spawnData.pitch()); // Paper
private static final Map<Class<?>, EntityTypeData<?, ?>> CLASS_TYPE_DATA = new HashMap<>();
private static final Map<EntityType, EntityTypeData<?, ?>> ENTITY_TYPE_DATA = new HashMap<>();
@@ -360,10 +361,10 @@ public final class CraftEntityTypes {
// Set pos
register(new EntityTypeData<>(EntityType.MARKER, Marker.class, CraftMarker::new, createAndSetPos(net.minecraft.world.entity.EntityType.MARKER)));
- register(new EntityTypeData<>(EntityType.BLOCK_DISPLAY, BlockDisplay.class, CraftBlockDisplay::new, createAndSetPos(net.minecraft.world.entity.EntityType.BLOCK_DISPLAY)));
+ register(new EntityTypeData<>(EntityType.BLOCK_DISPLAY, BlockDisplay.class, CraftBlockDisplay::new, combine(createAndSetPos(net.minecraft.world.entity.EntityType.BLOCK_DISPLAY), ROT))); // Paper
register(new EntityTypeData<>(EntityType.INTERACTION, Interaction.class, CraftInteraction::new, createAndSetPos(net.minecraft.world.entity.EntityType.INTERACTION)));
- register(new EntityTypeData<>(EntityType.ITEM_DISPLAY, ItemDisplay.class, CraftItemDisplay::new, createAndSetPos(net.minecraft.world.entity.EntityType.ITEM_DISPLAY)));
- register(new EntityTypeData<>(EntityType.TEXT_DISPLAY, TextDisplay.class, CraftTextDisplay::new, createAndSetPos(net.minecraft.world.entity.EntityType.TEXT_DISPLAY)));
+ register(new EntityTypeData<>(EntityType.ITEM_DISPLAY, ItemDisplay.class, CraftItemDisplay::new, combine(createAndSetPos(net.minecraft.world.entity.EntityType.ITEM_DISPLAY), ROT))); // Paper
+ register(new EntityTypeData<>(EntityType.TEXT_DISPLAY, TextDisplay.class, CraftTextDisplay::new, combine(createAndSetPos(net.minecraft.world.entity.EntityType.TEXT_DISPLAY), ROT))); // Paper
// MISC
register(new EntityTypeData<>(EntityType.ITEM, Item.class, CraftItem::new, spawnData -> {

View file

@ -0,0 +1,73 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 21 Aug 2021 18:53:03 -0700
Subject: [PATCH] Only capture actual tree growth
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 5bbadc890a72f1cb22c6881ebcc163b0c06a367a..4fa838bf97ede6e1c893ba64f53aa7af5db0405a 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -654,6 +654,7 @@ public interface DispenseItemBehavior {
if (!fertilizeEvent.isCancelled()) {
for (org.bukkit.block.BlockState blockstate : blocks) {
blockstate.update(true);
+ worldserver.checkCapturedTreeStateForObserverNotify(blockposition, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
}
}
}
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 31f67c83416031079569375e5f69738dd639b93f..789740cadc1b66531b465bb0a052e2392852c4a8 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -437,6 +437,7 @@ public final class ItemStack implements DataComponentHolder {
for (CraftBlockState blockstate : blocks) {
// SPIGOT-7572 - Move fix for SPIGOT-7248 to CapturedBlockState, to allow bees in bee nest
CapturedBlockState.setBlockState(blockstate);
+ world.checkCapturedTreeStateForObserverNotify(blockposition, blockstate); // Paper - notify observers even if grow failed
}
entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 19a177041e6e9621b0e35ca4f4ceb79b72448680..f3486d042a592cb538c5e8f681673a0c2c45ffd9 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1366,4 +1366,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return range <= 0 ? 64.0 * 64.0 : range * range; // 64 is taken from default in ServerLevel#levelEvent
}
// Paper end - respect global sound events gamerule
+ // Paper start - notify observers even if grow failed
+ public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
+ // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
+ // blocks at the same Y level with the same state can be assumed to be saplings which trigger observers regardless of if the
+ // tree grew or not
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) {
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
+ }
+ }
+ // Paper end - notify observers even if grow failed
}
diff --git a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
index 2d7290ace5fc8890325a8ec623075ad32f9b1d44..d262a5a6da57ef9ba9a6fe0dfbc88f577105e74f 100644
--- a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
@@ -86,6 +86,7 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock {
if (event == null || !event.isCancelled()) {
for (BlockState blockstate : blocks) {
CapturedBlockState.setBlockState(blockstate);
+ world.checkCapturedTreeStateForObserverNotify(pos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
}
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index af219df5267589300f0ad1d30fa5c81a1f50234f..461a66c323a74db5a70981fafc5fa20f54f0f40d 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -572,6 +572,7 @@ public class CraftBlock implements Block {
if (!event.isCancelled()) {
for (BlockState blockstate : blocks) {
blockstate.update(true);
+ world.checkCapturedTreeStateForObserverNotify(this.position, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
}
}
}

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Tue, 8 Aug 2023 11:49:32 +0200
Subject: [PATCH] Use correct source for mushroom block spread event
diff --git a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java
index f549cac99a665f20f1cd1d8c807ed3649fed7531..1172d85c5c26ab2142343d91149766e5993cb36a 100644
--- a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java
@@ -68,6 +68,7 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock {
}
BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
+ final BlockPos sourcePos = pos; // Paper - Use correct source for mushroom block spread event
for (int j = 0; j < 4; ++j) {
if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
@@ -78,7 +79,7 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock {
}
if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition2, state, 2); // CraftBukkit
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, sourcePos, blockposition2, state, 2); // CraftBukkit // Paper - Use correct source for mushroom block spread event
}
}

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 13 Jul 2023 16:10:07 -0700
Subject: [PATCH] Respect randomizeData on more entities when spawning
* ItemEntity
* PrimedTNT
* FireworkRocketEntity
* ExperienceOrb
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 2c44056065b75efecdf7bc835d1e899d1b50ccfe..405caaff1459d8928f91be0fc85213b80ee8b8af 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -221,6 +221,13 @@ public final class CraftEntityTypes {
entity.assignPower(direction.getX(), direction.getY(), direction.getZ());
};
private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> ROT = (spawnData, entity) -> entity.setRot(spawnData.yaw(), spawnData.pitch()); // Paper
+ // Paper start - respect randomizeData
+ private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> CLEAR_MOVE_IF_NOT_RANDOMIZED = (spawnData, entity) -> {
+ if (!spawnData.randomizeData()) {
+ entity.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO);
+ }
+ };
+ // Paper end - respect randomizeData
private static final Map<Class<?>, EntityTypeData<?, ?>> CLASS_TYPE_DATA = new HashMap<>();
private static final Map<EntityType, EntityTypeData<?, ?>> ENTITY_TYPE_DATA = new HashMap<>();
@@ -373,11 +380,12 @@ public final class CraftEntityTypes {
net.minecraft.world.item.ItemStack itemStack = new net.minecraft.world.item.ItemStack(Items.STONE);
ItemEntity item = new ItemEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), itemStack);
item.setPickUpDelay(10);
+ CLEAR_MOVE_IF_NOT_RANDOMIZED.accept(spawnData, item); // Paper - respect randomizeData
return item;
}));
register(new EntityTypeData<>(EntityType.EXPERIENCE_ORB, ExperienceOrb.class, CraftExperienceOrb::new,
- spawnData -> new net.minecraft.world.entity.ExperienceOrb(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null) // Paper
+ combine(combine(spawnData -> new net.minecraft.world.entity.ExperienceOrb(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null), CLEAR_MOVE_IF_NOT_RANDOMIZED), (spawnData, experienceOrb) -> { if (!spawnData.randomizeData()) { experienceOrb.setYRot(0); } }) // Paper - respect randomizeData
));
register(new EntityTypeData<>(EntityType.AREA_EFFECT_CLOUD, AreaEffectCloud.class, CraftAreaEffectCloud::new, createAndMove(net.minecraft.world.entity.EntityType.AREA_EFFECT_CLOUD))); // Paper - set area effect cloud rotation
register(new EntityTypeData<>(EntityType.EGG, Egg.class, CraftEgg::new, spawnData -> new ThrownEgg(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));
@@ -389,12 +397,23 @@ public final class CraftEntityTypes {
entity.setItem(CraftItemStack.asNMSCopy(new ItemStack(Material.SPLASH_POTION, 1)));
return entity;
}));
- register(new EntityTypeData<>(EntityType.TNT, TNTPrimed.class, CraftTNTPrimed::new, spawnData -> new PrimedTnt(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), null)));
+ register(new EntityTypeData<>(EntityType.TNT, TNTPrimed.class, CraftTNTPrimed::new, combine(spawnData -> new PrimedTnt(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), null), CLEAR_MOVE_IF_NOT_RANDOMIZED))); // Paper - respect randomizeData
register(new EntityTypeData<>(EntityType.FALLING_BLOCK, FallingBlock.class, CraftFallingBlock::new, spawnData -> {
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
}));
- register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), net.minecraft.world.item.ItemStack.EMPTY)));
+ // Paper start - respect randomizeData
+ register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> {
+ FireworkRocketEntity entity = new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), net.minecraft.world.item.ItemStack.EMPTY);
+ if (!spawnData.randomizeData()) {
+ // logic below was taken from FireworkRocketEntity constructor
+ entity.setDeltaMovement(0, 0.05, 0);
+ //noinspection PointlessArithmeticExpression
+ entity.lifetime = 10 * 1 + 6;
+ }
+ return entity;
+ }));
+ // Paper end - respect randomizeData
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
register(new EntityTypeData<>(EntityType.COMMAND_BLOCK_MINECART, CommandMinecart.class, CraftMinecartCommand::new, spawnData -> new MinecartCommandBlock(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));
register(new EntityTypeData<>(EntityType.MINECART, RideableMinecart.class, CraftMinecartRideable::new, spawnData -> new Minecart(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Florian Schmidt <florian@f012.dev>
Date: Fri, 28 Jul 2023 14:14:35 +0200
Subject: [PATCH] Use correct seed on api world load
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 810ffd7cd1a8a7facc63e10e9eb5fed0504737e3..0daa352795a6533289370388c9c75c98c82396ca 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1364,7 +1364,7 @@ public final class CraftServer implements Server {
net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), this.console.options.has("eraseCache"), () -> true, iregistrycustom_dimension, this.console.options.has("recreateRegionFiles"));
}
- long j = BiomeManager.obfuscateSeed(creator.seed());
+ long j = BiomeManager.obfuscateSeed(worlddata.worldGenOptions().seed()); // Paper - use world seed
List<CustomSpawner> list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata));
LevelStem worlddimension = iregistry.get(actualDimension);

View file

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Wed, 9 Aug 2023 14:00:40 -0700
Subject: [PATCH] Remove UpgradeData neighbour ticks outside of range
The lists are only supposed to contain ticks for the 1 radius
neighbours of the chunk.
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 bfb73e016f107fb8da12903bf233a824d062ed73..22b6d0851a51da180cd8fbbe6554c5370f5ac5bd 100644
--- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
+++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
@@ -100,6 +100,25 @@ public class UpgradeData {
}
}
+ // Paper start - filter out relocated neighbour ticks
+ // The lists are only supposed to contain ticks for the 1 radius neighbours of the chunk
+ private static <T> void filterTickList(int chunkX, int chunkZ, List<SavedTick<T>> ticks) {
+ for (java.util.Iterator<SavedTick<T>> iterator = ticks.iterator(); iterator.hasNext();) {
+ SavedTick<T> tick = iterator.next();
+ BlockPos tickPos = tick.pos();
+ int tickCX = tickPos.getX() >> 4;
+ int tickCZ = tickPos.getZ() >> 4;
+
+ int dist = Math.max(Math.abs(chunkX - tickCX), Math.abs(chunkZ - tickCZ));
+
+ if (dist != 1) {
+ LOGGER.warn("Neighbour tick '" + tick + "' serialized in chunk (" + chunkX + "," + chunkZ + ") is too far (" + tickCX + "," + tickCZ + ")");
+ iterator.remove();
+ }
+ }
+ }
+ // Paper end - filter out relocated neighbour ticks
+
public void upgrade(LevelChunk chunk) {
this.upgradeInside(chunk);
@@ -107,6 +126,11 @@ public class UpgradeData {
upgradeSides(chunk, direction8);
}
+ // Paper start - filter out relocated neighbour ticks
+ filterTickList(chunk.locX, chunk.locZ, this.neighborBlockTicks);
+ filterTickList(chunk.locX, chunk.locZ, this.neighborFluidTicks);
+ // Paper end - filter out relocated neighbour ticks
+
Level level = chunk.getLevel();
this.neighborBlockTicks.forEach(tick -> {
Block block = tick.type() == Blocks.AIR ? level.getBlockState(tick.pos()).getBlock() : tick.type();

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Mon, 7 Aug 2023 12:58:28 +0200
Subject: [PATCH] Cache map ids on item frames
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index b195de05371e9762654b69365f0e722443425d33..fbb138aefe19237aeeba2f5fc8070bf81e289dc3 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -118,7 +118,7 @@ public class ServerEntity {
ItemStack itemstack = entityitemframe.getItem();
if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable
- MapId mapid = (MapId) itemstack.get(DataComponents.MAP_ID);
+ Integer integer = entityitemframe.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData worldmap = MapItem.getSavedData(mapid, this.level);
if (worldmap != null) {
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
index 6bf89686ce5cf700ac06ec1e38f53af745098fa3..3f35e16a91b3cf360a3b8a69ee495aaca9210e13 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -49,6 +49,7 @@ public class ItemFrame extends HangingEntity {
public static final int NUM_ROTATIONS = 8;
public float dropChance;
public boolean fixed;
+ public Integer cachedMapId; // Paper - Perf: Cache map ids on item frames
public ItemFrame(EntityType<? extends ItemFrame> type, Level world) {
super(type, world);
@@ -364,6 +365,7 @@ public class ItemFrame extends HangingEntity {
}
private void onItemChanged(ItemStack stack) {
+ this.cachedMapId = MapItem.getMapId(stack); // Paper - Perf: Cache map ids on item frames
if (!stack.isEmpty() && stack.getFrame() != this) {
stack.setEntityRepresentation(this);
}

View file

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Sat, 12 Aug 2023 15:33:49 +0200
Subject: [PATCH] Fix custom statistic criteria creation
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index b2755299789dea3bcc49e66d3647a6e8a5080b4d..9ed12c6f896470f140f9ed4bdc565d2b4edda1eb 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -635,6 +635,12 @@ public final class CraftMagicNumbers implements UnsafeValues {
net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> biomeBase = cra.getHandle().registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME).getHolderOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.BIOME, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(biomeKey)));
cra.setBiome(x, y, z, biomeBase);
}
+
+ @Override
+ public String getStatisticCriteriaKey(org.bukkit.Statistic statistic) {
+ if (statistic.getType() != org.bukkit.Statistic.Type.UNTYPED) return "minecraft.custom:minecraft." + statistic.getKey().getKey();
+ return org.bukkit.craftbukkit.CraftStatistic.getNMSStatistic(statistic).getName();
+ }
// Paper end
/**

View file

@ -0,0 +1,149 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 28 Jul 2023 15:02:44 -0700
Subject: [PATCH] Bandaid fix for Effect
Effect or LevelEvent needs to be replaced
but ideally after the enum PR has been merged
upstream. Until then, this test and these fixes
should address all the known issues with them
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftEffect.java b/src/main/java/org/bukkit/craftbukkit/CraftEffect.java
index 71733f918ed84b9879ac1b142ef6205c5e768a9c..7ee13c0a0cd12979c7f8cc2e403baf9300fd61c8 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftEffect.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftEffect.java
@@ -15,6 +15,8 @@ public class CraftEffect {
public static <T> int getDataValue(Effect effect, T data) {
int datavalue;
switch (effect) {
+ case PARTICLES_SCULK_CHARGE: // Paper - add missing effects
+ case TRIAL_SPAWNER_DETECT_PLAYER: // Paper - add missing effects
case VILLAGER_PLANT_GROW:
datavalue = (Integer) data;
break;
@@ -26,6 +28,13 @@ public class CraftEffect {
Preconditions.checkArgument(data == Material.AIR || ((Material) data).isRecord(), "Invalid record type for Material %s!", data);
datavalue = Item.getId(CraftItemType.bukkitToMinecraft((Material) data));
break;
+ // Paper start - handle shoot white smoke event
+ case SHOOT_WHITE_SMOKE:
+ final BlockFace face = (BlockFace) data;
+ Preconditions.checkArgument(face.isCartesian(), face + " isn't cartesian");
+ datavalue = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(face).get3DDataValue();
+ break;
+ // Paper end - handle shoot white smoke event
case SMOKE:
switch ((BlockFace) data) {
case DOWN:
@@ -57,8 +66,15 @@ public class CraftEffect {
}
break;
case STEP_SOUND:
+ if (data instanceof Material) { // Paper - support BlockData
Preconditions.checkArgument(((Material) data).isBlock(), "Material %s is not a block!", data);
datavalue = Block.getId(CraftBlockType.bukkitToMinecraft((Material) data).defaultBlockState());
+ // Paper start - support BlockData
+ break;
+ }
+ case PARTICLES_AND_SOUND_BRUSH_BLOCK_COMPLETE:
+ datavalue = Block.getId(((org.bukkit.craftbukkit.block.data.CraftBlockData) data).getState());
+ // Paper end
break;
case COMPOSTER_FILL_ATTEMPT:
datavalue = ((Boolean) data) ? 1 : 0;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 6231bc770ea6eb6aba47abbc74b6380fd9360d8c..81e5768f556628f3f37dc8091193c0a1b853f1da 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1400,7 +1400,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public <T> void playEffect(Location loc, Effect effect, T data, int radius) {
if (data != null) {
Preconditions.checkArgument(effect.getData() != null, "Effect.%s does not have a valid Data", effect);
- Preconditions.checkArgument(effect.getData().isAssignableFrom(data.getClass()), "%s data cannot be used for the %s effect", data.getClass().getName(), effect);
+ Preconditions.checkArgument(effect.isApplicable(data), "%s data cannot be used for the %s effect", data.getClass().getName(), effect); // Paper
} else {
// Special case: the axis is optional for ELECTRIC_SPARK
Preconditions.checkArgument(effect.getData() == null || effect == Effect.ELECTRIC_SPARK, "Wrong kind of data for the %s effect", effect);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 1c6fdad145d81a25ccd2b1193ebe4b5ad96bfb9c..0fe81e58541dbc46ac493897aa190ebf9ddbc805 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -914,7 +914,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
Preconditions.checkArgument(effect != null, "Effect cannot be null");
if (data != null) {
Preconditions.checkArgument(effect.getData() != null, "Effect.%s does not have a valid Data", effect);
- Preconditions.checkArgument(effect.getData().isAssignableFrom(data.getClass()), "%s data cannot be used for the %s effect", data.getClass().getName(), effect);
+ Preconditions.checkArgument(effect.isApplicable(data), "%s data cannot be used for the %s effect", data.getClass().getName(), effect); // Paper
} else {
// Special case: the axis is optional for ELECTRIC_SPARK
Preconditions.checkArgument(effect.getData() == null || effect == Effect.ELECTRIC_SPARK, "Wrong kind of data for the %s effect", effect);
diff --git a/src/test/java/org/bukkit/EffectTest.java b/src/test/java/org/bukkit/EffectTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..875eacc2e5776901ba8593d0183844db2571f71b
--- /dev/null
+++ b/src/test/java/org/bukkit/EffectTest.java
@@ -0,0 +1,64 @@
+package org.bukkit;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import net.minecraft.world.level.block.LevelEvent;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class EffectTest {
+
+ private static List<Integer> collectNmsLevelEvents() throws ReflectiveOperationException {
+ final List<Integer> events = new ArrayList<>();
+ for (final Field field : LevelEvent.class.getFields()) {
+ if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) && field.getType() == int.class) {
+ events.add((int) field.get(null));
+ }
+ }
+ return events;
+ }
+
+ private static boolean isNotDeprecated(Effect effect) throws ReflectiveOperationException {
+ return !Effect.class.getDeclaredField(effect.name()).isAnnotationPresent(Deprecated.class);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void checkAllApiExists() throws ReflectiveOperationException {
+ Map<Integer, Effect> toId = new HashMap<>();
+ for (final Effect effect : Effect.values()) {
+ if (isNotDeprecated(effect)) {
+ final Effect put = toId.put(effect.getId(), effect);
+ assertNull(put, "duplicate API effect: " + put);
+ }
+ }
+
+ for (final Integer event : collectNmsLevelEvents()) {
+ assertNotNull(toId.get(event), "missing API Effect: " + event);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void checkNoExtraApi() throws ReflectiveOperationException {
+ Map<Integer, Effect> toId = new HashMap<>();
+ for (final Effect effect : Effect.values()) {
+ if (isNotDeprecated(effect)) {
+ final Effect put = toId.put(effect.getId(), effect);
+ assertNull(put, "duplicate API effect: " + put);
+ }
+ }
+
+ final List<Integer> nmsEvents = collectNmsLevelEvents();
+ for (final Map.Entry<Integer, Effect> entry : toId.entrySet()) {
+ assertTrue(nmsEvents.contains(entry.getKey()), "Extra API Effect: " + entry.getValue());
+ }
+ }
+}

View file

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Oliwier Miodun <naczs@blueflow.pl>
Date: Mon, 10 Jul 2023 17:59:42 +0200
Subject: [PATCH] SculkCatalyst bloom API
== AT ==
public net.minecraft.world.level.block.entity.SculkCatalystBlockEntity$CatalystListener bloom(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/util/RandomSource;)V
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java
index 5211dc80f449cec09f992a42667e869ab9e7115e..407d5b1d87d14e18878f0ebf1d676a7f49e7cfaf 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java
@@ -38,4 +38,20 @@ public class CraftSculkCatalyst extends CraftBlockEntityState<SculkCatalystBlock
public CraftSculkCatalyst copy(Location location) {
return new CraftSculkCatalyst(this, location);
}
+
+ // Paper start - SculkCatalyst bloom API
+ @Override
+ public void bloom(@org.jetbrains.annotations.NotNull io.papermc.paper.math.Position position, int charge) {
+ com.google.common.base.Preconditions.checkNotNull(position);
+ requirePlaced();
+
+ getTileEntity().getListener().bloom(
+ world.getHandle(),
+ getTileEntity().getBlockPos(),
+ getTileEntity().getBlockState(),
+ world.getHandle().getRandom()
+ );
+ getTileEntity().getListener().getSculkSpreader().addCursors(io.papermc.paper.util.MCUtil.toBlockPos(position), charge);
+ }
+ // Paper end
}

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 9 Jul 2023 11:55:02 -0700
Subject: [PATCH] API for an entity's scoreboard name
Was obtainable through different methods, but you had to use different
methods depending on the implementation of Entity you were working with.
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 36c97ac40d7e1127d95eeca396570b1d50b69a5c..96448895a0a18e6f819d0a2a629c04abd331fa85 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1244,4 +1244,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return !this.getHandle().level().noCollision(this.getHandle(), aabb);
}
// Paper end - Collision API
+
+ // Paper start - entity scoreboard name
+ @Override
+ public String getScoreboardEntryName() {
+ return this.getHandle().getScoreboardName();
+ }
+ // Paper end - entity scoreboard name
}

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 10 Dec 2022 17:52:38 -0800
Subject: [PATCH] Deprecate and replace methods with old StructureType
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0daa352795a6533289370388c9c75c98c82396ca..ca4cce36d462567f9fbab53dd904cad6db382f72 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1977,6 +1977,11 @@ public final class CraftServer implements Server {
ServerLevel worldServer = ((CraftWorld) world).getHandle();
Location structureLocation = world.locateNearestStructure(location, structureType, radius, findUnexplored);
+ // Paper start - don't throw NPE
+ if (structureLocation == null) {
+ throw new IllegalStateException("Could not find a structure for " + structureType);
+ }
+ // Paper end
BlockPos structurePosition = CraftLocation.toBlockPosition(structureLocation);
// Create map with trackPlayer = true, unlimitedTracking = true
@@ -1987,6 +1992,31 @@ public final class CraftServer implements Server {
return CraftItemStack.asBukkitCopy(stack);
}
+ // Paper start - copied from above (uses un-deprecated StructureType type)
+ @Override
+ public ItemStack createExplorerMap(World world, Location location, org.bukkit.generator.structure.StructureType structureType, org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored) {
+ Preconditions.checkArgument(world != null, "World cannot be null");
+ Preconditions.checkArgument(location != null, "Location cannot be null");
+ Preconditions.checkArgument(structureType != null, "StructureType cannot be null");
+ Preconditions.checkArgument(mapIcon != null, "mapIcon cannot be null");
+
+ ServerLevel worldServer = ((CraftWorld) world).getHandle();
+ final org.bukkit.util.StructureSearchResult structureSearchResult = world.locateNearestStructure(location, structureType, radius, findUnexplored);
+ if (structureSearchResult == null) {
+ return null;
+ }
+ Location structureLocation = structureSearchResult.getLocation();
+ BlockPos structurePosition = new BlockPos(structureLocation.getBlockX(), structureLocation.getBlockY(), structureLocation.getBlockZ());
+
+ // Create map with showIcons = true, unlimitedTracking = true
+ net.minecraft.world.item.ItemStack stack = MapItem.create(worldServer, structurePosition.getX(), structurePosition.getZ(), MapView.Scale.NORMAL.getValue(), true, true);
+ MapItem.renderBiomePreviewMap(worldServer, stack);
+ // "+" map ID taken from VillagerTrades$TreasureMapForEmeralds
+ MapItem.getSavedData(stack, worldServer).addTargetDecoration(stack, structurePosition, "+", MapDecoration.Type.byIcon(mapIcon.getValue()));
+
+ return CraftItemStack.asBukkitCopy(stack);
+ }
+ // Paper end
@Override
public void shutdown() {

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: EpicPlayerA10 <adasko.lesiak@gmail.com>
Date: Sun, 18 Jun 2023 12:38:24 +0200
Subject: [PATCH] Don't tab-complete namespaced commands if send-namespaced is
false
Tab-complete packet is supposed to tab-complete args for commands, but
it also can suggest commands like in version 1.12.2 or lower.
This patch prevents server from sending namespaced commands when player
requests tab-complete only commands.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 8085e59bf16d3a5c85bd9d328126f226c026f163..b88d6230172311d92844a9621f2eb3be644ac2aa 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -823,6 +823,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
+ // Paper start - Don't tab-complete namespaced commands if send-namespaced is false
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && suggestions.getRange().getStart() <= 1) {
+ suggestions.getList().removeIf(suggestion -> suggestion.getText().contains(":"));
+ }
+ // Paper end - Don't tab-complete namespaced commands if send-namespaced is false
// Paper start - Brigadier API
com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, packet.getCommand());
suggestEvent.setCancelled(suggestions.isEmpty());

View file

@ -0,0 +1,161 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 4 Mar 2023 10:52:52 -0800
Subject: [PATCH] Properly handle BlockBreakEvent#isDropItems
Setting whether a block break dropped items controlled
far more than just whether blocks dropped, like stat increases
food consumption, turtle egg count decreases, ice to water
conversions and beehive releases
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index ee7f36700863b9f504a70a56c5f28c8e39b45c91..7b4426ac0435d3f419d9ece29dc9eccdb8f99950 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -434,8 +434,8 @@ public class ServerPlayerGameMode {
isCorrectTool = flag1; // Paper - Trigger bee_nest_destroyed trigger in the correct place
itemstack.mineBlock(this.level, iblockdata1, pos, this.player);
- if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
- block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1);
+ if (flag && flag1/* && event.isDropItems() */) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion
+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems(), false); // Paper - fix drops not preventing stats/food exhaustion
}
// return true; // CraftBukkit
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
index 4e8bafa97127632799a1f0260c1ef3367cb8a54c..6ef43d544e9d3dd31506c5a55b0db428fb074b47 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -86,8 +86,8 @@ public class BeehiveBlock extends BaseEntityBlock {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity tileentitybeehive) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) == 0) {
tileentitybeehive.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
index c09851136944bd58d82b3a9d19719b0354802824..a757a45d423e1729c9374391df4186ae0522e1ac 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -403,10 +403,18 @@ public class Block extends BlockBehaviour implements ItemLike {
return this.defaultBlockState();
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - fix drops not preventing stats/food exhaustion
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
+ // Paper start - fix drops not preventing stats/food exhaustion
+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true, true);
+ }
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) {
+ // Paper end - fix drops not preventing stats/food exhaustion
player.awardStat(Stats.BLOCK_MINED.get(this));
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
+ if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion
Block.dropResources(state, world, pos, blockEntity, player, tool);
+ } // Paper - fix drops not preventing stats/food exhaustion
}
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
index 7fdf744a2be55313cc75c1322f6534f55cf463f5..f446c40c4d90307c568faa2866800f5326634df6 100644
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
@@ -96,8 +96,8 @@ public class DoublePlantBlock extends BushBlock {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
}
protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) {
diff --git a/src/main/java/net/minecraft/world/level/block/IceBlock.java b/src/main/java/net/minecraft/world/level/block/IceBlock.java
index 4bfe53e3a231a7bec461759e78c7a6cbcb8bb625..013302623d3ca3ff88f242d740af935dcf4844a6 100644
--- a/src/main/java/net/minecraft/world/level/block/IceBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java
@@ -33,8 +33,8 @@ public class IceBlock extends HalfTransparentBlock {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
// Paper start - Improve Block#breakNaturally API
this.afterDestroy(world, pos, tool);
}
diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
index bdcb732a31fff0cfc2119132079ce197c7a77c9a..a6f408e56fa6c9de82fd93555fe21e1b11ce1022 100644
--- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -174,8 +174,8 @@ public class TurtleEggBlock extends Block {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
this.decreaseEggs(world, pos, state);
}
diff --git a/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java b/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c435f7079b429873f33d7bade82eca0c6b45842
--- /dev/null
+++ b/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java
@@ -0,0 +1,47 @@
+package io.papermc.paper.world.block;
+
+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.AbstractTestingBase;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class BlockPlayerDestroyOverrideTest extends AbstractTestingBase {
+
+ 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.level.block.Block")) {
+ final MethodInfoList playerDestroy = subclass.getDeclaredMethodInfo("playerDestroy");
+ if (!playerDestroy.isEmpty()) {
+ classInfo.add(subclass);
+ }
+ }
+ }
+ return classInfo.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameters")
+ public void checkPlayerDestroyOverrides(ClassInfo overridesPlayerDestroy) {
+ final MethodInfoList playerDestroy = overridesPlayerDestroy.getDeclaredMethodInfo("playerDestroy");
+ assertEquals(1, playerDestroy.size(), overridesPlayerDestroy.getName() + " has multiple playerDestroy methods");
+ final MethodInfo next = playerDestroy.iterator().next();
+ final MethodParameterInfo[] parameterInfo = next.getParameterInfo();
+ assertEquals("boolean", parameterInfo[parameterInfo.length - 1].getTypeDescriptor().toStringWithSimpleNames(), overridesPlayerDestroy.getName() + " needs to change its override of playerDestroy");
+ }
+}

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trevor Bedson <78997566+Prorickey@users.noreply.github.com>
Date: Fri, 14 Jul 2023 20:47:02 -0400
Subject: [PATCH] Fire entity death event for ender dragon
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
index e8be7ddbef12b27ed5c5fcfa8b726d5a85058aa9..6f14607a88761171a72e274b3c9b476b20a272f1 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -641,6 +641,15 @@ public class EnderDragon extends Mob implements Enemy {
@Override
public void kill() {
+ // Paper start - Fire entity death event
+ this.silentDeath = true;
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this);
+ if (deathEvent.isCancelled()) {
+ this.silentDeath = false; // Reset to default if event was cancelled
+ return;
+ }
+ // Paper end - Fire entity death event
+
this.remove(Entity.RemovalReason.KILLED, EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
this.gameEvent(GameEvent.ENTITY_DIE);
if (this.dragonFight != null) {

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ruViolence <78062896+ruViolence@users.noreply.github.com>
Date: Tue, 27 Jun 2023 15:38:18 +0800
Subject: [PATCH] Configurable entity tracking range by Y coordinate
Options to configure entity tracking by Y coordinate, also for each entity category.
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index bff776f07bcc7841acc5757c1f53bde1812756c8..e7994d0f45b186938dd5606284290f56f110d7ed 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1754,6 +1754,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
double d2 = d0 * d0;
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+ // Paper start - Configurable entity tracking range by Y
+ if (flag && level.paperConfig().entities.trackingRangeY.enabled) {
+ double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
+ if (rangeY != -1) {
+ double vec3d_dy = player.getY() - this.entity.getY();
+ flag = vec3d_dy * vec3d_dy <= rangeY * rangeY;
+ }
+ }
+ // Paper end - Configurable entity tracking range by Y
// CraftBukkit start - respect vanish API
if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {

View file

@ -0,0 +1,183 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Corey Shupe <coreyshupe101@gmail.com>
Date: Wed, 11 Jan 2023 16:40:39 -0500
Subject: [PATCH] Add Listing API for Player
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
index 6247a21c9c391abf1f6db3482c659593e4f29355..9ccca41bf23efadba5329cc584bbcdcacbe09a92 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
@@ -37,6 +37,17 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
this.actions = EnumSet.of(action);
this.entries = List.of(new ClientboundPlayerInfoUpdatePacket.Entry(player));
}
+ // Paper start - Add Listing API for Player
+ public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, List<ClientboundPlayerInfoUpdatePacket.Entry> entries) {
+ this.actions = actions;
+ this.entries = entries;
+ }
+
+ public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, ClientboundPlayerInfoUpdatePacket.Entry entry) {
+ this.actions = actions;
+ this.entries = List.of(entry);
+ }
+ // Paper end - Add Listing API for Player
public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
@@ -50,6 +61,28 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
}
+ // Paper start - Add Listing API for Player
+ public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players, ServerPlayer forPlayer) {
+ final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
+ final List<ClientboundPlayerInfoUpdatePacket.Entry> entries = new java.util.ArrayList<>(players.size());
+ final org.bukkit.craftbukkit.entity.CraftPlayer bukkitEntity = forPlayer.getBukkitEntity();
+ for (final ServerPlayer player : players) {
+ entries.add(new ClientboundPlayerInfoUpdatePacket.Entry(player, bukkitEntity.isListed(player.getBukkitEntity())));
+ }
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, entries);
+ }
+
+ public static ClientboundPlayerInfoUpdatePacket createSinglePlayerInitializing(ServerPlayer player, boolean listed) {
+ final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
+ final List<ClientboundPlayerInfoUpdatePacket.Entry> entries = List.of(new Entry(player, listed));
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, entries);
+ }
+
+ public static ClientboundPlayerInfoUpdatePacket updateListed(UUID playerInfoId, boolean listed) {
+ EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, listed));
+ }
+ // Paper end - Add Listing API for Player
private ClientboundPlayerInfoUpdatePacket(RegistryFriendlyByteBuf buf) {
this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
this.entries = buf.readList(buf2 -> {
@@ -158,16 +191,24 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
@Nullable RemoteChatSession.Data chatSession
) {
Entry(ServerPlayer player) {
+ // Paper start - Add Listing API for Player
+ this(player, true);
+ }
+ Entry(ServerPlayer player, boolean listed) {
this(
player.getUUID(),
player.getGameProfile(),
- true,
+ listed,
player.connection.latency(),
player.gameMode.getGameModeForPlayer(),
player.getTabListDisplayName(),
Optionull.map(player.getChatSession(), RemoteChatSession::asData)
);
}
+ Entry(UUID profileId, boolean listed) {
+ this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, null);
+ }
+ // Paper end - Add Listing API for Player
}
static class EntryBuilder {
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 2f62af670441d422133b18d00d9e5e5e58e4afe7..db1279f780e905e5b29fd4db0440d29f52596be0 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -359,14 +359,22 @@ public abstract class PlayerList {
// CraftBukkit end
// CraftBukkit start - sendAll above replaced with this loop
- ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player));
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
for (int i = 0; i < this.players.size(); ++i) {
ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
+ // Paper start - Add Listing API for Player
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
+ // Paper end - Add Listing API for Player
entityplayer1.connection.send(packet);
+ // Paper start - Add Listing API for Player
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ }
+ // Paper end - Add Listing API for Player
}
if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
@@ -377,7 +385,7 @@ public abstract class PlayerList {
}
// Paper start - Use single player info update packet on join
if (!onlinePlayers.isEmpty()) {
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers));
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
}
// Paper end - Use single player info update packet on join
player.sentListPacket = true;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0fe81e58541dbc46ac493897aa190ebf9ddbc805..1d6ea70c8039b7dcae3742ce7ef6a52015d6bc52 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -198,6 +198,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
private final ConversationTracker conversationTracker = new ConversationTracker();
private final Set<String> channels = new HashSet<String>();
private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new HashMap<>();
+ private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
private int hash = 0;
private double health = 20;
@@ -2073,7 +2074,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
otherPlayer.setUUID(uuidOverride);
}
// Paper end
- this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer)));
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer), this.getHandle())); // Paper - Add Listing API for Player
if (original != null) otherPlayer.setUUID(original); // Paper - uuid override
}
@@ -2180,6 +2181,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return (entity != null) ? this.canSee(entity) : false; // If we can't find it, we can't see it
}
+ // Paper start - Add Listing API for Player
+ @Override
+ public boolean isListed(Player other) {
+ return !this.unlistedEntities.contains(other.getUniqueId());
+ }
+
+ @Override
+ public boolean unlistPlayer(@NotNull Player other) {
+ Preconditions.checkNotNull(other, "hidden entity cannot be null");
+ if (this.getHandle().connection == null) return false;
+ if (!this.canSee(other)) return false;
+
+ if (unlistedEntities.add(other.getUniqueId())) {
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(other.getUniqueId(), false));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean listPlayer(@NotNull Player other) {
+ Preconditions.checkNotNull(other, "hidden entity cannot be null");
+ if (this.getHandle().connection == null) return false;
+ if (!this.canSee(other)) throw new IllegalStateException("Player cannot see other player");
+
+ if (this.unlistedEntities.remove(other.getUniqueId())) {
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(other.getUniqueId(), true));
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // Paper end - Add Listing API for Player
+
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Astralchroma <astralchroma@proton.me>
Date: Thu, 27 Oct 2022 22:19:31 +0100
Subject: [PATCH] Configurable Region Compression Format
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index f1237f6fd6414900ffbad0caee31aa83310eeef4..e956bca0d06382b8dd63453a6eb111deae68b62e 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -50,7 +50,7 @@ public class RegionFile implements AutoCloseable {
protected final RegionBitmap usedSectors;
public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException {
- this(storageKey, directory, path, RegionFileVersion.getSelected(), dsync);
+ this(file, directory, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format
}
public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync) throws IOException {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
index cbd892598287c9358c1c2a3840c517462820b389..ef68b57ef1d8d7cb317c417569dd23a777fba4ad 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
@@ -58,6 +58,15 @@ public class RegionFileVersion {
private final RegionFileVersion.StreamWrapper<InputStream> inputWrapper;
private final RegionFileVersion.StreamWrapper<OutputStream> outputWrapper;
+ // Paper start - Configurable region compression format
+ public static RegionFileVersion getCompressionFormat() {
+ return switch (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.compressionFormat) {
+ case GZIP -> VERSION_GZIP;
+ case ZLIB -> VERSION_DEFLATE;
+ case NONE -> VERSION_NONE;
+ };
+ }
+ // Paper end - Configurable region compression format
private RegionFileVersion(
int id,
@Nullable String name,

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: aerulion <aerulion@gmail.com>
Date: Mon, 21 Aug 2023 04:36:07 +0200
Subject: [PATCH] Add BlockFace to BlockDamageEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 7b4426ac0435d3f419d9ece29dc9eccdb8f99950..cef3a64b5e6c4d34ed079078420078a7adfcd574 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -256,7 +256,7 @@ public class ServerPlayerGameMode {
}
return;
}
- org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f);
+ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, direction, this.player.getInventory().getSelected(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent
if (blockEvent.isCancelled()) {
// Let the client know the block still exists
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 5af62603415865068ca4b79a7e68d8eb813596b1..47a02b7786d284370d8019b07b8d85f895dc280a 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -650,13 +650,13 @@ public class CraftEventFactory {
/**
* BlockDamageEvent
*/
- public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, ItemStack itemstack, boolean instaBreak) {
+ public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, Direction direction, ItemStack itemstack, boolean instaBreak) { // Paper - Add BlockFace to BlockDamageEvent
Player player = who.getBukkitEntity();
CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
Block blockClicked = CraftBlock.at(who.level(), pos);
- BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, itemInHand, instaBreak);
+ BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, CraftBlock.notchToBlockFace(direction), itemInHand, instaBreak); // Paper - Add BlockFace to BlockDamageEvent
player.getServer().getPluginManager().callEvent(event);
return event;

View file

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: LemonCaramel <admin@caramel.moe>
Date: Mon, 10 Apr 2023 20:48:26 +0900
Subject: [PATCH] Fix NPE on Boat getStatus
Boat status is null until the entity is added to the world and the tick() method is called.
== AT ==
public net.minecraft.world.entity.vehicle.Boat getStatus()Lnet/minecraft/world/entity/vehicle/Boat$Status;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
index d161cbf9c83cd78593864850b98f688da2c85aa5..e33b1b6fd50a4eea57500cc00dba20d6edcab75d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
@@ -88,6 +88,17 @@ public class CraftBoat extends CraftVehicle implements Boat {
@Override
public Status getStatus() {
+ // Paper start - Fix NPE on Boat getStatus
+ final net.minecraft.world.entity.vehicle.Boat handle = this.getHandle();
+ if (handle.status == null) {
+ if (handle.valid) {
+ // Don't actually set the status because it would skew the old status check in the next tick
+ return CraftBoat.boatStatusFromNms(handle.getStatus());
+ } else {
+ return Status.NOT_IN_WORLD;
+ }
+ }
+ // Paper end - Fix NPE on Boat getStatus
return CraftBoat.boatStatusFromNms(this.getHandle().status);
}

View file

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 11 Jan 2023 20:59:01 +0200
Subject: [PATCH] Expand Pose API
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 638aeef75dc5f7ab8b8e050118a7c709246a85f4..acf2cc8afaf4dee193ecf3bfc4a39b8c39ffc376 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -421,6 +421,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@javax.annotation.Nullable
private UUID originWorld;
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
+ public boolean fixedPose = false; // Paper - Expand Pose API
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -644,6 +645,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public void onClientRemoval() {}
public void setPose(net.minecraft.world.entity.Pose pose) {
+ if (this.fixedPose) return; // Paper - Expand Pose API
// CraftBukkit start
if (pose == this.getPose()) {
return;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 96448895a0a18e6f819d0a2a629c04abd331fa85..d52b7c5739b8ea51cb91c45ddcad6237b9ce5a5e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -897,6 +897,20 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isSneaking() {
return this.getHandle().isShiftKeyDown();
}
+
+ @Override
+ public void setPose(Pose pose, boolean fixed) {
+ Preconditions.checkNotNull(pose, "Pose cannot be null");
+ final Entity handle = this.getHandle();
+ handle.fixedPose = false;
+ handle.setPose(net.minecraft.world.entity.Pose.values()[pose.ordinal()]);
+ handle.fixedPose = fixed;
+ }
+
+ @Override
+ public boolean hasFixedPose() {
+ return this.getHandle().fixedPose;
+ }
// Paper end
@Override

View file

@ -0,0 +1,91 @@
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 f6f5fad52e41d5ccc37dc28c40904fce014907fb..6b59c4b5906c0fb4fdbc674452c6ff3df42b099b 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
@@ -439,6 +439,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
}

View file

@ -0,0 +1,48 @@
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 b88d6230172311d92844a9621f2eb3be644ac2aa..88baa1235210553248a7fec765bd5ad660ad5295 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -938,8 +938,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.disconnect("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 2c20441cce1e07239a65aadfb85004fcdf3672c8..1e77482a98869e464c1f0a873cff8febf7924c8c 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));

View file

@ -0,0 +1,32 @@
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 c75ac52f302e8e29e0bdea32c85ccf6713257a9b..3ff06cc6ad35567bcb1f29115db63c11a8e79dbb 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
@@ -35,10 +35,12 @@ 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);
+ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage
this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(stack));
this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil());
}
@@ -128,7 +130,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
if (entity instanceof LivingEntity entityliving) {
f += EnchantmentHelper.getDamageBonus(this.getPickupItemStackOrigin(), entityliving.getType());

View file

@ -0,0 +1,32 @@
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;

View file

@ -0,0 +1,39 @@
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 c4972e5767488878f7929226258c41c1cc30a47f..c9cd18ce79a6ee7297a8fd14f4dbe712570b3ced 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -266,12 +266,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);

View file

@ -0,0 +1,42 @@
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 4d654c4f0b6210a9841427789ba70ce5d1d308be..9d93130f23addb18b97d7f5ec013faef17a74529 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 1d6ea70c8039b7dcae3742ce7ef6a52015d6bc52..b8999852f132ac25da3ddb5164c73c886a3fa572 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -253,6 +253,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;

View file

@ -0,0 +1,31 @@
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 inventory desync
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index b7cc2b5ee85e8e6a5c8cb8ce1f3c934773be32e6..7f93b60e9bdfc2739c77f4dfa69031fbe2097d65 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -1464,6 +1464,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
// CraftBukkit start - fire PlayerLeashEntityEvent
if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) {
((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder()));
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
return InteractionResult.PASS;
}
// 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;

View file

@ -0,0 +1,120 @@
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 c70e1a17d855f2a9d160e8cd15a6a4bcf39b8945..b2bf086506ba7eda6ba6912ebf51a9da154cd414 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1607,12 +1607,17 @@ public class ServerPlayer extends 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) {
@@ -1634,7 +1639,7 @@ public class ServerPlayer extends 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 3d36d79a4e7f16f6face3465cdf54656984f3ebc..41f3cdec7deabf34358b8087df77169f85a5b919 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -358,12 +358,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
@@ -439,7 +443,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;
}
@@ -450,6 +457,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 47a02b7786d284370d8019b07b8d85f895dc280a..eefdb3da069d9615db7c663bcf8a72b78a0e6817 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1384,10 +1384,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
}
@@ -1402,10 +1413,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(Container matrix, Container resultInventory, ItemStack result, InventoryView lastCraftView, boolean isRepair) {

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