MOOOOOOOOOOORE

This commit is contained in:
Noah van der Aa 2024-10-24 00:08:29 +02:00
parent d52e2d241d
commit 4baf9ab44d
No known key found for this signature in database
GPG key ID: 547D90BC6FF753CF
26 changed files with 212 additions and 148 deletions

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, 22 Nov 2022 13:16:01 -0800
Subject: [PATCH] check global player list where appropriate
Makes certain entities check all players when searching for a player
instead of just checking players in their world.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 4b2309d27867eddc50093e895503e02184e1b825..3eaeeb3ec715d92fe99e14c37e224cb1e80a467b 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2383,4 +2383,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}
+
+ // Paper start - check global player list where appropriate
+ @Override
+ @Nullable
+ public Player getGlobalPlayerByUUID(UUID uuid) {
+ return this.server.getPlayerList().getPlayer(uuid);
+ }
+ // Paper end - check global player list where appropriate
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 16f349f8ce621c58f36f445016ea25d8af14910d..0a52f925b0ef28ca7cee067a40d5dc4d30c224b0 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3867,7 +3867,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
public void onItemPickup(ItemEntity item) {
- Entity entity = item.getOwner();
+ Entity entity = item.thrower != null ? this.level().getGlobalPlayerByUUID(item.thrower) : null; // Paper - check global player list where appropriate
if (entity instanceof ServerPlayer) {
CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entity, item.getItem(), this);
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
index 533cb2eff3d56e7e8a70aba5e1047250e192bf2c..18c19e4b675000aacb74344909fc104964231008 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -262,7 +262,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
entityvillager.finalizeSpawn(world, world.getCurrentDifficultyAt(entityvillager.blockPosition()), EntitySpawnReason.CONVERSION, (SpawnGroupData) null);
entityvillager.refreshBrain(world);
if (this.conversionStarter != null) {
- Player entityhuman = world.getPlayerByUUID(this.conversionStarter);
+ Player entityhuman = world.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check global player list where appropriate
if (entityhuman instanceof ServerPlayer) {
CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager);
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index dac8305f1c897e6f82a2dde67c5b1b6b8b649b19..e185a33b5b1f8e8e0a0e666b24ba3e9186a8a7ff 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -165,4 +165,11 @@ public interface EntityGetter {
return null;
}
+
+ // Paper start - check global player list where appropriate
+ @Nullable
+ default Player getGlobalPlayerByUUID(UUID uuid) {
+ return this.getPlayerByUUID(uuid);
+ }
+ // Paper end - check global player list where appropriate
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
index ea53c25c350c0cf8e0360ea409cd1f69a62054a8..275721d8b3d653b38af505dde30396c0b7b6a3da 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
@@ -105,6 +105,13 @@ public class SculkShriekerBlockEntity extends BlockEntity implements GameEventLi
@Nullable
public static ServerPlayer tryGetPlayer(@Nullable Entity entity) {
+ // Paper start - check global player list where appropriate; ensure level is the same for sculk events
+ final ServerPlayer player = tryGetPlayer0(entity);
+ return player != null && player.level() == entity.level() ? player : null;
+ }
+ @Nullable
+ private static ServerPlayer tryGetPlayer0(@Nullable Entity entity) {
+ // Paper end - check global player list where appropriate
if (entity instanceof ServerPlayer) {
return (ServerPlayer)entity;
} else {

View file

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 18 Mar 2022 21:30:00 -0700
Subject: [PATCH] Fix async entity add due to fungus trees
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
index 5bf438bb58833c1df3620e82d3d2b90207366372..2e72e92762877b28dd908711671e1dfb933de9b0 100644
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
@@ -237,6 +237,7 @@ public class WorldGenRegion implements WorldGenLevel {
if (iblockdata.isAir()) {
return false;
} else {
+ if (drop) LOGGER.warn("Potential async entity add during worldgen", new Throwable()); // Paper - Fix async entity add due to fungus trees; log when this happens
if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation
BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 6baa06dc0f102fe83b10015dbbe1410066961c82..29825ea687827c075b87e88c45672e7b0093ed17 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -261,10 +261,10 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
((ChorusFlowerBlock) Blocks.CHORUS_FLOWER).generatePlant(access, pos, random, 8);
return true;
case CRIMSON_FUNGUS:
- gen = TreeFeatures.CRIMSON_FUNGUS_PLANTED;
+ gen = this.isNormalWorld() ? TreeFeatures.CRIMSON_FUNGUS_PLANTED : TreeFeatures.CRIMSON_FUNGUS; // Paper - Fix async entity add due to fungus trees; if world gen, don't use planted version
break;
case WARPED_FUNGUS:
- gen = TreeFeatures.WARPED_FUNGUS_PLANTED;
+ gen = this.isNormalWorld() ? TreeFeatures.WARPED_FUNGUS_PLANTED : TreeFeatures.WARPED_FUNGUS; // Paper - Fix async entity add due to fungus trees; if world gen, don't use planted version
break;
case AZALEA:
gen = TreeFeatures.AZALEA_TREE;

View file

@ -0,0 +1,118 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 8 May 2022 13:35:45 -0700
Subject: [PATCH] ItemStack damage API
Adds methods notify clients about item breaks and
to simulate damage done to an itemstack and all
the logic associated with damaging them
== AT ==
public net.minecraft.world.entity.LivingEntity entityEventForEquipmentBreak(Lnet/minecraft/world/entity/EquipmentSlot;)B
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index bcb3a45166e5dd75dd727adf92304b3a75399c8d..d8dc3228f3cd8c9efc8359162edac601a87bf762 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -693,8 +693,13 @@ public final class ItemStack implements DataComponentHolder {
}
public void hurtAndBreak(int amount, ServerLevel world, @Nullable LivingEntity player, Consumer<Item> breakCallback) { // Paper - Add EntityDamageItemEvent
+ // Paper start - add force boolean overload
+ this.hurtAndBreak(amount, world, player, breakCallback, false);
+ }
+ public void hurtAndBreak(int amount, ServerLevel world, @Nullable LivingEntity player, Consumer<Item> breakCallback, boolean force) { // Paper - Add EntityDamageItemEvent
+ // Paper end
int originalDamage = amount; // Paper - Expand PlayerItemDamageEvent
- int j = this.processDurabilityChange(amount, world, player);
+ int j = this.processDurabilityChange(amount, world, player, force); // Paper
// CraftBukkit start
if (player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), j, originalDamage); // Paper - Add EntityDamageItemEvent
@@ -725,8 +730,8 @@ public final class ItemStack implements DataComponentHolder {
}
- private int processDurabilityChange(int baseDamage, ServerLevel world, @Nullable LivingEntity player) { // Paper - Add EntityDamageItemEvent
- return !this.isDamageableItem() ? 0 : (player instanceof ServerPlayer && player.hasInfiniteMaterials() ? 0 : (baseDamage > 0 ? EnchantmentHelper.processDurabilityChange(world, this, baseDamage) : baseDamage)); // Paper - Add EntityDamageItemEvent
+ private int processDurabilityChange(int baseDamage, ServerLevel world, @Nullable LivingEntity player, boolean force) { // Paper - Add EntityDamageItemEvent
+ return !this.isDamageableItem() ? 0 : (player instanceof ServerPlayer && player.hasInfiniteMaterials() && !force ? 0 : (baseDamage > 0 ? EnchantmentHelper.processDurabilityChange(world, this, baseDamage) : baseDamage)); // Paper - Add EntityDamageItemEvent
}
private void applyDamage(int damage, @Nullable LivingEntity player, Consumer<Item> breakCallback) { // Paper - Add EntityDamageItemEvent
@@ -766,6 +771,11 @@ public final class ItemStack implements DataComponentHolder {
}
public void hurtAndBreak(int amount, LivingEntity entity, EquipmentSlot slot) {
+ // Paper start - add param to skip infinite mats check
+ this.hurtAndBreak(amount, entity, slot, false);
+ }
+ public void hurtAndBreak(int amount, LivingEntity entity, EquipmentSlot slot, boolean force) {
+ // Paper end - add param to skip infinite mats check
Level world = entity.level();
if (world instanceof ServerLevel worldserver) {
@@ -778,8 +788,8 @@ public final class ItemStack implements DataComponentHolder {
}
this.hurtAndBreak(amount, worldserver, entity, (item) -> { // Paper - Add EntityDamageItemEvent
- entity.onEquippedItemBroken(item, slot);
- });
+ if (slot != null) entity.onEquippedItemBroken(item, slot); // Paper - itemstack damage API - do not process entity related callbacks when damaging from API
+ }, force); // Paper - itemstack damage API
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 4fa19ddb1414282020e118eea298d57d2bf42754..1ceaa081231a617bd87331b308c24d9c7a8dcf2b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1154,4 +1154,48 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
this.getHandle().knockback(strength, directionX, directionZ);
};
// Paper end - knockback API
+
+ // Paper start - ItemStack damage API
+ public void broadcastSlotBreak(final org.bukkit.inventory.EquipmentSlot slot) {
+ this.getHandle().level().broadcastEntityEvent(this.getHandle(), net.minecraft.world.entity.LivingEntity.entityEventForEquipmentBreak(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)));
+ }
+
+ @Override
+ public void broadcastSlotBreak(final org.bukkit.inventory.EquipmentSlot slot, final Collection<org.bukkit.entity.Player> players) {
+ if (players.isEmpty()) {
+ return;
+ }
+ final net.minecraft.network.protocol.game.ClientboundEntityEventPacket packet = new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(
+ this.getHandle(),
+ net.minecraft.world.entity.LivingEntity.entityEventForEquipmentBreak(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot))
+ );
+ players.forEach(player -> ((CraftPlayer) player).getHandle().connection.send(packet));
+ }
+
+ @Override
+ public ItemStack damageItemStack(ItemStack stack, final int amount) {
+ final net.minecraft.world.item.ItemStack nmsStack;
+ if (stack instanceof final CraftItemStack craftItemStack) {
+ if (craftItemStack.handle == null || craftItemStack.handle.isEmpty()) {
+ return stack;
+ }
+ nmsStack = craftItemStack.handle;
+ } else {
+ nmsStack = CraftItemStack.asNMSCopy(stack);
+ stack = CraftItemStack.asCraftMirror(nmsStack); // mirror to capture changes in hurt logic & events
+ }
+ this.damageItemStack0(nmsStack, amount, null);
+ return stack;
+ }
+
+ @Override
+ public void damageItemStack(final org.bukkit.inventory.EquipmentSlot slot, final int amount) {
+ final net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot);
+ this.damageItemStack0(this.getHandle().getItemBySlot(nmsSlot), amount, nmsSlot);
+ }
+
+ private void damageItemStack0(final net.minecraft.world.item.ItemStack nmsStack, final int amount, final net.minecraft.world.entity.EquipmentSlot slot) {
+ nmsStack.hurtAndBreak(amount, this.getHandle(), slot, true);
+ }
+ // Paper end - ItemStack damage API
}

View file

@ -0,0 +1,156 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Wed, 15 Sep 2021 20:44:22 +0200
Subject: [PATCH] Friction API
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0a52f925b0ef28ca7cee067a40d5dc4d30c224b0..abcb1065100597f66c9f76fdae5f873fa0d8f315 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -298,6 +298,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
public boolean bukkitPickUpLoot;
public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
@Override
public float getBukkitYaw() {
@@ -724,7 +725,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
public boolean shouldDiscardFriction() {
- return this.discardFriction;
+ return !this.frictionState.toBooleanOrElse(!this.discardFriction); // Paper - Friction API
}
public void setDiscardFriction(boolean noDrag) {
@@ -798,6 +799,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end - Friction API
nbt.putFloat("Health", this.getHealth());
nbt.putShort("HurtTime", (short) this.hurtTime);
nbt.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -841,6 +847,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
this.internalSetAbsorptionAmount(absorptionAmount);
// Paper end - Check for NaN
+ // Paper start - Friction API
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ LOGGER.error("Unknown friction state " + fs + " for " + this);
+ }
+ }
+ // Paper end - Friction API
if (nbt.contains("attributes", 9) && this.level() != null && !this.level().isClientSide) {
this.getAttributes().load(nbt.getList("attributes", 10));
}
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index aa41c4cf8d3ae291c4147118c96190ff0bb807b2..e83a705f54063a17fc69a22683333aacad5a43ce 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -63,6 +63,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit
public boolean canMobPickup = true; // Paper - Item#canEntityPickup
private int despawnRate = -1; // Paper - Alternative item-despawn-rate
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
public ItemEntity(EntityType<? extends ItemEntity> type, Level world) {
super(type, world);
@@ -186,7 +187,11 @@ public class ItemEntity extends Entity implements TraceableEntity {
this.applyEffectsFromBlocks();
float f = 0.98F;
- if (this.onGround()) {
+ // Paper start - Friction API
+ if (frictionState == net.kyori.adventure.util.TriState.FALSE) {
+ f = 1F;
+ } else if (this.onGround()) {
+ // Paper end - Friction API
f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F;
}
@@ -409,6 +414,11 @@ public class ItemEntity extends Entity implements TraceableEntity {
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end - Friction API
nbt.putShort("Health", (short) this.health);
nbt.putShort("Age", (short) this.age);
nbt.putShort("PickupDelay", (short) this.pickupDelay);
@@ -451,6 +461,17 @@ public class ItemEntity extends Entity implements TraceableEntity {
this.setItem(ItemStack.EMPTY);
}
+ // Paper start - Friction API
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ com.mojang.logging.LogUtils.getLogger().error("Unknown friction state " + fs + " for " + this);
+ }
+ }
+ // Paper end - Friction API
+
if (this.getItem().isEmpty()) {
this.discard(null); // CraftBukkit - add Bukkit remove cause
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index 1a291dd8a287db30e71dcb315599fc4b038764c4..30d62ee4d5cd2ddacb8783b5bbbf475d592b3e02 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -99,6 +99,18 @@ public class CraftItem extends CraftEntity implements Item {
this.getHandle().age = willAge ? 0 : NO_AGE_TIME;
}
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public net.kyori.adventure.util.TriState getFrictionState() {
+ return this.getHandle().frictionState;
+ }
+
+ @Override
+ public void setFrictionState(@org.jetbrains.annotations.NotNull net.kyori.adventure.util.TriState state) {
+ java.util.Objects.requireNonNull(state, "state may not be null");
+ this.getHandle().frictionState = state;
+ }
+
@Override
public int getHealth() {
return this.getHandle().health;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 1ceaa081231a617bd87331b308c24d9c7a8dcf2b..2fd4a3068d86a37cc18c9203448823c53d590ffb 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1198,4 +1198,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
nmsStack.hurtAndBreak(amount, this.getHandle(), slot, true);
}
// Paper end - ItemStack damage API
+ // Paper start - friction API
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public net.kyori.adventure.util.TriState getFrictionState() {
+ return this.getHandle().frictionState;
+ }
+
+ @Override
+ public void setFrictionState(@org.jetbrains.annotations.NotNull net.kyori.adventure.util.TriState state) {
+ java.util.Objects.requireNonNull(state, "state may not be null");
+ this.getHandle().frictionState = state;
+ }
+ // Paper end - friction API
}

View file

@ -0,0 +1,67 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jan Villim <jan.villim@student.tuke.sk>
Date: Sat, 22 Jan 2022 17:56:19 +0100
Subject: [PATCH] Ability to control player's insomnia and phantoms
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index 721321a19ce056f82de2bef44a8791dc9d5b3418..6bf691fcc6486bde73bae30eff09142802c29eda 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -27,7 +27,18 @@ public final class EntitySelector {
};
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
public static final Predicate<Entity> CAN_BE_PICKED = EntitySelector.NO_SPECTATORS.and(Entity::isPickable);
- public static Predicate<Player> IS_INSOMNIAC = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - Add phantom creative and insomniac controls
+ // Paper start - Ability to control player's insomnia and phantoms
+ public static Predicate<Player> IS_INSOMNIAC = (player) -> {
+ net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player;
+ int playerInsomniaTicks = serverPlayer.level().paperConfig().entities.behavior.playerInsomniaStartTicks;
+
+ if (playerInsomniaTicks <= 0) {
+ return false;
+ }
+
+ return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks;
+ };
+ // Paper end - Ability to control player's insomnia and phantoms
private EntitySelector() {}
// Paper start - Affects Spawning API
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
index 7d407a7597f3ae576ac7e94bc2eb96d9dcd78dd3..021221da5d0315f6e371380a705ac6b3f6ac18d3 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
@@ -32,13 +32,22 @@ public class PhantomSpawner implements CustomSpawner {
} else if (!world.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) {
return 0;
} else {
+ // Paper start - Ability to control player's insomnia and phantoms
+ if (world.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds <= 0) {
+ return 0;
+ }
+ // Paper end - Ability to control player's insomnia and phantoms
RandomSource randomsource = world.random;
--this.nextTick;
if (this.nextTick > 0) {
return 0;
} else {
- this.nextTick += (60 + randomsource.nextInt(60)) * 20;
+ // Paper start - Ability to control player's insomnia and phantoms
+ int spawnAttemptMinSeconds = world.paperConfig().entities.behavior.phantomsSpawnAttemptMinSeconds;
+ int spawnAttemptMaxSeconds = world.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds;
+ this.nextTick += (spawnAttemptMinSeconds + randomsource.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20;
+ // Paper end - Ability to control player's insomnia and phantoms
if (world.getSkyDarken() < 5 && world.dimensionType().hasSkyLight()) {
return 0;
} else {
@@ -59,7 +68,7 @@ public class PhantomSpawner implements CustomSpawner {
int j = Mth.clamp(serverstatisticmanager.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
boolean flag2 = true;
- if (randomsource.nextInt(j) >= 72000) {
+ if (randomsource.nextInt(j) >= world.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper - Ability to control player's insomnia and phantoms
BlockPos blockposition1 = blockposition.above(20 + randomsource.nextInt(15)).east(-10 + randomsource.nextInt(21)).south(-10 + randomsource.nextInt(21));
BlockState iblockdata = world.getBlockState(blockposition1);
FluidState fluid = world.getFluidState(blockposition1);

View file

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 11 Apr 2024 16:37:44 +0100
Subject: [PATCH] Fix premature player kicks on shutdown
When the server is stopping, the default execution handler method will throw a
RejectedExecutionException in order to prevent further execution, this causes
us to lose the actual kick reason. To mitigate this, we'll use a seperate marked
class in order to gracefully ignore these.
diff --git a/src/main/java/io/papermc/paper/util/ServerStopRejectedExecutionException.java b/src/main/java/io/papermc/paper/util/ServerStopRejectedExecutionException.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c5cd77103c5a33d4349ab6b9ee2d8378bb60eb4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/ServerStopRejectedExecutionException.java
@@ -0,0 +1,20 @@
+package io.papermc.paper.util;
+
+import java.util.concurrent.RejectedExecutionException;
+
+public class ServerStopRejectedExecutionException extends RejectedExecutionException {
+ public ServerStopRejectedExecutionException() {
+ }
+
+ public ServerStopRejectedExecutionException(final String message) {
+ super(message);
+ }
+
+ public ServerStopRejectedExecutionException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public ServerStopRejectedExecutionException(final Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 4d9f1fc884050993287adfa4578a87da710623fb..a8dfe7a4b3d01bf75587be078f471d1ef1d7a667 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -285,6 +285,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
Connection.genericsFtw(packet, packetlistener);
} catch (RunningOnDifferentThreadException cancelledpackethandleexception) {
;
+ } catch (io.papermc.paper.util.ServerStopRejectedExecutionException ignored) { // Paper - do not prematurely disconnect players on stop
} catch (RejectedExecutionException rejectedexecutionexception) {
this.disconnect((Component) Component.translatable("multiplayer.disconnect.server_shutdown"));
} catch (ClassCastException classcastexception) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 027d94dd08e7789b51c8779c65d4ddad4e62f21a..53c9be615a0f2939cd989e24e304e81e6e27f39d 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2170,7 +2170,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public void executeIfPossible(Runnable runnable) {
if (this.isStopped()) {
- throw new RejectedExecutionException("Server already shutting down");
+ throw new io.papermc.paper.util.ServerStopRejectedExecutionException("Server already shutting down"); // Paper - do not prematurely disconnect players on stop
} else {
super.executeIfPossible(runnable);
}

View file

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 14 Jan 2022 10:20:40 -0800
Subject: [PATCH] Sync offhand slot in menus
Menus don't add slots for the offhand, so on sendAllDataToRemote calls the
offhand slot isn't sent. This is not correct because you *can* put stuff into the offhand
by pressing the offhand swap item
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index bb0aaa16f0de18b15764ba39a781e8b86d690bb9..72072332578f6cffea79208442c12178bc68215e 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -350,6 +350,13 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
}
+ // Paper start - Sync offhand slot in menus
+ @Override
+ public void sendOffHandSlotChange() {
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
+ }
+ // Paper end - Sync offhand slot in menus
+
@Override
public void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(handler.containerId, handler.incrementStateId(), slot, stack));
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index d830504d08c9de92797c432a868c1ee9dfc46a91..fc23e2dc42e907d5f8dc134a06102cc3e7fde515 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -228,6 +228,7 @@ public abstract class AbstractContainerMenu {
if (this.synchronizer != null) {
this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray());
+ this.synchronizer.sendOffHandSlotChange(); // Paper - Sync offhand slot in menus; update player's offhand since the offhand slot is not added to the slots for menus but can be changed by swapping from a menu slot
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java b/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
index ff4fa86f9408e83e505f7e27692d3423f8570c48..a45ef5fcffc05e4e30801b73e82d29c6dbf5b8fd 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
@@ -6,6 +6,7 @@ import net.minecraft.world.item.ItemStack;
public interface ContainerSynchronizer {
void sendInitialData(AbstractContainerMenu handler, NonNullList<ItemStack> stacks, ItemStack cursorStack, int[] properties);
+ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus
void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack);
void sendCarriedChange(AbstractContainerMenu handler, ItemStack stack);

View file

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yannick Lamprecht <yannicklamprecht@live.de>
Date: Wed, 30 Mar 2022 18:16:52 +0200
Subject: [PATCH] Player Entity Tracking Events
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 1a724f9bb6ef82a0b5fdd9ade036d7365167f14b..ec19eb88705a07db45f1a3541571fb7f43efb5a9 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1592,7 +1592,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// CraftBukkit end
if (flag) {
if (this.seenBy.add(player.connection)) {
+ // Paper start - entity tracking events
+ if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) {
this.serverEntity.addPairing(player);
+ }
+ // Paper end - entity tracking events
}
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 24834be9b5596745f9456488076bd89c3c7d2352..c34f98152866945f0c7b7cc45bbc9da6a3ac8f5c 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4069,7 +4069,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public void startSeenByPlayer(ServerPlayer player) {}
- public void stopSeenByPlayer(ServerPlayer player) {}
+ // Paper start - entity tracking events
+ public void stopSeenByPlayer(ServerPlayer player) {
+ // Since this event cannot be cancelled, we should call it here to catch all "un-tracks"
+ if (io.papermc.paper.event.player.PlayerUntrackEntityEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.player.PlayerUntrackEntityEvent(player.getBukkitEntity(), this.getBukkitEntity()).callEvent();
+ }
+ }
+ // Paper end - entity tracking events
public float rotate(Rotation rotation) {
float f = Mth.wrapDegrees(this.getYRot());

View file

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Tue, 6 Dec 2022 18:45:54 +0100
Subject: [PATCH] Limit pet look distance
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
index bf9ad63343fa07105f217625bb81ed637a7f7f7e..15d7be9ed4a973044dd4399db46aaa244730b836 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
@@ -72,7 +72,7 @@ public class FollowOwnerGoal extends Goal {
public void tick() {
boolean bl = this.tamable.shouldTryTeleportToOwner();
if (!bl) {
- this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamable.getMaxHeadXRot());
+ if (this.tamable.distanceToSqr(this.owner) <= 16 * 16) this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamable.getMaxHeadXRot()); // Paper - Limit pet look distance
}
if (--this.timeToRecalcPath <= 0) {

View file

@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 9 Dec 2022 01:47:23 -0800
Subject: [PATCH] fix Instruments
properly handle Player#playNote
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 2c38725e6fc0a264df3a0d34c21ab774ad3e2fb5..2a0ca017130a76aff3f15064a334cc0be501d782 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -781,7 +781,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
Sound instrumentSound = instrument.getSound();
if (instrumentSound == null) return;
- float pitch = note.getPitch();
+ // Paper start - use correct pitch (modeled off of NoteBlock)
+ final net.minecraft.world.level.block.state.properties.NoteBlockInstrument noteBlockInstrument = CraftBlockData.toNMS(instrument, net.minecraft.world.level.block.state.properties.NoteBlockInstrument.class);
+ final float pitch = noteBlockInstrument.isTunable() ? note.getPitch() : 1.0f;
+ // Paper end
this.getHandle().connection.send(new ClientboundSoundPacket(CraftSound.bukkitToMinecraftHolder(instrumentSound), net.minecraft.sounds.SoundSource.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, pitch, this.getHandle().getRandom().nextLong()));
}
diff --git a/src/test/java/io/papermc/paper/block/InstrumentSoundTest.java b/src/test/java/io/papermc/paper/block/InstrumentSoundTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd718ed01ba5d448cdf0a2b6a39dc7ef2337f70d
--- /dev/null
+++ b/src/test/java/io/papermc/paper/block/InstrumentSoundTest.java
@@ -0,0 +1,28 @@
+package io.papermc.paper.block;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
+import org.bukkit.Instrument;
+import org.bukkit.craftbukkit.CraftSound;
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
+import org.bukkit.support.environment.AllFeatures;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@AllFeatures
+class InstrumentSoundTest {
+
+ static Stream<Instrument> bukkitInstruments() {
+ return Arrays.stream(Instrument.values()).filter(i -> i.getSound() != null);
+ }
+
+ @ParameterizedTest
+ @MethodSource("bukkitInstruments")
+ void checkInstrumentSound(final Instrument bukkit) {
+ final NoteBlockInstrument nms = CraftBlockData.toNMS(bukkit, NoteBlockInstrument.class);
+ assertEquals(nms.getSoundEvent(), CraftSound.bukkitToMinecraftHolder(bukkit.getSound()));
+ }
+}

View file

@ -0,0 +1,78 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 6 Jul 2020 20:46:50 -0700
Subject: [PATCH] Improve inlining for some hot BlockBehavior and FluidState
methods
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index 83a3c877f2969549ea154ad86687e96fdf34d881..0665ca48fe2f8ab1ce1c0306b11be19b06445f74 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -969,15 +969,15 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.shapeExceedsCube; // Paper - moved into shape cache init
}
- public boolean useShapeForLightOcclusion() {
+ public final boolean useShapeForLightOcclusion() { // Paper - Perf: Final for inlining
return this.useShapeForLightOcclusion;
}
- public int getLightEmission() {
+ public final int getLightEmission() { // Paper - Perf: Final for inlining
return this.lightEmission;
}
- public boolean isAir() {
+ public final boolean isAir() { // Paper - Perf: Final for inlining
return this.isAir;
}
@@ -1055,7 +1055,7 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.solidRender;
}
- public boolean canOcclude() {
+ public final boolean canOcclude() { // Paper - Perf: Final for inlining
return this.canOcclude;
}
@@ -1276,11 +1276,11 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.getBlock().builtInRegistryHolder().is(key);
}
- public FluidState getFluidState() {
+ public final FluidState getFluidState() { // Paper - Perf: Final for inlining
return this.fluidState;
}
- public boolean isRandomlyTicking() {
+ public final boolean isRandomlyTicking() { // Paper - Perf: Final for inlining
return this.isRandomlyTicking;
}
diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java
index 8310cb22e2e75d8b2cca32bfe076fdafabb1b0ec..87adfe152abd1b8b4d547034576883c5d1cdf134 100644
--- a/src/main/java/net/minecraft/world/level/material/FluidState.java
+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java
@@ -26,9 +26,11 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
public static final Codec<FluidState> CODEC = codec(BuiltInRegistries.FLUID.byNameCodec(), Fluid::defaultFluidState).stable();
public static final int AMOUNT_MAX = 9;
public static final int AMOUNT_FULL = 8;
+ protected final boolean isEmpty; // Paper - Perf: moved from isEmpty()
public FluidState(Fluid fluid, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<FluidState> codec) {
super(fluid, propertyMap, codec);
+ this.isEmpty = fluid.isEmpty(); // Paper - Perf: moved from isEmpty()
}
public Fluid getType() {
@@ -44,7 +46,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public boolean isEmpty() {
- return this.getType().isEmpty();
+ return this.isEmpty; // Paper - Perf: moved into constructor
}
public float getHeight(BlockGetter world, BlockPos pos) {

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 4f397dd8e5d333cb2561d03d20511a9194314d1c..1f29b2419914ca9257db6553f01b7e7ec49bfc18 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, 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 edd6017937a7f20a1b43fa15204ec130b524b52b..2a7d896dd9a02acf6e3596e2e2e7ed50f4b88377 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 775675483c1f90fbe8e9e5eadab7d791e81983f5..5e413803f9bdc898a9a644cb123363cbdf447ad8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -875,6 +875,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,104 @@
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 0828deee077a08db8e3fe5c870f9c242b4c550cf..5c8cf225d936617b6c8d265527a19bdfa371a93b 100644
--- a/src/main/java/net/minecraft/server/ServerAdvancementManager.java
+++ b/src/main/java/net/minecraft/server/ServerAdvancementManager.java
@@ -53,6 +53,7 @@ public class ServerAdvancementManager extends SimpleJsonResourceReloadListener<A
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 4037a1057ebc87e3df6333e0d546fc85b5148d2a..eb9dab7be7da11ab1c4046a7fc4a29d5bddf31d2 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -281,6 +281,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 6c7c6cd7c071b722faf7ec06e022a6ad8b1ecc42..1a9003f703f6911e37a086f490d4d65ab9d27014 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3443,7 +3443,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/org/bukkit/craftbukkit/legacy/CraftLegacy.java b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
index 46787d68eadc789c3409c0845f3fb0be713c70cc..51ae8eddadc87b143b93521a3cef374f1e3a24dc 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"));
@@ -264,7 +265,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,184 @@
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/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 72072332578f6cffea79208442c12178bc68215e..1a7d2ade0e85dd5e6cd6c9202e3277cc2fa43d4a 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1561,7 +1561,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
Location enter = this.getBukkitEntity().getLocation();
PositionMoveRotation absolutePosition = PositionMoveRotation.calculateAbsolute(PositionMoveRotation.of(this), PositionMoveRotation.of(teleportTarget), teleportTarget.relatives());
- Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(absolutePosition.position(), worldserver.getWorld(), absolutePosition.yRot(), absolutePosition.xRot());
+ Location exit = /* (worldserver == null) ? null : // Paper - always non-null */CraftLocation.toBukkit(absolutePosition.position(), worldserver.getWorld(), absolutePosition.yRot(), absolutePosition.xRot());
PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, teleportTarget.cause());
// Paper start - gateway-specific teleport event
if (this.portalProcess != null && this.portalProcess.isSamePortal(((net.minecraft.world.level.block.EndGatewayBlock) net.minecraft.world.level.block.Blocks.END_GATEWAY)) && this.serverLevel().getBlockEntity(this.portalProcess.getEntryPosition()) instanceof net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity theEndGatewayBlockEntity) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index c34f98152866945f0c7b7cc45bbc9da6a3ac8f5c..960b3541140bfe36fda5cdb43e3408bbc9db5fde 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3740,7 +3740,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
Location enter = bukkitEntity.getLocation();
- EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius, true, creationRadius);
+ // Paper start
+ final org.bukkit.PortalType portalType = switch (cause) {
+ case END_PORTAL -> org.bukkit.PortalType.ENDER;
+ case NETHER_PORTAL -> org.bukkit.PortalType.NETHER;
+ case END_GATEWAY -> org.bukkit.PortalType.END_GATEWAY; // not actually used yet
+ default -> org.bukkit.PortalType.CUSTOM;
+ };
+ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius, true, creationRadius, portalType);
+ // Paper end
event.getEntity().getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) {
return null;
diff --git a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java
index bb4800c60ac05f2db8821737b2b884ea99b64799..a7a21f071161fb7e73a046717d2462f871ab653c 100644
--- a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java
@@ -94,6 +94,10 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal {
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
+ // Paper start - call EntityPortalEnterEvent
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type
+ if (!event.callEvent()) return;
+ // Paper end - call EntityPortalEnterEvent
BlockEntity tileentity = world.getBlockEntity(pos);
if (!world.isClientSide && tileentity instanceof TheEndGatewayBlockEntity) {
diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java
index 6ed6c2123ed4c54f191ed8cf6da72109fb95eb69..4aa14f975e1ceedf3d4a427e0daefb58b12fcafe 100644
--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java
@@ -71,8 +71,9 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
// CraftBukkit start - Entity in portal
- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()));
+ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.ENDER); // Paper - add portal type
world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) return; // Paper - make cancellable
// CraftBukkit end
if (!world.isClientSide && world.dimension() == Level.END && entity instanceof ServerPlayer) {
ServerPlayer entityplayer = (ServerPlayer) entity;
@@ -95,7 +96,7 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal {
ServerLevel worldserver1 = world.getServer().getLevel(resourcekey);
if (worldserver1 == null) {
- return new TeleportTransition(PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit- always fire event in case plugins wish to change it
+ return null; // Paper - keep previous behavior of not firing PlayerTeleportEvent if the target world doesn't exist
} else {
boolean flag = resourcekey == Level.END;
BlockPos blockposition1 = flag ? ServerLevel.END_SPAWN_POINT : worldserver1.getSharedSpawnPos();
diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
index fb361eac03c16ecee02219ff0524cce2292c7976..2b31bf586c1c0bd393d2aa8d0b6635dd9f22f21c 100644
--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
@@ -118,8 +118,9 @@ public class NetherPortalBlock extends Block implements Portal {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
// CraftBukkit start - Entity in portal
- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()));
+ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.NETHER); // Paper - add portal type
world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) return; // Paper - make cancellable
// CraftBukkit end
entity.setAsInsidePortal(this, pos);
}
@@ -151,7 +152,7 @@ public class NetherPortalBlock extends Block implements Portal {
// Paper end - Add EntityPortalReadyEvent
if (worldserver1 == null) {
- return new TeleportTransition(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); // always fire event in case plugins wish to change it
+ return null; // Paper - keep previous behavior of not firing PlayerTeleportEvent if the target world doesn't exist
} else {
boolean flag = worldserver1.getTypeKey() == LevelStem.NETHER;
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/level/portal/DimensionTransition.java b/src/main/java/net/minecraft/world/level/portal/DimensionTransition.java
new file mode 100644
index 0000000000000000000000000000000000000000..36c8735312c885eb153f4ffdf0f2a5495e9c9f65
--- /dev/null
+++ b/src/main/java/net/minecraft/world/level/portal/DimensionTransition.java
@@ -0,0 +1,75 @@
+package net.minecraft.world.level.portal;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.network.protocol.game.ClientboundLevelEventPacket;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.event.player.PlayerTeleportEvent;
+
+public record DimensionTransition(ServerLevel newLevel, Vec3 pos, Vec3 speed, float yRot, float xRot, boolean missingRespawnBlock, DimensionTransition.PostDimensionTransition postDimensionTransition, PlayerTeleportEvent.TeleportCause cause) {
+
+ public DimensionTransition(ServerLevel newLevel, Vec3 pos, Vec3 speed, float yRot, float xRot, boolean missingRespawnBlock, DimensionTransition.PostDimensionTransition postDimensionTransition) {
+ this(newLevel, pos, speed, yRot, xRot, missingRespawnBlock, postDimensionTransition, PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ }
+
+ // Paper - remove unused constructor (for safety)
+ // CraftBukkit end
+
+ public static final DimensionTransition.PostDimensionTransition DO_NOTHING = (entity) -> {
+ };
+ public static final DimensionTransition.PostDimensionTransition PLAY_PORTAL_SOUND = DimensionTransition::playPortalSound;
+ public static final DimensionTransition.PostDimensionTransition PLACE_PORTAL_TICKET = DimensionTransition::placePortalTicket;
+
+ public DimensionTransition(ServerLevel world, Vec3 pos, Vec3 velocity, float yaw, float pitch, DimensionTransition.PostDimensionTransition postDimensionTransition) {
+ // CraftBukkit start
+ this(world, pos, velocity, yaw, pitch, postDimensionTransition, PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ }
+
+ public DimensionTransition(ServerLevel worldserver, Vec3 vec3d, Vec3 vec3d1, float f, float f1, DimensionTransition.PostDimensionTransition dimensiontransition_a, PlayerTeleportEvent.TeleportCause cause) {
+ this(worldserver, vec3d, vec3d1, f, f1, false, dimensiontransition_a, cause);
+ }
+
+ public DimensionTransition(ServerLevel world, Entity entity, DimensionTransition.PostDimensionTransition postDimensionTransition) {
+ this(world, entity, postDimensionTransition, PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ }
+
+ public DimensionTransition(ServerLevel worldserver, Entity entity, DimensionTransition.PostDimensionTransition dimensiontransition_a, PlayerTeleportEvent.TeleportCause cause) {
+ this(worldserver, findAdjustedSharedSpawnPos(worldserver, entity), Vec3.ZERO, worldserver.getSharedSpawnAngle(), 0.0F, false, dimensiontransition_a, cause); // Paper - MC-200092 - fix spawn pos yaw being ignored
+ // CraftBukkit end
+ }
+
+ private static void playPortalSound(Entity entity) {
+ if (entity instanceof ServerPlayer entityplayer) {
+ entityplayer.connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false));
+ }
+
+ }
+
+ private static void placePortalTicket(Entity entity) {
+ entity.placePortalTicket(BlockPos.containing(entity.position()));
+ }
+
+ public static DimensionTransition missingRespawnBlock(ServerLevel world, Entity entity, DimensionTransition.PostDimensionTransition postDimensionTransition) {
+ return new DimensionTransition(world, findAdjustedSharedSpawnPos(world, entity), Vec3.ZERO, world.getSharedSpawnAngle(), 0.0F, true, postDimensionTransition); // Paper - MC-200092 - fix spawn pos yaw being ignored
+ }
+
+ private static Vec3 findAdjustedSharedSpawnPos(ServerLevel world, Entity entity) {
+ return entity.adjustSpawnLocation(world, world.getSharedSpawnPos()).getBottomCenter();
+ }
+
+ @FunctionalInterface
+ public interface PostDimensionTransition {
+
+ void onTransition(Entity entity);
+
+ default DimensionTransition.PostDimensionTransition then(DimensionTransition.PostDimensionTransition next) {
+ return (entity) -> {
+ this.onTransition(entity);
+ next.onTransition(entity);
+ };
+ }
+ }
+}

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 ba4dfa26f4d54abe9ecbacfe1f409a34fb769579..6c2d4c2163cf299c0943af21d4dc367b5677c089 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 || !(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(this.level().getWorldBorder(), this.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) && this.level().getWorldBorder().isInsideCloseToBorder(this, this.getBoundingBox())))); // Paper - Add config option for spider worldborder climbing (Inflate by +EPSILON as collision will just barely place us outside border)
}
}

View file

@ -0,0 +1,31 @@
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
Co-authored-by: david <mrminecraft00@gmail.com>
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 1a9003f703f6911e37a086f490d4d65ab9d27014..e29cae56ddeb019d2ffd8dad412fd32e4db67091 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2070,7 +2070,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private void performUnsignedChatCommand(String command) {
// CraftBukkit start
String command1 = "/" + command;
+ if (org.spigotmc.SpigotConfig.logCommands) { // Paper - Add missing SpigotConfig logCommands check
ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command1);
+ }
PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command1, new LazyPlayerSet(this.server));
this.cserver.getPluginManager().callEvent(event);
@@ -2110,7 +2112,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 30e0a5fe3f9bd85d2b702c2c877c5682ed35d461..aca888c2f02b09ac6739bdc81b194c4527dd69f5 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -196,6 +196,7 @@ public abstract class Player extends LivingEntity {
private boolean ignoreFallDamageFromCurrentImpulse;
private int currentImpulseContextResetGraceTime;
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;
@@ -1651,7 +1652,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 2a0ca017130a76aff3f15064a334cc0be501d782..83a121331e3922ed8b90e530c2495bf19406c08d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2594,6 +2594,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,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 960b3541140bfe36fda5cdb43e3408bbc9db5fde..2c959a99376ed479415354c481801643c5f6b1a1 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 type, 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 {
@@ -1059,7 +1060,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 ab02f4ca0bb8cd4939f167b410db208e38f7102b..6b2f0a4bc911888b72b796099760af38b1e28656 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -579,6 +579,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 e29cae56ddeb019d2ffd8dad412fd32e4db67091..d77ab963802fcd7551058987a534ba54f080027a 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3481,7 +3481,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 8e71eeb5be2df1352447f3662a6d092a7db9e2d0..4fe3024e26b56c2d796acf703a1bc200ff309f09 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -365,6 +365,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);
@@ -372,12 +373,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 abcb1065100597f66c9f76fdae5f873fa0d8f315..447fb76a3eb1505b1ef1e1aed8a11239c0124f4f 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1674,7 +1674,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 83a121331e3922ed8b90e530c2495bf19406c08d..76d8f0d390abf588886b42b6d2e3ed6f79a4d991 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1318,6 +1318,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 502be683e8b04a9966043c9bee9d9fe793b12ef5..134db8c2dd72d0651fc889cc8931e7c971f62deb 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -198,7 +198,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;
}
}