Get sound working
This commit is contained in:
parent
185822a5fe
commit
4b5f07b37c
@ -19,7 +19,8 @@ public class NativePatchBukkit {
|
|||||||
private static MethodHandle getWorldNative;
|
private static MethodHandle getWorldNative;
|
||||||
private static MethodHandle freeStringNative;
|
private static MethodHandle freeStringNative;
|
||||||
private static MethodHandle getRegistryDataNative;
|
private static MethodHandle getRegistryDataNative;
|
||||||
private static MethodHandle entityPlaySoundNative;
|
private static MethodHandle playerEntityPlaySoundNative;
|
||||||
|
private static MethodHandle playerPlaySoundNative;
|
||||||
|
|
||||||
// Struct layout matching Rust's #[repr(C)] AbilitiesFFI
|
// Struct layout matching Rust's #[repr(C)] AbilitiesFFI
|
||||||
private static final StructLayout ABILITIES_LAYOUT =
|
private static final StructLayout ABILITIES_LAYOUT =
|
||||||
@ -188,7 +189,8 @@ public class NativePatchBukkit {
|
|||||||
long freeStringAddr,
|
long freeStringAddr,
|
||||||
long getWorldAddr,
|
long getWorldAddr,
|
||||||
long getRegistryDataAddr,
|
long getRegistryDataAddr,
|
||||||
long entityPlaySoundAddr
|
long playerEntityPlaySoundAddr,
|
||||||
|
long playerPlaySoundAddr
|
||||||
) {
|
) {
|
||||||
// void rust_send_message(const char* uuid, const char* message)
|
// void rust_send_message(const char* uuid, const char* message)
|
||||||
sendMessageNative = LINKER.downcallHandle(
|
sendMessageNative = LINKER.downcallHandle(
|
||||||
@ -250,10 +252,10 @@ public class NativePatchBukkit {
|
|||||||
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS)
|
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS)
|
||||||
);
|
);
|
||||||
|
|
||||||
// void rust_entity_play_sound(const char* player_uuid, const char* sound_name,
|
// void rust_player_entity_play_sound(const char* player_uuid, const char* sound_name,
|
||||||
// const char* sound_category, const char* entity_uuid, float volume, float pitch)
|
// const char* sound_category, const char* entity_uuid, float volume, float pitch)
|
||||||
entityPlaySoundNative = LINKER.downcallHandle(
|
playerEntityPlaySoundNative = LINKER.downcallHandle(
|
||||||
MemorySegment.ofAddress(entityPlaySoundAddr),
|
MemorySegment.ofAddress(playerEntityPlaySoundAddr),
|
||||||
FunctionDescriptor.ofVoid(
|
FunctionDescriptor.ofVoid(
|
||||||
ValueLayout.ADDRESS, // player_uuid
|
ValueLayout.ADDRESS, // player_uuid
|
||||||
ValueLayout.ADDRESS, // sound_name
|
ValueLayout.ADDRESS, // sound_name
|
||||||
@ -263,6 +265,22 @@ public class NativePatchBukkit {
|
|||||||
ValueLayout.JAVA_FLOAT // pitch
|
ValueLayout.JAVA_FLOAT // pitch
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// void rust_player_play_sound(const char* player_uuid, const char* sound_name,
|
||||||
|
// const char* sound_category, double x, double y, double z, float volume, float pitch)
|
||||||
|
playerPlaySoundNative = LINKER.downcallHandle(
|
||||||
|
MemorySegment.ofAddress(playerPlaySoundAddr),
|
||||||
|
FunctionDescriptor.ofVoid(
|
||||||
|
ValueLayout.ADDRESS, // player_uuid
|
||||||
|
ValueLayout.ADDRESS, // sound_name
|
||||||
|
ValueLayout.ADDRESS, // sound_category
|
||||||
|
ValueLayout.JAVA_DOUBLE, // x
|
||||||
|
ValueLayout.JAVA_DOUBLE, // y
|
||||||
|
ValueLayout.JAVA_DOUBLE, // z
|
||||||
|
ValueLayout.JAVA_FLOAT, // volume
|
||||||
|
ValueLayout.JAVA_FLOAT // pitch
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -457,7 +475,7 @@ public class NativePatchBukkit {
|
|||||||
* @param volume Volume (1.0 = normal)
|
* @param volume Volume (1.0 = normal)
|
||||||
* @param pitch Pitch (1.0 = normal)
|
* @param pitch Pitch (1.0 = normal)
|
||||||
*/
|
*/
|
||||||
public static void entityPlaySound(
|
public static void playerEntityPlaySound(
|
||||||
UUID playerUuid,
|
UUID playerUuid,
|
||||||
String soundName,
|
String soundName,
|
||||||
String soundCategory,
|
String soundCategory,
|
||||||
@ -471,7 +489,7 @@ public class NativePatchBukkit {
|
|||||||
MemorySegment soundCategoryStr = arena.allocateFrom(soundCategory);
|
MemorySegment soundCategoryStr = arena.allocateFrom(soundCategory);
|
||||||
MemorySegment entityUuidStr = arena.allocateFrom(entityUuid.toString());
|
MemorySegment entityUuidStr = arena.allocateFrom(entityUuid.toString());
|
||||||
|
|
||||||
entityPlaySoundNative.invokeExact(
|
playerEntityPlaySoundNative.invokeExact(
|
||||||
playerUuidStr,
|
playerUuidStr,
|
||||||
soundNameStr,
|
soundNameStr,
|
||||||
soundCategoryStr,
|
soundCategoryStr,
|
||||||
@ -483,4 +501,46 @@ public class NativePatchBukkit {
|
|||||||
throw new RuntimeException("Failed to call native entityPlaySound", t);
|
throw new RuntimeException("Failed to call native entityPlaySound", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play a sound effect at a location, heard by a specific player.
|
||||||
|
*
|
||||||
|
* @param playerUuid The player who will hear the sound
|
||||||
|
* @param soundName Sound identifier (e.g. "block.note_block.chime")
|
||||||
|
* @param soundCategory Category name (e.g. "master", "music", "blocks")
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
* @param z Z coordinate
|
||||||
|
* @param volume Volume (1.0 = normal)
|
||||||
|
* @param pitch Pitch (1.0 = normal)
|
||||||
|
*/
|
||||||
|
public static void playerPlaySound(
|
||||||
|
UUID playerUuid,
|
||||||
|
String soundName,
|
||||||
|
String soundCategory,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double z,
|
||||||
|
float volume,
|
||||||
|
float pitch
|
||||||
|
) {
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment playerUuidStr = arena.allocateFrom(playerUuid.toString());
|
||||||
|
MemorySegment soundNameStr = arena.allocateFrom(soundName);
|
||||||
|
MemorySegment soundCategoryStr = arena.allocateFrom(soundCategory);
|
||||||
|
|
||||||
|
playerPlaySoundNative.invokeExact(
|
||||||
|
playerUuidStr,
|
||||||
|
soundNameStr,
|
||||||
|
soundCategoryStr,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z,
|
||||||
|
volume,
|
||||||
|
pitch
|
||||||
|
);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new RuntimeException("Failed to call native playerPlaySound", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,6 +62,7 @@ import org.jetbrains.annotations.Unmodifiable;
|
|||||||
import org.jetbrains.annotations.UnmodifiableView;
|
import org.jetbrains.annotations.UnmodifiableView;
|
||||||
import org.patchbukkit.PatchBukkitServer;
|
import org.patchbukkit.PatchBukkitServer;
|
||||||
import org.patchbukkit.bridge.NativePatchBukkit;
|
import org.patchbukkit.bridge.NativePatchBukkit;
|
||||||
|
import org.patchbukkit.registry.PatchBukkitSound;
|
||||||
|
|
||||||
import com.destroystokyo.paper.ClientOption;
|
import com.destroystokyo.paper.ClientOption;
|
||||||
import com.destroystokyo.paper.Title;
|
import com.destroystokyo.paper.Title;
|
||||||
@ -685,14 +686,13 @@ public class PatchBukkitPlayer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playSound(Location location, Sound sound, SoundCategory category, float volume, float pitch) {
|
public void playSound(Location location, Sound sound, SoundCategory category, float volume, float pitch) {
|
||||||
// TODO Auto-generated method stub
|
var patchBukkitSound = (PatchBukkitSound) sound;
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'playSound'");
|
NativePatchBukkit.playerPlaySound(this.uuid, patchBukkitSound.getOriginalName(), category.name(), location.x(), location.y(), location.z(), volume, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playSound(Location location, String sound, SoundCategory category, float volume, float pitch) {
|
public void playSound(Location location, String sound, SoundCategory category, float volume, float pitch) {
|
||||||
// TODO Auto-generated method stub
|
NativePatchBukkit.playerPlaySound(this.uuid, sound, category.name(), location.x(), location.y(), location.z(), volume, pitch);
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'playSound'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -711,13 +711,13 @@ public class PatchBukkitPlayer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playSound(Entity entity, Sound sound, SoundCategory category, float volume, float pitch) {
|
public void playSound(Entity entity, Sound sound, SoundCategory category, float volume, float pitch) {
|
||||||
NativePatchBukkit.entityPlaySound(this.uuid, sound.toString(), category.name(), entity.getUniqueId(), volume, pitch);
|
var patchBukkitSound = (PatchBukkitSound) sound;
|
||||||
|
NativePatchBukkit.playerEntityPlaySound(this.uuid, patchBukkitSound.getOriginalName(), category.name(), entity.getUniqueId(), volume, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playSound(Entity entity, String sound, SoundCategory category, float volume, float pitch) {
|
public void playSound(Entity entity, String sound, SoundCategory category, float volume, float pitch) {
|
||||||
// TODO Auto-generated method stub
|
NativePatchBukkit.playerEntityPlaySound(this.uuid, sound, category.name(), entity.getUniqueId(), volume, pitch);
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'playSound'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -9,15 +9,21 @@ public class PatchBukkitSound implements Sound {
|
|||||||
private final NamespacedKey namespacedKey;
|
private final NamespacedKey namespacedKey;
|
||||||
private final Key adventureKey;
|
private final Key adventureKey;
|
||||||
private final String enumName;
|
private final String enumName;
|
||||||
|
private final String originalName;
|
||||||
private final int protocolId;
|
private final int protocolId;
|
||||||
|
|
||||||
public PatchBukkitSound(String soundName, int protocolId) {
|
public PatchBukkitSound(String soundName, int protocolId) {
|
||||||
this.namespacedKey = new NamespacedKey(NamespacedKey.MINECRAFT, soundName);
|
this.namespacedKey = new NamespacedKey(NamespacedKey.MINECRAFT, soundName);
|
||||||
this.adventureKey = Key.key(Key.MINECRAFT_NAMESPACE, soundName);
|
this.adventureKey = Key.key(Key.MINECRAFT_NAMESPACE, soundName);
|
||||||
this.protocolId = protocolId;
|
this.protocolId = protocolId;
|
||||||
|
this.originalName = soundName;
|
||||||
this.enumName = soundName.toUpperCase().replace('.', '_');
|
this.enumName = soundName.toUpperCase().replace('.', '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOriginalName() {
|
||||||
|
return originalName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamespacedKey getKey() {
|
public NamespacedKey getKey() {
|
||||||
return namespacedKey;
|
return namespacedKey;
|
||||||
|
|||||||
@ -45,7 +45,9 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
|
|||||||
let free_string_addr = memory::rust_free_string as *const () as i64;
|
let free_string_addr = memory::rust_free_string as *const () as i64;
|
||||||
let get_world_addr = world::rust_get_world as *const () as i64;
|
let get_world_addr = world::rust_get_world as *const () as i64;
|
||||||
let rust_get_registry_data_addr = registry::rust_get_registry_data as *const () as i64;
|
let rust_get_registry_data_addr = registry::rust_get_registry_data as *const () as i64;
|
||||||
let rust_entity_play_sound_addr = sound::rust_entity_play_sound as *const () as i64;
|
let rust_player_entity_play_sound_addr =
|
||||||
|
sound::rust_player_entity_play_sound as *const () as i64;
|
||||||
|
let rust_player_play_sound_addr = sound::rust_player_play_sound as *const () as i64;
|
||||||
|
|
||||||
jvm.invoke_static(
|
jvm.invoke_static(
|
||||||
"org.patchbukkit.bridge.NativePatchBukkit",
|
"org.patchbukkit.bridge.NativePatchBukkit",
|
||||||
@ -59,7 +61,8 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
|
|||||||
InvocationArg::try_from(free_string_addr)?.into_primitive()?,
|
InvocationArg::try_from(free_string_addr)?.into_primitive()?,
|
||||||
InvocationArg::try_from(get_world_addr)?.into_primitive()?,
|
InvocationArg::try_from(get_world_addr)?.into_primitive()?,
|
||||||
InvocationArg::try_from(rust_get_registry_data_addr)?.into_primitive()?,
|
InvocationArg::try_from(rust_get_registry_data_addr)?.into_primitive()?,
|
||||||
InvocationArg::try_from(rust_entity_play_sound_addr)?.into_primitive()?,
|
InvocationArg::try_from(rust_player_entity_play_sound_addr)?.into_primitive()?,
|
||||||
|
InvocationArg::try_from(rust_player_play_sound_addr)?.into_primitive()?,
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
use std::ffi::{c_char, c_float};
|
use std::ffi::{c_char, c_double, c_float};
|
||||||
|
|
||||||
use pumpkin::command::args::entities::{EntitySelectorType, TargetSelector};
|
use pumpkin::command::args::entities::{EntitySelectorType, TargetSelector};
|
||||||
use pumpkin_data::sound::{Sound, SoundCategory};
|
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||||
use pumpkin_protocol::{IdOr, java::client::play::CEntitySoundEffect};
|
use pumpkin_protocol::{IdOr, java::client::play::CEntitySoundEffect};
|
||||||
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use rand::{RngExt, rng};
|
use rand::{RngExt, rng};
|
||||||
|
|
||||||
use crate::java::native_callbacks::{CALLBACK_CONTEXT, utils::get_string};
|
use crate::java::native_callbacks::{CALLBACK_CONTEXT, utils::get_string};
|
||||||
|
|
||||||
pub extern "C" fn rust_entity_play_sound(
|
pub extern "C" fn rust_player_entity_play_sound(
|
||||||
player_uuid_ptr: *const c_char,
|
player_uuid_ptr: *const c_char,
|
||||||
sound_name_ptr: *const c_char,
|
sound_name_ptr: *const c_char,
|
||||||
sound_category_ptr: *const c_char,
|
sound_category_ptr: *const c_char,
|
||||||
@ -65,3 +66,46 @@ pub extern "C" fn rust_entity_play_sound(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub extern "C" fn rust_player_play_sound(
|
||||||
|
player_uuid_ptr: *const c_char,
|
||||||
|
sound_name_ptr: *const c_char,
|
||||||
|
sound_category_ptr: *const c_char,
|
||||||
|
x: c_double,
|
||||||
|
y: c_double,
|
||||||
|
z: c_double,
|
||||||
|
volume: c_float,
|
||||||
|
pitch: c_float,
|
||||||
|
) {
|
||||||
|
let player_uuid_str = get_string(player_uuid_ptr);
|
||||||
|
let sound_name = get_string(sound_name_ptr);
|
||||||
|
let sound_category = get_string(sound_category_ptr);
|
||||||
|
|
||||||
|
if let Some(ctx) = CALLBACK_CONTEXT.get() {
|
||||||
|
let player_uuid = uuid::Uuid::parse_str(&player_uuid_str).unwrap();
|
||||||
|
|
||||||
|
ctx.runtime.spawn(async move {
|
||||||
|
let player = ctx.plugin_context.server.get_player_by_uuid(player_uuid);
|
||||||
|
|
||||||
|
if let Some(player) = player {
|
||||||
|
let sound = match Sound::from_name(&sound_name) {
|
||||||
|
Some(sound) => sound,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let category = match SoundCategory::from_name(&sound_category.to_lowercase()) {
|
||||||
|
Some(category) => category,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let seed = rng().random::<f64>();
|
||||||
|
|
||||||
|
let position: Vector3<f64> = Vector3::new(x, y, z);
|
||||||
|
|
||||||
|
player
|
||||||
|
.play_sound(sound as u16, category, &position, volume, pitch, seed)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::Result;
|
||||||
use rust_embed::Embed;
|
use rust_embed::Embed;
|
||||||
|
|
||||||
#[derive(Embed)]
|
#[derive(Embed)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user