Fleshen out the play custom sound packet, make it work on all mc versions

Signed-off-by: Irmo van den Berge <irmo.vandenberge@ziggo.nl>
This commit is contained in:
Irmo van den Berge committed 2023-05-14 18:17:33 +02:00
1 parent 7cb2f7eadc
commit 22bfaedae5
10 files changed
+251 -83

No files matched your search

@@ -33,7 +33,7 @@ public abstract class RegistryMaterialsHandle extends Template.Handle {
public final Template.Method.Converted<Object> get = new Template.Method.Converted<Object>();
public final Template.Method<Object> getKey = new Template.Method<Object>();
@Template.Optional
public final Template.Method<Object> rawResourceKeyToHolder = new Template.Method<Object>();
public final Template.Method<Object> rawSoundEffectResourceKeyToHolder = new Template.Method<Object>();
}
@@ -10,7 +10,6 @@ import com.bergerkiller.generated.net.minecraft.network.protocol.PacketHandle;
* To access members without creating a handle type, use the static {@link #T} member.
* New handles can be created from raw instances using {@link #createHandle(Object)}.
*/
@Template.Optional
@Template.InstanceType("net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect")
public abstract class PacketPlayOutCustomSoundEffectHandle extends PacketHandle {
/** @see PacketPlayOutCustomSoundEffectClass */
@@ -23,32 +22,33 @@ public abstract class PacketPlayOutCustomSoundEffectHandle extends PacketHandle
/* ============================================================================== */
public void setPitch(float pitch) {
if (T.opt_pitch_float.isAvailable()) {
T.opt_pitch_float.setFloat(getRaw(), pitch);
} else {
T.opt_pitch_integer.setInteger(getRaw(), (int) (pitch * 63.0f));
}
public static PacketPlayOutCustomSoundEffectHandle createNew(ResourceKey<SoundEffect> soundEffect, String category, double x, double y, double z, float volume, float pitch, long randomSeed) {
return T.createNew.invokeVA(soundEffect, category, x, y, z, volume, pitch, randomSeed);
}
public float getPitch() {
if (T.opt_pitch_float.isAvailable()) {
return T.opt_pitch_float.getFloat(getRaw());
} else {
return (float) T.opt_pitch_integer.getInteger(getRaw()) / 63.0f;
}
public abstract String getCategory();
public abstract void setCategory(String category);
public abstract double getX();
public abstract double getY();
public abstract double getZ();
public abstract void setX(double x);
public abstract void setY(double y);
public abstract void setZ(double z);
public abstract void setPitch(float pitch);
public abstract float getPitch();
public abstract long getRandomSeed();
public abstract void setRandomSeed(long seed);
public static PacketPlayOutCustomSoundEffectHandle createNew(com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect> soundEffect, String category, org.bukkit.Location location, float volume, float pitch) {
return createNew(soundEffect, category, location.getWorld(), location.getX(), location.getY(), location.getZ(), volume, pitch);
}
public static PacketPlayOutCustomSoundEffectHandle createNew(com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect> soundEffect, String category, org.bukkit.World world, double x, double y, double z, float volume, float pitch) {
long randomSeed = com.bergerkiller.bukkit.common.utils.WorldUtil.getRandom(world).nextLong();
return createNew(soundEffect, category, x, y, z, volume, pitch, randomSeed);
}
public abstract ResourceKey<SoundEffect> getSound();
public abstract void setSound(ResourceKey<SoundEffect> value);
public abstract String getCategory();
public abstract void setCategory(String value);
public abstract int getX();
public abstract void setX(int value);
public abstract int getY();
public abstract void setY(int value);
public abstract int getZ();
public abstract void setZ(int value);
public abstract float getVolume();
public abstract void setVolume(float value);
/**
@@ -57,15 +57,22 @@ public abstract class PacketPlayOutCustomSoundEffectHandle extends PacketHandle
*/
public static final class PacketPlayOutCustomSoundEffectClass extends Template.Class<PacketPlayOutCustomSoundEffectHandle> {
public final Template.Field.Converted<ResourceKey<SoundEffect>> sound = new Template.Field.Converted<ResourceKey<SoundEffect>>();
public final Template.Field.Converted<String> category = new Template.Field.Converted<String>();
public final Template.Field.Integer x = new Template.Field.Integer();
public final Template.Field.Integer y = new Template.Field.Integer();
public final Template.Field.Integer z = new Template.Field.Integer();
public final Template.Field.Float volume = new Template.Field.Float();
@Template.Optional
public final Template.Field.Float opt_pitch_float = new Template.Field.Float();
@Template.Optional
public final Template.Field.Integer opt_pitch_integer = new Template.Field.Integer();
public final Template.StaticMethod.Converted<PacketPlayOutCustomSoundEffectHandle> createNew = new Template.StaticMethod.Converted<PacketPlayOutCustomSoundEffectHandle>();
public final Template.Method<String> getCategory = new Template.Method<String>();
public final Template.Method<Void> setCategory = new Template.Method<Void>();
public final Template.Method<Double> getX = new Template.Method<Double>();
public final Template.Method<Double> getY = new Template.Method<Double>();
public final Template.Method<Double> getZ = new Template.Method<Double>();
public final Template.Method<Void> setX = new Template.Method<Void>();
public final Template.Method<Void> setY = new Template.Method<Void>();
public final Template.Method<Void> setZ = new Template.Method<Void>();
public final Template.Method<Void> setPitch = new Template.Method<Void>();
public final Template.Method<Float> getPitch = new Template.Method<Float>();
public final Template.Method<Long> getRandomSeed = new Template.Method<Long>();
public final Template.Method<Void> setRandomSeed = new Template.Method<Void>();
}
@@ -87,7 +87,7 @@ public class MC1_18_2_Conversion {
@ConverterMethod(output="net.minecraft.core.Holder<net.minecraft.sounds.SoundEffect>")
public static Object soundEffectHolderFromResourceKey(ResourceKey<SoundEffect> soundKey) {
Object raw_registry = SoundEffectHandle.T.opt_getRegistry.raw.invoke();
return RegistryMaterialsHandle.T.rawResourceKeyToHolder.invoke(raw_registry, soundKey.getRawHandle());
return RegistryMaterialsHandle.T.rawSoundEffectResourceKeyToHolder.invoke(raw_registry, soundKey.getRawHandle());
}
@Template.Optional
@@ -434,6 +434,10 @@ public class CommonBootstrap {
// PacketPlayInUseItem and PacketPlayInBlockPlace were merged as one packet on these versions
remappings.put("net.minecraft.network.protocol.game.PacketPlayInUseItem", "net.minecraft.network.protocol.game.PacketPlayInBlockPlace");
// PacketPlayOutCustomSoundEffect does not yet exist on 1.8 - 1.8.8, it is proxied by
// the PacketPlayOutNamedSoundEffect packet so it still (mostly) works
remappings.put("net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect", "net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect");
// We proxy a bunch of classes, because they don't exist in 1.8.8
// Writing custom wrappers with switches would be too tiresome
// This allows continued use of the same API without trouble
@@ -651,6 +655,8 @@ public class CommonBootstrap {
remappings.put("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket", "net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
remappings.put("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$EnumPlayerInfoAction", "net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$a");
remappings.put("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$PlayerInfoData", "net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$b");
// CustomSoundEffect was removed as of 1.19.3, now fully handled by the unified NamedSoundEffect packet
remappings.put("net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect", "net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect");
} else {
// BuiltInRegistries class does not exist, but all relevant fields are found in IRegistry instead
remappings.put("net.minecraft.core.registries.BuiltInRegistries", "net.minecraft.core.IRegistry");
@@ -144,11 +144,6 @@ public class CommonCapabilities {
*/
public static final boolean BLOCK_SLAB_HAS_OWN_BLOCK = CommonBootstrap.evaluateMCVersion(">=", "1.13");
/**
* Since Minecraft 1.13 sound names can contain namespaces
*/
public static final boolean NAMESPACED_SOUNDS = CommonBootstrap.evaluateMCVersion(">=", "1.13");
/**
* Whether the ForcedChunk provider can make use of a chunk (plugin) ticket API to keep chunks loaded
*/
@@ -943,10 +943,26 @@ public class MapDisplay implements MapDisplayEvents {
}
}
/**
* Convenience function for playing sounds to the viewers of this map display
*
* @param soundKey of the sound to play
* @param category of the sound. Sets what sliders control playback volume
* @param volume of the sound
* @param pitch of the sound
*/
public void playSound(ResourceKey<SoundEffect> soundKey, String category, float volume, float pitch) {
for (Player viewer : this.getViewers()) {
if (this._playSoundToAllViewers || this.isHolding(viewer)) {
PlayerUtil.playSound(viewer, soundKey, category, this._masterVolume * volume, pitch);
}
}
}
/**
* Sends a status change event without argument to this map display and all widgets attached to it.
* First {@link #onStatusChanged(MapStatusEvent)} is called for all widgets, then for this display.
*
*
* @param name of the status change
*/
public final void sendStatusChange(String name) {
@@ -16,6 +16,7 @@ import com.bergerkiller.bukkit.common.resources.SoundEffect;
import com.bergerkiller.bukkit.common.wrappers.ChatText;
import com.bergerkiller.bukkit.common.wrappers.HumanHand;
import com.bergerkiller.generated.com.mojang.authlib.GameProfileHandle;
import com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffectHandle;
import com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlayOutWorldParticlesHandle;
import com.bergerkiller.generated.net.minecraft.server.level.EntityPlayerHandle;
import com.bergerkiller.generated.net.minecraft.server.network.PlayerConnectionHandle;
@@ -344,11 +345,20 @@ public class PlayerUtil extends EntityUtil {
* @param pitch of the sound
*/
public static void playSound(Player player, ResourceKey<SoundEffect> soundKey, float volume, float pitch) {
if (soundKey != null) {
String name = CommonCapabilities.NAMESPACED_SOUNDS
? soundKey.getName().toString() : soundKey.getName().getName();
player.playSound(player.getEyeLocation(), name, volume, pitch);
}
playSound(player, player.getEyeLocation(), soundKey, "master", volume, pitch);
}
/**
* Plays a named sound effect at the player's location for a single player
*
* @param player to play for and play at
* @param soundKey of the sound to play
* @param category of the sound. Sets what sliders control playback volume
* @param volume of the sound
* @param pitch of the sound
*/
public static void playSound(Player player, ResourceKey<SoundEffect> soundKey, String category, float volume, float pitch) {
playSound(player, player.getEyeLocation(), soundKey, category, volume, pitch);
}
/**
@@ -361,8 +371,23 @@ public class PlayerUtil extends EntityUtil {
* @param pitch of the sound
*/
public static void playSound(Player player, Location location, ResourceKey<SoundEffect> soundKey, float volume, float pitch) {
playSound(player, location, soundKey, "master", volume, pitch);
}
/**
* Plays a named sound effect at a location for a single player
*
* @param player to play for
* @param location to play at
* @param soundKey of the sound to play
* @param category of the sound. Sets what sliders control playback volume
* @param volume of the sound
* @param pitch of the sound
*/
public static void playSound(Player player, Location location, ResourceKey<SoundEffect> soundKey, String category, float volume, float pitch) {
if (soundKey != null) {
player.playSound(location, soundKey.getName().getName(), volume, pitch);
PacketUtil.sendPacket(player, PacketPlayOutCustomSoundEffectHandle.createNew(
soundKey, category, location, volume, pitch));
}
}
@@ -768,10 +768,54 @@ public class NMSPacketClasses {
public static class NMSPacketPlayOutCustomSoundEffect extends NMSPacket {
public final FieldAccessor<ResourceKey<SoundEffect>> sound = PacketPlayOutCustomSoundEffectHandle.T.sound.toFieldAccessor();
public final FieldAccessor<String> category = PacketPlayOutCustomSoundEffectHandle.T.category.toFieldAccessor();
public final FieldAccessor<Integer> x = PacketPlayOutCustomSoundEffectHandle.T.x.toFieldAccessor();
public final FieldAccessor<Integer> y = PacketPlayOutCustomSoundEffectHandle.T.y.toFieldAccessor();
public final FieldAccessor<Integer> z = PacketPlayOutCustomSoundEffectHandle.T.z.toFieldAccessor();
public final FieldAccessor<String> category = new SafeDirectField<String>() {
@Override
public String get(Object instance) {
return PacketPlayOutCustomSoundEffectHandle.createHandle(instance).getCategory();
}
@Override
public boolean set(Object instance, String value) {
PacketPlayOutCustomSoundEffectHandle.createHandle(instance).setCategory(value);
return false;
}
};
public final FieldAccessor<Double> x = new SafeDirectField<Double>() {
@Override
public Double get(Object instance) {
return Double.valueOf(PacketPlayOutCustomSoundEffectHandle.createHandle(instance).getX());
}
@Override
public boolean set(Object instance, Double value) {
PacketPlayOutCustomSoundEffectHandle.createHandle(instance).setX(value.floatValue());
return true;
}
};
public final FieldAccessor<Double> y = new SafeDirectField<Double>() {
@Override
public Double get(Object instance) {
return Double.valueOf(PacketPlayOutCustomSoundEffectHandle.createHandle(instance).getY());
}
@Override
public boolean set(Object instance, Double value) {
PacketPlayOutCustomSoundEffectHandle.createHandle(instance).setY(value.floatValue());
return true;
}
};
public final FieldAccessor<Double> z = new SafeDirectField<Double>() {
@Override
public Double get(Object instance) {
return Double.valueOf(PacketPlayOutCustomSoundEffectHandle.createHandle(instance).getZ());
}
@Override
public boolean set(Object instance, Double value) {
PacketPlayOutCustomSoundEffectHandle.createHandle(instance).setZ(value.floatValue());
return true;
}
};
public final FieldAccessor<Float> volume = PacketPlayOutCustomSoundEffectHandle.T.volume.toFieldAccessor();
public final FieldAccessor<Float> pitch = new SafeDirectField<Float>() {
@Override
@@ -27,12 +27,22 @@ class RegistryMaterials {
public (Object) K getKey:c(V value);
#endif
#if version >= 1.18.2
public optional Object rawResourceKeyToHolder(Object resourceKey) {
#if version >= 1.19.3
public optional Object rawSoundEffectResourceKeyToHolder(Object resourceKey) {
net.minecraft.resources.ResourceKey resourceKeyCasted = (net.minecraft.resources.ResourceKey) resourceKey;
java.util.Optional holderOpt = instance.getHolder(resourceKeyCasted);
if (holderOpt.isPresent()) {
return holderOpt.get();
} else {
return net.minecraft.core.Holder.direct(net.minecraft.sounds.SoundEffect.createVariableRangeEvent(resourceKeyCasted.location()));
}
}
#elseif version >= 1.18.2
public optional Object rawSoundEffectResourceKeyToHolder(Object resourceKey) {
return instance.getHolderOrThrow((net.minecraft.resources.ResourceKey) resourceKey);
}
#else
public optional Object rawResourceKeyToHolder:###(Object resourceKey);
public optional Object rawSoundEffectResourceKeyToHolder:###(Object resourceKey);
#endif
}
@@ -77,6 +77,7 @@ import com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlay
import com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlayOutCustomPayloadHandle;
import com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlayOutSetSlotHandle;
import com.bergerkiller.generated.net.minecraft.network.protocol.game.ClientboundBundlePacketHandle;
import com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffectHandle;
import com.bergerkiller.generated.net.minecraft.resources.MinecraftKeyHandle;
import com.bergerkiller.generated.net.minecraft.sounds.SoundCategoryHandle;
import com.bergerkiller.generated.net.minecraft.world.effect.MobEffectListHandle;
@@ -1519,9 +1520,14 @@ class PacketPlayOutNamedSoundEffect extends Packet {
}
// Since MC 1.9
optional class PacketPlayOutCustomSoundEffect extends Packet {
#if version >= 1.17
// This packet class is handled by PacketPlayOutNamedSoundEffect on MC 1.8 - 1.8.8, where it
// can only really play Vanilla sound effects.
// It is also handled by PacketPlayOutNamedSoundEffect on MC 1.19.3+ where the two packets
// were merged into one.
class PacketPlayOutCustomSoundEffect extends Packet {
#if version >= 1.19.3
private (com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) net.minecraft.core.Holder<net.minecraft.sounds.SoundEffect> sound;
#elseif version >= 1.17
private (com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) net.minecraft.resources.MinecraftKey sound:name;
#elseif version >= 1.13
private (com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) net.minecraft.resources.MinecraftKey sound:a;
@@ -1530,47 +1536,106 @@ optional class PacketPlayOutCustomSoundEffect extends Packet {
#endif
#if version >= 1.17
private (String) SoundCategory category:source;
private int x;
private int y;
private int z;
private float volume;
#else
private (String) SoundCategory category:b;
private int x:c;
private int y:d;
private int z:e;
#elseif version >= 1.9
private float volume:f;
#else
private float volume:e;
#endif
#if version >= 1.17
private optional float opt_pitch_float:pitch;
private optional int opt_pitch_integer:###;
#elseif version >= 1.10.2
private optional float opt_pitch_float:g;
private optional int opt_pitch_integer:###;
#if version >= 1.19.3
// Note: is PacketPlayOutNamedSoundEffect
public static (PacketPlayOutCustomSoundEffectHandle) PacketPlayOutCustomSoundEffect createNew((com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) net.minecraft.core.Holder<net.minecraft.sounds.SoundEffect> soundEffect, (String) SoundCategory category, double x, double y, double z, float volume, float pitch, long randomSeed) {
return new PacketPlayOutCustomSoundEffect(soundEffect, category, x, y, z, volume, pitch, randomSeed);
}
#elseif version >= 1.13
public static (PacketPlayOutCustomSoundEffectHandle) PacketPlayOutCustomSoundEffect createNew((com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) net.minecraft.resources.MinecraftKey soundEffect, (String) SoundCategory category, double x, double y, double z, float volume, float pitch, long randomSeed) {
#if version >= 1.19
return new PacketPlayOutCustomSoundEffect(soundEffect, category, new Vec3D(x, y, z), volume, pitch, randomSeed);
#else
return new PacketPlayOutCustomSoundEffect(soundEffect, category, new Vec3D(x, y, z), volume, pitch);
#endif
}
#elseif version >= 1.9
public static (PacketPlayOutCustomSoundEffectHandle) PacketPlayOutCustomSoundEffect createNew((com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) String soundEffect, (String) SoundCategory category, double x, double y, double z, float volume, float pitch, long randomSeed) {
return new PacketPlayOutCustomSoundEffect(soundEffect, category, x, y, z, volume, pitch);
}
#else
private optional float opt_pitch_float:###;
private optional int opt_pitch_integer:g;
// Note: no sound category supported. Is PacketPlayOutNamedSoundEffect
public static (PacketPlayOutCustomSoundEffectHandle) PacketPlayOutCustomSoundEffect createNew((com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect>) String soundEffect, (String) String category, double x, double y, double z, float volume, float pitch, long randomSeed) {
return new PacketPlayOutCustomSoundEffect(soundEffect, x, y, z, volume, pitch);
}
#endif
<code>
public void setPitch(float pitch) {
if (T.opt_pitch_float.isAvailable()) {
T.opt_pitch_float.setFloat(getRaw(), pitch);
} else {
T.opt_pitch_integer.setInteger(getRaw(), (int) (pitch * 63.0f));
}
public static PacketPlayOutCustomSoundEffectHandle createNew(com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect> soundEffect, String category, org.bukkit.Location location, float volume, float pitch) {
return createNew(soundEffect, category, location.getWorld(), location.getX(), location.getY(), location.getZ(), volume, pitch);
}
public float getPitch() {
if (T.opt_pitch_float.isAvailable()) {
return T.opt_pitch_float.getFloat(getRaw());
} else {
return (float) T.opt_pitch_integer.getInteger(getRaw()) / 63.0f;
}
public static PacketPlayOutCustomSoundEffectHandle createNew(com.bergerkiller.bukkit.common.resources.ResourceKey<com.bergerkiller.bukkit.common.resources.SoundEffect> soundEffect, String category, org.bukkit.World world, double x, double y, double z, float volume, float pitch) {
long randomSeed = com.bergerkiller.bukkit.common.utils.WorldUtil.getRandom(world).nextLong();
return createNew(soundEffect, category, x, y, z, volume, pitch, randomSeed);
}
</code>
#if version >= 1.17
#require PacketPlayOutCustomSoundEffect private (String) SoundCategory customSoundCategory:source;
#require PacketPlayOutCustomSoundEffect private int customSoundX:x;
#require PacketPlayOutCustomSoundEffect private int customSoundY:y;
#require PacketPlayOutCustomSoundEffect private int customSoundZ:z;
#require PacketPlayOutCustomSoundEffect private float customSoundPitch:pitch;
#elseif version >= 1.9
#require PacketPlayOutCustomSoundEffect private (String) SoundCategory customSoundCategory:b;
#require PacketPlayOutCustomSoundEffect private int customSoundX:c;
#require PacketPlayOutCustomSoundEffect private int customSoundY:d;
#require PacketPlayOutCustomSoundEffect private int customSoundZ:e;
#if version <= 1.10.2
#require PacketPlayOutCustomSoundEffect private float customSoundPitch:g;
#else
#require PacketPlayOutCustomSoundEffect private int customSoundPitchInt:g;
#endif
#else
#require PacketPlayOutCustomSoundEffect private int customSoundX:b;
#require PacketPlayOutCustomSoundEffect private int customSoundY:c;
#require PacketPlayOutCustomSoundEffect private int customSoundZ:d;
#require PacketPlayOutCustomSoundEffect private int customSoundPitchInt:f;
#endif
// Category supported since 1.9
#if version >= 1.9
public String getCategory() { return instance#customSoundCategory; }
public void setCategory(String category) { instance#customSoundCategory = category; }
#else
public String getCategory() { return "master"; }
public void setCategory(String category) { /* No-op */ }
#endif
// x/y/z fields are encoded as int fields x8 scale
public double getX() { return (double) instance#customSoundX / 8.0; }
public double getY() { return (double) instance#customSoundY / 8.0; }
public double getZ() { return (double) instance#customSoundZ / 8.0; }
public void setX(double x) { instance#customSoundX = (int)(x*8.0); }
public void setY(double y) { instance#customSoundY = (int)(y*8.0); }
public void setZ(double z) { instance#customSoundZ = (int)(z*8.0); }
// For whatever ungodly reason Pitch was encoded as int at one point
#if version >= 1.10.2
public void setPitch(float pitch) { instance#customSoundPitch = pitch; }
public float getPitch() { return instance#customSoundPitch; }
#else
public void setPitch(float pitch) { instance#customSoundPitchInt = (int)(pitch*63.0f); }
public float getPitch() { return (float) instance#customSoundPitchInt / 63.0f; }
#endif
// New 'seed' field since 1.19
#if version >= 1.19
#require PacketPlayOutCustomSoundEffect private final long customSoundSeed:seed;
public long getRandomSeed() { return instance#customSoundSeed; }
public void setRandomSeed(long seed) { instance#customSoundSeed = seed; }
#else
public long getRandomSeed() { return 0L; }
public void setRandomSeed(long seed) { /* No-op */ }
#endif
}
class PacketPlayInSteerVehicle extends Packet {