More more more more more more more more more more more more more more more work

This commit is contained in:
Nassim Jahnke 2021-11-24 17:39:04 +01:00 committed by MiniDigger | Martin
parent 97a4a70766
commit 26dcf812a4
71 changed files with 199 additions and 213 deletions

View file

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 15:22:44 +0200
Subject: [PATCH] Add more Evoker API
diff --git a/src/main/java/org/bukkit/entity/Evoker.java b/src/main/java/org/bukkit/entity/Evoker.java
index f8d173adc09197418883dc7bc66dd8bfff8c5c72..76f81cd124090337876c9e5e469862a1c8da4ec8 100644
--- a/src/main/java/org/bukkit/entity/Evoker.java
+++ b/src/main/java/org/bukkit/entity/Evoker.java
@@ -64,4 +64,19 @@ public interface Evoker extends Spellcaster {
*/
@Deprecated
void setCurrentSpell(@Nullable Spell spell);
+
+ // Paper start
+ /**
+ * @return the sheep being targeted by the {@link Spell#WOLOLO wololo spell}, or {@code null} if none
+ */
+ @Nullable
+ Sheep getWololoTarget();
+
+ /**
+ * Set the sheep to be the target of the {@link Spell#WOLOLO wololo spell}, or {@code null} to clear.
+ *
+ * @param sheep new wololo target
+ */
+ void setWololoTarget(@Nullable Sheep sheep);
+ // Paper end
}

View file

