From 40c6716ffd8fb3a6146dba8c7912dacb37db6d8c Mon Sep 17 00:00:00 2001 From: Mgazul Date: Sun, 8 Dec 2024 01:30:30 +0800 Subject: [PATCH] Update CraftBukkit-1.21.4 --- docs/README.md | 2 +- .../world/item/crafting/RecipeItemStack.patch | 66 ---------- .../DedicatedServerProperties.java.patch | 7 +- .../entity/vehicle/MinecartTNT.java.patch | 13 ++ .../world/item/crafting/Ingredient.java.patch | 39 +++++- .../AbstractFurnaceBlockEntity.java.patch | 11 +- .../java/org/bukkit/craftbukkit/CraftArt.java | 108 ++++++++++++++-- .../org/bukkit/craftbukkit/CraftFluid.java | 89 +++++++++++-- .../org/bukkit/craftbukkit/CraftParticle.java | 10 +- .../craftbukkit/CraftRegionAccessor.java | 6 + .../org/bukkit/craftbukkit/CraftRegistry.java | 24 +++- .../org/bukkit/craftbukkit/CraftServer.java | 10 ++ .../org/bukkit/craftbukkit/CraftSound.java | 94 +++++++++++--- .../org/bukkit/craftbukkit/CraftWorld.java | 15 +-- .../advancement/CraftAdvancement.java | 6 + .../CraftAdvancementRequirement.java | 26 ++++ .../CraftAdvancementRequirements.java | 21 ++++ .../craftbukkit/attribute/CraftAttribute.java | 97 ++++++++++++-- .../bukkit/craftbukkit/block/CraftBiome.java | 99 ++++++++++++--- .../craftbukkit/block/CraftFurnace.java | 8 +- .../block/data/CraftBlockData.java | 11 +- .../block/data/type/CraftCreakingHeart.java | 21 +++- .../block/impl/CraftCreakingHeart.java | 20 ++- .../block/impl/CraftMultiface.java | 79 ++++++++++++ ...ryLeaves.java => CraftParticleLeaves.java} | 24 ++-- .../craftbukkit/block/impl/CraftVault.java | 14 ++- .../command/VanillaCommandWrapper.java | 6 + .../craftbukkit/entity/CraftBreeze.java | 9 ++ .../entity/CraftCreakingTransient.java | 22 ---- .../craftbukkit/entity/CraftEntityTypes.java | 9 +- .../craftbukkit/entity/CraftLivingEntity.java | 4 +- .../craftbukkit/entity/CraftMinecart.java | 3 +- .../craftbukkit/entity/CraftMinecartTNT.java | 10 ++ .../craftbukkit/entity/CraftPlayer.java | 17 +-- .../generator/CustomChunkGenerator.java | 7 +- .../craftbukkit/inventory/CraftInventory.java | 28 ++--- .../inventory/CraftItemFactory.java | 2 + .../inventory/CraftMerchantCustom.java | 5 + .../craftbukkit/inventory/CraftMetaItem.java | 46 +++++-- .../craftbukkit/inventory/CraftRecipe.java | 14 +-- .../inventory/CraftShapelessRecipe.java | 4 +- .../inventory/SerializableMeta.java | 37 ++++++ .../CraftCustomModelDataComponent.java | 119 ++++++++++++++++++ .../components/CraftEquippableComponent.java | 26 ++-- .../components/CraftUseCooldownComponent.java | 8 +- .../craftbukkit/legacy/FieldRename.java | 38 +++++- .../craftbukkit/legacy/enums/EnumEvil.java | 10 ++ .../craftbukkit/scheduler/CraftScheduler.java | 6 +- .../scoreboard/CraftScoreboard.java | 2 +- .../bukkit/craftbukkit/util/ApiVersion.java | 2 +- .../util/BlockStateListPopulator.java | 7 ++ .../bukkit/craftbukkit/util/Commodore.java | 21 ++-- .../craftbukkit/util/CraftMagicNumbers.java | 16 ++- 53 files changed, 1082 insertions(+), 316 deletions(-) delete mode 100644 nms-patches/net/minecraft/world/item/crafting/RecipeItemStack.patch create mode 100644 patches/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch create mode 100644 src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirement.java create mode 100644 src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirements.java create mode 100644 src/main/java/org/bukkit/craftbukkit/block/impl/CraftMultiface.java rename src/main/java/org/bukkit/craftbukkit/block/impl/{CraftCherryLeaves.java => CraftParticleLeaves.java} (55%) delete mode 100644 src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java create mode 100644 src/main/java/org/bukkit/craftbukkit/inventory/components/CraftCustomModelDataComponent.java diff --git a/docs/README.md b/docs/README.md index 0dfbe610..716bc8f9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,7 +24,7 @@ Progress - [x] Rectify NeoForge([**00f3f80ef9**](https://github.com/neoforged/NeoForge/commit/00f3f80ef9)) - [ ] Start patch * [x] Bukkit([**3339db16**](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/3339db16)) - * [ ] CraftBukkit([**d50f50585**](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/d50f50585)) + * [ ] CraftBukkit([**665900b91**](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/665900b91)) * [ ] Spigot ([**d2eba2c8**](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/commits/d2eba2c8)) * [ ] Bukkit-Patches * [ ] CraftBukkit-Patches diff --git a/nms-patches/net/minecraft/world/item/crafting/RecipeItemStack.patch b/nms-patches/net/minecraft/world/item/crafting/RecipeItemStack.patch deleted file mode 100644 index bf6a66a8..00000000 --- a/nms-patches/net/minecraft/world/item/crafting/RecipeItemStack.patch +++ /dev/null @@ -1,66 +0,0 @@ ---- a/net/minecraft/world/item/crafting/RecipeItemStack.java -+++ b/net/minecraft/world/item/crafting/RecipeItemStack.java -@@ -21,6 +21,11 @@ - import net.minecraft.world.item.crafting.display.SlotDisplay; - import net.minecraft.world.level.IMaterial; - -+// CraftBukkit start -+import java.util.List; -+import javax.annotation.Nullable; -+// CraftBukkit end -+ - public final class RecipeItemStack implements AutoRecipeStackManager.a>, Predicate { - - public static final StreamCodec CONTENTS_STREAM_CODEC = ByteBufCodecs.holderSet(Registries.ITEM).map(RecipeItemStack::new, (recipeitemstack) -> { -@@ -38,6 +43,24 @@ - return recipeitemstack.values; - }); - private final HolderSet values; -+ // CraftBukkit start -+ @Nullable -+ private List itemStacks; -+ -+ public boolean isExact() { -+ return this.itemStacks != null; -+ } -+ -+ public List itemStacks() { -+ return this.itemStacks; -+ } -+ -+ public static RecipeItemStack ofStacks(List stacks) { -+ RecipeItemStack recipe = RecipeItemStack.of(stacks.stream().map(ItemStack::getItem)); -+ recipe.itemStacks = stacks; -+ return recipe; -+ } -+ // CraftBukkit end - - private RecipeItemStack(HolderSet holderset) { - holderset.unwrap().ifRight((list) -> { -@@ -70,6 +93,17 @@ - } - - public boolean test(ItemStack itemstack) { -+ // CraftBukkit start -+ if (this.isExact()) { -+ for (ItemStack itemstack1 : this.itemStacks()) { -+ if (itemstack1.getItem() == itemstack.getItem() && ItemStack.isSameItemSameComponents(itemstack, itemstack1)) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ // CraftBukkit end - return itemstack.is(this.values); - } - -@@ -79,7 +113,7 @@ - - public boolean equals(Object object) { - if (object instanceof RecipeItemStack recipeitemstack) { -- return Objects.equals(this.values, recipeitemstack.values); -+ return Objects.equals(this.values, recipeitemstack.values) && Objects.equals(this.itemStacks, recipeitemstack.itemStacks); // CraftBukkit - } else { - return false; - } diff --git a/patches/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch b/patches/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch index 4f163736..dd4c5f6d 100644 --- a/patches/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch +++ b/patches/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch @@ -9,7 +9,12 @@ public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false); public final String serverIp = this.get("server-ip", ""); public final boolean pvp = this.get("pvp", true); -@@ -103,6 +_,7 @@ +@@ -99,10 +_,11 @@ + public final Settings.MutableValue whiteList = this.getMutable("white-list", false); + public final boolean enforceSecureProfile = this.get("enforce-secure-profile", true); + public final boolean logIPs = this.get("log-ips", true); +- public final int pauseWhenEmptySeconds = this.get("pause-when-empty-seconds", 60); ++ public int pauseWhenEmptySeconds = this.get("pause-when-empty-seconds", 60); private final DedicatedServerProperties.WorldDimensionData worldDimensionData; public final WorldOptions worldOptions; public boolean acceptsTransfers = this.get("accepts-transfers", false); diff --git a/patches/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch b/patches/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch new file mode 100644 index 00000000..5cbba7ea --- /dev/null +++ b/patches/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -31,8 +_,8 @@ + private static final float DEFAULT_EXPLOSION_POWER_BASE = 4.0F; + private static final float DEFAULT_EXPLOSION_SPEED_FACTOR = 1.0F; + public int fuse = -1; +- private float explosionPowerBase = 4.0F; +- private float explosionSpeedFactor = 1.0F; ++ public float explosionPowerBase = 4.0F; ++ public float explosionSpeedFactor = 1.0F; + + public MinecartTNT(EntityType p_38649_, Level p_38650_) { + super(p_38649_, p_38650_); diff --git a/patches/net/minecraft/world/item/crafting/Ingredient.java.patch b/patches/net/minecraft/world/item/crafting/Ingredient.java.patch index 8843005c..b03d4717 100644 --- a/patches/net/minecraft/world/item/crafting/Ingredient.java.patch +++ b/patches/net/minecraft/world/item/crafting/Ingredient.java.patch @@ -1,7 +1,10 @@ --- a/net/minecraft/world/item/crafting/Ingredient.java +++ b/net/minecraft/world/item/crafting/Ingredient.java -@@ -23,16 +_,20 @@ +@@ -21,18 +_,42 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.display.SlotDisplay; import net.minecraft.world.level.ItemLike; ++import org.jetbrains.annotations.Nullable; public class Ingredient implements StackedContents.IngredientInfo>, Predicate { - public static final StreamCodec CONTENTS_STREAM_CODEC = ByteBufCodecs.holderSet(Registries.ITEM) @@ -24,10 +27,29 @@ + private net.neoforged.neoforge.common.crafting.ICustomIngredient customIngredient = null; + @org.jetbrains.annotations.Nullable + private List> customIngredientValues; ++ ++ // CraftBukkit start ++ @Nullable ++ private List itemStacks; ++ ++ public boolean isExact() { ++ return this.itemStacks != null; ++ } ++ ++ public List itemStacks() { ++ return this.itemStacks; ++ } ++ ++ public static Ingredient ofStacks(List stacks) { ++ Ingredient recipe = Ingredient.of(stacks.stream().map(ItemStack::getItem)); ++ recipe.itemStacks = stacks; ++ return recipe; ++ } ++ // CraftBukkit end private Ingredient(HolderSet p_365027_) { p_365027_.unwrap().ifRight(p_360057_ -> { -@@ -45,30 +_,96 @@ +@@ -45,30 +_,107 @@ this.values = p_365027_; } @@ -59,6 +81,17 @@ + if (this.customIngredient != null) { + return this.customIngredient.test(p_43914_); + } ++ // CraftBukkit start ++ if (this.isExact()) { ++ for (ItemStack itemstack1 : this.itemStacks()) { ++ if (itemstack1.getItem() == p_43914_.getItem() && ItemStack.isSameItemSameComponents(p_43914_, itemstack1)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // CraftBukkit end return p_43914_.is(this.values); } @@ -72,7 +105,7 @@ @Override public boolean equals(Object p_301003_) { - return p_301003_ instanceof Ingredient ingredient ? Objects.equals(this.values, ingredient.values) : false; -+ return p_301003_ instanceof Ingredient ingredient ? java.util.Objects.equals(this.customIngredient, ingredient.customIngredient) && Objects.equals(this.values, ingredient.values) : false; ++ return p_301003_ instanceof Ingredient ingredient ? java.util.Objects.equals(this.customIngredient, ingredient.customIngredient) && Objects.equals(this.values, ingredient.values) && Objects.equals(this.itemStacks, ingredient.itemStacks) : false; + } + + @Override diff --git a/patches/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch b/patches/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch index 0d5b214c..89931080 100644 --- a/patches/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch +++ b/patches/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch @@ -1,14 +1,19 @@ --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -53,6 +_,7 @@ +@@ -53,19 +_,25 @@ public static final int NUM_DATA_VALUES = 4; public static final int BURN_TIME_STANDARD = 200; public static final int BURN_COOL_SPEED = 2; + private final RecipeType recipeType; protected NonNullList items = NonNullList.withSize(3, ItemStack.EMPTY); - int litTimeRemaining; +- int litTimeRemaining; ++ public int litTimeRemaining; int litTotalTime; -@@ -63,9 +_,14 @@ +- int cookingTimer; ++ public int cookingTimer; + public int cookingTotalTime; + protected final ContainerData dataAccess = new ContainerData() { + @Override public int get(int p_58431_) { switch (p_58431_) { case 0: diff --git a/src/main/java/org/bukkit/craftbukkit/CraftArt.java b/src/main/java/org/bukkit/craftbukkit/CraftArt.java index a4f3edb4..b80c97d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftArt.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftArt.java @@ -1,24 +1,23 @@ package org.bukkit.craftbukkit; import com.google.common.base.Preconditions; +import java.util.Locale; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.decoration.PaintingVariant; import org.bukkit.Art; +import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Handleable; +import org.jetbrains.annotations.NotNull; -public class CraftArt { +public class CraftArt implements Art, Handleable { - public static Art minecraftToBukkit(PaintingVariant minecraft) { - Preconditions.checkArgument(minecraft != null); - - net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT); - Art bukkit = Registry.ART.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location())); - - Preconditions.checkArgument(bukkit != null); + private static int count = 0; - return bukkit; + public static Art minecraftToBukkit(PaintingVariant minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.PAINTING_VARIANT, Registry.ART); } public static Art minecraftHolderToBukkit(Holder minecraft) { @@ -26,10 +25,7 @@ public static Art minecraftHolderToBukkit(Holder minecraft) { } public static PaintingVariant bukkitToMinecraft(Art bukkit) { - Preconditions.checkArgument(bukkit != null); - - return CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT) - .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow(); + return CraftRegistry.bukkitToMinecraft(bukkit); } public static Holder bukkitToMinecraftHolder(Art bukkit) { @@ -44,4 +40,90 @@ public static Holder bukkitToMinecraftHolder(Art bukkit) { throw new IllegalArgumentException("No Reference holder found for " + bukkit + ", this can happen if a plugin creates its own painting variant with out properly registering it."); } + + private final NamespacedKey key; + private final PaintingVariant paintingVariant; + private final String name; + private final int ordinal; + + public CraftArt(NamespacedKey key, PaintingVariant paintingVariant) { + this.key = key; + this.paintingVariant = paintingVariant; + // For backwards compatibility, minecraft values will stile return the uppercase name without the namespace, + // in case plugins use for example the name as key in a config file to receive art specific values. + // Custom arts will return the key with namespace. For a plugin this should look than like a new art + // (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly). + if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) { + this.name = key.getKey().toUpperCase(Locale.ROOT); + } else { + this.name = key.toString(); + } + this.ordinal = count++; + } + + @Override + public PaintingVariant getHandle() { + return paintingVariant; + } + + @Override + public int getBlockWidth() { + return paintingVariant.width(); + } + + @Override + public int getBlockHeight() { + return paintingVariant.height(); + } + + @Override + public int getId() { + return CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT).getId(paintingVariant); + } + + @NotNull + @Override + public NamespacedKey getKey() { + return key; + } + + @Override + public int compareTo(@NotNull Art art) { + return ordinal - art.ordinal(); + } + + @NotNull + @Override + public String name() { + return name; + } + + @Override + public int ordinal() { + return ordinal; + } + + @Override + public String toString() { + // For backwards compatibility + return name(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof CraftArt otherArt)) { + return false; + } + + return getKey().equals(otherArt.getKey()); + } + + @Override + public int hashCode() { + return getKey().hashCode(); + } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftFluid.java b/src/main/java/org/bukkit/craftbukkit/CraftFluid.java index 0d4ed5f5..b1b4178b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftFluid.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftFluid.java @@ -1,28 +1,93 @@ package org.bukkit.craftbukkit; -import com.google.common.base.Preconditions; +import java.util.Locale; import net.minecraft.core.registries.Registries; import org.bukkit.Fluid; +import org.bukkit.NamespacedKey; import org.bukkit.Registry; -import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Handleable; +import org.jetbrains.annotations.NotNull; -public class CraftFluid { +public class CraftFluid implements Fluid, Handleable { + + private static int count = 0; public static Fluid minecraftToBukkit(net.minecraft.world.level.material.Fluid minecraft) { - Preconditions.checkArgument(minecraft != null); + return CraftRegistry.minecraftToBukkit(minecraft, Registries.FLUID, Registry.FLUID); + } - net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.FLUID); - Fluid bukkit = Registry.FLUID.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location())); + public static net.minecraft.world.level.material.Fluid bukkitToMinecraft(Fluid bukkit) { + return CraftRegistry.bukkitToMinecraft(bukkit); + } - Preconditions.checkArgument(bukkit != null); + private final NamespacedKey key; + private final net.minecraft.world.level.material.Fluid fluidType; + private final String name; + private final int ordinal; - return bukkit; + public CraftFluid(NamespacedKey key, net.minecraft.world.level.material.Fluid fluidType) { + this.key = key; + this.fluidType = fluidType; + // For backwards compatibility, minecraft values will stile return the uppercase name without the namespace, + // in case plugins use for example the name as key in a config file to receive fluid specific values. + // Custom fluids will return the key with namespace. For a plugin this should look than like a new fluid + // (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly). + if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) { + this.name = key.getKey().toUpperCase(Locale.ROOT); + } else { + this.name = key.toString(); + } + this.ordinal = count++; } - public static net.minecraft.world.level.material.Fluid bukkitToMinecraft(Fluid bukkit) { - Preconditions.checkArgument(bukkit != null); + @Override + public net.minecraft.world.level.material.Fluid getHandle() { + return fluidType; + } + + @NotNull + @Override + public NamespacedKey getKey() { + return key; + } + + @Override + public int compareTo(@NotNull Fluid fluid) { + return ordinal - fluid.ordinal(); + } + + @NotNull + @Override + public String name() { + return name; + } + + @Override + public int ordinal() { + return ordinal; + } + + @Override + public String toString() { + // For backwards compatibility + return name(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof CraftFluid otherFluid)) { + return false; + } + + return getKey().equals(otherFluid.getKey()); + } - return CraftRegistry.getMinecraftRegistry(Registries.FLUID) - .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow(); + @Override + public int hashCode() { + return getKey().hashCode(); } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftParticle.java b/src/main/java/org/bukkit/craftbukkit/CraftParticle.java index 0be9c773..61e139ef 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftParticle.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftParticle.java @@ -13,7 +13,7 @@ import net.minecraft.core.particles.SculkChargeParticleOptions; import net.minecraft.core.particles.ShriekParticleOption; import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.core.particles.TargetColorParticleOption; +import net.minecraft.core.particles.TrailParticleOption; import net.minecraft.core.particles.VibrationParticleOption; import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.Entity; @@ -189,10 +189,10 @@ public ParticleOptions createParticleParam(Color color) { } }; - BiFunction, CraftParticle> targetColorFunction = (name, particle) -> new CraftParticle<>(name, particle, Particle.TargetColor.class) { + BiFunction, CraftParticle> trailFunction = (name, particle) -> new CraftParticle<>(name, particle, Particle.Trail.class) { @Override - public ParticleOptions createParticleParam(Particle.TargetColor data) { - return new TargetColorParticleOption(CraftLocation.toVec3D(data.getTarget()), data.getColor().asRGB()); + public ParticleOptions createParticleParam(Particle.Trail data) { + return new TrailParticleOption(CraftLocation.toVec3D(data.getTarget()), data.getColor().asRGB(), data.getDuration()); } }; @@ -208,7 +208,7 @@ public ParticleOptions createParticleParam(Particle.TargetColor data) { add("entity_effect", colorFunction); add("dust_pillar", blockDataFunction); add("block_crumble", blockDataFunction); - add("trail", targetColorFunction); + add("trail", trailFunction); } private static void add(String name, BiFunction, CraftParticle> function) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java index 2b5e8d01..92a0c204 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java @@ -271,6 +271,12 @@ public boolean generateTree(WorldGenLevel access, ChunkGenerator chunkGenerator, case CHERRY: gen = TreeFeatures.CHERRY; break; + case PALE_OAK: + gen = TreeFeatures.PALE_OAK; + break; + case PALE_OAK_CREAKING: + gen = TreeFeatures.PALE_OAK_CREAKING; + break; case TREE: default: gen = TreeFeatures.OAK; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java index b4ed857f..c5194fa9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java @@ -10,6 +10,8 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; +import org.bukkit.Art; +import org.bukkit.Fluid; import org.bukkit.GameEvent; import org.bukkit.JukeboxSong; import org.bukkit.Keyed; @@ -17,10 +19,13 @@ import org.bukkit.NamespacedKey; import org.bukkit.Particle; import org.bukkit.Registry; +import org.bukkit.Sound; import org.bukkit.attribute.Attribute; import org.bukkit.block.Biome; import org.bukkit.block.BlockType; import org.bukkit.block.banner.PatternType; +import org.bukkit.craftbukkit.attribute.CraftAttribute; +import org.bukkit.craftbukkit.block.CraftBiome; import org.bukkit.craftbukkit.block.CraftBlockType; import org.bukkit.craftbukkit.block.banner.CraftPatternType; import org.bukkit.craftbukkit.damage.CraftDamageType; @@ -130,9 +135,21 @@ public static Holder bukkitToMinecraftHolder(B bukkit, R * @return the bukkit registry of the provided class */ public static Registry createRegistry(Class bukkitClass, RegistryAccess registryHolder) { + if (bukkitClass == Art.class) { + return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), CraftArt::new, FieldRename.NONE); + } + if (bukkitClass == Attribute.class) { + return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), CraftAttribute::new, FieldRename.ATTRIBUTE_RENAME); + } + if (bukkitClass == Biome.class) { + return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), CraftBiome::new, FieldRename.BIOME_RENAME); + } if (bukkitClass == Enchantment.class) { return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new, FieldRename.ENCHANTMENT_RENAME); } + if (bukkitClass == Fluid.class) { + return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), CraftFluid::new, FieldRename.NONE); + } if (bukkitClass == GameEvent.class) { return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), CraftGameEvent::new, FieldRename.NONE); } @@ -145,6 +162,9 @@ public static Registry createRegistry(Class bukk if (bukkitClass == PotionEffectType.class) { return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new, FieldRename.NONE); } + if (bukkitClass == Sound.class) { + return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), CraftSound::new, FieldRename.NONE); + } if (bukkitClass == Structure.class) { return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), CraftStructure::new, FieldRename.NONE); } @@ -202,10 +222,6 @@ public static B get(Registry bukkit, NamespacedKey namespac if (bukkit instanceof Registry.SimpleRegistry simple) { Class bClass = simple.getType(); - if (bClass == Biome.class) { - return bukkit.get(FieldRename.BIOME_RENAME.apply(namespacedKey, apiVersion)); - } - if (bClass == EntityType.class) { return bukkit.get(FieldRename.ENTITY_TYPE_RENAME.apply(namespacedKey, apiVersion)); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index c48b1d5f..e224e3c2 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -2321,6 +2321,16 @@ public int getIdleTimeout() { return this.console.getPlayerIdleTimeout(); } + @Override + public int getPauseWhenEmptyTime() { + return this.getProperties().pauseWhenEmptySeconds; + } + + @Override + public void setPauseWhenEmptyTime(int seconds) { + this.getProperties().pauseWhenEmptySeconds = seconds; + } + @Override public ChunkGenerator.ChunkData createChunkData(World world) { Preconditions.checkArgument(world != null, "World cannot be null"); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java index 260a738d..60761c3c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java @@ -1,31 +1,26 @@ package org.bukkit.craftbukkit; import com.google.common.base.Preconditions; +import java.util.Locale; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.sounds.SoundEvent; +import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.Sound; -import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Handleable; +import org.jetbrains.annotations.NotNull; -public class CraftSound { +public class CraftSound implements Sound, Handleable { - public static Sound minecraftToBukkit(SoundEvent minecraft) { - Preconditions.checkArgument(minecraft != null); - - net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.SOUND_EVENT); - Sound bukkit = Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location())); - - Preconditions.checkArgument(bukkit != null); + private static int count = 0; - return bukkit; + public static Sound minecraftToBukkit(SoundEvent minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.SOUND_EVENT, Registry.SOUNDS); } public static SoundEvent bukkitToMinecraft(Sound bukkit) { - Preconditions.checkArgument(bukkit != null); - - return CraftRegistry.getMinecraftRegistry(Registries.SOUND_EVENT) - .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow(); + return CraftRegistry.bukkitToMinecraft(bukkit); } public static Holder bukkitToMinecraftHolder(Sound bukkit) { @@ -40,4 +35,75 @@ public static Holder bukkitToMinecraftHolder(Sound bukkit) { throw new IllegalArgumentException("No Reference holder found for " + bukkit + ", this can happen if a plugin creates its own sound effect with out properly registering it."); } + + private final NamespacedKey key; + private final SoundEvent soundEffect; + private final String name; + private final int ordinal; + + public CraftSound(NamespacedKey key, SoundEvent soundEffect) { + this.key = key; + this.soundEffect = soundEffect; + // For backwards compatibility, minecraft values will stile return the uppercase name without the namespace, + // in case plugins use for example the name as key in a config file to receive sound specific values. + // Custom sounds will return the key with namespace. For a plugin this should look than like a new sound + // (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly). + if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) { + this.name = key.getKey().toUpperCase(Locale.ROOT).replace('.', '_'); + } else { + this.name = key.toString(); + } + this.ordinal = count++; + } + + @Override + public SoundEvent getHandle() { + return soundEffect; + } + + @NotNull + @Override + public NamespacedKey getKey() { + return key; + } + + @Override + public int compareTo(@NotNull Sound sound) { + return ordinal - sound.ordinal(); + } + + @NotNull + @Override + public String name() { + return name; + } + + @Override + public int ordinal() { + return ordinal; + } + + @Override + public String toString() { + // For backwards compatibility + return name(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof CraftSound otherSound)) { + return false; + } + + return getKey().equals(otherSound.getKey()); + } + + @Override + public int hashCode() { + return getKey().hashCode(); + } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 799444e4..e5032d9a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -47,6 +47,7 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; import net.minecraft.util.SortedArraySet; import net.minecraft.util.Unit; import net.minecraft.world.entity.EntitySpawnReason; @@ -567,9 +568,9 @@ public org.bukkit.entity.Item dropItemNaturally(Location loc, ItemStack item, Co Preconditions.checkArgument(loc != null, "Location cannot be null"); Preconditions.checkArgument(item != null, "ItemStack cannot be null"); - double xs = (this.world.random.nextFloat() * 0.5F) + 0.25D; - double ys = (this.world.random.nextFloat() * 0.5F) + 0.25D; - double zs = (this.world.random.nextFloat() * 0.5F) + 0.25D; + double xs = Mth.nextDouble(world.random, -0.25D, 0.25D); + double ys = Mth.nextDouble(world.random, -0.25D, 0.25D) - ((double) net.minecraft.world.entity.EntityType.ITEM.getHeight() / 2.0D); + double zs = Mth.nextDouble(world.random, -0.25D, 0.25D); loc = loc.clone().add(xs, ys, zs); return this.dropItem(loc, item, function); } @@ -1296,7 +1297,7 @@ public int getMinHeight() { @Override public int getMaxHeight() { - return this.world.getMaxY(); + return this.world.getMaxY() + 1; } @Override @@ -1905,14 +1906,14 @@ public void spawnParticle(Particle particle, Location location, int count, d @Override public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { - this.getHandle().sendParticles( + this.getHandle().sendParticlesSource( null, // Sender CraftParticle.createParticleParam(particle, data), // Particle + false, force, x, y, z, // Position count, // Count offsetX, offsetY, offsetZ, // Random offset - extra, // Speed? - force + extra // Speed? ); } diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java index 52baf818..d2130b3f 100644 --- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java +++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java @@ -5,6 +5,7 @@ import net.minecraft.advancements.AdvancementHolder; import org.bukkit.NamespacedKey; import org.bukkit.advancement.AdvancementDisplay; +import org.bukkit.advancement.AdvancementRequirements; import org.bukkit.craftbukkit.util.CraftNamespacedKey; public class CraftAdvancement implements org.bukkit.advancement.Advancement { @@ -29,6 +30,11 @@ public Collection getCriteria() { return Collections.unmodifiableCollection(this.handle.value().criteria().keySet()); } + @Override + public AdvancementRequirements getRequirements() { + return new CraftAdvancementRequirements(handle.value().requirements()); + } + @Override public AdvancementDisplay getDisplay() { if (this.handle.value().display().isEmpty()) { diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirement.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirement.java new file mode 100644 index 00000000..fd567c06 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirement.java @@ -0,0 +1,26 @@ +package org.bukkit.craftbukkit.advancement; + +import java.util.Collections; +import java.util.List; +import org.bukkit.advancement.AdvancementRequirement; +import org.jetbrains.annotations.NotNull; + +public class CraftAdvancementRequirement implements AdvancementRequirement { + + private final List requirements; + + public CraftAdvancementRequirement(List list) { + this.requirements = list; + } + + @NotNull + @Override + public List getRequiredCriteria() { + return Collections.unmodifiableList(requirements); + } + + @Override + public boolean isStrict() { + return requirements.size() == 1; + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirements.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirements.java new file mode 100644 index 00000000..6993911b --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementRequirements.java @@ -0,0 +1,21 @@ +package org.bukkit.craftbukkit.advancement; + +import java.util.List; +import net.minecraft.advancements.AdvancementRequirements; +import org.bukkit.advancement.AdvancementRequirement; +import org.jetbrains.annotations.NotNull; + +public class CraftAdvancementRequirements implements org.bukkit.advancement.AdvancementRequirements { + + private final AdvancementRequirements requirements; + + public CraftAdvancementRequirements(AdvancementRequirements requirements) { + this.requirements = requirements; + } + + @NotNull + @Override + public List getRequirements() { + return requirements.requirements().stream().map((requirement) -> (AdvancementRequirement) new CraftAdvancementRequirement(requirement)).toList(); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java index cc97638e..ed7543a8 100644 --- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java +++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java @@ -11,18 +11,15 @@ import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.util.ApiVersion; import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Handleable; +import org.jetbrains.annotations.NotNull; -public class CraftAttribute { +public class CraftAttribute implements Attribute, Handleable { - public static Attribute minecraftToBukkit(net.minecraft.world.entity.ai.attributes.Attribute minecraft) { - Preconditions.checkArgument(minecraft != null); - - net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE); - Attribute bukkit = Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location())); - - Preconditions.checkArgument(bukkit != null); + private static int count = 0; - return bukkit; + public static Attribute minecraftToBukkit(net.minecraft.world.entity.ai.attributes.Attribute minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.ATTRIBUTE, Registry.ATTRIBUTE); } public static Attribute minecraftHolderToBukkit(Holder minecraft) { @@ -43,10 +40,7 @@ public static Attribute stringToBukkit(String string) { } public static net.minecraft.world.entity.ai.attributes.Attribute bukkitToMinecraft(Attribute bukkit) { - Preconditions.checkArgument(bukkit != null); - - return CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE) - .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow(); + return CraftRegistry.bukkitToMinecraft(bukkit); } public static Holder bukkitToMinecraftHolder(Attribute bukkit) { @@ -67,4 +61,81 @@ public static String bukkitToString(Attribute bukkit) { return bukkit.getKey().toString(); } + + private final NamespacedKey key; + private final net.minecraft.world.entity.ai.attributes.Attribute attributeBase; + private final String name; + private final int ordinal; + + public CraftAttribute(NamespacedKey key, net.minecraft.world.entity.ai.attributes.Attribute attributeBase) { + this.key = key; + this.attributeBase = attributeBase; + // For backwards compatibility, minecraft values will stile return the uppercase name without the namespace, + // in case plugins use for example the name as key in a config file to receive attribute specific values. + // Custom attributes will return the key with namespace. For a plugin this should look than like a new attribute + // (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly). + if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) { + this.name = key.getKey().toUpperCase(Locale.ROOT); + } else { + this.name = key.toString(); + } + this.ordinal = count++; + } + + @Override + public net.minecraft.world.entity.ai.attributes.Attribute getHandle() { + return attributeBase; + } + + @NotNull + @Override + public NamespacedKey getKey() { + return key; + } + + @NotNull + @Override + public String getTranslationKey() { + return attributeBase.getDescriptionId(); + } + + @Override + public int compareTo(@NotNull Attribute attribute) { + return ordinal - attribute.ordinal(); + } + + @NotNull + @Override + public String name() { + return name; + } + + @Override + public int ordinal() { + return ordinal; + } + + @Override + public String toString() { + // For backwards compatibility + return name(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof CraftAttribute otherAttribute)) { + return false; + } + + return getKey().equals(otherAttribute.getKey()); + } + + @Override + public int hashCode() { + return getKey().hashCode(); + } } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java index 95b95680..f40256e8 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBiome.java @@ -1,26 +1,21 @@ package org.bukkit.craftbukkit.block; -import com.google.common.base.Preconditions; +import java.util.Locale; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; +import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.block.Biome; import org.bukkit.craftbukkit.CraftRegistry; -import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Handleable; +import org.jetbrains.annotations.NotNull; -public class CraftBiome { +public class CraftBiome implements Biome, Handleable { - public static Biome minecraftToBukkit(net.minecraft.world.level.biome.Biome minecraft) { - Preconditions.checkArgument(minecraft != null); - - net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.BIOME); - Biome bukkit = Registry.BIOME.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location())); - - if (bukkit == null) { - return Biome.CUSTOM; - } + private static int count = 0; - return bukkit; + public static Biome minecraftToBukkit(net.minecraft.world.level.biome.Biome minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.BIOME, Registry.BIOME); } public static Biome minecraftHolderToBukkit(Holder minecraft) { @@ -28,16 +23,15 @@ public static Biome minecraftHolderToBukkit(Holder bukkitToMinecraftHolder(Biome bukkit) { - if (bukkit == null || bukkit == Biome.CUSTOM) { + if (bukkit == Biome.CUSTOM) { return null; } @@ -50,4 +44,75 @@ public static Holder bukkitToMinecraftHol throw new IllegalArgumentException("No Reference holder found for " + bukkit + ", this can happen if a plugin creates its own biome base with out properly registering it."); } + + private final NamespacedKey key; + private final net.minecraft.world.level.biome.Biome biomeBase; + private final String name; + private final int ordinal; + + public CraftBiome(NamespacedKey key, net.minecraft.world.level.biome.Biome biomeBase) { + this.key = key; + this.biomeBase = biomeBase; + // For backwards compatibility, minecraft values will stile return the uppercase name without the namespace, + // in case plugins use for example the name as key in a config file to receive biome specific values. + // Custom biomes will return the key with namespace. For a plugin this should look than like a new biome + // (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly). + if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) { + this.name = key.getKey().toUpperCase(Locale.ROOT); + } else { + this.name = key.toString(); + } + this.ordinal = count++; + } + + @Override + public net.minecraft.world.level.biome.Biome getHandle() { + return biomeBase; + } + + @NotNull + @Override + public NamespacedKey getKey() { + return key; + } + + @Override + public int compareTo(@NotNull Biome biome) { + return ordinal - biome.ordinal(); + } + + @NotNull + @Override + public String name() { + return name; + } + + @Override + public int ordinal() { + return ordinal; + } + + @Override + public String toString() { + // For backwards compatibility + return name(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof CraftBiome otherBiome)) { + return false; + } + + return getKey().equals(otherBiome.getKey()); + } + + @Override + public int hashCode() { + return getKey().hashCode(); + } } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java index 7ed43bc2..57529166 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java @@ -40,24 +40,24 @@ public FurnaceInventory getInventory() { @Override public short getBurnTime() { - return (short) this.getSnapshot().litTime; + return (short) this.getSnapshot().litTimeRemaining; } @Override public void setBurnTime(short burnTime) { - this.getSnapshot().litTime = burnTime; + this.getSnapshot().litTimeRemaining = burnTime; // SPIGOT-844: Allow lighting and relighting using this API this.data = this.data.setValue(AbstractFurnaceBlock.LIT, burnTime > 0); } @Override public short getCookTime() { - return (short) this.getSnapshot().cookingProgress; + return (short) this.getSnapshot().cookingTimer; } @Override public void setCookTime(short cookTime) { - this.getSnapshot().cookingProgress = cookTime; + this.getSnapshot().cookingTimer = cookTime; } @Override 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 da39a252..214710be 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java @@ -251,10 +251,14 @@ public String toString(Map, Comparable> states) { return stateString.toString(); } - public Map toStates() { + public Map toStates(boolean hideUnspecified) { + return (hideUnspecified && parsedStates != null) ? toStates(parsedStates) : toStates(state.getValues()); + } + + private static Map toStates(Map, Comparable> states) { Map compound = new HashMap<>(); - for (Map.Entry, Comparable> entry : this.state.getValues().entrySet()) { + for (Map.Entry, Comparable> entry : states.entrySet()) { Property iblockstate = (Property) entry.getKey(); compound.put(iblockstate.getName(), iblockstate.getName(entry.getValue())); @@ -493,7 +497,6 @@ protected static int getMax(IntegerProperty state) { register(net.minecraft.world.level.block.CaveVinesBlock.class, org.bukkit.craftbukkit.block.impl.CraftCaveVines::new); register(net.minecraft.world.level.block.CaveVinesPlantBlock.class, org.bukkit.craftbukkit.block.impl.CraftCaveVinesPlant::new); register(net.minecraft.world.level.block.CeilingHangingSignBlock.class, org.bukkit.craftbukkit.block.impl.CraftCeilingHangingSign::new); - register(net.minecraft.world.level.block.CherryLeavesBlock.class, org.bukkit.craftbukkit.block.impl.CraftCherryLeaves::new); register(net.minecraft.world.level.block.ChiseledBookShelfBlock.class, org.bukkit.craftbukkit.block.impl.CraftChiseledBookShelf::new); register(net.minecraft.world.level.block.CopperBulbBlock.class, org.bukkit.craftbukkit.block.impl.CraftCopperBulb::new); register(net.minecraft.world.level.block.CrafterBlock.class, org.bukkit.craftbukkit.block.impl.CraftCrafter::new); @@ -511,6 +514,8 @@ protected static int getMax(IntegerProperty state) { register(net.minecraft.world.level.block.MangrovePropaguleBlock.class, org.bukkit.craftbukkit.block.impl.CraftMangrovePropagule::new); register(net.minecraft.world.level.block.MangroveRootsBlock.class, org.bukkit.craftbukkit.block.impl.CraftMangroveRoots::new); register(net.minecraft.world.level.block.MossyCarpetBlock.class, org.bukkit.craftbukkit.block.impl.CraftMossyCarpet::new); + register(net.minecraft.world.level.block.MultifaceBlock.class, org.bukkit.craftbukkit.block.impl.CraftMultiface::new); + register(net.minecraft.world.level.block.ParticleLeavesBlock.class, org.bukkit.craftbukkit.block.impl.CraftParticleLeaves::new); register(net.minecraft.world.level.block.PiglinWallSkullBlock.class, org.bukkit.craftbukkit.block.impl.CraftPiglinWallSkull::new); register(net.minecraft.world.level.block.PinkPetalsBlock.class, org.bukkit.craftbukkit.block.impl.CraftPinkPetals::new); register(net.minecraft.world.level.block.PitcherCropBlock.class, org.bukkit.craftbukkit.block.impl.CraftPitcherCrop::new); diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftCreakingHeart.java b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftCreakingHeart.java index d2cf3dc4..cfa40c05 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftCreakingHeart.java +++ b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftCreakingHeart.java @@ -5,15 +5,26 @@ public abstract class CraftCreakingHeart extends CraftBlockData implements CreakingHeart { - private static final net.minecraft.world.level.block.state.properties.EnumProperty CREAKING = getEnum("creaking"); + private static final net.minecraft.world.level.block.state.properties.BooleanProperty ACTIVE = getBoolean("active"); + private static final net.minecraft.world.level.block.state.properties.BooleanProperty NATURAL = getBoolean("natural"); @Override - public org.bukkit.block.data.type.CreakingHeart.Creaking getCreaking() { - return this.get(CraftCreakingHeart.CREAKING, org.bukkit.block.data.type.CreakingHeart.Creaking.class); + public boolean isActive() { + return get(ACTIVE); } @Override - public void setCreaking(org.bukkit.block.data.type.CreakingHeart.Creaking creaking) { - this.set(CraftCreakingHeart.CREAKING, creaking); + public void setActive(boolean active) { + set(ACTIVE, active); + } + + @Override + public boolean isNatural() { + return get(NATURAL); + } + + @Override + public void setNatural(boolean natural) { + set(NATURAL, natural); } } diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCreakingHeart.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCreakingHeart.java index 47526758..5d4675ef 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCreakingHeart.java +++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCreakingHeart.java @@ -15,16 +15,26 @@ public CraftCreakingHeart(net.minecraft.world.level.block.state.BlockState state // org.bukkit.craftbukkit.block.data.type.CraftCreakingHeart - private static final net.minecraft.world.level.block.state.properties.EnumProperty CREAKING = getEnum(net.minecraft.world.level.block.CreakingHeartBlock.class, "creaking"); + private static final net.minecraft.world.level.block.state.properties.BooleanProperty ACTIVE = getBoolean(net.minecraft.world.level.block.CreakingHeartBlock.class, "active"); + private static final net.minecraft.world.level.block.state.properties.BooleanProperty NATURAL = getBoolean(net.minecraft.world.level.block.CreakingHeartBlock.class, "natural"); + @Override + public boolean isActive() { + return get(ACTIVE); + } + + @Override + public void setActive(boolean active) { + set(ACTIVE, active); + } @Override - public org.bukkit.block.data.type.CreakingHeart.Creaking getCreaking() { - return this.get(CraftCreakingHeart.CREAKING, org.bukkit.block.data.type.CreakingHeart.Creaking.class); + public boolean isNatural() { + return get(NATURAL); } @Override - public void setCreaking(org.bukkit.block.data.type.CreakingHeart.Creaking creaking) { - this.set(CraftCreakingHeart.CREAKING, creaking); + public void setNatural(boolean natural) { + set(NATURAL, natural); } // org.bukkit.craftbukkit.block.data.CraftOrientable diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMultiface.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMultiface.java new file mode 100644 index 00000000..40524035 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftMultiface.java @@ -0,0 +1,79 @@ +/** + * Automatically generated file, changes will be lost. + */ +package org.bukkit.craftbukkit.block.impl; + +public final class CraftMultiface extends org.bukkit.craftbukkit.block.data.CraftBlockData implements org.bukkit.block.data.type.ResinClump, org.bukkit.block.data.MultipleFacing, org.bukkit.block.data.Waterlogged { + + public CraftMultiface() { + super(); + } + + public CraftMultiface(net.minecraft.world.level.block.state.BlockState state) { + super(state); + } + + // org.bukkit.craftbukkit.block.data.CraftMultipleFacing + + private static final net.minecraft.world.level.block.state.properties.BooleanProperty[] FACES = new net.minecraft.world.level.block.state.properties.BooleanProperty[]{ + getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "north", true), getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "east", true), getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "south", true), getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "west", true), getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "up", true), getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "down", true) + }; + + @Override + public boolean hasFace(org.bukkit.block.BlockFace face) { + net.minecraft.world.level.block.state.properties.BooleanProperty state = FACES[face.ordinal()]; + if (state == null) { + throw new IllegalArgumentException("Non-allowed face " + face + ". Check MultipleFacing.getAllowedFaces."); + } + return get(state); + } + + @Override + public void setFace(org.bukkit.block.BlockFace face, boolean has) { + net.minecraft.world.level.block.state.properties.BooleanProperty state = FACES[face.ordinal()]; + if (state == null) { + throw new IllegalArgumentException("Non-allowed face " + face + ". Check MultipleFacing.getAllowedFaces."); + } + set(state, has); + } + + @Override + public java.util.Set getFaces() { + com.google.common.collect.ImmutableSet.Builder faces = com.google.common.collect.ImmutableSet.builder(); + + for (int i = 0; i < FACES.length; i++) { + if (FACES[i] != null && get(FACES[i])) { + faces.add(org.bukkit.block.BlockFace.values()[i]); + } + } + + return faces.build(); + } + + @Override + public java.util.Set getAllowedFaces() { + com.google.common.collect.ImmutableSet.Builder faces = com.google.common.collect.ImmutableSet.builder(); + + for (int i = 0; i < FACES.length; i++) { + if (FACES[i] != null) { + faces.add(org.bukkit.block.BlockFace.values()[i]); + } + } + + return faces.build(); + } + + // org.bukkit.craftbukkit.block.data.CraftWaterlogged + + private static final net.minecraft.world.level.block.state.properties.BooleanProperty WATERLOGGED = getBoolean(net.minecraft.world.level.block.MultifaceBlock.class, "waterlogged"); + + @Override + public boolean isWaterlogged() { + return get(WATERLOGGED); + } + + @Override + public void setWaterlogged(boolean waterlogged) { + set(WATERLOGGED, waterlogged); + } +} \ No newline at end of file diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftParticleLeaves.java similarity index 55% rename from src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java rename to src/main/java/org/bukkit/craftbukkit/block/impl/CraftParticleLeaves.java index af29ff86..db4849a3 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftCherryLeaves.java +++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftParticleLeaves.java @@ -3,52 +3,52 @@ */ package org.bukkit.craftbukkit.block.impl; -public final class CraftCherryLeaves extends org.bukkit.craftbukkit.block.data.CraftBlockData implements org.bukkit.block.data.type.Leaves, org.bukkit.block.data.Waterlogged { +public final class CraftParticleLeaves extends org.bukkit.craftbukkit.block.data.CraftBlockData implements org.bukkit.block.data.type.Leaves, org.bukkit.block.data.Waterlogged { - public CraftCherryLeaves() { + public CraftParticleLeaves() { super(); } - public CraftCherryLeaves(net.minecraft.world.level.block.state.BlockState state) { + public CraftParticleLeaves(net.minecraft.world.level.block.state.BlockState state) { super(state); } // org.bukkit.craftbukkit.block.data.type.CraftLeaves - private static final net.minecraft.world.level.block.state.properties.IntegerProperty DISTANCE = getInteger(net.minecraft.world.level.block.CherryLeavesBlock.class, "distance"); - private static final net.minecraft.world.level.block.state.properties.BooleanProperty PERSISTENT = getBoolean(net.minecraft.world.level.block.CherryLeavesBlock.class, "persistent"); + private static final net.minecraft.world.level.block.state.properties.IntegerProperty DISTANCE = getInteger(net.minecraft.world.level.block.ParticleLeavesBlock.class, "distance"); + private static final net.minecraft.world.level.block.state.properties.BooleanProperty PERSISTENT = getBoolean(net.minecraft.world.level.block.ParticleLeavesBlock.class, "persistent"); @Override public boolean isPersistent() { - return this.get(CraftCherryLeaves.PERSISTENT); + return this.get(CraftParticleLeaves.PERSISTENT); } @Override public void setPersistent(boolean persistent) { - this.set(CraftCherryLeaves.PERSISTENT, persistent); + this.set(CraftParticleLeaves.PERSISTENT, persistent); } @Override public int getDistance() { - return this.get(CraftCherryLeaves.DISTANCE); + return this.get(CraftParticleLeaves.DISTANCE); } @Override public void setDistance(int distance) { - this.set(CraftCherryLeaves.DISTANCE, distance); + this.set(CraftParticleLeaves.DISTANCE, distance); } // org.bukkit.craftbukkit.block.data.CraftWaterlogged - private static final net.minecraft.world.level.block.state.properties.BooleanProperty WATERLOGGED = getBoolean(net.minecraft.world.level.block.CherryLeavesBlock.class, "waterlogged"); + private static final net.minecraft.world.level.block.state.properties.BooleanProperty WATERLOGGED = getBoolean(net.minecraft.world.level.block.ParticleLeavesBlock.class, "waterlogged"); @Override public boolean isWaterlogged() { - return this.get(CraftCherryLeaves.WATERLOGGED); + return this.get(CraftParticleLeaves.WATERLOGGED); } @Override public void setWaterlogged(boolean waterlogged) { - this.set(CraftCherryLeaves.WATERLOGGED, waterlogged); + this.set(CraftParticleLeaves.WATERLOGGED, waterlogged); } } diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftVault.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftVault.java index 4c62caba..7d536683 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftVault.java +++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftVault.java @@ -19,13 +19,23 @@ public CraftVault(net.minecraft.world.level.block.state.BlockState state) { private static final net.minecraft.world.level.block.state.properties.BooleanProperty OMINOUS = getBoolean(net.minecraft.world.level.block.VaultBlock.class, "ominous"); @Override - public org.bukkit.block.data.type.Vault.State getTrialSpawnerState() { + public org.bukkit.block.data.type.Vault.State getVaultState() { return this.get(CraftVault.VAULT_STATE, org.bukkit.block.data.type.Vault.State.class); } + @Override + public org.bukkit.block.data.type.Vault.State getTrialSpawnerState() { + return getVaultState(); + } + + @Override + public void setVaultState(org.bukkit.block.data.type.Vault.State state) { + set(VAULT_STATE, state); + } + @Override public void setTrialSpawnerState(org.bukkit.block.data.type.Vault.State state) { - this.set(CraftVault.VAULT_STATE, state); + setVaultState(state); } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java index 87c93ee9..a4524352 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -10,6 +10,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.vehicle.MinecartCommandBlock; import org.bukkit.Location; import org.bukkit.command.BlockCommandSender; @@ -21,6 +22,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftMinecartCommand; +import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.minecart.CommandMinecart; public final class VanillaCommandWrapper extends BukkitCommand { @@ -67,6 +69,10 @@ public static CommandSourceStack getListener(CommandSender sender) { return ((MinecartCommandBlock) ((CraftMinecartCommand) sender).getHandle()).getCommandBlock().createCommandSourceStack(); } + if (sender instanceof CraftPlayer player) { + return player.getHandle().createCommandSourceStack(); + } + return entity.getHandle().createCommandSourceStackForNameResolution((ServerLevel) entity.getHandle().level()); } if (sender instanceof BlockCommandSender) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java index 3f3d0873..7648e2c7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java @@ -1,7 +1,9 @@ package org.bukkit.craftbukkit.entity; +import net.minecraft.world.entity.ai.memory.MemoryModuleType; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Breeze; +import org.bukkit.entity.LivingEntity; public class CraftBreeze extends CraftMonster implements Breeze { @@ -14,6 +16,13 @@ public net.minecraft.world.entity.monster.breeze.Breeze getHandle() { return (net.minecraft.world.entity.monster.breeze.Breeze) this.entity; } + @Override + public void setTarget(LivingEntity target) { + super.setTarget(target); + net.minecraft.world.entity.LivingEntity entityLivingTarget = (target instanceof CraftLivingEntity craftLivingEntity) ? craftLivingEntity.getHandle() : null; + this.getHandle().getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, entityLivingTarget); // SPIGOT-7957: We need override memory for set target and trigger attack behaviours + } + @Override public String toString() { return "CraftBreeze"; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java deleted file mode 100644 index 8be3dc39..00000000 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.bukkit.craftbukkit.entity; - -import net.minecraft.world.entity.monster.creaking.CreakingTransient; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.entity.Creaking; - -public class CraftCreakingTransient extends CraftCreaking implements Creaking { - - public CraftCreakingTransient(CraftServer server, CreakingTransient entity) { - super(server, entity); - } - - @Override - public CreakingTransient getHandle() { - return (CreakingTransient) this.entity; - } - - @Override - public String toString() { - return "CraftCreakingTransient"; - } -} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java index 9dac0116..5fe46a7d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java @@ -341,7 +341,6 @@ Level minecraftWorld() { register(new EntityTypeData<>(EntityType.BREEZE, Breeze.class, CraftBreeze::new, createLiving(net.minecraft.world.entity.EntityType.BREEZE))); register(new EntityTypeData<>(EntityType.ARMADILLO, Armadillo.class, CraftArmadillo::new, createLiving(net.minecraft.world.entity.EntityType.ARMADILLO))); register(new EntityTypeData<>(EntityType.CREAKING, Creaking.class, CraftCreaking::new, createLiving(net.minecraft.world.entity.EntityType.CREAKING))); - register(new EntityTypeData<>(EntityType.CREAKING_TRANSIENT, CreakingTransient.class, CraftCreakingTransient::new, createLiving(net.minecraft.world.entity.EntityType.CREAKING_TRANSIENT))); Function dragonFunction = createLiving(net.minecraft.world.entity.EntityType.ENDER_DRAGON); register(new EntityTypeData<>(EntityType.ENDER_DRAGON, EnderDragon.class, CraftEnderDragon::new, spawnData -> { @@ -481,7 +480,13 @@ private static Function crea } private static Function createMinecart(net.minecraft.world.entity.EntityType entityTypes) { - return spawnData -> AbstractMinecart.createMinecart(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), entityTypes, EntitySpawnReason.TRIGGERED, ItemStack.EMPTY, null); + return spawnData -> { + if (spawnData.normalWorld()) { + return AbstractMinecart.createMinecart(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), entityTypes, EntitySpawnReason.TRIGGERED, ItemStack.EMPTY, null); + } else { + return combine(fromEntityType(entityTypes), (spawnData2, entity) -> entity.setInitialPos(spawnData.x(), spawnData.y(), spawnData.z())).apply(spawnData); + } + }; } private static Function createAndMove(net.minecraft.world.entity.EntityType entityTypes) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index 8146e3df..e92bd027 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -483,7 +483,7 @@ public T launchProjectile(Class projectile, launch = new ThrownExperienceBottle(world, this.getHandle(), new net.minecraft.world.item.ItemStack(Items.EXPERIENCE_BOTTLE)); ((ThrowableProjectile) launch).shootFromRotation(this.getHandle(), this.getHandle().getXRot(), this.getHandle().getYRot(), -20.0F, 0.7F, 1.0F); // ItemExpBottle } else if (FishHook.class.isAssignableFrom(projectile) && this.getHandle() instanceof net.minecraft.world.entity.player.Player) { - launch = new FishingHook((net.minecraft.world.entity.player.Player) this.getHandle(), world, 0, 0, new net.minecraft.world.item.ItemStack(Items.FISHING_ROD)); + launch = new FishingHook((net.minecraft.world.entity.player.Player) this.getHandle(), world, 0, 0); } else if (Fireball.class.isAssignableFrom(projectile)) { Location location = this.getEyeLocation(); Vector direction = location.getDirection().multiply(10); @@ -610,7 +610,7 @@ private boolean unleash() { if (!this.isLeashed()) { return false; } - ((Mob) this.getHandle()).dropLeash(true, false); + ((Mob) this.getHandle()).removeLeash(); return true; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java index ee010d53..a9669b23 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java @@ -1,5 +1,6 @@ package org.bukkit.craftbukkit.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; @@ -28,7 +29,7 @@ public double getDamage() { @Override public double getMaxSpeed() { - return this.getHandle().maxSpeed; + return getHandle().getBehavior().getMaxSpeed((ServerLevel) getHandle().level()); } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java index 1fe06d39..8835ea9c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java @@ -30,6 +30,16 @@ public void setYield(float yield) { this.getHandle().explosionPowerBase = yield; } + @Override + public float getExplosionSpeedFactor() { + return getHandle().explosionSpeedFactor; + } + + @Override + public void setExplosionSpeedFactor(float factor) { + getHandle().explosionSpeedFactor = factor; + } + @Override public void setFuseTicks(int ticks) { this.getHandle().fuse = ticks; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 8ad04c03..bead963d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -2008,21 +2008,6 @@ public void setAllowFlight(boolean value) { this.getHandle().onUpdateAbilities(); } - @Override - public int getNoDamageTicks() { - if (this.getHandle().spawnInvulnerableTime > 0) { - return Math.max(this.getHandle().spawnInvulnerableTime, this.getHandle().invulnerableTime); - } else { - return this.getHandle().invulnerableTime; - } - } - - @Override - public void setNoDamageTicks(int ticks) { - super.setNoDamageTicks(ticks); - this.getHandle().spawnInvulnerableTime = ticks; // SPIGOT-5921: Update both for players, like the getter above - } - @Override public void setFlySpeed(float value) { this.validateSpeed(value); @@ -2281,7 +2266,7 @@ public void spawnParticle(Particle particle, Location location, int count, d @Override public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { - ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.createParticleParam(particle, data), force, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); + ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.createParticleParam(particle, data), false, force, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); this.getHandle().connection.send(packetplayoutworldparticles); } diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java index 625562a3..df09d1b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java @@ -8,11 +8,13 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.util.Mth; import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.NoiseColumn; import net.minecraft.world.level.StructureManager; @@ -32,6 +34,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.world.level.levelgen.blending.Blender; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; +import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.craftbukkit.CraftHeightMap; import org.bukkit.craftbukkit.block.CraftBiome; @@ -114,14 +117,14 @@ public int getSeaLevel() { } @Override - public void createStructures(RegistryAccess registryManager, ChunkGeneratorStructureState placementCalculator, StructureManager structureAccessor, ChunkAccess chunk, StructureTemplateManager structureTemplateManager) { + public void createStructures(RegistryAccess registryManager, ChunkGeneratorStructureState placementCalculator, StructureManager structureAccessor, ChunkAccess chunk, StructureTemplateManager structureTemplateManager, ResourceKey resourcekey) { WorldgenRandom random = CustomChunkGenerator.getSeededRandom(); int x = chunk.getPos().x; int z = chunk.getPos().z; random.setSeed(Mth.getSeed(x, "should-structures".hashCode(), z) ^ this.world.getSeed()); if (this.generator.shouldGenerateStructures(this.world.getWorld(), new RandomSourceWrapper.RandomWrapper(random), x, z)) { - super.createStructures(registryManager, placementCalculator, structureAccessor, chunk, structureTemplateManager); + super.createStructures(registryManager, placementCalculator, structureAccessor, chunk, structureTemplateManager, resourcekey); } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java index 88d5590a..6e5b7e84 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -254,19 +254,6 @@ public boolean isEmpty() { return this.inventory.isEmpty(); } - public int firstPartial(Material material) { - Preconditions.checkArgument(material != null, "Material cannot be null"); - material = CraftLegacy.fromLegacy(material); - ItemStack[] inventory = this.getStorageContents(); - for (int i = 0; i < inventory.length; i++) { - ItemStack item = inventory[i]; - if (item != null && item.getType() == material && item.getAmount() < item.getMaxStackSize()) { - return i; - } - } - return -1; - } - private int firstPartial(ItemStack item) { ItemStack[] inventory = this.getStorageContents(); ItemStack filteredItem = CraftItemStack.asCraftCopy(item); @@ -275,7 +262,7 @@ private int firstPartial(ItemStack item) { } for (int i = 0; i < inventory.length; i++) { ItemStack cItem = inventory[i]; - if (cItem != null && cItem.getAmount() < cItem.getMaxStackSize() && cItem.isSimilar(filteredItem)) { + if (cItem != null && cItem.getAmount() < getMaxItemStack(cItem) && cItem.isSimilar(filteredItem)) { return i; } } @@ -311,11 +298,12 @@ public HashMap addItem(ItemStack... items) { break; } else { // More than a single stack! - if (item.getAmount() > this.getMaxItemStack()) { + int maxAmount = getMaxItemStack(item); + if (item.getAmount() > maxAmount) { CraftItemStack stack = CraftItemStack.asCraftCopy(item); - stack.setAmount(this.getMaxItemStack()); + stack.setAmount(maxAmount); this.setItem(firstFree, stack); - item.setAmount(item.getAmount() - this.getMaxItemStack()); + item.setAmount(item.getAmount() - maxAmount); } else { // Just store it this.setItem(firstFree, item); @@ -328,7 +316,7 @@ public HashMap addItem(ItemStack... items) { int amount = item.getAmount(); int partialAmount = partialItem.getAmount(); - int maxAmount = partialItem.getMaxStackSize(); + int maxAmount = getMaxItemStack(partialItem); // Check if it fully fits if (amount + partialAmount <= maxAmount) { @@ -394,8 +382,8 @@ public HashMap removeItem(ItemStack... items) { return leftover; } - private int getMaxItemStack() { - return this.getInventory().getMaxStackSize(); + private int getMaxItemStack(ItemStack itemstack) { + return Math.min(itemstack.getMaxStackSize(), getInventory().getMaxStackSize()); } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java index 6e111222..cc70796e 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -24,6 +24,7 @@ import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntityType; +import org.bukkit.craftbukkit.inventory.components.CraftCustomModelDataComponent; import org.bukkit.craftbukkit.inventory.components.CraftEquippableComponent; import org.bukkit.craftbukkit.inventory.components.CraftFoodComponent; import org.bukkit.craftbukkit.inventory.components.CraftJukeboxComponent; @@ -44,6 +45,7 @@ public final class CraftItemFactory implements ItemFactory { static { instance = new CraftItemFactory(); ConfigurationSerialization.registerClass(SerializableMeta.class); + ConfigurationSerialization.registerClass(CraftCustomModelDataComponent.class); ConfigurationSerialization.registerClass(CraftEquippableComponent.class); ConfigurationSerialization.registerClass(CraftFoodComponent.class); ConfigurationSerialization.registerClass(CraftToolComponent.class); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java index b9025adf..508c3e33 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java @@ -103,5 +103,10 @@ public void overrideOffers(MerchantOffers offers) { public boolean isClientSide() { return false; } + + @Override + public boolean stillValid(Player entityhuman) { + return this.tradingPlayer == entityhuman; + } } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java index bc68a45a..42e8208c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -95,6 +95,7 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific; +import org.bukkit.craftbukkit.inventory.components.CraftCustomModelDataComponent; import org.bukkit.craftbukkit.inventory.components.CraftEquippableComponent; import org.bukkit.craftbukkit.inventory.components.CraftFoodComponent; import org.bukkit.craftbukkit.inventory.components.CraftJukeboxComponent; @@ -118,6 +119,7 @@ import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.Repairable; +import org.bukkit.inventory.meta.components.CustomModelDataComponent; import org.bukkit.inventory.meta.components.EquippableComponent; import org.bukkit.inventory.meta.components.FoodComponent; import org.bukkit.inventory.meta.components.JukeboxPlayableComponent; @@ -278,7 +280,7 @@ DataComponentPatch build() { private Component displayName; private Component itemName; private List lore; // null and empty are two different states internally - private Integer customModelData; + private CraftCustomModelDataComponent customModelData; private Integer enchantableValue; private Map blockData; private Map enchantments; @@ -325,7 +327,9 @@ DataComponentPatch build() { this.lore = new ArrayList(meta.lore); } - this.customModelData = meta.customModelData; + if (meta.hasCustomModelData()) { + this.customModelData = new CraftCustomModelDataComponent(meta.customModelData); + } this.enchantableValue = meta.enchantableValue; this.blockData = meta.blockData; @@ -395,7 +399,7 @@ DataComponentPatch build() { }); CraftMetaItem.getOrEmpty(tag, CraftMetaItem.CUSTOM_MODEL_DATA).ifPresent((i) -> { - this.customModelData = i.value(); + this.customModelData = new CraftCustomModelDataComponent(i); }); CraftMetaItem.getOrEmpty(tag, CraftMetaItem.ENCHANTABLE).ifPresent((i) -> { this.enchantableValue = i.value(); @@ -579,9 +583,11 @@ static Multimap buildModifiers(ItemAttributeModifi CraftMetaItem.safelyAdd(lore, this.lore = new ArrayList(), true); } - Integer customModelData = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, true); - if (customModelData != null) { - this.setCustomModelData(customModelData); + Object customModelData = SerializableMeta.getObject(Object.class, map, CUSTOM_MODEL_DATA.BUKKIT, true); + if (customModelData instanceof CustomModelDataComponent component) { + setCustomModelDataComponent(component); + } else { + setCustomModelData((Integer) customModelData); } Integer enchantmentValue = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.ENCHANTABLE.BUKKIT, true); if (enchantmentValue != null) { @@ -912,7 +918,7 @@ void applyToItem(CraftMetaItem.Applicator itemTag) { } if (this.hasCustomModelData()) { - itemTag.put(CraftMetaItem.CUSTOM_MODEL_DATA, new CustomModelData(this.customModelData)); + itemTag.put(CraftMetaItem.CUSTOM_MODEL_DATA, customModelData.getHandle()); } if (this.hasEnchantable()) { @@ -1278,12 +1284,24 @@ public boolean hasCustomModelData() { @Override public int getCustomModelData() { Preconditions.checkState(this.hasCustomModelData(), "We don't have CustomModelData! Check hasCustomModelData first!"); - return this.customModelData; + List floats = customModelData.getFloats(); + Preconditions.checkState(!floats.isEmpty(), "No numeric custom model data"); + return floats.get(0).intValue(); + } + + @Override + public CustomModelDataComponent getCustomModelDataComponent() { + return (this.hasCustomModelData()) ? new CraftCustomModelDataComponent(this.customModelData) : new CraftCustomModelDataComponent(new CustomModelData(List.of(), List.of(), List.of(), List.of())); } @Override public void setCustomModelData(Integer data) { - this.customModelData = data; + this.customModelData = (data == null) ? null : new CraftCustomModelDataComponent(new CustomModelData(List.of(data.floatValue()), List.of(), List.of(), List.of())); + } + + @Override + public void setCustomModelDataComponent(CustomModelDataComponent customModelData) { + this.customModelData = (customModelData == null) ? null : new CraftCustomModelDataComponent((CraftCustomModelDataComponent) customModelData); } @Override @@ -1315,7 +1333,7 @@ public BlockData getBlockData(Material material) { @Override public void setBlockData(BlockData blockData) { - this.blockData = (blockData == null) ? null : ((CraftBlockData) blockData).toStates(); + this.blockData = (blockData == null) ? null : ((CraftBlockData) blockData).toStates(true); } @Override @@ -1485,7 +1503,7 @@ public boolean hasUseCooldown() { @Override public UseCooldownComponent getUseCooldown() { - return (this.hasUseCooldown()) ? new CraftUseCooldownComponent(this.useCooldown) : new CraftUseCooldownComponent(new UseCooldown(0)); + return (this.hasUseCooldown()) ? new CraftUseCooldownComponent(this.useCooldown) : new CraftUseCooldownComponent(new UseCooldown(1)); } @Override @@ -1535,7 +1553,7 @@ public EquippableComponent getEquippable() { @Override public void setEquippable(EquippableComponent equippable) { - this.equippable = (equippable == null) ? null : new CraftEquippableComponent((CraftEquippableComponent) this.equippable); + this.equippable = (equippable == null) ? null : new CraftEquippableComponent((CraftEquippableComponent) equippable); } @Override @@ -1880,7 +1898,9 @@ public CraftMetaItem clone() { if (this.lore != null) { clone.lore = new ArrayList(this.lore); } - clone.customModelData = this.customModelData; + if (this.hasCustomModelData()) { + clone.customModelData = new CraftCustomModelDataComponent(customModelData); + } clone.enchantableValue = this.enchantableValue; clone.blockData = this.blockData; if (this.enchantments != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java index 6f1da5aa..3676853a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java @@ -32,14 +32,13 @@ default Ingredient toNMS(RecipeChoice bukkit, boolean requireNotEmpty) { } else if (bukkit instanceof RecipeChoice.MaterialChoice) { stack = Ingredient.of(((RecipeChoice.MaterialChoice) bukkit).getChoices().stream().map((mat) -> CraftItemType.bukkitToMinecraft(mat))); } else if (bukkit instanceof RecipeChoice.ExactChoice) { - stack = Ingredient.ofStacks(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> CraftItemStack.asNMSCopy(mat))); + stack = Ingredient.ofStacks(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> CraftItemStack.asNMSCopy(mat)).toList()); } else { throw new IllegalArgumentException("Unknown recipe stack instance " + bukkit); } - List> items = stack.items(); if (requireNotEmpty) { - Preconditions.checkArgument(!items.isEmpty(), "Recipe requires at least one non-air choice"); + Preconditions.checkArgument(!stack.isEmpty(), "Recipe requires at least one non-air choice"); } return stack; @@ -50,9 +49,7 @@ public static RecipeChoice toBukkit(Optional list) { } public static RecipeChoice toBukkit(Ingredient list) { - List> items = list.items(); - - if (items.isEmpty()) { + if (list.isEmpty()) { return null; } @@ -64,10 +61,7 @@ public static RecipeChoice toBukkit(Ingredient list) { return new RecipeChoice.ExactChoice(choices); } else { - List choices = new ArrayList<>(items.size()); - for (Holder i : items) { - choices.add(CraftItemType.minecraftToBukkit(i.value())); - } + List choices = list.items().map((i) -> CraftItemType.minecraftToBukkit(i.value())).toList(); return new RecipeChoice.MaterialChoice(choices); } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java index 0a3b5ebb..386d6b81 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java @@ -40,8 +40,8 @@ public static CraftShapelessRecipe fromBukkitRecipe(ShapelessRecipe recipe) { public void addToCraftingManager() { List ingred = this.getChoiceList(); List data = new ArrayList<>(ingred.size()); - for (int i = 0; i < ingred.size(); i++) { - data.set(i, this.toNMS(ingred.get(i), true)); + for (org.bukkit.inventory.RecipeChoice i : ingred) { + data.add(toNMS(i, true)); } MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftRecipe.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.ShapelessRecipe(this.getGroup(), CraftRecipe.getCategory(this.getCategory()), CraftItemStack.asNMSCopy(this.getResult()), data))); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java b/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java index e00b757d..7c07ce8a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java @@ -4,6 +4,8 @@ import com.google.common.collect.ImmutableMap; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.bukkit.block.Banner; @@ -136,4 +138,39 @@ public static T getObject(Class clazz, Map map, Object field, boole } throw new IllegalArgumentException(field + "(" + object + ") is not a valid " + clazz); } + + public static List getList(Class clazz, Map map, Object field) { + List result = new ArrayList<>(); + + List list = SerializableMeta.getObject(List.class, map, field, true); + if (list == null || list.isEmpty()) { + return result; + } + + for (Object object : list) { + T cast = null; + + if (clazz.isInstance(object)) { + cast = clazz.cast(object); + } + + // SPIGOT-7675 - More lenient conversion of floating point numbers from other number types: + if (clazz == Float.class || clazz == Double.class) { + if (Number.class.isInstance(object)) { + Number number = Number.class.cast(object); + if (clazz == Float.class) { + cast = clazz.cast(number.floatValue()); + } else { + cast = clazz.cast(number.doubleValue()); + } + } + } + + if (cast != null) { + result.add(cast); + } + } + + return result; + } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftCustomModelDataComponent.java b/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftCustomModelDataComponent.java new file mode 100644 index 00000000..023fa455 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftCustomModelDataComponent.java @@ -0,0 +1,119 @@ +package org.bukkit.craftbukkit.inventory.components; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import net.minecraft.world.item.component.CustomModelData; +import org.bukkit.Color; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.craftbukkit.inventory.SerializableMeta; +import org.bukkit.inventory.meta.components.CustomModelDataComponent; + +@SerializableAs("CustomModelData") +public final class CraftCustomModelDataComponent implements CustomModelDataComponent { + + private CustomModelData handle; + + public CraftCustomModelDataComponent(CustomModelData handle) { + this.handle = handle; + } + + public CraftCustomModelDataComponent(CraftCustomModelDataComponent craft) { + this.handle = craft.handle; + } + + public CraftCustomModelDataComponent(Map map) { + handle = new CustomModelData( + SerializableMeta.getList(Float.class, map, "floats"), + SerializableMeta.getList(Boolean.class, map, "flags"), + SerializableMeta.getList(String.class, map, "strings"), + SerializableMeta.getList(Color.class, map, "colors").stream().map(Color::asRGB).toList() + ); + } + + @Override + public Map serialize() { + Map result = new LinkedHashMap<>(); + + result.put("floats", getFloats()); + result.put("flags", getFlags()); + result.put("strings", getStrings()); + result.put("colors", getColors()); + + return result; + } + + public CustomModelData getHandle() { + return handle; + } + + @Override + public List getFloats() { + return Collections.unmodifiableList(handle.floats()); + } + + @Override + public void setFloats(List floats) { + handle = new CustomModelData(new ArrayList<>(floats), handle.flags(), handle.strings(), handle.colors()); + } + + @Override + public List getFlags() { + return Collections.unmodifiableList(handle.flags()); + } + + @Override + public void setFlags(List flags) { + handle = new CustomModelData(handle.floats(), new ArrayList<>(handle.flags()), handle.strings(), handle.colors()); + } + + @Override + public List getStrings() { + return Collections.unmodifiableList(handle.strings()); + } + + @Override + public void setStrings(List strings) { + handle = new CustomModelData(handle.floats(), handle.flags(), new ArrayList<>(handle.strings()), handle.colors()); + } + + @Override + public List getColors() { + return getHandle().colors().stream().map(Color::fromRGB).toList(); + } + + @Override + public void setColors(List colors) { + handle = new CustomModelData(handle.floats(), handle.flags(), handle.strings(), new ArrayList<>(handle.colors())); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final CraftCustomModelDataComponent other = (CraftCustomModelDataComponent) obj; + return Objects.equals(this.handle, other.handle); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 19 * hash + Objects.hashCode(this.handle); + return hash; + } + + @Override + public String toString() { + return "CraftCustomModelDataComponent{" + "handle=" + handle + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftEquippableComponent.java b/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftEquippableComponent.java index 1f1589bc..5598fcb5 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftEquippableComponent.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftEquippableComponent.java @@ -11,8 +11,10 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.item.equipment.EquipmentAssets; import net.minecraft.world.item.equipment.Equippable; import org.bukkit.NamespacedKey; import org.bukkit.Registry; @@ -66,7 +68,7 @@ public CraftEquippableComponent(Map map) { this.handle = new Equippable(slot, (equipSound != null) ? CraftSound.bukkitToMinecraftHolder(equipSound) : SoundEvents.ARMOR_EQUIP_GENERIC, - Optional.ofNullable(model).map(ResourceLocation::parse), + Optional.ofNullable(model).map(ResourceLocation::parse).map((k) -> ResourceKey.create(EquipmentAssets.ROOT_ID, k)), Optional.ofNullable(cameraOverlay).map(ResourceLocation::parse), Optional.ofNullable(allowedEntities), (dispensable != null) ? dispensable : true, @@ -114,7 +116,7 @@ public EquipmentSlot getSlot() { @Override public void setSlot(EquipmentSlot slot) { - this.handle = new Equippable(CraftEquipmentSlot.getNMS(slot), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); + this.handle = new Equippable(CraftEquipmentSlot.getNMS(slot), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); } @Override @@ -124,17 +126,17 @@ public Sound getEquipSound() { @Override public void setEquipSound(Sound sound) { - this.handle = new Equippable(this.handle.slot(), (sound != null) ? CraftSound.bukkitToMinecraftHolder(sound) : SoundEvents.ARMOR_EQUIP_GENERIC, this.handle.model(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); + this.handle = new Equippable(this.handle.slot(), (sound != null) ? CraftSound.bukkitToMinecraftHolder(sound) : SoundEvents.ARMOR_EQUIP_GENERIC, this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); } @Override public NamespacedKey getModel() { - return this.handle.model().map(CraftNamespacedKey::fromMinecraft).orElse(null); + return handle.assetId().map((a) -> CraftNamespacedKey.fromMinecraft(a.location())).orElse(null); } @Override public void setModel(NamespacedKey key) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft).map((k) -> ResourceKey.create(EquipmentAssets.ROOT_ID, k)), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); } @Override @@ -144,7 +146,7 @@ public NamespacedKey getCameraOverlay() { @Override public void setCameraOverlay(NamespacedKey key) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), Optional.ofNullable(key).map(CraftNamespacedKey::toMinecraft), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt()); } @Override @@ -154,7 +156,7 @@ public Collection getAllowedEntities() { @Override public void setAllowedEntities(EntityType entities) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), (entities != null) ? Optional.of(HolderSet.direct(CraftEntityType.bukkitToMinecraftHolder(entities))) : Optional.empty(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt() ); @@ -162,7 +164,7 @@ public void setAllowedEntities(EntityType entities) { @Override public void setAllowedEntities(Collection entities) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), (entities != null) ? Optional.of(HolderSet.direct(entities.stream().map(CraftEntityType::bukkitToMinecraftHolder).collect(Collectors.toList()))) : Optional.empty(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt() ); @@ -172,7 +174,7 @@ public void setAllowedEntities(Collection entities) { public void setAllowedEntities(Tag tag) { Preconditions.checkArgument(tag instanceof CraftEntityTag, "tag must be an entity tag"); - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), (tag != null) ? Optional.of(((CraftEntityTag) tag).getHandle()) : Optional.empty(), this.handle.dispensable(), this.handle.swappable(), this.handle.damageOnHurt() ); @@ -185,7 +187,7 @@ public boolean isDispensable() { @Override public void setDispensable(boolean dispensable) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), this.handle.allowedEntities(), dispensable, this.handle.swappable(), this.handle.damageOnHurt()); + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), dispensable, this.handle.swappable(), this.handle.damageOnHurt()); } @Override @@ -195,7 +197,7 @@ public boolean isSwappable() { @Override public void setSwappable(boolean swappable) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), swappable, this.handle.damageOnHurt()); + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), swappable, this.handle.damageOnHurt()); } @Override @@ -205,7 +207,7 @@ public boolean isDamageOnHurt() { @Override public void setDamageOnHurt(boolean damage) { - this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.model(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), damage); + this.handle = new Equippable(this.handle.slot(), this.handle.equipSound(), this.handle.assetId(), this.handle.cameraOverlay(), this.handle.allowedEntities(), this.handle.dispensable(), this.handle.swappable(), damage); } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftUseCooldownComponent.java b/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftUseCooldownComponent.java index 952e7fa0..d0478621 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftUseCooldownComponent.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/components/CraftUseCooldownComponent.java @@ -38,7 +38,7 @@ public Map serialize() { Map result = new LinkedHashMap<>(); result.put("seconds", this.getCooldownSeconds()); if (this.getCooldownGroup() != null) { - result.put("cooldown-group", this.getCooldownGroup()); + result.put("cooldown-group", this.getCooldownGroup().toString()); } return result; @@ -54,10 +54,10 @@ public float getCooldownSeconds() { } @Override - public void setCooldownSeconds(float eatSeconds) { - Preconditions.checkArgument(eatSeconds >= 0, "eatSeconds cannot be less than 0"); + public void setCooldownSeconds(float cooldown) { + Preconditions.checkArgument(cooldown >= 0, "cooldown cannot be less than 0"); - this.handle = new UseCooldown(eatSeconds, this.handle.cooldownGroup()); + this.handle = new UseCooldown(cooldown, this.handle.cooldownGroup()); } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java b/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java index c1023eff..091e1193 100644 --- a/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java +++ b/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java @@ -175,8 +175,6 @@ public static Biome valueOf_Biome(String name) { .change("SNOWMAN", "SNOW_GOLEM") .change("FISHING_HOOK", "FISHING_BOBBER") .change("LIGHTNING", "LIGHTNING_BOLT") - .change("BOAT", "OAK_BOAT") - .change("CHEST_BOAT", "OAK_CHEST_BOAT") .withKeyRename() .change("XP_ORB", "EXPERIENCE_ORB") .change("EYE_OF_ENDER_SIGNAL", "EYE_OF_ENDER") @@ -191,6 +189,8 @@ public static Biome valueOf_Biome(String name) { .change("VILLAGER_GOLEM", "IRON_GOLEM") .change("ENDER_CRYSTAL", "END_CRYSTAL") .change("ZOMBIE_PIGMAN", "ZOMBIFIED_PIGLIN") + .change("BOAT", "OAK_BOAT") + .change("CHEST_BOAT", "OAK_CHEST_BOAT") .build(); public static final BiFunction ENTITY_TYPE_RENAME = ENTITY_TYPE_DATA::getReplacement; @@ -354,7 +354,39 @@ public static LootTables valueOf_LootTables(String name) { private static final FieldRenameData ATTRIBUTE_DATA = FieldRenameData.Builder.newBuilder() .forAllVersions() .withKeyRename() - .change("HORSE.JUMP_STRENGTH", "GENERIC.JUMP_STRENGTH") + .change("HORSE.JUMP_STRENGTH", "JUMP_STRENGTH") + .change("GENERIC.MAX_HEALTH", "MAX_HEALTH") + .change("GENERIC.FOLLOW_RANGE", "FOLLOW_RANGE") + .change("GENERIC.KNOCKBACK_RESISTANCE", "KNOCKBACK_RESISTANCE") + .change("GENERIC.MOVEMENT_SPEED", "MOVEMENT_SPEED") + .change("GENERIC.FLYING_SPEED", "FLYING_SPEED") + .change("GENERIC.ATTACK_DAMAGE", "ATTACK_DAMAGE") + .change("GENERIC.ATTACK_KNOCKBACK", "ATTACK_KNOCKBACK") + .change("GENERIC.ATTACK_SPEED", "ATTACK_SPEED") + .change("GENERIC.ARMOR", "ARMOR") + .change("GENERIC.ARMOR_TOUGHNESS", "ARMOR_TOUGHNESS") + .change("GENERIC.FALL_DAMAGE_MULTIPLIER", "FALL_DAMAGE_MULTIPLIER") + .change("GENERIC.LUCK", "LUCK") + .change("GENERIC.MAX_ABSORPTION", "MAX_ABSORPTION") + .change("GENERIC.SAFE_FALL_DISTANCE", "SAFE_FALL_DISTANCE") + .change("GENERIC.SCALE", "SCALE") + .change("GENERIC.STEP_HEIGHT", "STEP_HEIGHT") + .change("GENERIC.GRAVITY", "GRAVITY") + .change("GENERIC.JUMP_STRENGTH", "JUMP_STRENGTH") + .change("GENERIC.BURNING_TIME", "BURNING_TIME") + .change("GENERIC.EXPLOSION_KNOCKBACK_RESISTANCE", "EXPLOSION_KNOCKBACK_RESISTANCE") + .change("GENERIC.MOVEMENT_EFFICIENCY", "MOVEMENT_EFFICIENCY") + .change("GENERIC.OXYGEN_BONUS", "OXYGEN_BONUS") + .change("GENERIC.WATER_MOVEMENT_EFFICIENCY", "WATER_MOVEMENT_EFFICIENCY") + .change("GENERIC.TEMPT_RANGE", "TEMPT_RANGE") + .change("PLAYER.BLOCK_INTERACTION_RANGE", "BLOCK_INTERACTION_RANGE") + .change("PLAYER.ENTITY_INTERACTION_RANGE", "ENTITY_INTERACTION_RANGE") + .change("PLAYER.BLOCK_BREAK_SPEED", "BLOCK_BREAK_SPEED") + .change("PLAYER.MINING_EFFICIENCY", "MINING_EFFICIENCY") + .change("PLAYER.SNEAKING_SPEED", "SNEAKING_SPEED") + .change("PLAYER.SUBMERGED_MINING_SPEED", "SUBMERGED_MINING_SPEED") + .change("PLAYER.SWEEPING_DAMAGE_RATIO", "SWEEPING_DAMAGE_RATIO") + .change("ZOMBIE.SPAWN_REINFORCEMENTS", "SPAWN_REINFORCEMENTS") .build(); public static final BiFunction ATTRIBUTE_RENAME = ATTRIBUTE_DATA::getReplacement; diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java b/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java index bee74a37..faba7efb 100644 --- a/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java +++ b/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java @@ -15,8 +15,13 @@ import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.Collectors; +import org.bukkit.Art; +import org.bukkit.Fluid; import org.bukkit.NamespacedKey; import org.bukkit.Registry; +import org.bukkit.Sound; +import org.bukkit.attribute.Attribute; +import org.bukkit.block.Biome; import org.bukkit.block.banner.PatternType; import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.legacy.reroute.DoNotReroute; @@ -44,8 +49,13 @@ public class EnumEvil { static { // Add Classes which got changed here + REGISTRIES.put(Art.class, new LegacyRegistryData(Registry.ART, Art::valueOf)); + REGISTRIES.put(Attribute.class, new LegacyRegistryData(Registry.ATTRIBUTE, Attribute::valueOf)); + REGISTRIES.put(Biome.class, new LegacyRegistryData(Registry.BIOME, Biome::valueOf)); + REGISTRIES.put(Fluid.class, new LegacyRegistryData(Registry.FLUID, Fluid::valueOf)); REGISTRIES.put(Villager.Type.class, new LegacyRegistryData(Registry.VILLAGER_TYPE, Villager.Type::valueOf)); REGISTRIES.put(Villager.Profession.class, new LegacyRegistryData(Registry.VILLAGER_PROFESSION, Villager.Profession::valueOf)); + REGISTRIES.put(Sound.class, new LegacyRegistryData(Registry.SOUNDS, Sound::valueOf)); REGISTRIES.put(Frog.Variant.class, new LegacyRegistryData(Registry.FROG_VARIANT, Frog.Variant::valueOf)); REGISTRIES.put(Cat.Type.class, new LegacyRegistryData(Registry.CAT_VARIANT, Cat.Type::valueOf)); REGISTRIES.put(MapCursor.Type.class, new LegacyRegistryData(Registry.MAP_DECORATION_TYPE, MapCursor.Type::valueOf)); diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java index 163d54a8..a25ccafc 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -446,11 +446,7 @@ public void mainThreadHeartbeat() { } private void addTask(final CraftTask task) { - final AtomicReference tail = this.tail; - CraftTask tailTask = tail.get(); - while (!tail.compareAndSet(tailTask, task)) { - tailTask = tail.get(); - } + final CraftTask tailTask = this.tail.getAndSet(task); tailTask.setNext(task); } diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java index d9f8a0c8..e8be35f8 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java @@ -54,7 +54,7 @@ public CraftObjective registerNewObjective(String name, Criteria criteria, Strin Preconditions.checkArgument(name.length() <= Short.MAX_VALUE, "The name '%s' is longer than the limit of 32767 characters (%s)", name, name.length()); Preconditions.checkArgument(this.board.getObjective(name) == null, "An objective of name '%s' already exists", name); - net.minecraft.world.scores.Objective objective = this.board.addObjective(name, ((CraftCriteria) criteria).criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType), true, null); + net.minecraft.world.scores.Objective objective = this.board.addObjective(name, ((CraftCriteria) criteria).criteria, CraftChatMessage.fromStringOrEmpty(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType), true, null); return new CraftObjective(this, objective); } diff --git a/src/main/java/org/bukkit/craftbukkit/util/ApiVersion.java b/src/main/java/org/bukkit/craftbukkit/util/ApiVersion.java index 1fa606ab..3c50d80b 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/ApiVersion.java +++ b/src/main/java/org/bukkit/craftbukkit/util/ApiVersion.java @@ -16,7 +16,7 @@ public final class ApiVersion implements Comparable, Serializable { static { versions = new HashMap<>(); - CURRENT = getOrCreateVersion("1.21.2"); + CURRENT = getOrCreateVersion("1.21.4"); FLATTENING = getOrCreateVersion("1.13"); FIELD_NAME_PARITY = getOrCreateVersion("1.20.5"); NONE = getOrCreateVersion("none"); diff --git a/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java b/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java index 072d105f..a4bc24cc 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java +++ b/src/main/java/org/bukkit/craftbukkit/util/BlockStateListPopulator.java @@ -10,6 +10,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.RegistryAccess; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; @@ -152,4 +153,10 @@ public LevelData getLevelData() { public long nextSubTickCount() { return this.world.nextSubTickCount(); } + + // SPIGOT-7966: Needed for some tree generations + @Override + public RandomSource getRandom() { + return world.getRandom(); + } } diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java index b60b715a..40fbbff1 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -80,14 +80,19 @@ public class Commodore { "org/spigotmc/event/entity/EntityDismountEvent", "org/bukkit/event/entity/EntityDismountEvent" ); - private static final Map CLASS_TO_INTERFACE = Map.of( - "org/bukkit/inventory/InventoryView", "org/bukkit/craftbukkit/inventory/CraftAbstractInventoryView", - "org/bukkit/entity/Villager$Type", "NOP", - "org/bukkit/entity/Villager$Profession", "NOP", - "org/bukkit/entity/Frog$Variant", "NOP", - "org/bukkit/entity/Cat$Type", "NOP", - "org/bukkit/map/MapCursor$Type", "NOP", - "org/bukkit/block/banner/PatternType", "NOP" + private static final Map CLASS_TO_INTERFACE = Map.ofEntries( + Map.entry("org/bukkit/inventory/InventoryView", "org/bukkit/craftbukkit/inventory/CraftAbstractInventoryView"), + Map.entry("org/bukkit/entity/Villager$Type", "NOP"), + Map.entry("org/bukkit/entity/Villager$Profession", "NOP"), + Map.entry("org/bukkit/entity/Frog$Variant", "NOP"), + Map.entry("org/bukkit/entity/Cat$Type", "NOP"), + Map.entry("org/bukkit/map/MapCursor$Type", "NOP"), + Map.entry("org/bukkit/block/banner/PatternType", "NOP"), + Map.entry("org/bukkit/Art", "NOP"), + Map.entry("org/bukkit/attribute/Attribute", "NOP"), + Map.entry("org/bukkit/block/Biome", "NOP"), + Map.entry("org/bukkit/Fluid", "NOP"), + Map.entry("org/bukkit/Sound", "NOP") ); private final List reroutes = new ArrayList<>(); // only for testing diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index fc444b73..e019a8a4 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -46,11 +46,13 @@ import org.bukkit.advancement.Advancement; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; +import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; import org.bukkit.craftbukkit.CraftFeatureFlag; import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.attribute.CraftAttribute; +import org.bukkit.craftbukkit.block.CraftBiome; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.damage.CraftDamageEffect; import org.bukkit.craftbukkit.damage.CraftDamageSourceBuilder; @@ -231,7 +233,7 @@ public Material getMaterial(String material, int version) { * @return string */ public String getMappingsVersion() { - return "ec8b033a89c54252f1dfcb809eab710a"; + return "60ac387ca8007aa018e6aeb394a6988c"; } @Override @@ -367,7 +369,7 @@ public String getTranslationKey(ItemStack itemStack) { @Override public String getTranslationKey(final Attribute attribute) { - return CraftAttribute.bukkitToMinecraft(attribute).getDescriptionId(); + return attribute.getTranslationKey(); } @Override @@ -410,6 +412,16 @@ public B get(Registry registry, NamespacedKey namespacedKey return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); } + private Biome customBiome; + @Override + public Biome getCustomBiome() { + if (customBiome == null) { + customBiome = new CraftBiome(NamespacedKey.minecraft("custom"), null); + } + + return customBiome; + } + /** * This helper class represents the different NBT Tags. *