update to latest pumpkin
This commit is contained in:
parent
9ec7a3d08e
commit
9d23556460
940
rust/Cargo.lock
generated
940
rust/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,19 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use pumpkin::{
|
use pumpkin::{
|
||||||
command::{
|
command::{
|
||||||
CommandExecutor, CommandSender,
|
CommandExecutor, CommandExecutorResult, CommandSender,
|
||||||
args::{Arg, ArgumentConsumer, GetClientSideArgParser, SuggestResult},
|
argument_builder::{ArgumentBuilder, CommandArgumentBuilder, argument, command},
|
||||||
tree::{CommandTree, builder::argument},
|
argument_types::core::string::StringArgumentType,
|
||||||
|
context::command_context::CommandContext,
|
||||||
|
suggestion::{
|
||||||
|
provider::SuggestionProvider,
|
||||||
|
suggestions::{Suggestions, SuggestionsBuilder},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
entity::EntityBase,
|
entity::EntityBase,
|
||||||
};
|
};
|
||||||
use pumpkin_protocol::java::client::play::{
|
|
||||||
ArgumentType, StringProtoArgBehavior, SuggestionProviders,
|
|
||||||
};
|
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use crate::java::jvm::commands::{JvmCommand, Location, Rotation};
|
use crate::java::jvm::commands::{JvmCommand, Location, Rotation};
|
||||||
@ -29,48 +32,16 @@ pub enum SimpleCommandSender {
|
|||||||
Player(String, String, bool),
|
Player(String, String, bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AnyCommandNode {
|
pub struct JavaSuggestionProvider {
|
||||||
command_tx: mpsc::Sender<JvmCommand>,
|
pub command_tx: mpsc::Sender<JvmCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetClientSideArgParser for AnyCommandNode {
|
impl SuggestionProvider for JavaSuggestionProvider {
|
||||||
fn get_client_side_parser(&self) -> ArgumentType {
|
fn suggest(&self, context: &CommandContext, mut builder: SuggestionsBuilder) -> Suggestions {
|
||||||
ArgumentType::String(StringProtoArgBehavior::GreedyPhrase)
|
let sender = &context.source.output;
|
||||||
}
|
let location = if let Some(world) = &context.source.world {
|
||||||
|
let position = context.source.position;
|
||||||
fn get_client_side_suggestion_type_override(&self) -> Option<SuggestionProviders> {
|
let rotation = if let Some(player) = context.source.as_player() {
|
||||||
Some(SuggestionProviders::AskServer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ArgumentConsumer for AnyCommandNode {
|
|
||||||
fn consume<'a>(
|
|
||||||
&'a self,
|
|
||||||
_sender: &'a pumpkin::command::CommandSender,
|
|
||||||
_server: &'a pumpkin::server::Server,
|
|
||||||
args: &mut pumpkin::command::tree::RawArgs<'a>,
|
|
||||||
) -> pumpkin::command::args::ConsumeResult<'a> {
|
|
||||||
let first_word = args.pop()?;
|
|
||||||
let mut msg = first_word.value.to_string();
|
|
||||||
|
|
||||||
while let Some(word) = args.pop() {
|
|
||||||
msg.push(' ');
|
|
||||||
msg.push_str(word.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Arg::Msg(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn suggest(
|
|
||||||
&self,
|
|
||||||
sender: &pumpkin::command::CommandSender,
|
|
||||||
_server: &pumpkin::server::Server,
|
|
||||||
input: &str,
|
|
||||||
) -> SuggestResult {
|
|
||||||
let location = if let Some(position) = sender.position()
|
|
||||||
&& let Some(world) = sender.world()
|
|
||||||
{
|
|
||||||
let rotation = if let Some(player) = sender.as_player() {
|
|
||||||
let entity = player.get_entity();
|
let entity = player.get_entity();
|
||||||
let yaw = entity.yaw.load();
|
let yaw = entity.yaw.load();
|
||||||
let pitch = entity.pitch.load();
|
let pitch = entity.pitch.load();
|
||||||
@ -87,8 +58,9 @@ impl ArgumentConsumer for AnyCommandNode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let command_sender: SimpleCommandSender = sender.into();
|
let command_sender: SimpleCommandSender = sender.into();
|
||||||
|
let full_command = builder.input.clone();
|
||||||
|
|
||||||
if let Ok(handle) = tokio::runtime::Handle::try_current() {
|
let res = if let Ok(handle) = tokio::runtime::Handle::try_current() {
|
||||||
tokio::task::block_in_place(|| {
|
tokio::task::block_in_place(|| {
|
||||||
handle.block_on(async move {
|
handle.block_on(async move {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
@ -96,20 +68,17 @@ impl ArgumentConsumer for AnyCommandNode {
|
|||||||
.command_tx
|
.command_tx
|
||||||
.send(JvmCommand::GetCommandTabComplete {
|
.send(JvmCommand::GetCommandTabComplete {
|
||||||
command_sender,
|
command_sender,
|
||||||
full_command: input.to_string(),
|
full_command,
|
||||||
respond_to: tx,
|
respond_to: tx,
|
||||||
location,
|
location,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
tracing::warn!("Failed to send tab complete to JVM worker: {e}");
|
tracing::warn!("Failed to send tab complete to JVM worker: {e}");
|
||||||
return Ok(None);
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match rx.await {
|
rx.await.unwrap_or(None)
|
||||||
Ok(res) => res,
|
|
||||||
Err(_) => Ok(None),
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -118,20 +87,29 @@ impl ArgumentConsumer for AnyCommandNode {
|
|||||||
.command_tx
|
.command_tx
|
||||||
.blocking_send(JvmCommand::GetCommandTabComplete {
|
.blocking_send(JvmCommand::GetCommandTabComplete {
|
||||||
command_sender,
|
command_sender,
|
||||||
full_command: input.to_string(),
|
full_command,
|
||||||
respond_to: tx,
|
respond_to: tx,
|
||||||
location,
|
location,
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
tracing::warn!("Failed to send tab complete to JVM worker: {e}");
|
tracing::warn!("Failed to send tab complete to JVM worker: {e}");
|
||||||
return Ok(None);
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
match rx.blocking_recv() {
|
rx.blocking_recv().unwrap_or(None)
|
||||||
Ok(res) => res,
|
};
|
||||||
Err(_) => Ok(None),
|
|
||||||
|
if let Some(suggestions) = res {
|
||||||
|
for item in suggestions {
|
||||||
|
if let Some(tooltip) = item.tooltip {
|
||||||
|
builder = builder.suggest_with_tooltip(item.suggestion, tooltip);
|
||||||
|
} else {
|
||||||
|
builder = builder.suggest(item.suggestion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,25 +132,20 @@ impl From<&CommandSender> for SimpleCommandSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CommandExecutor for JavaCommandExecutor {
|
impl CommandExecutor for JavaCommandExecutor {
|
||||||
fn execute(
|
fn execute(&self, context: &CommandContext) -> CommandExecutorResult {
|
||||||
&self,
|
if let CommandSender::Player(player) = &context.source.output {
|
||||||
sender: &pumpkin::command::CommandSender,
|
|
||||||
_server: &pumpkin::server::Server,
|
|
||||||
args: &pumpkin::command::args::ConsumedArgs,
|
|
||||||
) -> pumpkin::command::CommandResult {
|
|
||||||
if let CommandSender::Player(player) = sender {
|
|
||||||
crate::java::native_callbacks::utils::cache_player(player.clone());
|
crate::java::native_callbacks::utils::cache_player(player.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let full_command = match args.get(ARG_ANY) {
|
let full_command = match context.get_argument::<String>(ARG_ANY) {
|
||||||
Some(Arg::Msg(msg)) => {
|
Ok(msg) => {
|
||||||
if self.cmd_name.starts_with('/') {
|
if self.cmd_name.starts_with('/') {
|
||||||
format!("{} {}", self.cmd_name, msg)
|
format!("{} {}", self.cmd_name, msg)
|
||||||
} else {
|
} else {
|
||||||
format!("/{} {}", self.cmd_name, msg)
|
format!("/{} {}", self.cmd_name, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
Err(_) => {
|
||||||
if self.cmd_name.starts_with('/') {
|
if self.cmd_name.starts_with('/') {
|
||||||
self.cmd_name.clone()
|
self.cmd_name.clone()
|
||||||
} else {
|
} else {
|
||||||
@ -181,7 +154,7 @@ impl CommandExecutor for JavaCommandExecutor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let command_sender: SimpleCommandSender = sender.into();
|
let command_sender: SimpleCommandSender = (&context.source.output).into();
|
||||||
|
|
||||||
if let Ok(handle) = tokio::runtime::Handle::try_current() {
|
if let Ok(handle) = tokio::runtime::Handle::try_current() {
|
||||||
tokio::task::block_in_place(|| {
|
tokio::task::block_in_place(|| {
|
||||||
@ -224,26 +197,20 @@ impl CommandExecutor for JavaCommandExecutor {
|
|||||||
pub fn init_java_command(
|
pub fn init_java_command(
|
||||||
cmd_name: impl Into<String>,
|
cmd_name: impl Into<String>,
|
||||||
command_tx: mpsc::Sender<JvmCommand>,
|
command_tx: mpsc::Sender<JvmCommand>,
|
||||||
names: impl IntoIterator<Item: Into<String>>,
|
|
||||||
description: impl Into<Cow<'static, str>>,
|
description: impl Into<Cow<'static, str>>,
|
||||||
) -> CommandTree {
|
) -> CommandArgumentBuilder {
|
||||||
let cmd_name = cmd_name.into();
|
let cmd_name = cmd_name.into();
|
||||||
CommandTree::new(names, description)
|
let executor = Arc::new(JavaCommandExecutor {
|
||||||
.execute(JavaCommandExecutor {
|
cmd_name: cmd_name.clone(),
|
||||||
cmd_name: cmd_name.clone(),
|
command_tx: command_tx.clone(),
|
||||||
command_tx: command_tx.clone(),
|
});
|
||||||
})
|
|
||||||
|
command(cmd_name, description)
|
||||||
|
.executes_arc(executor.clone())
|
||||||
.then(
|
.then(
|
||||||
argument(
|
argument(ARG_ANY, StringArgumentType::GreedyPhrase)
|
||||||
ARG_ANY,
|
.suggests(JavaSuggestionProvider { command_tx })
|
||||||
AnyCommandNode {
|
.executes_arc(executor),
|
||||||
command_tx: command_tx.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.execute(JavaCommandExecutor {
|
|
||||||
cmd_name,
|
|
||||||
command_tx,
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,12 +224,12 @@ mod tests {
|
|||||||
let mut dispatcher = CommandDispatcher::default();
|
let mut dispatcher = CommandDispatcher::default();
|
||||||
|
|
||||||
let (tx, _rx) = mpsc::channel(100);
|
let (tx, _rx) = mpsc::channel(100);
|
||||||
let names = vec!["fly".to_string(), "/fly".to_string(), "//fly".to_string()];
|
let aliases = vec!["/fly".to_string(), "//fly".to_string()];
|
||||||
let tree = init_java_command("fly", tx, names, "Fly command");
|
let builder = init_java_command("fly", tx, "Fly command");
|
||||||
dispatcher.register(tree, "patchbukkit:command.fly");
|
dispatcher.register_with_aliases(builder, &aliases);
|
||||||
|
|
||||||
assert!(dispatcher.get_tree("fly").is_ok());
|
assert!(dispatcher.has_command("fly"));
|
||||||
assert!(dispatcher.get_tree("/fly").is_ok());
|
assert!(dispatcher.has_command("/fly"));
|
||||||
assert!(dispatcher.get_tree("//fly").is_ok());
|
assert!(dispatcher.has_command("//fly"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::{path::PathBuf, sync::Arc};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pumpkin::{command::dispatcher::CommandError, plugin::Context};
|
use pumpkin::plugin::Context;
|
||||||
use pumpkin_protocol::java::client::play::CommandSuggestion;
|
use pumpkin_protocol::java::client::play::CommandSuggestion;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -61,7 +61,7 @@ pub enum JvmCommand {
|
|||||||
GetCommandTabComplete {
|
GetCommandTabComplete {
|
||||||
command_sender: SimpleCommandSender,
|
command_sender: SimpleCommandSender,
|
||||||
full_command: String,
|
full_command: String,
|
||||||
respond_to: oneshot::Sender<Result<Option<Vec<CommandSuggestion>>, CommandError>>,
|
respond_to: oneshot::Sender<Option<Vec<CommandSuggestion>>>,
|
||||||
location: Option<Location>,
|
location: Option<Location>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -219,11 +219,11 @@ impl JvmWorker {
|
|||||||
Ok(inner_res) => inner_res,
|
Ok(inner_res) => inner_res,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Failed to get tab complete: {e}");
|
tracing::error!("Failed to get tab complete: {e}");
|
||||||
Ok(None)
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = respond_to.send(res);
|
let _ = respond_to.send(res);
|
||||||
|
|||||||
@ -47,7 +47,14 @@ pub fn ffi_native_bridge_register_command_impl(request: RegisterCommandRequest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = init_java_command(cmd_name.clone(), command_tx, names.clone(), description);
|
let primary_name = cmd_name.trim_start_matches('/').to_string();
|
||||||
|
let alias_names: Vec<String> = names
|
||||||
|
.iter()
|
||||||
|
.filter(|n| *n != &primary_name)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let node = init_java_command(primary_name.clone(), command_tx, description);
|
||||||
|
|
||||||
let clean_perm = cmd_name.trim_start_matches('/');
|
let clean_perm = cmd_name.trim_start_matches('/');
|
||||||
let permission = format!("patchbukkit:command.{clean_perm}");
|
let permission = format!("patchbukkit:command.{clean_perm}");
|
||||||
@ -62,7 +69,7 @@ pub fn ffi_native_bridge_register_command_impl(request: RegisterCommandRequest)
|
|||||||
tracing::debug!("Permission '{}' registration notice: {}", permission, e);
|
tracing::debug!("Permission '{}' registration notice: {}", permission, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_context.register_command(node, permission.clone());
|
plugin_context.register_command_with_aliases(node, &alias_names, permission.clone());
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"Successfully registered command '{}' with names {:?} and permission '{}'",
|
"Successfully registered command '{}' with names {:?} and permission '{}'",
|
||||||
|
|||||||
@ -322,7 +322,7 @@ pub fn ffi_native_bridge_set_player_list_header_footer_impl(
|
|||||||
ctx.runtime.spawn(async move {
|
ctx.runtime.spawn(async move {
|
||||||
let h = pumpkin_util::text::TextComponent::from_legacy_string(&header);
|
let h = pumpkin_util::text::TextComponent::from_legacy_string(&header);
|
||||||
let f = pumpkin_util::text::TextComponent::from_legacy_string(&footer);
|
let f = pumpkin_util::text::TextComponent::from_legacy_string(&footer);
|
||||||
player.set_tab_list_header_footer(h, f).await;
|
player.set_tab_list_header_footer(&h, &f);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use pumpkin::command::args::entities::{EntitySelectorType, TargetSelector};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
java::native_callbacks::CALLBACK_CONTEXT,
|
java::native_callbacks::CALLBACK_CONTEXT,
|
||||||
proto::patchbukkit::common::{Location, Uuid, Vec3, World},
|
proto::patchbukkit::common::{Location, Uuid, Vec3, World},
|
||||||
@ -19,30 +17,29 @@ pub fn ffi_native_bridge_get_location_impl(entity_uuid: Uuid) -> Option<Location
|
|||||||
let entity = ctx
|
let entity = ctx
|
||||||
.plugin_context
|
.plugin_context
|
||||||
.server
|
.server
|
||||||
.select_entities(&TargetSelector::new(EntitySelectorType::Uuid(uuid)), None);
|
.worlds
|
||||||
|
.load()
|
||||||
|
.iter()
|
||||||
|
.find_map(|world| world.get_entity_by_uuid(uuid))?;
|
||||||
|
|
||||||
if entity.len() == 1 {
|
let entity = entity.get_entity();
|
||||||
let entity = entity.first().unwrap().get_entity();
|
let position = entity.pos.load();
|
||||||
let position = entity.pos.load();
|
let world = entity.world.load().uuid;
|
||||||
let world = entity.world.load().uuid;
|
let yaw = entity.yaw.load();
|
||||||
let yaw = entity.yaw.load();
|
let pitch = entity.pitch.load();
|
||||||
let pitch = entity.pitch.load();
|
|
||||||
|
|
||||||
return Some(Location {
|
Some(Location {
|
||||||
world: Some(World {
|
world: Some(World {
|
||||||
uuid: Some(Uuid {
|
uuid: Some(Uuid {
|
||||||
value: world.to_string(),
|
value: world.to_string(),
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
position: Some(Vec3 {
|
}),
|
||||||
x: position.x,
|
position: Some(Vec3 {
|
||||||
y: position.y,
|
x: position.x,
|
||||||
z: position.z,
|
y: position.y,
|
||||||
}),
|
z: position.z,
|
||||||
yaw,
|
}),
|
||||||
pitch,
|
yaw,
|
||||||
});
|
pitch,
|
||||||
}
|
})
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
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 pumpkin_util::math::vector3::Vector3;
|
||||||
@ -26,16 +25,15 @@ pub fn ffi_native_bridge_player_entity_play_sound_impl(
|
|||||||
let seed = rng().random::<i64>();
|
let seed = rng().random::<i64>();
|
||||||
|
|
||||||
ctx.runtime.spawn(async move {
|
ctx.runtime.spawn(async move {
|
||||||
let entity = ctx.plugin_context.server.select_entities(
|
let entity = ctx
|
||||||
&TargetSelector::new(EntitySelectorType::Uuid(entity_uuid)),
|
.plugin_context
|
||||||
None,
|
.server
|
||||||
);
|
.worlds
|
||||||
|
.load()
|
||||||
|
.iter()
|
||||||
|
.find_map(|world| world.get_entity_by_uuid(entity_uuid))?;
|
||||||
|
|
||||||
if entity.len() != 1 {
|
let entity = entity.get_entity();
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let entity = entity.first()?.get_entity();
|
|
||||||
|
|
||||||
player
|
player
|
||||||
.send_client_packet(&CEntitySoundEffect::new(
|
.send_client_packet(&CEntitySoundEffect::new(
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use jni::Env;
|
use jni::Env;
|
||||||
use pumpkin::command::dispatcher::CommandError;
|
|
||||||
use pumpkin_protocol::java::client::play::CommandSuggestion;
|
use pumpkin_protocol::java::client::play::CommandSuggestion;
|
||||||
|
|
||||||
use crate::{commands::SimpleCommandSender, java::jvm::commands::Location};
|
use crate::{commands::SimpleCommandSender, java::jvm::commands::Location};
|
||||||
@ -25,12 +24,12 @@ impl CommandManager {
|
|||||||
sender: SimpleCommandSender,
|
sender: SimpleCommandSender,
|
||||||
full_command: String,
|
full_command: String,
|
||||||
location: Option<Location>,
|
location: Option<Location>,
|
||||||
) -> Result<Option<Vec<CommandSuggestion>>, CommandError> {
|
) -> Option<Vec<CommandSuggestion>> {
|
||||||
match self.try_tab_complete(env, sender, full_command, location) {
|
match self.try_tab_complete(env, sender, full_command, location) {
|
||||||
Ok(suggestions) => Ok(suggestions),
|
Ok(suggestions) => suggestions,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::warn!("Tab completion failed: {e}");
|
tracing::warn!("Tab completion failed: {e}");
|
||||||
Ok(None)
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user