@ -1,382 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 11 Aug 2020 19:17:46 +0200
Subject: [PATCH] Add methods to get translation keys
Co-authored-by: MeFisto94 <MeFisto94@users.noreply.github.com>
diff --git a/src/main/java/org/bukkit/Difficulty.java b/src/main/java/org/bukkit/Difficulty.java
index 3f6cbefc2b1414ba2dad709e79288013b3ef73be..122884098f08c9aa5e144876746b5ce4e8f1a4b6 100644
--- a/src/main/java/org/bukkit/Difficulty.java
+++ b/src/main/java/org/bukkit/Difficulty.java
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents the various difficulty levels that are available.
*/
-public enum Difficulty {
+public enum Difficulty implements net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
/**
* Players regain health over time, hostile mobs don't spawn, the hunger
* bar does not deplete.
@@ -51,6 +51,12 @@ public enum Difficulty {
return value;
}
+ // Paper start
+ @Override
+ public @org.jetbrains.annotations.NotNull String translationKey() {
+ return "options.difficulty." + this.name().toLowerCase(java.util.Locale.ENGLISH);
+ }
+ // Paper end
/**
* Gets the Difficulty represented by the specified value
*
diff --git a/src/main/java/org/bukkit/FireworkEffect.java b/src/main/java/org/bukkit/FireworkEffect.java
index 4a97e73ce59c0eee77661967f1d3ac23508aae3e..d543b2b6aa131efec9b978d0b71a228f79a31f9a 100644
--- a/src/main/java/org/bukkit/FireworkEffect.java
+++ b/src/main/java/org/bukkit/FireworkEffect.java
@@ -18,28 +18,44 @@ public final class FireworkEffect implements ConfigurationSerializable {
/**
* The type or shape of the effect.
*/
- public enum Type {
+ public enum Type implements net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
/**
* A small ball effect.
*/
- BALL,
+ BALL("small_ball"), // Paper - add name
/**
* A large ball effect.
*/
- BALL_LARGE,
+ BALL_LARGE("large_ball"), // Paper - add name
/**
* A star-shaped effect.
*/
- STAR,
+ STAR("star"), // Paper - add name
/**
* A burst effect.
*/
- BURST,
+ BURST("burst"), // Paper - add name
/**
* A creeper-face effect.
*/
- CREEPER,
+ CREEPER("creeper"), // Paper - add name
;
+ // Paper start
+ /**
+ * The name map.
+ */
+ public static final net.kyori.adventure.util.Index<String, org.bukkit.FireworkEffect.Type> NAMES = net.kyori.adventure.util.Index.create(Type.class, type -> type.name);
+ private final String name;
+
+ Type(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public @NotNull String translationKey() {
+ return "item.minecraft.firework_star.shape." + this.name;
+ }
+ // Paper end
}
/**
diff --git a/src/main/java/org/bukkit/GameRule.java b/src/main/java/org/bukkit/GameRule.java
index 442db40bc6ea2cfd2f724807544a080bb62bd8c5..d3365e44e64c2e72416d3a50be20ada79320ba2a 100644
--- a/src/main/java/org/bukkit/GameRule.java
+++ b/src/main/java/org/bukkit/GameRule.java
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
*
* @param <T> type of rule (Boolean or Integer)
*/
-public final class GameRule<T> {
+public final class GameRule<T> implements net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
private static Map<String, GameRule<?>> gameRules = new HashMap<>();
// Boolean rules
@@ -283,4 +283,11 @@ public final class GameRule<T> {
public static GameRule<?>[] values() {
return gameRules.values().toArray(new GameRule<?>[gameRules.size()]);
}
+
+ // Paper start
+ @Override
+ public @NotNull String translationKey() {
+ return "gamerule." + this.name;
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
index 58c3ab444d484ac781810e26e04b9919eaff3bf2..b637686404f0aa87c6996220987ed4a303496b43 100644
--- a/src/main/java/org/bukkit/Material.java
+++ b/src/main/java/org/bukkit/Material.java
@@ -100,7 +100,7 @@ import org.jetbrains.annotations.Nullable;
* An enum of all material IDs accepted by the official server and client
*/
@SuppressWarnings({"DeprecatedIsStillUsed", "deprecation"}) // Paper
-public enum Material implements Keyed {
+public enum Material implements Keyed, net.kyori.adventure.translation.Translatable { // Paper
//<editor-fold desc="Materials" defaultstate="collapsed">
AIR(9648, 0),
STONE(22948),
@@ -3984,6 +3984,23 @@ public enum Material implements Keyed {
}
return false;
}
+
+ /**
+ * Return the translation key for the Material, so the client can translate it into the active
+ * locale when using a TranslatableComponent.
+ * @return the translation key
+ * @deprecated use {@link #translationKey()}
+ */
+ @NotNull
+ @Deprecated
+ public String getTranslationKey() {
+ return this.translationKey();
+ }
+
+ @Override
+ public @NotNull String translationKey() {
+ return Bukkit.getUnsafe().getTranslationKey(this);
+ }
// Paper end
/**
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index e348034288c74ab80360086d71f0b7f61551df24..2d9264ffe0fee863f1b814952ef063daa7962d76 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -101,5 +101,34 @@ public interface UnsafeValues {
byte[] serializeItem(ItemStack item);
ItemStack deserializeItem(byte[] data);
+
+ /**
+ * Return the translation key for the Material, so the client can translate it into the active
+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
+ * @return the translation key
+ */
+ String getTranslationKey(Material mat);
+
+ /**
+ * Return the translation key for the Block, so the client can translate it into the active
+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
+ * @return the translation key
+ */
+ String getTranslationKey(org.bukkit.block.Block block);
+
+ /**
+ * Return the translation key for the EntityType, so the client can translate it into the active
+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.<br>
+ * This is <code>null</code>, when the EntityType isn't known to NMS (custom entities)
+ * @return the translation key
+ */
+ String getTranslationKey(org.bukkit.entity.EntityType type);
+
+ /**
+ * Return the translation key for the ItemStack, so the client can translate it into the active
+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.<br>
+ * @return the translation key
+ */
+ String getTranslationKey(ItemStack itemStack);
// Paper end
}
diff --git a/src/main/java/org/bukkit/attribute/Attribute.java b/src/main/java/org/bukkit/attribute/Attribute.java
index 13eac9ad2c1672051635d1c35cc49239252e7a61..107e36ef02a9481954bd770ce9a55a0b1e84be7a 100644
--- a/src/main/java/org/bukkit/attribute/Attribute.java
+++ b/src/main/java/org/bukkit/attribute/Attribute.java
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
/**
* Types of attributes which may be present on an {@link Attributable}.
*/
-public enum Attribute implements Keyed {
+public enum Attribute implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
/**
* Maximum health of an Entity.
@@ -73,4 +73,10 @@ public enum Attribute implements Keyed {
public NamespacedKey getKey() {
return key;
}
+ // Paper start
+ @Override
+ public @NotNull String translationKey() {
+ return "attribute.name." + this.key.getKey();
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
index 25294bd8c4faa05af1429d934c5666742e3ee23c..271ebba09fd9248717750e998668ae6fe013bacc 100644
--- a/src/main/java/org/bukkit/block/Block.java
+++ b/src/main/java/org/bukkit/block/Block.java
@@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
* (i.e. lighting and power) may not be able to be safely accessed during world
* generation when used in cases like BlockPhysicsEvent!!!!
*/
-public interface Block extends Metadatable {
+public interface Block extends Metadatable, net.kyori.adventure.translation.Translatable { // Paper - translatable
/**
* Gets the metadata for this block
@@ -618,5 +618,15 @@ public interface Block extends Metadatable {
*/
@NotNull
com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup();
+
+ /**
+ * Return the translation key for the Block, so the client can translate it into the active
+ * locale when using a TranslatableComponent.
+ * @return the translation key
+ * @deprecated use {@link #translationKey()}
+ */
+ @NotNull
+ @Deprecated
+ String getTranslationKey();
// Paper end
}
diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java
index 8eb0497c81744874809ebc4bc2e28b128e66a926..b277034fee2d4f38c40713842d14a8f6dde757aa 100644
--- a/src/main/java/org/bukkit/enchantments/Enchantment.java
+++ b/src/main/java/org/bukkit/enchantments/Enchantment.java
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
/**
* The various type of enchantments that may be added to armour or weapons
*/
-public abstract class Enchantment implements Keyed {
+public abstract class Enchantment implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
/**
* Provides protection against environmental damage
*/
diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
index 4d5f0837bd0e02a30c943d8969fb6b13452322e0..a39f9c078f42451bd122f3e3729d10ca299bee5f 100644
--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
+++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
@@ -69,5 +69,10 @@ public class EnchantmentWrapper extends Enchantment {
public net.kyori.adventure.text.Component displayName(int level) {
return getEnchantment().displayName(level);
}
+
+ @Override
+ public @NotNull String translationKey() {
+ return getEnchantment().translationKey();
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java
index 9be5371c7f398d0ec8241403661415ff40661067..d36d314383713bac3b11f18d95b0809dce3cd6e0 100644
--- a/src/main/java/org/bukkit/entity/EntityType.java
+++ b/src/main/java/org/bukkit/entity/EntityType.java
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public enum EntityType implements Keyed {
+public enum EntityType implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - translatable
// These strings MUST match the strings in nms.EntityTypes and are case sensitive.
/**
@@ -419,4 +419,27 @@ public enum EntityType implements Keyed {
public boolean isAlive() {
return living;
}
+ // Paper start
+ /**
+ * Return the translation key for the EntityType, so the client can translate it into the active
+ * locale when using a TranslatableComponent.<br>
+ * This is <code>null</code>, when the EntityType isn't known to NMS (custom entities)
+ * @return the translation key
+ * @deprecated use {@link #translationKey()}
+ */
+ @Deprecated
+ @Nullable
+ public String getTranslationKey() {
+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the entity does not have a translation key (is probably a custom entity)
+ */
+ @Override
+ public @NotNull String translationKey() {
+ Preconditions.checkArgument(this != UNKNOWN, "UNKNOWN entities do not have translation keys");
+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java
index 511b96841f7342d0a6b38d7cff56252ea8ef9bfe..02ecc87a90bbd81e7d21279fac701ba41c74fd9f 100644
--- a/src/main/java/org/bukkit/entity/Villager.java
+++ b/src/main/java/org/bukkit/entity/Villager.java
@@ -148,7 +148,7 @@ public interface Villager extends AbstractVillager {
* Represents the various different Villager professions there may be.
* Villagers have different trading options depending on their profession,
*/
- public enum Profession implements Keyed {
+ public enum Profession implements Keyed, net.kyori.adventure.translation.Translatable { // Paper
NONE,
/**
* Armorer profession. Wears a black apron. Armorers primarily trade for
@@ -231,6 +231,13 @@ public interface Villager extends AbstractVillager {
public NamespacedKey getKey() {
return key;
}
+
+ // Paper start
+ @Override
+ public @NotNull String translationKey() {
+ return "entity.minecraft.villager." + this.key.getKey();
+ }
+ // Paper end
}
// Paper start - Add villager reputation API
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
index b80ef2e5c23764ee68f809268185492bf5577913..e6eab5d8ca3fea8d2e0ccc1cd1c1a7a110b589db 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
* use this class to encapsulate Materials for which {@link Material#isItem()}
* returns false.</b>
*/
-public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowItem> { // Paper
+public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowItem>, net.kyori.adventure.translation.Translatable { // Paper
private Material type = Material.AIR;
private int amount = 0;
private MaterialData data = null;
@@ -852,5 +852,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor
ItemMeta itemMeta = getItemMeta();
return itemMeta != null && itemMeta.hasItemFlag(flag);
}
+
+ /**
+ * Gets the translation key for this itemstack.
+ * This is not the same as getting the translation key
+ * for the material of this itemstack.
+ *
+ * @return the translation key
+ * @deprecated use {@link #translationKey()}
+ */
+ @NotNull
+ @Deprecated
+ public String getTranslationKey() {
+ return this.translationKey();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This is not the same as getting the translation key
+ * for the material of this itemstack.
+ */
+ @Override
+ public @NotNull String translationKey() {
+ return Bukkit.getUnsafe().getTranslationKey(this);
+ }
// Paper end
}

View file

@ -1,73 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ysl3000 <yannicklamprecht@live.de>
Date: Mon, 6 Jul 2020 22:17:37 +0200
Subject: [PATCH] Create HoverEvent from ItemStack Entity
diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java
index d773e8594f91017bddd7ea8aada3a1ff2781d05b..0a4466c6ca519c3a5da76ff870fb2a4e3a06effd 100644
--- a/src/main/java/org/bukkit/inventory/ItemFactory.java
+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
@@ -184,5 +184,62 @@ public interface ItemFactory {
*/
@NotNull
ItemStack ensureServerConversions(@NotNull ItemStack item);
+
+ /**
+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying.
+ *
+ * @param itemStack
+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack
+ */
+ @NotNull
+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull ItemStack itemStack);
+
+ /**
+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying.
+ * Uses the display name of the entity, if present.
+ *
+ * @param entity Entity to create the HoverEvent for
+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity}
+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent()}
+ */
+ @NotNull
+ @Deprecated
+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity);
+
+ /**
+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying.
+ *
+ * @param entity Entity to create the HoverEvent for
+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed
+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity}
+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)}
+ */
+ @NotNull
+ @Deprecated
+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable String customName);
+
+ /**
+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying.
+ *
+ * @param entity Entity to create the HoverEvent for
+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed
+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity}
+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)}
+ */
+ @NotNull
+ @Deprecated
+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable net.md_5.bungee.api.chat.BaseComponent customName);
+
+ /**
+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying.
+ *
+ * @param entity Entity to create the HoverEvent for
+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed
+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity}
+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)}
+ */
+ @NotNull
+ @Deprecated
+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName);
// Paper end
}

View file

@ -1,103 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Wed, 26 Aug 2020 02:11:58 -0400
Subject: [PATCH] Add additional open container api to HumanEntity
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
index 9cb7a9b1e1d7c20760a54bdf6aea346828ad8fc7..aae6331de24c1a65e3f708cfdc3890364bc8e681 100644
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
@@ -153,6 +153,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
@Nullable
public InventoryView openMerchant(@NotNull Merchant merchant, boolean force);
+ // Paper start - Add additional containers
+ /**
+ * Opens an empty anvil inventory window with the player's inventory
+ * on the bottom.
+ *
+ * @param location The location to attach it to. If null, the player's
+ * location is used.
+ * @param force If false, and there is no anvil block at the location,
+ * no inventory will be opened and null will be returned.
+ * @return The newly opened inventory view, or null if it could not be
+ * opened.
+ */
+ @Nullable
+ public InventoryView openAnvil(@Nullable Location location, boolean force);
+
+ /**
+ * Opens an empty cartography table inventory window with the player's inventory
+ * on the bottom.
+ *
+ * @param location The location to attach it to. If null, the player's
+ * location is used.
+ * @param force If false, and there is no cartography table block at the location,
+ * no inventory will be opened and null will be returned.
+ * @return The newly opened inventory view, or null if it could not be
+ * opened.
+ */
+ @Nullable
+ public InventoryView openCartographyTable(@Nullable Location location, boolean force);
+
+ /**
+ * Opens an empty grindstone inventory window with the player's inventory
+ * on the bottom.
+ *
+ * @param location The location to attach it to. If null, the player's
+ * location is used.
+ * @param force If false, and there is no grindstone block at the location,
+ * no inventory will be opened and null will be returned.
+ * @return The newly opened inventory view, or null if it could not be
+ * opened.
+ */
+ @Nullable
+ public InventoryView openGrindstone(@Nullable Location location, boolean force);
+
+ /**
+ * Opens an empty loom inventory window with the player's inventory
+ * on the bottom.
+ *
+ * @param location The location to attach it to. If null, the player's
+ * location is used.
+ * @param force If false, and there is no loom block at the location,
+ * no inventory will be opened and null will be returned.
+ * @return The newly opened inventory view, or null if it could not be
+ * opened.
+ */
+ @Nullable
+ public InventoryView openLoom(@Nullable Location location, boolean force);
+
+ /**
+ * Opens an empty smithing table inventory window with the player's inventory
+ * on the bottom.
+ *
+ * @param location The location to attach it to. If null, the player's
+ * location is used.
+ * @param force If false, and there is no smithing table block at the location,
+ * no inventory will be opened and null will be returned.
+ * @return The newly opened inventory view, or null if it could not be
+ * opened.
+ */
+ @Nullable
+ public InventoryView openSmithingTable(@Nullable Location location, boolean force);
+
+ /**
+ * Opens an empty stonecutter inventory window with the player's inventory
+ * on the bottom.
+ *
+ * @param location The location to attach it to. If null, the player's
+ * location is used.
+ * @param force If false, and there is no stonecutter block at the location,
+ * no inventory will be opened and null will be returned.
+ * @return The newly opened inventory view, or null if it could not be
+ * opened.
+ */
+ @Nullable
+ public InventoryView openStonecutter(@Nullable Location location, boolean force);
+ // Paper end
+
/**
* Force-closes the currently open inventory view for this player, if any.
*/

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MeFisto94 <MeFisto94@users.noreply.github.com>
Date: Fri, 28 Aug 2020 01:41:31 +0200
Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and
non-conflicting Entity Ids
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index 2d9264ffe0fee863f1b814952ef063daa7962d76..84eda68281c6c6968d95b1313a33696c3a9980d4 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -130,5 +130,12 @@ public interface UnsafeValues {
* @return the translation key
*/
String getTranslationKey(ItemStack itemStack);
+
+ /**
+ * Creates and returns the next EntityId available.
+ * <p>
+ * Use this when sending custom packets, so that there are no collisions on the client or server.
+ */
+ public int nextEntityId();
// Paper end
}

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 21:39:07 -0500
Subject: [PATCH] Entity#isTicking
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index c729cb44290cd719e7684fd919bf74300484b883..57717976b5281ecf316064793f300426d0983a32 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -755,5 +755,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
* Check if entity is in lava
*/
public boolean isInLava();
+
+ /**
+ * Check if entity is inside a ticking chunk
+ */
+ public boolean isTicking();
// Paper end
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aurora <aurora@relanet.eu>
Date: Sat, 3 Oct 2020 16:28:41 +0200
Subject: [PATCH] Clarify the Javadocs for Entity.getEntitySpawnReason()
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 57717976b5281ecf316064793f300426d0983a32..b02704b0535522c5535b560105eec2885fdd3e77 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -721,7 +721,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
}
/**
- * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity.
+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that initially spawned this entity. <!-- Paper - added "initially" to clarify that the SpawnReason doesn't change after the Entity was initially spawned" -->
*/
@NotNull
org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason();

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Mon, 7 Oct 2019 00:15:28 -0500
Subject: [PATCH] Villager#resetOffers
diff --git a/src/main/java/org/bukkit/entity/AbstractVillager.java b/src/main/java/org/bukkit/entity/AbstractVillager.java
index d2b0c08554dba4d34b37b440f1d77ae0e64cb99e..7fbe31c4fd69d4fca7ef96c0a56b0e0204d60cf4 100644
--- a/src/main/java/org/bukkit/entity/AbstractVillager.java
+++ b/src/main/java/org/bukkit/entity/AbstractVillager.java
@@ -21,4 +21,11 @@ public interface AbstractVillager extends Breedable, NPC, InventoryHolder, Merch
@NotNull
@Override
Inventory getInventory();
+
+ // Paper start
+ /**
+ * Reset this villager's trade offers
+ */
+ public void resetOffers();
+ // Paper end
}

View file

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Tue, 14 Apr 2020 12:06:14 +0200
Subject: [PATCH] Player elytra boost API
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index d0d44acb364bafca80e6efa04532b66663ca336a..e3d56cc4122de5237b89ed670493eecd3413b2b6 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -2116,6 +2116,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/
@NotNull
<T> T getClientOption(@NotNull ClientOption<T> option);
+
+ /**
+ * Boost a Player that's {@link #isGliding()} using a {@link Firework}.
+ * If the creation of the entity is cancelled, no boosting is done.
+ * This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}.
+ *
+ * @param firework The {@link Material#FIREWORK_ROCKET} to boost the player with
+ * @return The {@link Firework} boosting the Player or null if the spawning of the entity was cancelled
+ * @throws IllegalArgumentException if {@link #isGliding()} is false
+ * or if the {@code firework} isn't a {@link Material#FIREWORK_ROCKET}
+ */
+ @Nullable
+ Firework boostElytra(@NotNull ItemStack firework);
// Paper end
// Spigot start

View file

@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: oxygencraft <21054297+oxygencraft@users.noreply.github.com>
Date: Sun, 25 Oct 2020 18:35:58 +1100
Subject: [PATCH] Add getOfflinePlayerIfCached(String)
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 1171971a8f9b566ddc6f529845bc8e4ac11a112f..5b95ef65a8cffbb303952c071d0addc7430bd1c4 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -1081,6 +1081,27 @@ public final class Bukkit {
return server.getOfflinePlayer(name);
}
+ // Paper start
+ /**
+ * Gets the player by the given name, regardless if they are offline or
+ * online.
+ * <p>
+ * This will not make a web request to get the UUID for the given name,
+ * thus this method will not block. However this method will return
+ * {@code null} if the player is not cached.
+ * </p>
+ *
+ * @param name the name of the player to retrieve
+ * @return an offline player if cached, {@code null} otherwise
+ * @see #getOfflinePlayer(String)
+ * @see #getOfflinePlayer(java.util.UUID)
+ */
+ @Nullable
+ public static OfflinePlayer getOfflinePlayerIfCached(@NotNull String name) {
+ return server.getOfflinePlayerIfCached(name);
+ }
+ // Paper end
+
/**
* Gets the player by the given UUID, regardless if they are offline or
* online.
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 221bc443695289a21aee9f7ac7d8453fea3f774e..95b07b5c13291203cde6653b2de400ff8430011f 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -914,6 +914,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@NotNull
public OfflinePlayer getOfflinePlayer(@NotNull String name);
+ // Paper start
+ /**
+ * Gets the player by the given name, regardless if they are offline or
+ * online.
+ * <p>
+ * This will not make a web request to get the UUID for the given name,
+ * thus this method will not block. However this method will return
+ * {@code null} if the player is not cached.
+ * </p>
+ *
+ * @param name the name of the player to retrieve
+ * @return an offline player if cached, {@code null} otherwise
+ * @see #getOfflinePlayer(String)
+ * @see #getOfflinePlayer(java.util.UUID)
+ */
+ @Nullable
+ public OfflinePlayer getOfflinePlayerIfCached(@NotNull String name);
+ // Paper end
+
/**
* Gets the player by the given UUID, regardless if they are offline or
* online.

View file

@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Mon, 9 Nov 2020 20:33:38 +0100
Subject: [PATCH] Add ignore discounts API
diff --git a/src/main/java/org/bukkit/inventory/MerchantRecipe.java b/src/main/java/org/bukkit/inventory/MerchantRecipe.java
index 1fb4a1c53791776f9c5a952a592f15fc35cb2703..2be2f3fe655c417bfc8f8e840f9e9415d168f37e 100644
--- a/src/main/java/org/bukkit/inventory/MerchantRecipe.java
+++ b/src/main/java/org/bukkit/inventory/MerchantRecipe.java
@@ -28,6 +28,7 @@ public class MerchantRecipe implements Recipe {
private boolean experienceReward;
private int villagerExperience;
private float priceMultiplier;
+ private boolean ignoreDiscounts; // Paper
public MerchantRecipe(@NotNull ItemStack result, int maxUses) {
this(result, 0, maxUses, false);
@@ -38,6 +39,12 @@ public class MerchantRecipe implements Recipe {
}
public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier) {
+ // Paper start - add ignoreDiscounts param
+ this(result, uses, maxUses, experienceReward, villagerExperience, priceMultiplier, false);
+ }
+ public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier, boolean ignoreDiscounts) {
+ this.ignoreDiscounts = ignoreDiscounts;
+ // Paper end
this.result = result;
this.uses = uses;
this.maxUses = maxUses;
@@ -172,4 +179,20 @@ public class MerchantRecipe implements Recipe {
public void setPriceMultiplier(float priceMultiplier) {
this.priceMultiplier = priceMultiplier;
}
+
+ // Paper start
+ /**
+ * @return Whether all discounts on this trade should be ignored.
+ */
+ public boolean shouldIgnoreDiscounts() {
+ return ignoreDiscounts;
+ }
+
+ /**
+ * @param ignoreDiscounts Whether all discounts on this trade should be ignored.
+ */
+ public void setIgnoreDiscounts(boolean ignoreDiscounts) {
+ this.ignoreDiscounts = ignoreDiscounts;
+ }
+ // Paper end
}

View file

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alfie Smith <alfie@alfiesmith.net>
Date: Sat, 7 Nov 2020 01:20:27 +0000
Subject: [PATCH] Item no age & no player pickup
diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java
index c404a5b8efea7c780db5ddae19456753808abb3d..0ee072645ecf1bf5feb74de6960947ef76db366e 100644
--- a/src/main/java/org/bukkit/entity/Item.java
+++ b/src/main/java/org/bukkit/entity/Item.java
@@ -90,5 +90,34 @@ public interface Item extends Entity {
* @param canMobPickup True to allow non-player entity pickup
*/
public void setCanMobPickup(boolean canMobPickup);
+
+ /**
+ * Gets whether the player can pickup the item or not
+ *
+ * @return True if a player can pickup the item
+ */
+ public boolean canPlayerPickup();
+
+ /**
+ * Sets whether the item can be picked up or not. Modifies the pickup delay value to do so.
+ *
+ * @param canPlayerPickup True if the player can pickup the item
+ */
+ public void setCanPlayerPickup(boolean canPlayerPickup);
+
+ /**
+ * Gets whether the item will age and despawn from being on the ground too long
+ *
+ * @return True if the item will age
+ */
+ public boolean willAge();
+
+ /**
+ * Sets whether the item will age or not. If the item is not ageing, it will not despawn
+ * by being on the ground for too long.
+ *
+ * @param willAge True if the item should age
+ */
+ public void setWillAge(boolean willAge);
// Paper end
}

View file

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 24 Jun 2020 12:38:15 -0600
Subject: [PATCH] Beacon API - custom effect ranges
diff --git a/src/main/java/org/bukkit/block/Beacon.java b/src/main/java/org/bukkit/block/Beacon.java
index 6349fa9da3f96df3553fb9552c1cab95338cecb0..78475fc6faff0f295828d7b53792001d51aa2889 100644
--- a/src/main/java/org/bukkit/block/Beacon.java
+++ b/src/main/java/org/bukkit/block/Beacon.java
@@ -64,4 +64,26 @@ public interface Beacon extends TileState, Lockable, Nameable {
* @param effect desired secondary effect
*/
void setSecondaryEffect(@Nullable PotionEffectType effect);
+
+ // Paper start - Custom effect ranges
+ /**
+ * Gets the effect range of this beacon.
+ * A negative range value means the beacon is using its default range based on tier.
+ * @return Either the custom range set with {@link #setEffectRange(double)} or the range based on the beacon tier.
+ */
+ double getEffectRange();
+
+ /**
+ * Sets the effect range of the beacon
+ * A negative range value means the beacon is using its default range based on tier.
+ * @param range Radius of effect range.
+ */
+ void setEffectRange(double range);
+
+ /**
+ * Resets the custom range from this beacon and falls back to the range based on the the beacon tier.
+ * Shortcut for setting the effect range to a negative number.
+ */
+ void resetEffectRange();
+ // Paper end
}

View file

@ -1,79 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 14 Nov 2020 16:19:58 +0100
Subject: [PATCH] Add API for quit reason
diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java
index 849e8f10dd77e9fb46aab17752b8f1ff79e9d42e..b6016aa1e91863efc252eecab69ade6f54c89f27 100644
--- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java
+++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java
@@ -11,16 +11,28 @@ import org.jetbrains.annotations.Nullable;
public class PlayerQuitEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private net.kyori.adventure.text.Component quitMessage; // Paper
+ private final QuitReason reason; // Paper
@Deprecated // Paper
public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) {
+ // Paper start
+ this(who, quitMessage, null);
+ }
+ @Deprecated // Paper
+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage, @Nullable QuitReason quitReason) {
super(who);
this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper
+ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason;
}
// Paper start
+ @Deprecated
public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) {
+ this(who, quitMessage, null);
+ }
+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage, @Nullable QuitReason quitReason) {
super(who);
this.quitMessage = quitMessage;
+ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason;
}
/**
@@ -75,4 +87,39 @@ public class PlayerQuitEvent extends PlayerEvent {
public static HandlerList getHandlerList() {
return handlers;
}
+
+ // Paper start
+ @NotNull
+ public QuitReason getReason() {
+ return this.reason;
+ }
+
+ public enum QuitReason {
+ /**
+ * The player left on their own behalf.
+ * <p>
+ * This does not mean they pressed the disconnect button in their client, but rather that the client severed the
+ * connection themselves. This may occur if no keep-alive packet is received on their side, among other things.
+ */
+ DISCONNECTED,
+
+ /**
+ * The player was kicked from the server.
+ */
+ KICKED,
+
+ /**
+ * The player has timed out.
+ */
+ TIMED_OUT,
+
+ /**
+ * The player's connection has entered an erroneous state.
+ * <p>
+ * Reasons for this may include invalid packets, invalid data, and uncaught exceptions in the packet handler,
+ * among others.
+ */
+ ERRONEOUS_STATE,
+ }
+ // Paper end
}

View file

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ineusia <ineusia@yahoo.com>
Date: Mon, 26 Oct 2020 11:37:48 -0500
Subject: [PATCH] Add Destroy Speed API
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
index 271ebba09fd9248717750e998668ae6fe013bacc..33fa378176d2a46e60de539246e5e13a34cb4bac 100644
--- a/src/main/java/org/bukkit/block/Block.java
+++ b/src/main/java/org/bukkit/block/Block.java
@@ -628,5 +628,29 @@ public interface Block extends Metadatable, net.kyori.adventure.translation.Tran
@NotNull
@Deprecated
String getTranslationKey();
+
+ /**
+ * Gets the speed at which this block will be destroyed by a given {@link ItemStack}
+ *
+ * <p>Default value is 1.0</p>
+ *
+ * @param itemStack {@link ItemStack} used to mine this Block
+ * @return the speed that this Block will be mined by the given {@link ItemStack}
+ */
+ @NotNull
+ public default float getDestroySpeed(@NotNull ItemStack itemStack) {
+ return getDestroySpeed(itemStack, false);
+ }
+
+ /**
+ * Gets the speed at which this blook will be destroyed by a given {@link org.bukkit.inventory.ItemStack}
+ * <p>
+ * Default value is 1.0
+ * @param itemStack {@link org.bukkit.inventory.ItemStack} used to mine this Block
+ * @param considerEnchants true to look at enchants on the itemstack
+ * @return the speed that this Block will be mined by the given {@link org.bukkit.inventory.ItemStack}
+ */
+ @NotNull
+ float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants);
// Paper end
}

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anrza <andrzejrzeczycki314@gmail.com>
Date: Wed, 15 Jul 2020 12:07:58 +0200
Subject: [PATCH] Add LivingEntity#clearActiveItem
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index 1b6c2b2cfb910e7651e7f18ea407e31db685af8a..751a7345b650e96bbfd3ca9d22c9623bd5444f67 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -773,6 +773,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@Nullable
ItemStack getActiveItem();
+ // Paper start
+ /**
+ * Interrupts any ongoing active "usage" or consumption or an item.
+ */
+ void clearActiveItem();
+ // Paper end
+
/**
* Get's remaining time a player needs to keep hands raised with an item to finish using it.
* @return Remaining ticks to use the item

View file

@ -1,89 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kennytv <jahnke.nassim@gmail.com>
Date: Tue, 25 Aug 2020 13:45:15 +0200
Subject: [PATCH] Add PlayerItemCooldownEvent
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..58d18f05af13d836ddc62fcd30befcb06f07c57c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java
@@ -0,0 +1,77 @@
+package io.papermc.paper.event.player;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Fired when a player receives an item cooldown.
+ */
+public class PlayerItemCooldownEvent extends PlayerEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ @NotNull
+ private final Material type;
+ private boolean cancelled;
+ private int cooldown;
+
+ public PlayerItemCooldownEvent(@NotNull Player player, @NotNull Material type, int cooldown) {
+ super(player);
+ this.type = type;
+ this.cooldown = cooldown;
+ }
+
+ /**
+ * Get the material affected by the cooldown.
+ *
+ * @return material affected by the cooldown
+ */
+ @NotNull
+ public Material getType() {
+ return type;
+ }
+
+ /**
+ * Gets the cooldown in ticks.
+ *
+ * @return cooldown in ticks
+ */
+ public int getCooldown() {
+ return cooldown;
+ }
+
+ /**
+ * Sets the cooldown of the material in ticks.
+ * Setting the cooldown to 0 results in removing an already existing cooldown for the material.
+ *
+ * @param cooldown cooldown in ticks, has to be a positive number
+ */
+ public void setCooldown(int cooldown) {
+ Preconditions.checkArgument(cooldown >= 0, "The cooldown has to be equal to or greater than 0!");
+ this.cooldown = cooldown;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View file

@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kennytv <jahnke.nassim@gmail.com>
Date: Sun, 26 Jul 2020 14:44:16 +0200
Subject: [PATCH] More lightning API
diff --git a/src/main/java/org/bukkit/entity/LightningStrike.java b/src/main/java/org/bukkit/entity/LightningStrike.java
index be347c3d0291f44036bae29a4e7e4645d6a4cdf6..6f5b6901032eb03606c4566b24459a03baac0c73 100644
--- a/src/main/java/org/bukkit/entity/LightningStrike.java
+++ b/src/main/java/org/bukkit/entity/LightningStrike.java
@@ -31,4 +31,72 @@ public interface LightningStrike extends Entity {
@Override
Spigot spigot();
// Spigot end
+
+ // Paper start
+ /**
+ * Returns the amount of flash iterations that will be done before the lightning dies.
+ *
+ * @see #getLifeTicks() for how long the current flash will last
+ * @return amount of flashes that will be shown before the lightning dies
+ */
+ int getFlashCount();
+
+ /**
+ * Sets the amount of life iterations that will be done before the lightning dies.
+ * Default number of flashes on creation is between 1-3.
+ *
+ * @param flashes amount of iterations that will be done before the lightning dies, must to be a positive number
+ */
+ void setFlashCount(int flashes);
+
+ /**
+ * Returns the amount of ticks the current flash will do damage for.
+ * Starts with 2 by default, will damage while it is equal to or above 0, with the next flash beginning somewhere between 0 and -9.
+ *
+ * @return ticks the current flash will do damage for
+ */
+ int getLifeTicks();
+
+ /**
+ * Sets the amount of ticks the current flash will do damage/fire for.
+ * Default is 2 for each flash, on which the sound and effect will also be played.
+ *
+ * @param lifeTicks ticks the current flash will do damage for
+ */
+ void setLifeTicks(int lifeTicks);
+
+ /**
+ * Returns the potential entity that caused this lightning strike to spawn in the world.
+ * <p>
+ * As of implementing this method, only {@link Player}s are capable of causing a lightning strike, however as this
+ * might change in future minecraft releases, this method does not guarantee a player as the cause of a lightning.
+ * Consumers of this method should hence validate whether or not the entity is a player if they want to use player
+ * specific methods through an {@code instanceOf} check.
+ * </p>
+ * <p>
+ * A player is, as of implementing this method, responsible for a lightning, and will hence be returned here as
+ * a cause, if they channeled a {@link Trident} to summon it or were explicitly defined as the cause of this
+ * lightning through {@link #setCausingPlayer(Player)}.
+ * </p>
+ *
+ * @return the entity that caused this lightning or null if the lightning was not caused by a entity (e.g. normal
+ * weather)
+ */
+ @org.jetbrains.annotations.Nullable
+ Entity getCausingEntity();
+
+ /**
+ * Updates the player that caused this lightning to be summoned into the world.
+ * By default, players that channel their {@link Trident} will be the cause of the respective lightning.
+ * <p>
+ * While the respective getter method {@link #getCausingEntity()} does not guarantee a player as the cause of a
+ * lightning to stay as future proof as possible, as of implementing this method, players are the only entities
+ * that can cause a lightning strike and hence this setter is restricted to players.
+ * </p>
+ *
+ * @param causingPlayer the player that should be the new cause of this lightning. {@code null} may be passed to
+ * indicate that no player is responsible for this lightning.
+ */
+ void setCausingPlayer(@org.jetbrains.annotations.Nullable Player causingPlayer);
+ // Paper end
}

View file

@ -1,120 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Thu, 27 Aug 2020 12:32:35 -0400
Subject: [PATCH] Add PlayerShearBlockEvent
diff --git a/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa7d440b797eac9e62678d03cc87f42838758bfd
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java
@@ -0,0 +1,108 @@
+package io.papermc.paper.event.block;
+
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * Called when a player uses sheers on a block.
+ * <p>
+ * This event is <b>not</b> called when breaking blocks with shears but instead only when a
+ * player uses the sheer item on a block to garner drops from said block and/or change its state.
+ * <p>
+ * Examples include shearing a pumpkin to turn it into a carved pumpkin or shearing a beehive to get honeycomb.
+ */
+public class PlayerShearBlockEvent extends PlayerEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancelled = false;
+ private final Block block;
+ private final ItemStack item;
+ private final EquipmentSlot hand;
+ private final List<ItemStack> drops;
+
+ public PlayerShearBlockEvent(@NotNull Player who, @NotNull Block block, @NotNull ItemStack item, @NotNull EquipmentSlot hand, @NotNull List<ItemStack> drops) {
+ super(who);
+ this.block = block;
+ this.item = item;
+ this.hand = hand;
+ this.drops = drops;
+ }
+
+ /**
+ * Gets the block being sheared in this event.
+ *
+ * @return The {@link Block} which block is being sheared in this event.
+ */
+ @NotNull
+ public Block getBlock() {
+ return block;
+ }
+
+ /**
+ * Gets the item used to shear the block.
+ *
+ * @return The {@link ItemStack} of the shears.
+ */
+ @NotNull
+ public ItemStack getItem() {
+ return item;
+ }
+
+ /**
+ * Gets the hand used to shear the block.
+ *
+ * @return Either {@link EquipmentSlot#HAND} OR {@link EquipmentSlot#OFF_HAND}.
+ */
+ @NotNull
+ public EquipmentSlot getHand() {
+ return hand;
+ }
+
+ /**
+ * Gets the resulting drops of this event.
+ *
+ * @return A {@link List list} of {@link ItemStack items} that will be dropped as result of this event.
+ */
+ @NotNull
+ public List<ItemStack> getDrops() {
+ return drops;
+ }
+
+ /**
+ * Gets whether the shearing of the block should be cancelled or not.
+ *
+ * @return Whether the shearing of the block should be cancelled or not.
+ */
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ /**
+ * Sets whether the shearing of the block should be cancelled or not.
+ *
+ * @param cancel whether the shearing of the block should be cancelled or not.
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kyle Wood <kyle@denwav.dev>
Date: Fri, 4 Dec 2020 15:53:19 -0800
Subject: [PATCH] Enable multi-release plugin jars
diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
index 6b5d7c350c216b7a234d96ecacae1d39a1acd814..81292899918c4dc880661ee628384cb840a6244f 100644
--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
@@ -58,7 +58,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot
this.description = description;
this.dataFolder = dataFolder;
this.file = file;
- this.jar = new JarFile(file);
+ this.jar = new JarFile(file, true, java.util.zip.ZipFile.OPEN_READ, JarFile.runtimeVersion()); // Paper - enable multi-release jars for Java 9+
this.manifest = jar.getManifest();
this.url = file.toURI().toURL();
this.libraryLoader = libraryLoader;

View file

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Thu, 27 Aug 2020 16:57:25 -0400
Subject: [PATCH] Fix hex colors not working in some kick messages
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
index c09d3cdb3acb04b6a833c30a619ff2af5e8b6b18..2384ae5082afd01c4f28fe2f3f782cdce15ff3f2 100644
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
synchronized (ServerHandshakePacketListenerImpl.throttleTracker) {
if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) {
ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime);
- TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message
+ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages
this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
this.connection.disconnect(chatmessage);
return;
@@ -76,12 +76,12 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
}
// CraftBukkit end
if (packet.getProtocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
- TranslatableComponent chatmessage;
+ Component chatmessage; // Paper - Fix hex colors not working in some kick messages
if (packet.getProtocolVersion() < 754) {
- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot
+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages
} else {
- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot
+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages
}
this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
@@ -99,7 +99,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
if (event.callEvent()) {
// If we've failed somehow, let the client know so and go no further.
if (event.isFailed()) {
- TranslatableComponent chatmessage = new TranslatableComponent(event.getFailMessage());
+ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages
this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
this.connection.disconnect(chatmessage);
return;
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 6468a675862ee2956308b760012fe25cf505563f..f4cff18afa816aa7efb2f80e0af51216129963a4 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -106,14 +106,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
// CraftBukkit start
@Deprecated
public void disconnect(String s) {
- try {
- Component ichatbasecomponent = new TextComponent(s);
- ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), s);
- this.connection.send(new ClientboundLoginDisconnectPacket(ichatbasecomponent));
- this.connection.disconnect(ichatbasecomponent);
- } catch (Exception exception) {
- ServerLoginPacketListenerImpl.LOGGER.error("Error whilst disconnecting player", exception);
- }
+ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages
}
// CraftBukkit end

View file

@ -1,146 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Fri, 21 Aug 2020 20:57:54 +0200
Subject: [PATCH] PortalCreateEvent needs to know its entity
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index ab5c59676451e6b338cd8678689bce776513d921..e4736190358181a6a7e7e81f4452045f41134060 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -409,7 +409,7 @@ public final class ItemStack {
net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition);
if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically
- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true);
+ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext
}
world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point
diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
index a36d31caa5bfc82a5fd9b16dc42334955fe7511d..177d1da44c83da5f99ae91891dec41dc210bd31d 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
@@ -11,6 +11,7 @@ import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
@@ -141,20 +142,23 @@ public abstract class BaseFireBlock extends Block {
super.entityInside(state, world, pos, entity);
}
+ // Paper start - ItemActionContext param
+ @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { this.onPlace(state, world, pos, oldState, notify, null); }
@Override
- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
- if (!oldState.is(state.getBlock())) {
+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) {
+ // Paper end
+ if (!iblockdata1.is(iblockdata.getBlock())) {
if (BaseFireBlock.inPortalDimension(world)) {
- Optional<PortalShape> optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, pos, Direction.Axis.X);
+ Optional<PortalShape> optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, blockposition, Direction.Axis.X);
if (optional.isPresent()) {
- ((PortalShape) optional.get()).createPortal();
+ ((PortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param
return;
}
}
- if (!state.canSurvive(world, pos)) {
- this.fireExtinguished(world, pos); // CraftBukkit - fuel block broke
+ if (!iblockdata.canSurvive(world, blockposition)) {
+ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java
index 4156f212461201e8f8001f3fbcd7fb683e86ed6b..c8a58cd67bb7f7491de04bda703e2a1f166fb845 100644
--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java
@@ -13,6 +13,7 @@ import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
@@ -359,9 +360,11 @@ public class FireBlock extends BaseFireBlock {
}
@Override
- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
- super.onPlace(state, world, pos, oldState, notify);
- world.getBlockTicks().scheduleTick(pos, this, FireBlock.getFireTickDelay(world.random));
+ // Paper start - ItemActionContext param
+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) {
+ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext);
+ // Paper end
+ world.getBlockTicks().scheduleTick(blockposition, this, getFireTickDelay(world.random));
}
private static int getFireTickDelay(Random random) {
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 bea9c7ac0fe08c3ca3309e8311f192cc557ca67d..983ca190dadc6f0b552133e6296f1c4165b75ad4 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
@@ -32,6 +32,7 @@ import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.Level;
@@ -128,6 +129,12 @@ public abstract class BlockBehaviour {
DebugPackets.sendNeighborsUpdatePacket(world, pos);
}
+ // Paper start - add ItemActionContext param
+ @Deprecated
+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) {
+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag);
+ }
+ // Paper end
@Deprecated
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java
index b68fa6cb68bb8fa078d4572bad338f43f20e8dc7..c07b5d1f1ef8b5e6026c7555d476880c8802d6c5 100644
--- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java
+++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java
@@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityDimensions;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.NetherPortalBlock;
@@ -185,7 +186,10 @@ public class PortalShape {
}
// CraftBukkit start - return boolean
- public boolean createPortal() {
+ // Paper start - ItemActionContext param
+ @Deprecated public boolean createPortal() { return this.createPortal(null); }
+ public boolean createPortal(UseOnContext itemActionContext) {
+ // Paper end
org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld();
// Copy below for loop
@@ -195,7 +199,7 @@ public class PortalShape {
this.blocks.setBlock(blockposition, iblockdata, 18);
});
- PortalCreateEvent event = new PortalCreateEvent((java.util.List<org.bukkit.block.BlockState>) (java.util.List) this.blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE);
+ PortalCreateEvent event = new PortalCreateEvent((java.util.List<org.bukkit.block.BlockState>) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param
this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event);
if (event.isCancelled()) {

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: foss-mc <69294560+foss-mc@users.noreply.github.com>
Date: Sun, 30 Aug 2020 15:30:29 +0800
Subject: [PATCH] Fix CraftTeam null check
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
index f86776aa42bd5520f8aaeaa46bb93ec4d5b4e27d..2b87a652798cb632fe76bf20e9e7f8cb8bfb3b7b 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
@@ -253,7 +253,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
@Override
public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException {
- Validate.notNull("Entry cannot be null");
+ Validate.notNull(entry, "Entry cannot be null"); // Paper
CraftScoreboard scoreboard = this.checkState();

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sun, 23 Aug 2020 15:28:35 +0200
Subject: [PATCH] Add more Evoker API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java
index 91d07e6996e315734689ea25336992b0ed21cf25..7e861636710aa44ed36e7f20c6320dabb809c35d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java
@@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.entity;
+import net.minecraft.world.entity.animal.Sheep;
import net.minecraft.world.entity.monster.SpellcasterIllager;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.EntityType;
@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker {
public void setCurrentSpell(Evoker.Spell spell) {
this.getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal()));
}
+
+ // Paper start
+ @Override
+ public org.bukkit.entity.Sheep getWololoTarget() {
+ Sheep sheep = getHandle().getWololoTarget();
+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity();
+ }
+
+ @Override
+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) {
+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle());
+ }
+ // Paper end
}

View file

@ -1,124 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 11 Aug 2020 19:16:09 +0200
Subject: [PATCH] Add methods to get translation keys
Co-authored-by: MeFisto94 <MeFisto94@users.noreply.github.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 5f9f35c25a6247b6cd1ba31888a0afb8cea31da2..4febad176d8dc7c56e9cb09c8e5ce55f4c9f3288 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -612,5 +612,15 @@ public class CraftBlock implements Block {
public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() {
return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMS().getBlock().defaultBlockState().getSoundType());
}
+
+ @Override
+ public String getTranslationKey() {
+ return this.translationKey();
+ }
+
+ @Override
+ public String translationKey() {
+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
index eb99e0c2462a2d1ab4508a5c3f1580b6e31d7465..c536eceef3365a7b726cd970df345ba1d055207d 100644
--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
@@ -192,6 +192,11 @@ public class CraftEnchantment extends Enchantment {
public net.kyori.adventure.text.Component displayName(int level) {
return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getFullname(level));
}
+
+ @Override
+ public String translationKey() {
+ return this.target.getDescriptionId();
+ }
// Paper end
public net.minecraft.world.item.enchantment.Enchantment getHandle() {
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 3b727b96c4166e88ec23df3e3e1e98d6aed58637..aceb11620972d13324aa05c841b5251d0fda3fab 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -425,6 +425,30 @@ public final class CraftMagicNumbers implements UnsafeValues {
Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!");
return compound;
}
+
+ @Override
+ public String getTranslationKey(Material mat) {
+ if (mat.isBlock()) {
+ return getBlock(mat).getDescriptionId();
+ }
+ return getItem(mat).getDescriptionId();
+ }
+
+ @Override
+ public String getTranslationKey(org.bukkit.block.Block block) {
+ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getDescriptionId();
+ }
+
+ @Override
+ public String getTranslationKey(org.bukkit.entity.EntityType type) {
+ return net.minecraft.world.entity.EntityType.byString(type.getName()).map(net.minecraft.world.entity.EntityType::getDescriptionId).orElse(null);
+ }
+
+ @Override
+ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) {
+ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack);
+ return nmsItemStack.getItem().getDescriptionId(nmsItemStack);
+ }
// Paper end
/**
diff --git a/src/test/java/io/papermc/paper/world/TranslationKeyTest.java b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
index 6cd015dc5a2e012ac827c2b2d9aa5542b0591afb..b2e73df86683b88c83349b6d13456f5b051ac5d5 100644
--- a/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
+++ b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
@@ -7,7 +7,7 @@ import org.bukkit.Difficulty;
import org.junit.Assert;
import org.junit.Test;
-public class TranslationKeyTest {
+public class TranslationKeyTest extends org.bukkit.support.AbstractTestingBase {
@Test
public void testChatVisibilityKeys() {
@@ -16,4 +16,32 @@ public class TranslationKeyTest {
Assert.assertEquals(chatVisibility + "'s translation key doesn't match", ChatVisiblity.valueOf(chatVisibility.name()).getKey(), chatVisibility.translationKey());
}
}
+
+ @Test
+ public void testDifficultyKeys() {
+ for (Difficulty bukkitDifficulty : Difficulty.values()) {
+ Assert.assertEquals(bukkitDifficulty + "'s translation key doesn't match", ((TranslatableComponent) net.minecraft.world.Difficulty.byId(bukkitDifficulty.ordinal()).getDisplayName()).getKey(), bukkitDifficulty.translationKey());
+ }
+ }
+
+ @Test
+ public void testGameruleKeys() {
+ for (org.bukkit.GameRule<?> rule : org.bukkit.GameRule.values()) {
+ Assert.assertEquals(rule.getName() + "'s translation doesn't match", org.bukkit.craftbukkit.CraftWorld.getGameRulesNMS().get(rule.getName()).getDescriptionId(), rule.translationKey());
+ }
+ }
+
+ @Test
+ public void testAttributeKeys() {
+ for (org.bukkit.attribute.Attribute attribute : org.bukkit.attribute.Attribute.values()) {
+ Assert.assertEquals("translation key mismatch for " + attribute, org.bukkit.craftbukkit.attribute.CraftAttributeMap.toMinecraft(attribute).getDescriptionId(), attribute.translationKey());
+ }
+ }
+
+ @Test
+ public void testFireworkEffectType() {
+ for (org.bukkit.FireworkEffect.Type type : org.bukkit.FireworkEffect.Type.values()) {
+ Assert.assertEquals("translation key mismatch for " + type, net.minecraft.world.item.FireworkRocketItem.Shape.byId(org.bukkit.craftbukkit.inventory.CraftMetaFirework.getNBT(type)).getName(), org.bukkit.FireworkEffect.Type.NAMES.key(type));
+ }
+ }
}

View file

@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ysl3000 <yannicklamprecht@live.de>
Date: Mon, 6 Jul 2020 22:18:04 +0200
Subject: [PATCH] Create HoverEvent from ItemStack Entity
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
index c50d3cee3dfebb62ad30f8d4efe23b5c7c9f2b57..fcbd28fdeab4815c005c7dca547aee246f52fd26 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -375,5 +375,40 @@ public final class CraftItemFactory implements ItemFactory {
return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId()) : null;
}
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) {
+ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString());
+ return new net.md_5.bungee.api.chat.hover.content.Item(
+ itemStack.getType().getKey().toString(),
+ itemStack.getAmount(),
+ itemTag);
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) {
+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName()));
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) {
+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName));
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) {
+ return new net.md_5.bungee.api.chat.hover.content.Entity(
+ entity.getType().getKey().toString(),
+ entity.getUniqueId().toString(),
+ customName);
+ }
+
+ @Override
+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) {
+ return new net.md_5.bungee.api.chat.hover.content.Entity(
+ entity.getType().getKey().toString(),
+ entity.getUniqueId().toString(),
+ new net.md_5.bungee.api.chat.TextComponent(customName));
+ }
// Paper end
}

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: miclebrick <miclebrick@outlook.com>
Date: Thu, 6 Dec 2018 19:52:50 -0500
Subject: [PATCH] Cache block data strings
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 968476493bcea8b4d961e838b142912d3eac91cd..b9c628b2786df4b85329b4d1da55452f61d80dfd 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2043,6 +2043,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getPlayerList().reloadResources();
this.functionManager.replaceLibrary(this.resources.getFunctionLibrary());
this.structureManager.onResourceManagerReload(this.resources.getResourceManager());
+ org.bukkit.craftbukkit.block.data.CraftBlockData.reloadCache(); // Paper - cache block data strings, they can be defined by datapacks so refresh it here
}, this);
if (this.isSameThread()) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index 3594f432a25b580173e8577bf324be954f5eddd1..6dc8f9f269db6971b8b46819e017357899ccd118 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -13,6 +13,7 @@ import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.core.Direction;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
+import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@@ -494,9 +495,39 @@ public class CraftBlockData implements BlockData {
Preconditions.checkState(CraftBlockData.MAP.put(nms, bukkit) == null, "Duplicate mapping %s->%s", nms, bukkit);
}
+ // Paper start - cache block data strings
+ private static Map<String, CraftBlockData> stringDataCache = new HashMap<>();
+
+ static {
+ // cache all of the default states at startup, will not cache ones with the custom states inside of the
+ // brackets in a different order, though
+ reloadCache();
+ }
+
+ public static void reloadCache() {
+ stringDataCache.clear();
+ Block.BLOCK_STATE_REGISTRY.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData()));
+ }
+ // Paper end
+
public static CraftBlockData newData(Material material, String data) {
Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material);
+ // Paper start - cache block data strings
+ if (material != null) {
+ Block block = CraftMagicNumbers.getBlock(material);
+ if (block != null) {
+ ResourceLocation key = Registry.BLOCK.getKey(block);
+ data = data == null ? key.toString() : key + data;
+ }
+ }
+
+ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s));
+ return (CraftBlockData) cached.clone();
+ }
+
+ private static CraftBlockData createNewData(Material material, String data) {
+ // Paper end - cache block data strings
BlockState blockData;
Block block = CraftMagicNumbers.getBlock(material);
Map<Property<?>, Comparable<?>> parsed = null;

View file

@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 25 Aug 2020 20:45:36 -0400
Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported
Uses correct setPositionRotation for Entity teleporting instead of setLocation
as this is how Vanilla teleports entities.
Cancel any pending motion when teleported.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index f20578abf959bf4005b2de0726de99ab7daaba47..17289eeb53dc4463897819a1c732fab3ec6a9cdd 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -681,7 +681,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit
- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
+ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); // Paper - use proper setPositionRotation for teleportation
this.lastGoodX = this.awaitingPositionFromClient.x;
this.lastGoodY = this.awaitingPositionFromClient.y;
this.lastGoodZ = this.awaitingPositionFromClient.z;
@@ -1548,7 +1548,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// CraftBukkit end
this.awaitingTeleportTime = this.tickCount;
- this.player.absMoveTo(d0, d1, d2, f, f1);
+ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation
this.player.forceCheckHighPriority(); // Paper
this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag));
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 8df955a0aa6cd0c7d10619fb63abd16af4754be8..a652bbc4b3c768fecfb6f067d21a90315256f885 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -152,6 +152,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
+ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation
static boolean isLevelAtLeast(CompoundTag tag, int level) {
return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
}
@@ -1568,6 +1569,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
}
public void moveTo(double x, double y, double z, float yaw, float pitch) {
+ // Paper - cancel entity velocity if teleported
+ if (!preserveMotion) {
+ this.deltaMovement = Vec3.ZERO;
+ } else {
+ this.preserveMotion = false;
+ }
+ // Paper end
this.setPosRaw(x, y, z);
this.setYRot(yaw);
this.setXRot(pitch);
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index 409467ca9a8a21d1e22e3a08f462e54d6124f6a1..56d3867f748d92a55976820215d9b8316989677b 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -171,6 +171,7 @@ public abstract class BaseSpawner {
return;
}
+ entity.preserveMotion = true; // Paper - preserve entity motion from tag
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 38e38abd5302a9f8c5eb2d3d81d825cdae99d7c4..0547727afbd1b37c1a75fd8b4da585d80d54245a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -577,7 +577,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
// entity.setLocation() throws no event, and so cannot be cancelled
- this.entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+ entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting
// SPIGOT-619: Force sync head rotation also
this.entity.setYHeadRot(location.getYaw());

View file

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

View file

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

View file

@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 17 Sep 2020 00:36:05 +0100
Subject: [PATCH] Extend block drop capture to capture all items added to the
world
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 1b13c67441c46208a9b2adde5ca109f90bbb92e2..3563690e404a68b8940d9c06a0198dd0a4b2d220 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1252,6 +1252,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit
return false;
} else {
+ // Paper start - capture all item additions to the world
+ if (captureDrops != null && entity instanceof net.minecraft.world.entity.item.ItemEntity) {
+ captureDrops.add((net.minecraft.world.entity.item.ItemEntity) entity);
+ return true;
+ }
+ // Paper end
+
if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) {
return false;
}
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 784e6c2db5bb346408948cff8ac3cc9b964dd6d8..0b274a5b9e0bf68769637f10e43dbff6d909512b 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -7,6 +7,7 @@ import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.DoubleHighBlockItem;
import net.minecraft.world.item.ItemStack;
@@ -424,10 +425,12 @@ public class ServerPlayerGameMode {
// return true; // CraftBukkit
}
// CraftBukkit start
+ java.util.List<ItemEntity> itemsToDrop = level.captureDrops; // Paper - store current list
+ level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff
if (event.isDropItems()) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref
}
- level.captureDrops = null;
+ //world.captureDrops = null; // Paper - move up
// Drop event experience
if (flag && event != null) {

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sun, 27 Sep 2020 16:25:24 +0200
Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086)
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index 96759f349e10c8ef634a11a6b48f9affae77d65a..823451570e02ee75bfce1c106779a0502187fcea 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -381,6 +381,7 @@ public class ChunkHolder {
}
public void blockChanged(BlockPos pos) {
+ if (!pos.isValidLocation(levelHeightAccessor)) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks
LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance
if (chunk != null) {

View file

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MeFisto94 <MeFisto94@users.noreply.github.com>
Date: Fri, 28 Aug 2020 01:41:26 +0200
Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and
non-conflicting Entity Ids
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index dd98f228135c634235dc28c8edd396fb90fc98bc..595428849a32374678fc4125cb4a6f90186a1340 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3958,4 +3958,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
void accept(Entity entity, double x, double y, double z);
}
+
+ // Paper start
+ public static int nextEntityId() {
+ return ENTITY_COUNTER.incrementAndGet();
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index aceb11620972d13324aa05c841b5251d0fda3fab..ee974e615096f78906a31b4774e3dde7a156d023 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -449,6 +449,10 @@ public final class CraftMagicNumbers implements UnsafeValues {
net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack);
return nmsItemStack.getItem().getDescriptionId(nmsItemStack);
}
+
+ public int nextEntityId() {
+ return net.minecraft.world.entity.Entity.nextEntityId();
+ }
// Paper end
/**

View file

@ -1,103 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Sat, 3 Oct 2020 04:15:09 -0400
Subject: [PATCH] Lazily track plugin scoreboards by default
On servers with plugins that constantly churn through scoreboards, there is a risk of
degraded GC performance due to the number of scoreboards held on by weak references.
Most plugins don't even need the (vanilla) functionality that requires all plugin
scoreboards to be tracked by the server. Instead, only track scoreboards when an
objective is added with a non-dummy criteria.
This is a breaking change, however the change is a much more sensible default. In case
this breaks your workflow you can always force all scoreboards to be tracked with
settings.track-plugin-scoreboards in paper.yml.
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 6733e78ba6bf2993bb2adde4cf9f1f6ca366679c..380c4f46b98e6296cf28568abb1e74a80278ffa0 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -486,4 +486,9 @@ public class PaperConfig {
private static void maxJoinsPerTick() {
maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3);
}
+
+ public static boolean trackPluginScoreboards;
+ private static void trackPluginScoreboards() {
+ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false);
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
index 68aa66c340b7a686a353e2a15084d811a3955a0a..b1fbbfeadb63d495b57f6c29b00de5327ca713cd 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
@@ -18,6 +18,7 @@ import org.bukkit.scoreboard.Team;
public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
final Scoreboard board;
+ boolean registeredGlobally = false; // Paper
CraftScoreboard(Scoreboard board) {
this.board = board;
@@ -44,6 +45,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters");
Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists");
CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria);
+ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective
+ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.DUMMY && !registeredGlobally) {
+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this);
+ registeredGlobally = true;
+ }
+ // Paper end
net.minecraft.world.scores.Objective objective = board.addObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
return new CraftObjective(this, objective);
}
@@ -68,6 +75,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
net.minecraft.world.scores.Objective objective = this.board.addObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria);
+ // Paper start
+ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) {
+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this);
+ registeredGlobally = true;
+ }
+ // Paper end
ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
return new CraftObjective(this, objective);*/ // Paper
return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
index ff090edcc85713083449cebb22bd1490123bc1ee..8ccfe9488db44d7d2cf4040a5b4cead33da1d5f4 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager {
public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) {
this.mainScoreboard = new CraftScoreboard(scoreboardServer);
+ mainScoreboard.registeredGlobally = true; // Paper
this.server = minecraftserver;
this.scoreboards.add(mainScoreboard);
}
@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager {
public CraftScoreboard getNewScoreboard() {
org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot
CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(this.server));
- this.scoreboards.add(scoreboard);
+ // Paper start
+ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) {
+ scoreboard.registeredGlobally = true;
+ scoreboards.add(scoreboard);
+ }
+ // Paper end
return scoreboard;
}
+ // Paper start
+ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) {
+ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration");
+ scoreboards.add(scoreboard);
+ }
+ // Paper end
+
// CraftBukkit method
public CraftScoreboard getPlayerBoard(CraftPlayer player) {
CraftScoreboard board = this.playerBoards.get(player);

View file

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 21:39:16 -0500
Subject: [PATCH] Entity#isTicking
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 9e6a2c5fc55674ab144ebd46da6152e51d3c1dba..9524771be6268b28f14618523d59cff00a127d9b 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -52,6 +52,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MCUtil;
import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
@@ -3963,5 +3964,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
public static int nextEntityId() {
return ENTITY_COUNTER.incrementAndGet();
}
+
+ public boolean isTicking() {
+ return ((ServerChunkCache) level.getChunkSource()).isPositionTicking(this);
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index a0a24a46624b3d174d08c806c8ad45d8a9028a09..2712aa554383a3b2b742c945e2f0be7ee96eea69 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1259,5 +1259,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isInLava() {
return getHandle().isInLava();
}
+
+ public boolean isTicking() {
+ return getHandle().isTicking();
+ }
// Paper end
}

View file

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

View file

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 6 Jul 2020 18:36:41 -0400
Subject: [PATCH] Fix Concurrency issue in WeightedList
if multiple threads from worldgen sort at same time, it will crash.
So make a copy of the list for sorting purposes.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
index 893c37cc7e33f4baa98131afca45a258600ddc75..09998d160a6d79fdb5a5041a5d572649a1532e6a 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java
@@ -16,7 +16,7 @@ public class GateBehavior<E extends LivingEntity> extends Behavior<E> {
private final Set<MemoryModuleType<?>> exitErasedMemories;
private final GateBehavior.OrderPolicy orderPolicy;
private final GateBehavior.RunningPolicy runningPolicy;
- private final ShufflingList<Behavior<? super E>> behaviors = new ShufflingList<>();
+ private final ShufflingList<Behavior<? super E>> behaviors = new ShufflingList<>(false); // Paper - don't use a clone
public GateBehavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState, Set<MemoryModuleType<?>> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List<Pair<Behavior<? super E>, Integer>> tasks) {
super(requiredMemoryState);
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
index d4c9def80154c3e62a0b6928057062a0808f339f..4fa64b1e2004810906bb0b174436c8e687a75ada 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
@@ -14,12 +14,25 @@ import java.util.stream.Stream;
public class ShufflingList<U> {
protected final List<ShufflingList.WeightedEntry<U>> entries;
private final Random random = new Random();
+ private final boolean isUnsafe; // Paper
public ShufflingList() {
+ // Paper start
+ this(true);
+ }
+ public ShufflingList(boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end
this.entries = Lists.newArrayList();
}
private ShufflingList(List<ShufflingList.WeightedEntry<U>> list) {
+ // Paper start
+ this(list, true);
+ }
+ private ShufflingList(List<ShufflingList.WeightedEntry<U>> list, boolean isUnsafe) {
+ this.isUnsafe = isUnsafe;
+ // Paper end
this.entries = Lists.newArrayList(list);
}
@@ -35,11 +48,12 @@ public class ShufflingList<U> {
}
public ShufflingList<U> shuffle() {
- this.entries.forEach((entry) -> {
- entry.setRandom(this.random.nextFloat());
- });
- this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
- return this;
+ // Paper start - make concurrent safe, work off a clone of the list
+ List<ShufflingList.WeightedEntry<U>> list = this.isUnsafe ? Lists.newArrayList(this.entries) : this.entries;
+ list.forEach(entry -> entry.setRandom(this.random.nextFloat()));
+ list.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
+ return this.isUnsafe ? new ShufflingList<>(list, this.isUnsafe) : this;
+ // Paper end
}
public Stream<U> stream() {

View file

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

View file

@ -1,105 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Sun, 17 May 2020 23:47:33 -0700
Subject: [PATCH] Fix for large move vectors crashing server
Check movement distance also based on current position.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index be682e8459bb7293256c3552d90f5cdb8d97a29d..557817c8ac1eadabc11f7f3efc8485b226d7657e 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -506,20 +506,31 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) {
ServerLevel worldserver = this.player.getLevel();
- double d0 = entity.getX();
- double d1 = entity.getY();
- double d2 = entity.getZ();
- double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX());
- double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY());
- double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ());
+ double d0 = entity.getX();final double fromX = d0; // Paper - OBFHELPER
+ double d1 = entity.getY();final double fromY = d1; // Paper - OBFHELPER
+ double d2 = entity.getZ();final double fromZ = d2; // Paper - OBFHELPER
+ double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX());final double toX = d3; // Paper - OBFHELPER
+ double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY());final double toY = d4; // Paper - OBFHELPER
+ double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ());final double toZ = d5; // Paper - OBFHELPER
float f = Mth.wrapDegrees(packet.getYRot());
float f1 = Mth.wrapDegrees(packet.getXRot());
double d6 = d3 - this.vehicleFirstGoodX;
double d7 = d4 - this.vehicleFirstGoodY;
double d8 = d5 - this.vehicleFirstGoodZ;
double d9 = entity.getDeltaMovement().lengthSqr();
- double d10 = d6 * d6 + d7 * d7 + d8 * d8;
-
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - fromX;
+ double currDeltaY = toY - fromY;
+ double currDeltaZ = toZ - fromZ;
+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ // Paper end - fix large move vectors killing the server
+
+ // Paper start - fix large move vectors killing the server
+ double otherFieldX = d3 - this.vehicleLastGoodX;
+ double otherFieldY = d4 - this.vehicleLastGoodY - 1.0E-6D;
+ double otherFieldZ = d5 - this.vehicleLastGoodZ;
+ d10 = Math.max(d10, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
// CraftBukkit start - handle custom speeds and skipped ticks
this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
@@ -562,9 +573,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
- d6 = d3 - this.vehicleLastGoodX;
- d7 = d4 - this.vehicleLastGoodY - 1.0E-6D;
- d8 = d5 - this.vehicleLastGoodZ;
+ d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
+ d8 = d5 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
double d11 = d7;
@@ -1232,14 +1243,25 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
float prevPitch = this.player.getXRot();
// CraftBukkit end
double d3 = this.player.getX(); final double toX = d3; // Paper - OBFHELPER
- double d4 = this.player.getY();
+ double d4 = this.player.getY(); final double toY = d4; // Paper - OBFHELPER
double d5 = this.player.getZ(); final double toZ = d5; // Paper - OBFHELPER
double d6 = this.player.getY();
double d7 = d0 - this.firstGoodX;
double d8 = d1 - this.firstGoodY;
double d9 = d2 - this.firstGoodZ;
double d10 = this.player.getDeltaMovement().lengthSqr();
- double d11 = d7 * d7 + d8 * d8 + d9 * d9;
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - prevX;
+ double currDeltaY = toY - prevY;
+ double currDeltaZ = toZ - prevZ;
+ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ // Paper end - fix large move vectors killing the server
+ // Paper start - fix large move vectors killing the server
+ double otherFieldX = d0 - this.lastGoodX;
+ double otherFieldY = d1 - this.lastGoodY;
+ double otherFieldZ = d2 - this.lastGoodZ;
+ d11 = Math.max(d11, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
if (this.player.isSleeping()) {
if (d11 > 1.0D) {
@@ -1291,9 +1313,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
AABB axisalignedbb = this.player.getBoundingBox();
- d7 = d0 - this.lastGoodX;
- d8 = d1 - this.lastGoodY;
- d9 = d2 - this.lastGoodZ;
+ d7 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d8 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
+ d9 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag = d8 > 0.0D;
if (this.player.isOnGround() && !packet.isOnGround() && flag) {

View file

@ -1,94 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Wed, 3 Jun 2020 11:37:13 -0700
Subject: [PATCH] Optimise getType calls
Remove the map lookup for converting from Block->Bukkit Material
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
index 3581aa7dcba934017896dc947adeb9d548d5f333..6158ef624ddbf02179afcc4aebc8284ae326ffb1 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
@@ -10,6 +10,17 @@ import net.minecraft.world.level.block.state.properties.Property;
public class BlockState extends BlockBehaviour.BlockStateBase {
public static final Codec<BlockState> CODEC = codec(Registry.BLOCK, Block::defaultBlockState).stable();
+ // Paper start - optimise getType calls
+ org.bukkit.Material cachedMaterial;
+
+ public final org.bukkit.Material getBukkitMaterial() {
+ if (this.cachedMaterial == null) {
+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock());
+ }
+
+ return this.cachedMaterial;
+ }
+ // Paper end - optimise getType calls
public BlockState(Block block, ImmutableMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
super(block, propertyMap, codec);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
index e2e6652fc227173b69580dba74855c3ed8884a3b..2c23712aadfe32439ae014c62aa16f1b2a677439 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
@@ -81,7 +81,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
public Material getBlockType(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
- return CraftMagicNumbers.getMaterial(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBlock());
+ return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 4febad176d8dc7c56e9cb09c8e5ce55f4c9f3288..fd4a0bbd1438bfc94580f29382d0c5f50531292b 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -212,7 +212,7 @@ public class CraftBlock implements Block {
@Override
public Material getType() {
- return CraftMagicNumbers.getMaterial(this.world.getBlockState(position).getBlock());
+ return this.world.getBlockState(this.position).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
index 8f7da903c75feaaf31e368ac8d798af8ed845ebf..db7a6af045364e7b1e9c0449faaf5f49394f6204 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
@@ -166,7 +166,7 @@ public class CraftBlockState implements BlockState {
@Override
public Material getType() {
- return CraftMagicNumbers.getMaterial(this.data.getBlock());
+ return this.data.getBukkitMaterial(); // Paper - optimise getType calls
}
public void setFlag(int flag) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index 6dc8f9f269db6971b8b46819e017357899ccd118..7f49c7c7048b5778f20ddce1d844d4b389e6597f 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData {
@Override
public Material getMaterial() {
- return CraftMagicNumbers.getMaterial(this.state.getBlock());
+ return this.state.getBukkitMaterial(); // Paper - optimise getType calls
}
public BlockState getState() {
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
index 0b8975b34ef47d5ea91d34acd2ec5a1d548d74ff..68c47608a50a0cb6bd75ecbf73637d6f2e9db361 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
@@ -99,7 +99,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData {
@Override
public Material getType(int x, int y, int z) {
- return CraftMagicNumbers.getMaterial(this.getTypeId(x, y, z).getBlock());
+ return this.getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override

View file

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

View file

@ -1,96 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Mon, 6 Jul 2020 20:46:50 -0700
Subject: [PATCH] Improve inlinig for some hot IBlockData 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 983ca190dadc6f0b552133e6296f1c4165b75ad4..b534fd9e5d2a17926282cf40c9d66a2143a37bfe 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
@@ -659,8 +659,14 @@ public abstract class BlockBehaviour {
return this.shapeExceedsCube;
}
// Paper end
+ // Paper start
+ protected boolean isTicking;
+ protected FluidState fluid;
+ // Paper end
public void initCache() {
+ this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid()
+ this.isTicking = this.getBlock().isRandomlyTicking(this.asState()); // Paper - moved from isTicking()
if (!this.getBlock().hasDynamicShape()) {
this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState());
}
@@ -704,15 +710,15 @@ public abstract class BlockBehaviour {
return this.shapeExceedsCube; // Paper - moved into shape cache init
}
- public boolean useShapeForLightOcclusion() {
+ public final boolean useShapeForLightOcclusion() { // Paper
return this.useShapeForLightOcclusion;
}
- public int getLightEmission() {
+ public final int getLightEmission() { // Paper
return this.lightEmission;
}
- public boolean isAir() {
+ public final boolean isAir() { // Paper
return this.isAir;
}
@@ -786,7 +792,7 @@ public abstract class BlockBehaviour {
}
}
- public boolean canOcclude() {
+ public final boolean canOcclude() { // Paper
return this.canOcclude;
}
@@ -979,12 +985,12 @@ public abstract class BlockBehaviour {
return this.getBlock() == block;
}
- public FluidState getFluidState() {
- return this.getBlock().getFluidState(this.asState());
+ public final FluidState getFluidState() { // Paper
+ return this.fluid; // Paper - moved into init
}
- public boolean isRandomlyTicking() {
- return this.getBlock().isRandomlyTicking(this.asState());
+ public final boolean isRandomlyTicking() { // Paper
+ return this.isTicking; // Paper - moved into init
}
public long getSeed(BlockPos pos) {
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 65911334082f9d53fc930d7c6b0313e8acef0c5e..0ae876f0bbfac74a9d5f06fb73f9cfcf5991b02e 100644
--- a/src/main/java/net/minecraft/world/level/material/FluidState.java
+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java
@@ -23,8 +23,12 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
public static final int AMOUNT_MAX = 9;
public static final int AMOUNT_FULL = 8;
+ // Paper start
+ protected final boolean isEmpty;
+ // Paper end
public FluidState(Fluid fluid, ImmutableMap<Property<?>, Comparable<?>> propertiesMap, MapCodec<FluidState> codec) {
super(fluid, propertiesMap, codec);
+ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty()
}
public Fluid getType() {
@@ -40,7 +44,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public boolean isEmpty() {
- return this.getType().isEmpty();
+ return this.isEmpty; // Paper - moved into constructor
}
public float getHeight(BlockGetter world, BlockPos pos) {

View file

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

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Sat, 25 Apr 2020 17:10:55 -0700
Subject: [PATCH] Reduce blockpos allocation from pathfinding
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
index b37acb6e6e253529a38f44a518a02c7747d3145e..2ad5ff9a1d7de54e75436e99da8a73db9dc91bde 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -471,7 +471,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
return BlockPathTypes.DANGER_FIRE;
}
- if (world.getFluidState(pos).is(FluidTags.WATER)) {
+ if (blockState.getFluidState().is(FluidTags.WATER)) {
return BlockPathTypes.WATER_BORDER;
}
} // Paper
@@ -502,7 +502,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
} else if (blockState.is(Blocks.COCOA)) {
return BlockPathTypes.COCOA;
} else {
- FluidState fluidState = world.getFluidState(pos);
+ FluidState fluidState = blockState.getFluidState(); // Paper - remove another get type call
if (fluidState.is(FluidTags.LAVA)) {
return BlockPathTypes.LAVA;
} else if (isBurningBlock(blockState)) {

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 20:32:25 -0500
Subject: [PATCH] Fix item locations dropped from campfires
Fixes #4259 by not flooring the blockposition among other weirdness
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
index 7a5f748f974429ce4faa8f64fae905994b5e59a9..ad35d82f03f7643507dde6adbb38c911d12ec6c1 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
@@ -71,7 +71,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
result = blockCookEvent.getResult();
itemstack1 = CraftItemStack.asNMSCopy(result);
// CraftBukkit end
- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1);
+ // Paper start
+ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(world, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemstack1.split(world.random.nextInt(21) + 10));
+ droppedItem.setDeltaMovement(world.random.nextGaussian() * 0.05D, world.random.nextGaussian() * 0.05D + 0.2D, world.random.nextGaussian() * 0.05D);
+ world.addFreshEntity(droppedItem);
+ // Paper end
campfire.items.set(i, ItemStack.EMPTY);
world.sendBlockUpdated(pos, state, state, 3);
}

View file

@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Tue, 14 Apr 2020 12:05:22 +0200
Subject: [PATCH] Player elytra boost API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index c661f6f29633fd5b28bb6ce71ed49463a3d7ecf0..434fba86e04894a3a2c4daeb4582980319d64d8e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -539,6 +539,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
throw new RuntimeException("Unknown settings type");
}
+
+ @Override
+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) {
+ Validate.isTrue(isGliding(), "Player must be gliding");
+ Validate.isTrue(firework != null, "firework == null");
+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET");
+
+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework);
+ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle();
+ net.minecraft.world.entity.projectile.FireworkRocketEntity entity = new net.minecraft.world.entity.projectile.FireworkRocketEntity(world, item, getHandle());
+ return world.addFreshEntity(entity)
+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity()
+ : null;
+ }
// Paper end
@Override

View file

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

View file

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

View file

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

View file

@ -1,143 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Mon, 9 Nov 2020 20:44:51 +0100
Subject: [PATCH] Add ignore discounts API
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 64d5ddb8ce06e17e1a4dee284ba4c6ecfcdae11e..2eb60384b244a5c1dc8bcbeb59c8adc69e3f18cd 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -474,6 +474,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator.hasNext()) {
MerchantOffer merchantrecipe = (MerchantOffer) iterator.next();
+ if (merchantrecipe.ignoreDiscounts) continue; // Paper
// CraftBukkit start
int bonus = -Mth.floor((float) i * merchantrecipe.getPriceMultiplier());
@@ -493,6 +494,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator1.hasNext()) {
MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next();
+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper
double d0 = 0.3D + 0.0625D * (double) j;
int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount());
diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
index 75827fcad36a551d832f4be094167936092b6caf..70b703b920752e7301e4f19cdc07a1a4ceac5e0e 100644
--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
@@ -19,6 +19,7 @@ public class MerchantOffer {
private int demand;
public float priceMultiplier;
public int xp;
+ public boolean ignoreDiscounts; // Paper
// CraftBukkit start
private CraftMerchantRecipe bukkitHandle;
@@ -27,7 +28,12 @@ public class MerchantOffer {
}
public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) {
- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier);
+ // Paper start - add ignoreDiscounts param
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit);
+ }
+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) {
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, ignoreDiscounts);
+ // Paper end
this.bukkitHandle = bukkit;
}
// CraftBukkit end
@@ -59,6 +65,7 @@ public class MerchantOffer {
this.specialPriceDiff = nbt.getInt("specialPrice");
this.demand = nbt.getInt("demand");
+ this.ignoreDiscounts = nbt.getBoolean("Paper.IgnoreDiscounts"); // Paper
}
public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int merchantExperience, float priceMultiplier) {
@@ -70,10 +77,19 @@ public class MerchantOffer {
}
public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier) {
- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0);
+ // Paper start - add ignoreDiscounts param
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, false);
+ }
+ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, boolean ignoreDiscounts) {
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0, ignoreDiscounts);
}
public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus) {
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, demandBonus, false);
+ }
+ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus, boolean ignoreDiscounts) {
+ this.ignoreDiscounts = ignoreDiscounts;
+ // Paper end
this.rewardExp = true;
this.xp = 1;
this.baseCostA = firstBuyItem;
@@ -189,6 +205,7 @@ public class MerchantOffer {
nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier);
nbttagcompound.putInt("specialPrice", this.specialPriceDiff);
nbttagcompound.putInt("demand", this.demand);
+ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper
return nbttagcompound;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
index 8dfbac01a7c88797bb7adfee6278d090da2bedc9..fc69347b03ce197584b310f99e14799046ed5b70 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe {
}
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) {
- super(result, uses, maxUses, experienceReward, experience, priceMultiplier);
+ // Paper start - add ignoreDiscounts param
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) {
+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts);
+ // Paper end
this.handle = new net.minecraft.world.item.trading.MerchantOffer(
net.minecraft.world.item.ItemStack.EMPTY,
net.minecraft.world.item.ItemStack.EMPTY,
@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
maxUses,
experience,
priceMultiplier,
+ ignoreDiscounts, // Paper - add ignoreDiscounts param
this
);
this.setExperienceReward(experienceReward);
@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe {
handle.priceMultiplier = priceMultiplier;
}
+ // Paper start
+ @Override
+ public boolean shouldIgnoreDiscounts() {
+ return this.handle.ignoreDiscounts;
+ }
+
+ @Override
+ public void setIgnoreDiscounts(boolean ignoreDiscounts) {
+ this.handle.ignoreDiscounts = ignoreDiscounts;
+ }
+ // Paper end
+
public net.minecraft.world.item.trading.MerchantOffer toMinecraft() {
List<ItemStack> ingredients = getIngredients();
Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients");
@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
if (recipe instanceof CraftMerchantRecipe) {
return (CraftMerchantRecipe) recipe;
} else {
- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier());
+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts
craft.setIngredients(recipe.getIngredients());
return craft;

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Wed, 30 Sep 2020 22:49:14 +0200
Subject: [PATCH] Toggle for removing existing dragon
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index b70be9eea934aa88a9597581dbd1fd5662876c2d..568da8f2ef3c5e1412cf13c10b425100af75e902 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -72,6 +72,14 @@ public class PaperWorldConfig {
}
}
+ public boolean shouldRemoveDragon = false;
+ private void shouldRemoveDragon() {
+ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon);
+ if (shouldRemoveDragon) {
+ log("The Ender Dragon will be removed if she already exists without a portal.");
+ }
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
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 9899c70b88fc371963e33caccd7125ef8c333df4..e1d689aa65b8d993c7223d306363366f3adff62f 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
@@ -212,7 +212,7 @@ public class EndDragonFight {
this.dragonUUID = enderDragon.getUUID();
LOGGER.info("Found that there's a dragon still alive ({})", (Object)enderDragon);
this.dragonKilled = false;
- if (!bl) {
+ if (!bl && this.level.paperConfig.shouldRemoveDragon) {
LOGGER.info("But we didn't have a portal, let's remove it.");
enderDragon.discard();
this.dragonUUID = null;

View file

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

View file

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

View file

@ -1,130 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 4 Aug 2020 22:24:15 +0200
Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections
1.17 Update: Please do this k thx bb
I utilized the IDE to convert streams to non streams code, so shouldn't
be any risk of behavior change. Only did minor optimization of the
generated code set to remove unnecessary things.
I expect us to just drop this patch on next major update and re-apply
it with the IDE again and re-apply the collections optimization.
Optimize collection by creating a list instead of a set of the key and value.
This lets us get faster foreach iteration, as well as avoids map lookups on
the values when needed.
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
index 076f2dea0e75577ccb0316b3171ed8f44ab6d2ba..3dc896a7ded8d5d109100a393c8299e308954d99 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
@@ -35,27 +35,31 @@ public class PathFinder {
this.openSet.clear();
this.nodeEvaluator.prepare(world, mob);
Node node = this.nodeEvaluator.getStart();
- Map<Target, BlockPos> map = positions.stream().collect(Collectors.toMap((blockPos) -> {
- return this.nodeEvaluator.getGoal((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ());
- }, Function.identity()));
+ // Paper start - remove streams - and optimize collection
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
+ for (BlockPos blockPos : positions) {
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(blockPos.getX(), blockPos.getY(), blockPos.getZ()), blockPos));
+ }
+ // Paper end
Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
this.nodeEvaluator.done();
return path;
}
@Nullable
- private Path findPath(ProfilerFiller profiler, Node startNode, Map<Target, BlockPos> positions, float followRange, int distance, float rangeMultiplier) {
+ // Paper start - optimize collection
+ private Path findPath(ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) {
profiler.push("find_path");
profiler.markForCharting(MetricCategory.PATH_FINDING);
- Set<Target> set = positions.keySet();
+ //Set<Target> set = positions.keySet();
startNode.g = 0.0F;
- startNode.h = this.getBestH(startNode, set);
+ startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection
startNode.f = startNode.h;
this.openSet.clear();
this.openSet.insert(startNode);
- Set<Node> set2 = ImmutableSet.of();
+ //Set<Node> set2 = ImmutableSet.of(); // Paper - unused - diff on change
int i = 0;
- Set<Target> set3 = Sets.newHashSetWithExpectedSize(set.size());
+ List<Map.Entry<Target, BlockPos>> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection
int j = (int)((float)this.maxVisitedNodes * rangeMultiplier);
while(!this.openSet.isEmpty()) {
@@ -67,14 +71,18 @@ public class PathFinder {
Node node = this.openSet.pop();
node.closed = true;
- for(Target target : set) {
+ // Paper start - optimize collection
+ for(int i1 = 0; i1 < positions.size(); i1++) {
+ final Map.Entry<Target, BlockPos> entry = positions.get(i1);
+ Target target = entry.getKey();
if (node.distanceManhattan(target) <= (float)distance) {
target.setReached();
- set3.add(target);
+ entryList.add(entry);
+ // Paper end
}
}
- if (!set3.isEmpty()) {
+ if (!entryList.isEmpty()) { // Paper - rename variable
break;
}
@@ -89,7 +97,7 @@ public class PathFinder {
if (node2.walkedDistance < followRange && (!node2.inOpenSet() || g < node2.g)) {
node2.cameFrom = node;
node2.g = g;
- node2.h = this.getBestH(node2, set) * 1.5F;
+ node2.h = this.getBestH(node2, positions) * 1.5F; // Paper - list instead of set
if (node2.inOpenSet()) {
this.openSet.changeCost(node2, node2.g + node2.h);
} else {
@@ -101,19 +109,27 @@ public class PathFinder {
}
}
- Optional<Path> optional = !set3.isEmpty() ? set3.stream().map((target) -> {
- return this.reconstructPath(target.getBestNode(), positions.get(target), true);
- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> {
- return this.reconstructPath(target.getBestNode(), positions.get(target), false);
- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
- profiler.pop();
- return !optional.isPresent() ? null : optional.get();
+ // Paper start - remove streams - and optimize collection
+ Path best = null;
+ boolean entryListIsEmpty = entryList.isEmpty();
+ Comparator<Path> comparator = entryListIsEmpty ? Comparator.comparingInt(Path::getNodeCount)
+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount);
+ for (Map.Entry<Target, BlockPos> entry : entryListIsEmpty ? positions : entryList) {
+ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty);
+ if (best == null || comparator.compare(path, best) < 0)
+ best = path;
+ }
+ return best;
+ // Paper end
}
- private float getBestH(Node node, Set<Target> targets) {
+ private float getBestH(Node node, List<Map.Entry<Target, BlockPos>> targets) { // Paper - optimize collection - Set<Target> -> List<Map.Entry<Target, BlockPos>>
float f = Float.MAX_VALUE;
- for(Target target : targets) {
+ // Paper start - optimize collection
+ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) {
+ final Target target = targets.get(i).getKey();
+ // Paper end
float g = node.distanceTo(target);
target.updateBest(g, node);
f = Math.min(g, f);

View file

@ -1,131 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 24 Jun 2020 12:39:08 -0600
Subject: [PATCH] Beacon API - custom effect ranges
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 0fa01b98f4a2ce2a7d34437a71d8c1cc7e718fb1..11740e6a312cf8ab10b52461f455feba0e1b2788 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
@@ -79,6 +79,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null;
}
// CraftBukkit end
+ // Paper start - add field/methods for custom range
+ private final String PAPER_RANGE_TAG = "Paper.Range";
+ private double effectRange = -1;
+
+ public double getEffectRange() {
+ if (this.effectRange < 0) {
+ return this.levels * 10 + 10;
+ } else {
+ return effectRange;
+ }
+ }
+
+ public void setEffectRange(double range) {
+ this.effectRange = range;
+ }
+
+ public void resetEffectRange() {
+ this.effectRange = -1;
+ }
+ // Paper end
public BeaconBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.BEACON, pos, state);
@@ -182,7 +202,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
- BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower);
+ BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
}
}
@@ -268,8 +288,13 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
public static List getHumansInRange(Level world, BlockPos blockposition, int i) {
+ // Paper start
+ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null);
+ }
+ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end
{
- double d0 = (double) (i * 10 + 10);
+ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10);// Paper - custom beacon ranges
AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
@@ -310,12 +335,17 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect) {
+ // Paper start
+ BeaconBlockEntity.applyEffects(world, pos, beaconLevel, primaryEffect, secondaryEffect, null);
+ }
+ private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end
if (!world.isClientSide && primaryEffect != null) {
double d0 = (double) (beaconLevel * 10 + 10);
byte b0 = BeaconBlockEntity.getAmplification(beaconLevel, primaryEffect, secondaryEffect);
int j = BeaconBlockEntity.getLevel(beaconLevel);
- List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel);
+ List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel, blockEntity); // Paper
BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent
@@ -366,6 +396,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
this.lockKey = LockCode.fromTag(nbt);
+ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper
}
@Override
@@ -379,6 +410,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
this.lockKey.addToTag(nbt);
+ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper
return nbt;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
index 22e9245b0a0d30972980c6c13a22cb4501c3d3ca..046981c5611d2064811fa34a02218db4a7c1c0c6 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
@@ -29,7 +29,7 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
if (tileEntity instanceof BeaconBlockEntity) {
BeaconBlockEntity beacon = (BeaconBlockEntity) tileEntity;
- Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels);
+ Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels, beacon); // Paper
Collection<LivingEntity> bukkit = new ArrayList<LivingEntity>(nms.size());
for (Player human : nms) {
@@ -106,4 +106,21 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
public void setLock(String key) {
this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key);
}
+
+ // Paper start
+ @Override
+ public double getEffectRange() {
+ return this.getSnapshot().getEffectRange();
+ }
+
+ @Override
+ public void setEffectRange(double range) {
+ this.getSnapshot().setEffectRange(range);
+ }
+
+ @Override
+ public void resetEffectRange() {
+ this.getSnapshot().resetEffectRange();
+ }
+ // Paper end
}

View file

@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 14 Nov 2020 16:19:52 +0100
Subject: [PATCH] Add API for quit reason
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 7f6405ac44fef423dc8b21f3dbeaae26a1005077..bdd4f4db9849d9107b5c62d5e83b1277621f49f1 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -142,12 +142,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.handlingFault = true;
if (this.channel.isOpen()) {
+ net.minecraft.server.level.ServerPlayer player = this.getPlayer(); // Paper
if (throwable instanceof TimeoutException) {
Connection.LOGGER.debug("Timeout", throwable);
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper
this.disconnect(new TranslatableComponent("disconnect.timeout"));
} else {
TranslatableComponent chatmessage = new TranslatableComponent("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable});
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper
if (flag) {
Connection.LOGGER.debug("Failed to sent packet", throwable);
ConnectionProtocol enumprotocol = this.getCurrentProtocol();
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index d8df3bcf6ddd87e9fa932f01a41a48a641328f9d..4f1291a1f840000aac782389e4c93b317cbf90d1 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -262,6 +262,7 @@ public class ServerPlayer extends Player {
public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
boolean needsChunkCenterUpdate; // Paper - no-tick view distance
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 557817c8ac1eadabc11f7f3efc8485b226d7657e..7cfdd686773b8ef67c99f3211c3ed2bf84fb54ea 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -443,6 +443,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure
// CraftBukkit end
+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper
this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> {
this.connection.disconnect(ichatbasecomponent);
});
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 4d1d5dacb175e7059a6af036432ef891bcf77970..76e21498b6cfd1c9a601a55e1483eb8dfd892c2e 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -597,7 +597,7 @@ public abstract class PlayerList {
entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper
}
- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())));
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason
if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());

View file

@ -1,71 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Phoenix616 <mail@moep.tv>
Date: Mon, 13 Jan 2020 15:40:32 +0100
Subject: [PATCH] Seed based feature search
This tries to work around the issue where the server will load
surrounding chunks up to a radius of 100 chunks in order to search for
features e.g. when running the /locate command or for treasure maps
(issue #2312).
This is done by backporting Mojang's change in 1.17 which makes it so
that the biome (generated by the seed) is checked first if the feature
can be generated before actually to load the chunk.
Additionally to that the center location of the target chunk is simply
returned if the chunk is not loaded to avoid the sync chunk load.
As this can lead to less precise locations a toggle is provided to
enable the sync loading of the target chunk again.
The main downside of this is that it breaks once the seed or generator
changes but this should usually not happen. A config option to disable
this completely is added though in case that should ever be necessary.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 568da8f2ef3c5e1412cf13c10b425100af75e902..7ef45c941dacaa1f5cc4f0544af9ec76424cc783 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -417,6 +417,14 @@ public class PaperWorldConfig {
}
}
+ public boolean seedBasedFeatureSearch = true;
+ public boolean seedBasedFeatureSearchLoadsChunks = true;
+ private void seedBasedFeatureSearch() {
+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch);
+ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks);
+ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks);
+ }
+
public int maxCollisionsPerEntity;
private void maxEntityCollision() {
maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) );
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java
index d7129f3379f2edecbcfd85f83d75e4d7064ce71d..7705ad4460ddf5166d922888f3a1368c50bb11ca 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java
@@ -171,7 +171,24 @@ public abstract class StructureFeature<C extends FeatureConfiguration> {
if (!world.getWorldBorder().isChunkInBounds(chunkPos.x, chunkPos.z)) { continue; } // Paper
boolean bl3 = world.getBiomeManager().getPrimaryBiomeAtChunk(chunkPos).getGenerationSettings().isValidStart(this);
if (bl3) {
- ChunkAccess chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS);
+ // Paper start - seed based feature search
+ ChunkAccess chunkAccess = null;
+ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) {
+ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkPos.getMinBlockX() + 9, 0, chunkPos.getMinBlockZ() + 9));
+ if (!biomeBase.getGenerationSettings().isValidStart(this)) {
+ continue;
+ }
+ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) {
+ chunkAccess = structureAccessor.getWorld().getChunkIfLoaded(chunkPos.x, chunkPos.z);
+ if (chunkAccess == null) {
+ return chunkPos.getWorldPosition().offset(8, searchStartPos.getY(), 8);
+ }
+ }
+ }
+ if (chunkAccess == null) {
+ chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS);
+ }
+ // Paper end
StructureStart<?> structureStart = structureAccessor.getStartForFeature(SectionPos.bottomOf(chunkAccess), this, chunkAccess);
if (structureStart != null && structureStart.isValid()) {
if (skipExistingChunks && structureStart.canBeReferenced()) {

View file

@ -1,111 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Thu, 20 Aug 2020 11:20:12 -0700
Subject: [PATCH] Add Wandering Trader spawn rate config options
Adds config options for modifying the spawn rates of Wandering Traders.
These values are all easy to understand and configure after a quick read of this
page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning
Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values
in IWorldServerData are removed as they were only used in certain places, with hardcoded
values used in other places.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 7ef45c941dacaa1f5cc4f0544af9ec76424cc783..e1aa521a3947b38643866e038c7d0536658c58f2 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -80,6 +80,19 @@ public class PaperWorldConfig {
}
}
+ public int wanderingTraderSpawnMinuteTicks = 1200;
+ public int wanderingTraderSpawnDayTicks = 24000;
+ public int wanderingTraderSpawnChanceFailureIncrement = 25;
+ public int wanderingTraderSpawnChanceMin = 25;
+ public int wanderingTraderSpawnChanceMax = 75;
+ private void wanderingTraderSettings() {
+ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks);
+ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks);
+ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement);
+ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin);
+ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
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 12aa0fd5b6bada9820c3a08eee47c870f9c183cb..60f08ecd0034e8ef2965b54b3abccce582d0ca54 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
@@ -43,43 +43,53 @@ public class WanderingTraderSpawner implements CustomSpawner {
public WanderingTraderSpawner(ServerLevelData properties) {
this.serverLevelData = properties;
- this.tickDelay = 1200;
- this.spawnDelay = properties.getWanderingTraderSpawnDelay();
- this.spawnChance = properties.getWanderingTraderSpawnChance();
- if (this.spawnDelay == 0 && this.spawnChance == 0) {
- this.spawnDelay = 24000;
- properties.setWanderingTraderSpawnDelay(this.spawnDelay);
- this.spawnChance = 25;
- properties.setWanderingTraderSpawnChance(this.spawnChance);
- }
+ // Paper start
+ this.tickDelay = Integer.MIN_VALUE;
+ //this.spawnDelay = properties.getWanderingTraderSpawnDelay(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value
+ //this.spawnChance = properties.getWanderingTraderSpawnChance(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value
+ //if (this.spawnDelay == 0 && this.spawnChance == 0) {
+ // this.spawnDelay = 24000;
+ // properties.setWanderingTraderSpawnDelay(this.spawnDelay);
+ // this.spawnChance = 25;
+ // properties.setWanderingTraderSpawnChance(this.spawnChance);
+ //}
+ // Paper end
}
@Override
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
+ // Paper start
+ if (this.tickDelay == Integer.MIN_VALUE) {
+ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks;
+ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks;
+ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin;
+ }
if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) {
return 0;
- } else if (--this.tickDelay > 0) {
+ } else if (this.tickDelay - 1 > 0) {
+ this.tickDelay = this.tickDelay - 1;
return 0;
} else {
- this.tickDelay = 1200;
- this.spawnDelay -= 1200;
- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay);
+ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks;
+ this.spawnDelay = this.spawnDelay - world.paperConfig.wanderingTraderSpawnMinuteTicks;
+ //this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways
if (this.spawnDelay > 0) {
return 0;
} else {
- this.spawnDelay = 24000;
+ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks;
if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
return 0;
} else {
int i = this.spawnChance;
- this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75);
- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance);
+ this.spawnChance = Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax);
+ //this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways
if (this.random.nextInt(100) > i) {
return 0;
} else if (this.spawn(world)) {
- this.spawnChance = 25;
+ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin;
+ // Paper end
return 1;
} else {
return 0;

View file

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

View file

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
Date: Tue, 17 Nov 2020 19:13:09 +0200
Subject: [PATCH] Expose world spawn angle
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index d95403513eb3b497187d9a93ea8230a632025d79..51764416bc8adcd3bca28200453e57e6e52cab5b 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -875,7 +875,7 @@ public abstract class PlayerList {
if (location == null) {
worldserver1 = this.server.getLevel(Level.OVERWORLD);
blockposition = entityplayer1.getSpawnPoint(worldserver1);
- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F));
+ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle
}
Player respawnPlayer = entityplayer1.getBukkitEntity();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index c21b98fbd9b410e0e993f3073e5cbb37015776eb..9088d41108fa355850def4a9afcca6439c406fc3 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -236,7 +236,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public Location getSpawnLocation() {
BlockPos spawn = this.world.getSharedSpawnPos();
- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ());
+ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.levelData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle
}
@Override

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ineusia <ineusia@yahoo.com>
Date: Mon, 26 Oct 2020 11:48:06 -0500
Subject: [PATCH] Add Destroy Speed API
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index fd4a0bbd1438bfc94580f29382d0c5f50531292b..6d79409f58715038de1e9e397e73f8739fb9dca2 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -622,5 +622,23 @@ public class CraftBlock implements Block {
public String translationKey() {
return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
}
+
+ @Override
+ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) {
+ net.minecraft.world.item.ItemStack nmsItemStack;
+ if (itemStack instanceof CraftItemStack) {
+ nmsItemStack = ((CraftItemStack) itemStack).handle;
+ } else {
+ nmsItemStack = CraftItemStack.asNMSCopy(itemStack);
+ }
+ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMS().getBlock().defaultBlockState());
+ if (speed > 1.0F && considerEnchants) {
+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack);
+ if (enchantLevel > 0) {
+ speed += enchantLevel * enchantLevel + 1;
+ }
+ }
+ return speed;
+ }
// Paper end
}

