diff --git a/patches/api/Add-predicate-for-blocks-when-raytracing.patch b/patches/api/Add-predicate-for-blocks-when-raytracing.patch index 20f69eca0c..a3366b99f1 100644 --- a/patches/api/Add-predicate-for-blocks-when-raytracing.patch +++ b/patches/api/Add-predicate-for-blocks-when-raytracing.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/World.java @@ -0,0 +0,0 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient @Nullable - public RayTraceResult rayTraceEntities(@NotNull Location start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate filter); + public RayTraceResult rayTraceEntities(@NotNull Location start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate filter); + // Paper start + /** @@ -30,8 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @return the closest ray trace hit result, or null if there + * is no hit + */ -+ @Nullable -+ public RayTraceResult rayTraceEntities(@NotNull io.papermc.paper.math.Position start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate filter); ++ @Nullable RayTraceResult rayTraceEntities(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate filter); + // Paper end + /** @@ -66,8 +65,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * with, or null to consider all blocks + * @return the ray trace hit result, or null if there is no hit + */ -+ @Nullable -+ public RayTraceResult rayTraceBlocks(@NotNull io.papermc.paper.math.Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, @Nullable Predicate canCollide); ++ @Nullable RayTraceResult rayTraceBlocks(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, @Nullable Predicate canCollide); + // Paper end + /** @@ -75,7 +73,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 *