View file

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

View file

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

View file

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

View file

@ -1,49 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kennytv <jahnke.nassim@gmail.com>
Date: Sun, 26 Jul 2020 14:44:09 +0200
Subject: [PATCH] More lightning API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
index f7991ff14ef9cda0327b8621bf615b49cffd7ac5..e515e819774bfb31ec03f05a5502921e66f2b0e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
@@ -45,4 +45,38 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike
return this.spigot;
}
// Spigot end
+
+ // Paper start
+ @Override
+ public int getFlashCount() {
+ return getHandle().flashes;
+ }
+
+ @Override
+ public void setFlashCount(int flashes) {
+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!");
+ getHandle().flashes = flashes;
+ }
+
+ @Override
+ public int getLifeTicks() {
+ return getHandle().life;
+ }
+
+ @Override
+ public void setLifeTicks(int lifeTicks) {
+ getHandle().life = lifeTicks;
+ }
+
+ @Override
+ public @org.jetbrains.annotations.Nullable org.bukkit.entity.Entity getCausingEntity() {
+ final var cause = this.getHandle().getCause();
+ return cause == null ? null : cause.getBukkitEntity();
+ }
+
+ @Override
+ public void setCausingPlayer(@org.jetbrains.annotations.Nullable org.bukkit.entity.Player causingPlayer) {
+ this.getHandle().setCause(causingPlayer == null ? null : ((CraftPlayer) causingPlayer).getHandle());
+ }
+ // Paper end
}

View file

@ -1,173 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 23 Aug 2020 20:59:00 +0200
Subject: [PATCH] Climbing should not bypass cramming gamerule
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index e1aa521a3947b38643866e038c7d0536658c58f2..a6cfc237fe5e06d43732dcd76b3a52a886ae8fe3 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -93,6 +93,11 @@ public class PaperWorldConfig {
wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax);
}
+ public boolean fixClimbingBypassingCrammingRule = false;
+ private void fixClimbingBypassingCrammingRule() {
+ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 368c80ac596b66396985521e6e8c6aee6af26697..7e0f711ded0ecf0b94a79f69a3d75c2afa57c5a9 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1749,6 +1749,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
}
public boolean isPushable() {
+ // Paper start
+ return isCollidable(false);
+ }
+
+ public boolean isCollidable(boolean ignoreClimbing) {
+ // Paper end
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index 8fb89326395a7e70982c0d757b506565e98b12a4..a060cca08631fb42041e3a79a9abc422fe7757af 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -44,11 +44,17 @@ public final class EntitySelector {
}
public static Predicate<Entity> pushableBy(Entity entity) {
+ // Paper start - ignoreClimbing param
+ return pushable(entity, false);
+ }
+
+ public static Predicate<Entity> pushable(Entity entity, boolean ignoreClimbing) {
+ // Paper end
Team scoreboardteambase = entity.getTeam();
Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule();
return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> {
- if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API
+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable
return false;
} else if (entity.level.isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) {
return false;
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 40964014376aa911f412f6a5b717c6cf523530ab..327199d0e002bb7e7c2194fb54c213e837dd8dd8 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3277,7 +3277,7 @@ public abstract class LivingEntity extends Entity {
return;
}
// Paper end - don't run getEntities if we're not going to use its result
- List<Entity> list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this));
+ List<Entity> list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule
if (!list.isEmpty()) {
// Paper - move up
@@ -3444,9 +3444,16 @@ public abstract class LivingEntity extends Entity {
return !this.isRemoved() && this.collides; // CraftBukkit
}
+ // Paper start
@Override
public boolean isPushable() {
- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit
+ return this.isCollidable(level.paperConfig.fixClimbingBypassingCrammingRule);
+ }
+
+ @Override
+ public boolean isCollidable(boolean ignoreClimbing) {
+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit
+ // Paper end
}
// CraftBukkit start - collidable API
diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
index ee55623cddc6d9e0dde5f384d66a750b92cc4f0e..9ed2f8f2843c634fd14dda4459f85b7140dd447a 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
@@ -83,7 +83,7 @@ public class Bat extends AmbientCreature {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
index 57378e42d6ef1be70a0abcca846cab9108c76783..ae21d260b2d4673eb4aa56a82e1043d20507adb2 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
@@ -380,8 +380,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
}
@Override
- public boolean isPushable() {
- return super.isPushable(); // CraftBukkit - collidable API
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
index c613a5e4d3ae360ce3eed312c5eecc553fae0066..630b6491ee186e1e3f17489311a91681e52b7ff5 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -239,7 +239,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return !this.isVehicle();
}
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
index c5e9273055ff7302941b7475d8175be53eaece1f..02bce120fc93caa9e1e92b61e74c28209a1b2385 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -345,7 +345,7 @@ public class ArmorStand extends LivingEntity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
index fa889f93a5c6782957bdbf803915cb5e80e05f3e..9653b142c199c068e4d6175bcd3cbecb6465853f 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
@@ -149,7 +149,7 @@ public abstract class AbstractMinecart extends Entity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return true;
}
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
index 3f1059569da23bd02c00279050bf7bce7a160462..a1b93f2878e22fa1d0cad639416d2dc5b8339c73 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
@@ -158,7 +158,7 @@ public class Boat extends Entity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return true;
}

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 16 Nov 2020 12:01:52 -0800
Subject: [PATCH] Added missing default perms for commands
diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
index ca30f9c590f792caa8f1b76d7219e9121d932673..6cc517b394bafefce50d877761e5b2eee8e14c78 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
@@ -31,6 +31,59 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands);
+ // Paper start
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item)
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands);
+ // Paper end
DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands);

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Thu, 27 Aug 2020 15:02:48 -0400
Subject: [PATCH] Add PlayerShearBlockEvent
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
index 96bc2cc1e3005a5273b8834569f5dee5c3a08293..d3b85a29662d33d458cfd4d7942b8e2d2264b750 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -115,7 +115,7 @@ public class BeehiveBlock extends BaseEntityBlock {
}
public static void dropHoneycomb(Level world, BlockPos pos) {
- popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3));
+ popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); // Paper - conflict on change, item needs to be set below
}
@Override
@@ -128,8 +128,19 @@ public class BeehiveBlock extends BaseEntityBlock {
Item item = itemstack.getItem();
if (itemstack.is(Items.SHEARS)) {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F);
- BeehiveBlock.dropHoneycomb(world, pos);
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack itemDrop : event.getDrops()) {
+ popResource(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemDrop));
+ }
+ // Paper end
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
entityhuman1.broadcastBreakEvent(hand);
});
diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
index 0e8cbe7a465edc31b78b7e47a928435f9c2b6bd9..f998598a34315389dd74b82e4b9c8448f0aae253 100644
--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
@@ -27,13 +27,24 @@ public class PumpkinBlock extends StemGrownBlock {
ItemStack itemStack = player.getItemInHand(hand);
if (itemStack.is(Items.SHEARS)) {
if (!world.isClientSide) {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
Direction direction = hit.getDirection();
Direction direction2 = direction.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : direction;
world.playSound((Player)null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F);
world.setBlock(pos, Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, direction2), 11);
- ItemEntity itemEntity = new ItemEntity(world, (double)pos.getX() + 0.5D + (double)direction2.getStepX() * 0.65D, (double)pos.getY() + 0.1D, (double)pos.getZ() + 0.5D + (double)direction2.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4));
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) {
+ ItemEntity itemEntity = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) direction2.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) direction2.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item));
+ // Paper end
itemEntity.setDeltaMovement(0.05D * (double)direction2.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double)direction2.getStepZ() + world.random.nextDouble() * 0.02D);
world.addFreshEntity(itemEntity);
+ } // Paper - Add PlayerShearBlockEvent
itemStack.hurtAndBreak(1, player, (playerx) -> {
playerx.broadcastBreakEvent(hand);
});