@@ -0,0 +0,0 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient @Nullable - public RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate filter); + public RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate filter); + // Paper start + /** @@ -110,8 +108,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @return the closest ray trace hit result with either a block or an + * entity, or null if there is no hit + */ -+ @Nullable -+ public RayTraceResult rayTrace(@NotNull io.papermc.paper.math.Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate filter, @Nullable Predicate canCollide); ++ @Nullable RayTraceResult rayTrace(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate filter, @Nullable Predicate canCollide); + // Paper end + /** diff --git a/patches/api/Fix-Spigot-annotation-mistakes.patch b/patches/api/Fix-Spigot-annotation-mistakes.patch index faba120ed4..1e58717fd7 100644 --- a/patches/api/Fix-Spigot-annotation-mistakes.patch +++ b/patches/api/Fix-Spigot-annotation-mistakes.patch @@ -200,7 +200,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/EntityEffect.java +++ b/src/main/java/org/bukkit/EntityEffect.java @@ -0,0 +0,0 @@ public enum EntityEffect { - * Gets the data value of this EntityEffect + * Gets the data value of this EntityEffect, may not be unique. * * @return The data value - * @deprecated Magic value diff --git a/patches/api/Spawn-Reason-API.patch b/patches/api/Spawn-Reason-API.patch index 7e9d84d3a0..7986cc3988 100644 --- a/patches/api/Spawn-Reason-API.patch +++ b/patches/api/Spawn-Reason-API.patch @@ -8,46 +8,36 @@ diff --git a/src/main/java/org/bukkit/RegionAccessor.java b/src/main/java/org/bu index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/RegionAccessor.java +++ b/src/main/java/org/bukkit/RegionAccessor.java -@@ -0,0 +0,0 @@ import org.bukkit.block.data.BlockData; - import org.bukkit.entity.Entity; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.entity.CreatureSpawnEvent; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - @@ -0,0 +0,0 @@ public interface RegionAccessor { + * @throws IllegalArgumentException if either parameter is null or the * {@link Entity} requested cannot be spawned */ - @NotNull -- T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException; +- @NotNull +- T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException; + // Paper start -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException { -+ return spawn(location, clazz, CreatureSpawnEvent.SpawnReason.CUSTOM, function); ++ default @NotNull T spawn(final @NotNull Location location, final @NotNull Class clazz, final @Nullable Consumer function) throws IllegalArgumentException { ++ return this.spawn(location, clazz, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CUSTOM, function); + } + -+ @NotNull -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { -+ return spawn(location, clazz, reason, null); ++ default @NotNull T spawn(final @NotNull Location location, final @NotNull Class clazz, final org.bukkit.event.entity.CreatureSpawnEvent.@NotNull SpawnReason reason) throws IllegalArgumentException { ++ return this.spawn(location, clazz, reason, null); + } + -+ @NotNull -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) throws IllegalArgumentException { -+ return spawn(location, clazz, function, reason); ++ default @NotNull T spawn(final @NotNull Location location, final @NotNull Class clazz, final org.bukkit.event.entity.CreatureSpawnEvent.@NotNull SpawnReason reason, final @Nullable Consumer function) throws IllegalArgumentException { ++ return this.spawn(location, clazz, function, reason); + } + -+ @NotNull -+ public default Entity spawnEntity(@NotNull Location loc, @NotNull org.bukkit.entity.EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, null); ++ default @NotNull Entity spawnEntity(final @NotNull Location loc, final @NotNull EntityType type, final org.bukkit.event.entity.CreatureSpawnEvent.@NotNull SpawnReason reason) { ++ com.google.common.base.Preconditions.checkArgument(type.getEntityClass() != null, "%s is not a valid EntityType, must have an entity class", type); ++ return this.spawn(loc, type.getEntityClass(), reason, null); + } + -+ @NotNull -+ public default Entity spawnEntity(@NotNull Location loc, @NotNull org.bukkit.entity.EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, function); ++ default @NotNull Entity spawnEntity(final @NotNull Location loc, final @NotNull EntityType type, final org.bukkit.event.entity.CreatureSpawnEvent.@NotNull SpawnReason reason, final @Nullable Consumer function) { ++ com.google.common.base.Preconditions.checkArgument(type.getEntityClass() != null, "%s is not a valid EntityType, must have an entity class", type); ++ return this.spawn(loc, type.getEntityClass(), reason, function); + } + -+ @NotNull -+ public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException; ++ @NotNull T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function, org.bukkit.event.entity.CreatureSpawnEvent.@NotNull SpawnReason reason) throws IllegalArgumentException; + // Paper end /** diff --git a/patches/api/fix-Instruments.patch b/patches/api/fix-Instruments.patch index 64f4461eac..1638df4a33 100644 --- a/patches/api/fix-Instruments.patch +++ b/patches/api/fix-Instruments.patch @@ -17,63 +17,64 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - * Piano is the standard instrument for a note block. + * Piano (Harp) is the standard instrument for a note block. */ - PIANO(0x0), + PIANO(0x0, Sound.BLOCK_NOTE_BLOCK_HARP), /** @@ -0,0 +0,0 @@ public enum Instrument { */ - SNARE_DRUM(0x2), + SNARE_DRUM(0x2, Sound.BLOCK_NOTE_BLOCK_SNARE), /** - * Sticks are normally played when a note block is on top of a glass + * Sticks (Hat) are normally played when a note block is on top of a glass * block. */ - STICKS(0x3), + STICKS(0x3, Sound.BLOCK_NOTE_BLOCK_HAT), @@ -0,0 +0,0 @@ public enum Instrument { /** * Zombie is normally played when a Zombie Head is on top of the note block. */ -- ZOMBIE, -+ ZOMBIE(0x10), // Paper +- ZOMBIE(Sound.BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE), ++ ZOMBIE(0x10, Sound.BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE), // Paper /** * Skeleton is normally played when a Skeleton Head is on top of the note block. */ -- SKELETON, -+ SKELETON(0x11), // Paper +- SKELETON(Sound.BLOCK_NOTE_BLOCK_IMITATE_SKELETON), ++ SKELETON(0x11, Sound.BLOCK_NOTE_BLOCK_IMITATE_SKELETON), // Paper /** * Creeper is normally played when a Creeper Head is on top of the note block. */ -- CREEPER, -+ CREEPER(0x12), // Paper +- CREEPER(Sound.BLOCK_NOTE_BLOCK_IMITATE_CREEPER), ++ CREEPER(0x12, Sound.BLOCK_NOTE_BLOCK_IMITATE_CREEPER), // Paper /** * Dragon is normally played when a Dragon Head is on top of the note block. */ -- DRAGON, -+ DRAGON(0x13), // Paper +- DRAGON(Sound.BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON), ++ DRAGON(0x13, Sound.BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON), // Paper /** * Wither Skeleton is normally played when a Wither Skeleton Head is on top of the note block. */ -- WITHER_SKELETON, -+ WITHER_SKELETON(0x14), // Paper +- WITHER_SKELETON(Sound.BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON), ++ WITHER_SKELETON(0x14, Sound.BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON), // Paper /** * Piglin is normally played when a Piglin Head is on top of the note block. */ -- PIGLIN, -+ PIGLIN(0x15), // Paper +- PIGLIN(Sound.BLOCK_NOTE_BLOCK_IMITATE_PIGLIN), ++ PIGLIN(0x15, Sound.BLOCK_NOTE_BLOCK_IMITATE_PIGLIN), // Paper /** * Custom Sound is normally played when a Player Head with the required data is on top of the note block. */ -- CUSTOM_HEAD; -+ CUSTOM_HEAD(0x16); // Paper +- CUSTOM_HEAD(null); ++ CUSTOM_HEAD(0x16, null); // Paper private final byte type; + private final Sound sound; private static final Map BY_DATA = Maps.newHashMap(); -- private Instrument() { -- this(-1); +- private Instrument(final Sound sound) { +- this(-1, sound); - } + // Paper - remove ctor (the server still uses the byte magic value) - private Instrument(final int type) { + private Instrument(final int type, final Sound sound) { this.type = (byte) type; @@ -0,0 +0,0 @@ public enum Instrument { @@ -97,21 +98,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Nullable public static Instrument getByType(final byte type) { return BY_DATA.get(type); -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public void playNote(@NotNull Location loc, byte instrument, byte note); - - /** -- * Play a note for a player at a location. This requires a note block -- * at the particular location (as far as the client is concerned). This -- * will not work without a note block. This will not work with cake. -+ * Play a note for a player at a location. - * - * @param loc The location of a note block - * @param instrument The instrument diff --git a/src/test/java/org/bukkit/InstrumentTest.java b/src/test/java/org/bukkit/InstrumentTest.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/InstrumentTest.java diff --git a/patches/server/Add-predicate-for-blocks-when-raytracing.patch b/patches/server/Add-predicate-for-blocks-when-raytracing.patch index 6508d550fb..7094520917 100644 --- a/patches/server/Add-predicate-for-blocks-when-raytracing.patch +++ b/patches/server/Add-predicate-for-blocks-when-raytracing.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return clip(raytrace1, blockposition, null); + } + -+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate canCollide) { ++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate canCollide) { + // Paper end // Paper start - Prevent raytrace from loading chunks BlockState iblockdata = this.getBlockStateIfLoaded(blockposition); @@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return clip(context, (java.util.function.Predicate) null); + } + -+ default BlockHitResult clip(ClipContext context, java.util.function.Predicate canCollide) { ++ default BlockHitResult clip(ClipContext context, java.util.function.Predicate canCollide) { + // Paper end return (BlockHitResult) BlockGetter.traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> { - return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method @@ -53,12 +53,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override - public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate filter) { + public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate filter) { + // Paper start + return rayTraceEntities((io.papermc.paper.math.Position) start, direction, maxDistance, raySize, filter); + } + -+ public RayTraceResult rayTraceEntities(io.papermc.paper.math.Position start, Vector direction, double maxDistance, double raySize, Predicate filter) { ++ public RayTraceResult rayTraceEntities(io.papermc.paper.math.Position start, Vector direction, double maxDistance, double raySize, Predicate filter) { Preconditions.checkArgument(start != null, "Location start cannot be null"); - Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world"); - start.checkFinite(); @@ -77,7 +77,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate canCollide) { ++ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate canCollide) { Preconditions.checkArgument(start != null, "Location start cannot be null"); - Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world"); - start.checkFinite(); @@ -101,14 +101,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @Override - public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate filter) { + public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate filter) { - RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks); + // Paper start + return this.rayTrace(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, filter, null); + } + + @Override -+ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate filter, Predicate canCollide) { ++ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate filter, Predicate canCollide) { + RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, canCollide); + // Paper end Vector startVec = null; diff --git a/patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch index 5bbcd4069f..ebf283059c 100644 --- a/patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ b/patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch @@ -13,9 +13,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { @Override - public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { + public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { - this.runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); -+ this.runTaskTimerAsynchronously(plugin, (Object) task, delay, period); ++ this.runTaskTimerAsynchronously(plugin, (Object) task, delay, period); // Paper } @Override diff --git a/patches/server/fix-Instruments.patch b/patches/server/fix-Instruments.patch index 1c77af9662..7b74139c22 100644 --- a/patches/server/fix-Instruments.patch +++ b/patches/server/fix-Instruments.patch @@ -10,44 +10,47 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + Sound instrumentSound = instrument.getSound(); + if (instrumentSound == null) return; - if (this.getHandle().connection == null) return; - -- Sound instrumentSound = switch (instrument.ordinal()) { -- case 0 -> Sound.BLOCK_NOTE_BLOCK_HARP; -- case 1 -> Sound.BLOCK_NOTE_BLOCK_BASEDRUM; -- case 2 -> Sound.BLOCK_NOTE_BLOCK_SNARE; -- case 3 -> Sound.BLOCK_NOTE_BLOCK_HAT; -- case 4 -> Sound.BLOCK_NOTE_BLOCK_BASS; -- case 5 -> Sound.BLOCK_NOTE_BLOCK_FLUTE; -- case 6 -> Sound.BLOCK_NOTE_BLOCK_BELL; -- case 7 -> Sound.BLOCK_NOTE_BLOCK_GUITAR; -- case 8 -> Sound.BLOCK_NOTE_BLOCK_CHIME; -- case 9 -> Sound.BLOCK_NOTE_BLOCK_XYLOPHONE; -- case 10 -> Sound.BLOCK_NOTE_BLOCK_IRON_XYLOPHONE; -- case 11 -> Sound.BLOCK_NOTE_BLOCK_COW_BELL; -- case 12 -> Sound.BLOCK_NOTE_BLOCK_DIDGERIDOO; -- case 13 -> Sound.BLOCK_NOTE_BLOCK_BIT; -- case 14 -> Sound.BLOCK_NOTE_BLOCK_BANJO; -- case 15 -> Sound.BLOCK_NOTE_BLOCK_PLING; -- case 16 -> Sound.BLOCK_NOTE_BLOCK_XYLOPHONE; -- default -> null; -- }; -- -- float f = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D); -- this.getHandle().connection.send(new ClientboundSoundPacket(CraftSound.bukkitToMinecraftHolder(instrumentSound), net.minecraft.sounds.SoundSource.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f, this.getHandle().getRandom().nextLong())); -+ // Paper start - fix all this (modeled off of NoteBlock) -+ net.minecraft.world.level.block.state.properties.NoteBlockInstrument noteBlockInstrument = CraftBlockData.toNMS(instrument, net.minecraft.world.level.block.state.properties.NoteBlockInstrument.class); -+ float pitch; -+ if (noteBlockInstrument.isTunable()) { -+ pitch = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D); -+ } else { -+ pitch = 1.0f; -+ } -+ if (!noteBlockInstrument.hasCustomSound()) { -+ this.getHandle().connection.send(new ClientboundSoundPacket(noteBlockInstrument.getSoundEvent(), net.minecraft.sounds.SoundSource.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, pitch, this.getHandle().getRandom().nextLong())); -+ } +- float pitch = note.getPitch(); ++ // Paper start - use correct pitch (modeled off of NoteBlock) ++ final net.minecraft.world.level.block.state.properties.NoteBlockInstrument noteBlockInstrument = CraftBlockData.toNMS(instrument, net.minecraft.world.level.block.state.properties.NoteBlockInstrument.class); ++ final float pitch = noteBlockInstrument.isTunable() ? note.getPitch() : 1.0f; + // Paper end + this.getHandle().connection.send(new ClientboundSoundPacket(CraftSound.bukkitToMinecraftHolder(instrumentSound), net.minecraft.sounds.SoundSource.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, pitch, this.getHandle().getRandom().nextLong())); } - @Override +diff --git a/src/test/java/io/papermc/paper/block/InstrumentSoundTest.java b/src/test/java/io/papermc/paper/block/InstrumentSoundTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/block/InstrumentSoundTest.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.block; ++ ++import java.util.Arrays; ++import java.util.stream.Stream; ++import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; ++import org.bukkit.Instrument; ++import org.bukkit.craftbukkit.CraftSound; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.jupiter.params.ParameterizedTest; ++import org.junit.jupiter.params.provider.MethodSource; ++ ++import static org.junit.jupiter.api.Assertions.assertEquals; ++ ++class InstrumentSoundTest extends AbstractTestingBase { ++ ++ static Stream bukkitInstruments() { ++ return Arrays.stream(Instrument.values()).filter(i -> i.getSound() != null); ++ } ++ ++ @ParameterizedTest ++ @MethodSource("bukkitInstruments") ++ void checkInstrumentSound(final Instrument bukkit) { ++ final NoteBlockInstrument nms = CraftBlockData.toNMS(bukkit, NoteBlockInstrument.class); ++ assertEquals(nms.getSoundEvent(), CraftSound.bukkitToMinecraftHolder(bukkit.getSound())); ++ } ++} diff --git a/work/Bukkit b/work/Bukkit index fde5602a24..9634085818 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit fde5602a24e30d563009378e8c9b08f693b148e2 +Subproject commit 96340858187334c2f24f6acdc904561655c6cbab diff --git a/work/CraftBukkit b/work/CraftBukkit index c8feb06296..8e162d0083 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit c8feb062965f97a637d2a3aa1f597f82251fcbbb +Subproject commit 8e162d0083aa05bd3b4ec8972093fe7e9e9b53b0 diff --git a/work/Spigot b/work/Spigot index dba3cdc33b..7de1049b2a 160000 --- a/work/Spigot +++ b/work/Spigot @@ -1 +1 @@ -Subproject commit dba3cdc33be9abb98bb8d13b612b33b18a812db6 +Subproject commit 7de1049b2a99eaca8090596e3b8e2ba8431f27e6