View file

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Tue, 8 Dec 2020 20:14:20 -0600
Subject: [PATCH] Fix curing zombie villager discount exploit
This fixes the exploit used to gain absurd trading discounts with infecting
and curing a villager on repeat by simply resetting the relevant part of
the reputation when it is cured.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index a6cfc237fe5e06d43732dcd76b3a52a886ae8fe3..87e3f45057bde15e10b5bb55a9be6e9b6131e254 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -98,6 +98,11 @@ public class PaperWorldConfig {
fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule);
}
+ public boolean fixCuringZombieVillagerDiscountExploit = true;
+ private void fixCuringExploit() {
+ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 2eb60384b244a5c1dc8bcbeb59c8adc69e3f18cd..b746453774054dd2db023b7eea265a395cfc7cc9 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -1056,6 +1056,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public void onReputationEventFrom(ReputationEventType interaction, Entity entity) {
if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) {
+ // Paper start - fix MC-181190
+ if (level.paperConfig.fixCuringZombieVillagerDiscountExploit) {
+ final GossipContainer.EntityGossips playerReputation = this.getGossips().getReputations().get(entity.getUUID());
+ if (playerReputation != null) {
+ playerReputation.remove(GossipType.MAJOR_POSITIVE);
+ playerReputation.remove(GossipType.MINOR_POSITIVE);
+ }
+ }
+ // Paper end
this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20);
this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25);
} else if (interaction == ReputationEventType.TRADE) {

View file

@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sat, 12 Dec 2020 23:45:28 +0000
Subject: [PATCH] Limit recipe packets
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 380c4f46b98e6296cf28568abb1e74a80278ffa0..288310df8ca9eff6901d906b48ba7cd1b6bc8ae3 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -355,6 +355,13 @@ public class PaperConfig {
tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit);
}
+ public static int autoRecipeIncrement = 1;
+ public static int autoRecipeLimit = 20;
+ private static void autoRecipieLimiters() {
+ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement);
+ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit);
+ }
+
public static boolean velocitySupport;
public static boolean velocityOnlineMode;
public static byte[] velocitySecretKey;
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 7cfdd686773b8ef67c99f3211c3ed2bf84fb54ea..7a4766d4fd86b6f0ab725955e364c631d37752b6 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -231,6 +231,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// CraftBukkit start - multithreaded fields
private AtomicInteger chatSpamTickCount = new AtomicInteger();
private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits
+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit
// CraftBukkit end
private int dropSpamTickCount;
private double firstGoodX;
@@ -376,6 +377,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// CraftBukkit start
for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ;
if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable
+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper
/* Use thread-safe field access instead
if (this.chatSpamTickCount > 0) {
--this.chatSpamTickCount;
@@ -2801,6 +2803,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
@Override
public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {
+ // Paper start
+ if (!org.bukkit.Bukkit.isPrimaryThread()) {
+ if (recipeSpamPackets.addAndGet(com.destroystokyo.paper.PaperConfig.autoRecipeIncrement) > com.destroystokyo.paper.PaperConfig.autoRecipeLimit) {
+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper
+ return;
+ }
+ }
+ // Paper end
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
this.player.resetLastActionTime();
if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) {

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 17 Dec 2020 15:25:49 -0600
Subject: [PATCH] Fix CraftSound backwards compatibility
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
index 266563e72b563fd9db85f17bca710bbe45e8a22d..b2667c5f0794d521766203fea3299f12e21f5c76 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
@@ -26,4 +26,10 @@ public class CraftSound {
public static Sound getBukkit(SoundEvent soundEffect) {
return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.SOUND_EVENT.getKey(soundEffect)));
}
+
+ // Paper start
+ public static String getSound(Sound sound) {
+ return sound.getKey().getKey();
+ }
+ // Paper end
}