chore: update to latest build

This commit is contained in:
Alexander Medvedev 2026-08-27 11:31:28 +02:00
parent 46d7ee1be2
commit 4ba797cca2
10 changed files with 358 additions and 391 deletions

30
rust/Cargo.lock generated
View File

@ -696,9 +696,9 @@ dependencies = [
[[package]]
name = "combine"
version = "4.6.7"
version = "4.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
dependencies = [
"bytes",
"memchr",
@ -3512,7 +3512,7 @@ dependencies = [
[[package]]
name = "pumpkin"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"aes 0.9.2",
"arc-swap",
@ -3578,7 +3578,7 @@ dependencies = [
[[package]]
name = "pumpkin-api-macros"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"proc-macro-error2",
"proc-macro2",
@ -3589,7 +3589,7 @@ dependencies = [
[[package]]
name = "pumpkin-codecs"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"serde_json",
"tracing",
@ -3598,7 +3598,7 @@ dependencies = [
[[package]]
name = "pumpkin-config"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"pumpkin-util",
"serde",
@ -3610,7 +3610,7 @@ dependencies = [
[[package]]
name = "pumpkin-data"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"crc-fast",
"phf",
@ -3623,7 +3623,7 @@ dependencies = [
[[package]]
name = "pumpkin-inventory"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"pumpkin-data",
"pumpkin-protocol",
@ -3638,7 +3638,7 @@ dependencies = [
[[package]]
name = "pumpkin-macros"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"heck",
"proc-macro-error2",
@ -3651,7 +3651,7 @@ dependencies = [
[[package]]
name = "pumpkin-nbt"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"bytes",
"cesu8",
@ -3665,7 +3665,7 @@ dependencies = [
[[package]]
name = "pumpkin-protocol"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"aes 0.9.2",
"async-compression",
@ -3690,7 +3690,7 @@ dependencies = [
[[package]]
name = "pumpkin-util"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"base64 0.23.1",
"bytes",
@ -3716,7 +3716,7 @@ dependencies = [
[[package]]
name = "pumpkin-world"
version = "0.1.0-dev+26.2-26.40"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#d8c7c23c0bd547a72dc3df84c5e2855aba975cf8"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#3d69190a3766fd901adc6023f1c1c399d7e591bf"
dependencies = [
"arc-swap",
"bitflags 2.13.1",
@ -5359,9 +5359,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.25.0"
version = "1.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc"
checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812"
dependencies = [
"getrandom 0.4.3",
"js-sys",

View File

@ -50,27 +50,23 @@ impl ArgumentConsumer for AnyCommandNode {
_server: &'a pumpkin::server::Server,
args: &mut pumpkin::command::tree::RawArgs<'a>,
) -> pumpkin::command::args::ConsumeResult<'a> {
let first_word_opt = args.pop();
let mut msg = match first_word_opt {
Some(word) => word.value.to_string(),
None => return Box::pin(async { None }),
};
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);
}
Box::pin(async move { Some(Arg::Msg(msg)) })
Some(Arg::Msg(msg))
}
fn suggest<'a>(
&'a self,
fn suggest(
&self,
sender: &pumpkin::command::CommandSender,
_server: &'a pumpkin::server::Server,
input: &'a str,
) -> SuggestResult<'a> {
_server: &pumpkin::server::Server,
input: &str,
) -> SuggestResult {
let location = if let Some(position) = sender.position()
&& let Some(world) = sender.world()
{
@ -92,27 +88,50 @@ impl ArgumentConsumer for AnyCommandNode {
let command_sender: SimpleCommandSender = sender.into();
Box::pin(async move {
if let Ok(handle) = tokio::runtime::Handle::try_current() {
tokio::task::block_in_place(|| {
handle.block_on(async move {
let (tx, rx) = oneshot::channel();
if let Err(e) = self
.command_tx
.send(JvmCommand::GetCommandTabComplete {
command_sender,
full_command: input.to_string(),
respond_to: tx,
location,
})
.await
{
tracing::warn!("Failed to send tab complete to JVM worker: {e}");
return Ok(None);
}
match rx.await {
Ok(res) => res,
Err(_) => Ok(None),
}
})
})
} else {
let (tx, rx) = oneshot::channel();
if let Err(e) = self
.command_tx
.send(JvmCommand::GetCommandTabComplete {
.blocking_send(JvmCommand::GetCommandTabComplete {
command_sender,
full_command: input.to_string(),
respond_to: tx,
location,
})
.await
{
tracing::warn!("Failed to send tab complete to JVM worker: {e}");
return Ok(None);
}
match rx.await {
match rx.blocking_recv() {
Ok(res) => res,
Err(_) => Ok(None),
}
})
}
}
}
@ -135,51 +154,70 @@ impl From<&CommandSender> for SimpleCommandSender {
}
impl CommandExecutor for JavaCommandExecutor {
fn execute<'a>(
&'a self,
sender: &'a pumpkin::command::CommandSender,
_server: &'a pumpkin::server::Server,
args: &'a pumpkin::command::args::ConsumedArgs<'a>,
) -> pumpkin::command::CommandResult<'a> {
fn execute(
&self,
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());
}
Box::pin(async move {
let full_command = match args.get(ARG_ANY) {
Some(Arg::Msg(msg)) => {
if self.cmd_name.starts_with('/') {
format!("{} {}", self.cmd_name, msg)
} else {
format!("/{} {}", self.cmd_name, msg)
}
let full_command = match args.get(ARG_ANY) {
Some(Arg::Msg(msg)) => {
if self.cmd_name.starts_with('/') {
format!("{} {}", self.cmd_name, msg)
} else {
format!("/{} {}", self.cmd_name, msg)
}
_ => {
if self.cmd_name.starts_with('/') {
self.cmd_name.clone()
} else {
format!("/{}", self.cmd_name)
}
}
_ => {
if self.cmd_name.starts_with('/') {
self.cmd_name.clone()
} else {
format!("/{}", self.cmd_name)
}
};
}
};
let (tx, rx) = oneshot::channel();
if let Err(e) = self
.command_tx
.send(JvmCommand::TriggerCommand {
full_command,
respond_to: tx,
command_sender: sender.into(),
let command_sender: SimpleCommandSender = sender.into();
if let Ok(handle) = tokio::runtime::Handle::try_current() {
tokio::task::block_in_place(|| {
handle.block_on(async move {
let (tx, rx) = oneshot::channel();
if let Err(e) = self
.command_tx
.send(JvmCommand::TriggerCommand {
full_command,
respond_to: tx,
command_sender,
})
.await
{
tracing::error!("Failed to send command to JVM worker: {e}");
return Ok(0);
}
let _ = rx.await;
Ok(1)
})
.await
{
})
} else {
let (tx, rx) = oneshot::channel();
if let Err(e) = self.command_tx.blocking_send(JvmCommand::TriggerCommand {
full_command,
respond_to: tx,
command_sender,
}) {
tracing::error!("Failed to send command to JVM worker: {e}");
return Ok(0);
}
let _ = rx.await;
let _ = rx.blocking_recv();
Ok(1)
})
}
}
}

View File

@ -1,4 +1,4 @@
use crate::java::native_callbacks::{CALLBACK_CONTEXT, utils::with_player};
use crate::java::native_callbacks::utils::with_player;
use crate::proto::patchbukkit::{
abilities::{Abilities, SetAbilitiesRequest},
common::Uuid,
@ -50,23 +50,22 @@ pub fn ffi_native_bridge_get_abilities_impl(request: Uuid) -> Option<Abilities>
}
pub fn ffi_native_bridge_set_abilities_impl(request: SetAbilitiesRequest) -> Option<bool> {
let ctx = CALLBACK_CONTEXT.get()?;
let abilities = request.abilities?;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
{
let mut pumpkin_abilities = player.abilities.lock().await;
pumpkin_abilities.invulnerable = abilities.invulnerable;
pumpkin_abilities.flying = abilities.flying;
pumpkin_abilities.allow_flying = abilities.allow_flying;
pumpkin_abilities.creative = abilities.creative;
pumpkin_abilities.allow_modify_world = abilities.allow_modify_world;
pumpkin_abilities.fly_speed = abilities.fly_speed;
pumpkin_abilities.walk_speed = abilities.walk_speed;
}
player.send_abilities_update().await;
});
{
let mut pumpkin_abilities = player
.abilities
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
pumpkin_abilities.invulnerable = abilities.invulnerable;
pumpkin_abilities.flying = abilities.flying;
pumpkin_abilities.allow_flying = abilities.allow_flying;
pumpkin_abilities.creative = abilities.creative;
pumpkin_abilities.allow_modify_world = abilities.allow_modify_world;
pumpkin_abilities.fly_speed = abilities.fly_speed;
pumpkin_abilities.walk_speed = abilities.walk_speed;
}
player.send_abilities_update();
Some(true)
})?

View File

@ -62,9 +62,7 @@ pub fn ffi_native_bridge_register_command_impl(request: RegisterCommandRequest)
tracing::debug!("Permission '{}' registration notice: {}", permission, e);
}
plugin_context
.register_command(node, permission.clone())
.await;
plugin_context.register_command(node, permission.clone());
tracing::info!(
"Successfully registered command '{}' with names {:?} and permission '{}'",

View File

@ -33,25 +33,17 @@ pub fn ffi_native_bridge_get_entity_health_impl(request: Uuid) -> Option<EntityH
}
pub fn ffi_native_bridge_set_entity_health_impl(request: SetEntityHealthRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let health = request.health as f32;
let player = player.clone();
ctx.runtime.spawn(async move {
player.set_health(health).await;
});
player.set_health(health);
})
}
pub fn ffi_native_bridge_damage_entity_impl(request: DamageEntityRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let amount = request.amount as f32;
let player = player.clone();
ctx.runtime.spawn(async move {
let current = player.living_entity.health.load();
player.set_health((current - amount).max(0.0)).await;
});
let current = player.living_entity.health.load();
player.set_health((current - amount).max(0.0));
})
}
@ -95,14 +87,10 @@ pub fn ffi_native_bridge_get_gamemode_impl(
pub fn ffi_native_bridge_set_gamemode_impl(
request: crate::proto::patchbukkit::entity::SetGamemodeRequest,
) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let gamemode_val = request.gamemode as i8;
if let Ok(gamemode) = pumpkin_util::gamemode::GameMode::try_from(gamemode_val) {
let player = player.clone();
ctx.runtime.spawn(async move {
player.set_gamemode(gamemode).await;
});
player.set_gamemode(gamemode);
}
})
}
@ -211,26 +199,18 @@ pub fn ffi_native_bridge_get_food_level_impl(request: Uuid) -> Option<GetFoodLev
}
pub fn ffi_native_bridge_set_food_level_impl(request: SetFoodLevelRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let food_level = request.food_level as u8;
let player = player.clone();
ctx.runtime.spawn(async move {
player.hunger_manager.set_level(food_level);
player.send_health().await;
});
player.hunger_manager.set_level(food_level);
player.send_health();
})
}
pub fn ffi_native_bridge_set_saturation_impl(request: SetSaturationRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let saturation = request.saturation;
let player = player.clone();
ctx.runtime.spawn(async move {
player.hunger_manager.set_saturation(saturation);
player.send_health().await;
});
player.hunger_manager.set_saturation(saturation);
player.send_health();
})
}
@ -254,122 +234,82 @@ pub fn ffi_native_bridge_get_experience_impl(request: Uuid) -> Option<GetExperie
}
pub fn ffi_native_bridge_set_experience_impl(request: SetExperienceRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let level = request.level;
let progress = request.progress;
let total_experience = request.total_experience;
let player = player.clone();
ctx.runtime.spawn(async move {
player
.set_experience(level, progress, total_experience)
.await;
});
player.set_experience(level, progress, total_experience);
})
}
pub fn ffi_native_bridge_kick_player_impl(request: KickPlayerRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let msg = request.message;
let player = player.clone();
ctx.runtime.spawn(async move {
let text = pumpkin_util::text::TextComponent::from_legacy_string(&msg);
player
.kick(pumpkin::net::DisconnectReason::Kicked, text)
.await;
});
let text = pumpkin_util::text::TextComponent::from_legacy_string(&msg);
player.kick(pumpkin::net::DisconnectReason::Kicked, &text);
})
}
pub fn ffi_native_bridge_send_title_impl(request: SendTitleRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
let title = request.title;
let subtitle = request.subtitle;
let fade_in = request.fade_in;
let stay = request.stay;
let fade_out = request.fade_out;
ctx.runtime.spawn(async move {
if fade_in >= 0 && stay >= 0 && fade_out >= 0 {
player.send_title_animation(fade_in, stay, fade_out).await;
}
if !title.is_empty() {
let text = pumpkin_util::text::TextComponent::from_legacy_string(&title);
player
.show_title(&text, &pumpkin::entity::player::TitleMode::Title)
.await;
}
if !subtitle.is_empty() {
let text = pumpkin_util::text::TextComponent::from_legacy_string(&subtitle);
player
.show_title(&text, &pumpkin::entity::player::TitleMode::SubTitle)
.await;
}
});
if fade_in >= 0 && stay >= 0 && fade_out >= 0 {
player.send_title_animation(fade_in, stay, fade_out);
}
if !title.is_empty() {
let text = pumpkin_util::text::TextComponent::from_legacy_string(&title);
player.show_title(&text, &pumpkin::entity::player::TitleMode::Title);
}
if !subtitle.is_empty() {
let text = pumpkin_util::text::TextComponent::from_legacy_string(&subtitle);
player.show_title(&text, &pumpkin::entity::player::TitleMode::SubTitle);
}
})
}
pub fn ffi_native_bridge_send_action_bar_impl(request: SendActionBarRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let msg = request.message;
let player = player.clone();
ctx.runtime.spawn(async move {
let text = pumpkin_util::text::TextComponent::from_legacy_string(&msg);
player.send_system_message_raw(&text, true).await;
});
let text = pumpkin_util::text::TextComponent::from_legacy_string(&msg);
player.send_system_message_raw(&text, true);
})
}
pub fn ffi_native_bridge_reset_title_impl(request: Uuid) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(Some(&request), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
let text = pumpkin_util::text::TextComponent::text("");
player
.show_title(&text, &pumpkin::entity::player::TitleMode::Title)
.await;
player
.show_title(&text, &pumpkin::entity::player::TitleMode::SubTitle)
.await;
});
let text = pumpkin_util::text::TextComponent::text("");
player.show_title(&text, &pumpkin::entity::player::TitleMode::Title);
player.show_title(&text, &pumpkin::entity::player::TitleMode::SubTitle);
})
}
pub fn ffi_native_bridge_set_display_name_impl(request: SetDisplayNameRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let name = request.display_name;
let player = player.clone();
ctx.runtime.spawn(async move {
let comp = if name.is_empty() {
None
} else {
Some(pumpkin_util::text::TextComponent::from_legacy_string(&name))
};
player.set_display_name(comp).await;
});
let comp = if name.is_empty() {
None
} else {
Some(pumpkin_util::text::TextComponent::from_legacy_string(&name))
};
player.set_display_name(comp);
})
}
pub fn ffi_native_bridge_set_player_list_name_impl(
request: SetPlayerListNameRequest,
) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let name = request.list_name;
let player = player.clone();
ctx.runtime.spawn(async move {
let comp = if name.is_empty() {
None
} else {
Some(pumpkin_util::text::TextComponent::from_legacy_string(&name))
};
player.set_tab_list_name(comp).await;
});
let comp = if name.is_empty() {
None
} else {
Some(pumpkin_util::text::TextComponent::from_legacy_string(&name))
};
player.set_tab_list_name(comp);
})
}
@ -425,24 +365,16 @@ pub fn ffi_native_bridge_get_player_pose_state_impl(
}
pub fn ffi_native_bridge_set_sneaking_impl(request: SetSneakingRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
let sneaking = request.sneaking;
ctx.runtime.spawn(async move {
player.living_entity.entity.set_sneaking(sneaking).await;
});
player.living_entity.entity.set_sneaking(sneaking);
})
}
pub fn ffi_native_bridge_set_sprinting_impl(request: SetSprintingRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
let sprinting = request.sprinting;
ctx.runtime.spawn(async move {
player.living_entity.entity.set_sprinting(sprinting).await;
});
player.living_entity.entity.set_sprinting(sprinting);
})
}
@ -464,7 +396,12 @@ pub fn ffi_native_bridge_reset_player_time_impl(request: Uuid) -> Option<()> {
with_player(Some(&request), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
let world_time = player.world().level_time.lock().await.time_of_day;
let world_time = player
.world()
.level_time
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.time_of_day;
let packet = pumpkin_protocol::java::client::play::CUpdateTime::new(
world_time, world_time, true,
);
@ -495,7 +432,7 @@ pub fn ffi_native_bridge_reset_player_weather_impl(request: Uuid) -> Option<()>
with_player(Some(&request), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
let is_raining = player.world().is_raining().await;
let is_raining = player.world().is_raining();
let event = if is_raining {
pumpkin_protocol::java::client::play::GameEvent::BeginRaining
} else {
@ -544,20 +481,14 @@ pub fn ffi_native_bridge_get_compass_target_impl(
}
pub fn ffi_native_bridge_set_respawn_point_impl(request: SetRespawnPointRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
let pos = request.position?;
with_player(request.uuid.as_ref(), |player| {
let block_pos =
pumpkin_util::math::position::BlockPos::new(pos.x as i32, pos.y as i32, pos.z as i32);
let yaw = request.yaw;
let force = request.force;
let player = player.clone();
ctx.runtime.spawn(async move {
let dim = player.world().dimension.clone();
player
.set_respawn_point(dim, block_pos, yaw, 0.0, force)
.await;
});
let dim = player.world().dimension.clone();
player.set_respawn_point(dim, block_pos, yaw, 0.0, force);
})
}
@ -613,9 +544,7 @@ pub fn ffi_native_bridge_get_respawn_point_impl(
}
pub fn ffi_native_bridge_stop_sound_impl(request: StopSoundRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
let sound = if request.sound.is_empty() {
None
} else {
@ -626,9 +555,7 @@ pub fn ffi_native_bridge_stop_sound_impl(request: StopSoundRequest) -> Option<()
} else {
pumpkin_data::sound::SoundCategory::from_name(&request.category.to_lowercase())
};
ctx.runtime.spawn(async move {
player.stop_sound(sound, category).await;
});
player.stop_sound(sound, category);
})
}
@ -718,14 +645,10 @@ pub fn ffi_native_bridge_send_game_event_impl(request: SendGameEventRequest) ->
}
pub fn ffi_native_bridge_set_cooldown_impl(request: SetCooldownRequest) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
let group = request.item_group;
let duration = request.duration_ticks;
ctx.runtime.spawn(async move {
player.start_cooldown(group, duration).await;
});
player.start_cooldown(group, duration);
})
}
@ -758,23 +681,13 @@ pub fn ffi_native_bridge_get_cooldown_impl(
}
pub fn ffi_native_bridge_open_ender_chest_impl(request: Uuid) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(Some(&request), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
player.open_ender_chest().await;
});
player.open_ender_chest();
})
}
pub fn ffi_native_bridge_update_inventory_impl(request: Uuid) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(Some(&request), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
player
.on_screen_handler_opened(player.player_screen_handler.clone())
.await;
});
player.on_screen_handler_opened(&player.player_screen_handler);
})
}

View File

@ -3,7 +3,7 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack as PumpkinItemStack;
use crate::{
java::native_callbacks::{CALLBACK_CONTEXT, utils::with_player},
java::native_callbacks::utils::with_player,
proto::patchbukkit::{
common::Uuid,
itemstack::{
@ -98,31 +98,35 @@ pub fn ffi_native_bridge_get_player_inventory_impl(
pub fn ffi_native_bridge_set_player_inventory_slot_impl(
request: SetPlayerInventorySlotRequest,
) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
let slot = request.slot as usize;
let pumpkin_item = proto_item_to_pumpkin(request.item.as_ref());
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
if slot < 36 {
let mut main_guard = player.inventory.main_inventory.write().await;
main_guard[slot] = pumpkin_item;
} else {
let eq_slot = match slot {
36 => Some(EquipmentSlot::FEET),
37 => Some(EquipmentSlot::LEGS),
38 => Some(EquipmentSlot::CHEST),
39 => Some(EquipmentSlot::HEAD),
40 => Some(EquipmentSlot::OFF_HAND),
_ => None,
};
if let Some(eq_slot) = eq_slot {
let mut eq_guard = player.inventory.entity_equipment.lock().await;
eq_guard.put(&eq_slot, pumpkin_item);
}
if slot < 36 {
let mut main_guard = player
.inventory
.main_inventory
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
main_guard[slot] = pumpkin_item;
} else {
let eq_slot = match slot {
36 => Some(EquipmentSlot::FEET),
37 => Some(EquipmentSlot::LEGS),
38 => Some(EquipmentSlot::CHEST),
39 => Some(EquipmentSlot::HEAD),
40 => Some(EquipmentSlot::OFF_HAND),
_ => None,
};
if let Some(eq_slot) = eq_slot {
let mut eq_guard = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq_guard.put(&eq_slot, pumpkin_item);
}
});
}
})
}
@ -139,58 +143,78 @@ pub fn ffi_native_bridge_set_player_selected_slot_impl(
pub fn ffi_native_bridge_set_player_equipment_impl(
request: SetPlayerEquipmentRequest,
) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
let pumpkin_item = proto_item_to_pumpkin(request.item.as_ref());
let slot_type = request.slot_type;
with_player(request.uuid.as_ref(), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
match slot_type {
0 => {
// Main Hand
player.inventory.set_held_item(pumpkin_item).await;
}
1 => {
// Off Hand
let mut eq = player.inventory.entity_equipment.lock().await;
eq.put(&EquipmentSlot::OFF_HAND, pumpkin_item);
}
2 => {
// Feet
let mut eq = player.inventory.entity_equipment.lock().await;
eq.put(&EquipmentSlot::FEET, pumpkin_item);
}
3 => {
// Legs
let mut eq = player.inventory.entity_equipment.lock().await;
eq.put(&EquipmentSlot::LEGS, pumpkin_item);
}
4 => {
// Chest
let mut eq = player.inventory.entity_equipment.lock().await;
eq.put(&EquipmentSlot::CHEST, pumpkin_item);
}
5 => {
// Head
let mut eq = player.inventory.entity_equipment.lock().await;
eq.put(&EquipmentSlot::HEAD, pumpkin_item);
}
_ => {}
match slot_type {
0 => {
// Main Hand
player.inventory.set_held_item(pumpkin_item);
}
});
1 => {
// Off Hand
let mut eq = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq.put(&EquipmentSlot::OFF_HAND, pumpkin_item);
}
2 => {
// Feet
let mut eq = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq.put(&EquipmentSlot::FEET, pumpkin_item);
}
3 => {
// Legs
let mut eq = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq.put(&EquipmentSlot::LEGS, pumpkin_item);
}
4 => {
// Chest
let mut eq = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq.put(&EquipmentSlot::CHEST, pumpkin_item);
}
5 => {
// Head
let mut eq = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq.put(&EquipmentSlot::HEAD, pumpkin_item);
}
_ => {}
}
})
}
pub fn ffi_native_bridge_clear_player_inventory_impl(request: Uuid) -> Option<()> {
let ctx = CALLBACK_CONTEXT.get()?;
with_player(Some(&request), |player| {
let player = player.clone();
ctx.runtime.spawn(async move {
let mut main_guard = player.inventory.main_inventory.write().await;
main_guard.fill_with(|| PumpkinItemStack::EMPTY.clone());
let mut eq_guard = player.inventory.entity_equipment.lock().await;
eq_guard.clear();
});
let mut main_guard = player
.inventory
.main_inventory
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
main_guard.fill_with(|| PumpkinItemStack::EMPTY.clone());
let mut eq_guard = player
.inventory
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
eq_guard.clear();
})
}

View File

@ -8,14 +8,10 @@ pub fn ffi_native_bridge_send_message_impl(request: SendMessageRequest) -> Optio
let ctx = CALLBACK_CONTEXT.get()?;
let player_uuid = uuid::Uuid::parse_str(&request.uuid?.value).unwrap();
ctx.runtime.spawn(async move {
let player = ctx.plugin_context.server.get_player_by_uuid(player_uuid);
if let Some(player) = player {
player
.send_system_message(&TextComponent::from_legacy_string(&request.message))
.await;
}
});
let player = ctx.plugin_context.server.get_player_by_uuid(player_uuid);
if let Some(player) = player {
player.send_system_message(&TextComponent::from_legacy_string(&request.message));
}
Some(())
}

View File

@ -196,9 +196,7 @@ pub fn ffi_native_bridge_broadcast_message_impl(request: BroadcastMessageRequest
let server = ctx.plugin_context.server.clone();
let text = TextComponent::text(request.message);
let sender = TextComponent::text("Server");
ctx.runtime.spawn(async move {
server.broadcast_message(&text, &sender, 0, None).await;
});
server.broadcast_message(&text, &sender, 0, None);
Some(())
}
@ -229,21 +227,23 @@ pub fn ffi_native_bridge_set_whitelist_player_impl(
let target_name = request.name;
let server = ctx.plugin_context.server.clone();
ctx.runtime.spawn(async move {
let mut config = server.data.whitelist_config.write().await;
if request.whitelisted {
if !config.whitelist.iter().any(|e| e.uuid == target_uuid) {
config
.whitelist
.push(pumpkin_config::whitelist::WhitelistEntry {
uuid: target_uuid,
name: target_name,
});
}
} else {
config.whitelist.retain(|e| e.uuid != target_uuid);
let mut config = server
.data
.whitelist_config
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if request.whitelisted {
if !config.whitelist.iter().any(|e| e.uuid == target_uuid) {
config
.whitelist
.push(pumpkin_config::whitelist::WhitelistEntry {
uuid: target_uuid,
name: target_name,
});
}
});
} else {
config.whitelist.retain(|e| e.uuid != target_uuid);
}
Some(())
}
@ -280,23 +280,25 @@ pub fn ffi_native_bridge_set_operator_impl(request: SetOperatorRequest) -> Optio
};
let server = ctx.plugin_context.server.clone();
ctx.runtime.spawn(async move {
let mut config = server.data.operator_config.write().await;
if request.is_op {
if let Some(op) = config.ops.iter_mut().find(|e| e.uuid == target_uuid) {
op.level = level;
} else {
config.ops.push(pumpkin_config::op::Op {
uuid: target_uuid,
name: target_name,
level,
bypasses_player_limit: false,
});
}
let mut config = server
.data
.operator_config
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if request.is_op {
if let Some(op) = config.ops.iter_mut().find(|e| e.uuid == target_uuid) {
op.level = level;
} else {
config.ops.retain(|e| e.uuid != target_uuid);
config.ops.push(pumpkin_config::op::Op {
uuid: target_uuid,
name: target_name,
level,
bypasses_player_limit: false,
});
}
});
} else {
config.ops.retain(|e| e.uuid != target_uuid);
}
Some(())
}
@ -343,58 +345,63 @@ pub fn ffi_native_bridge_set_ban_entry_impl(request: SetBanEntryRequest) -> Opti
let ctx = CALLBACK_CONTEXT.get()?;
let server = ctx.plugin_context.server.clone();
ctx.runtime.spawn(async move {
if let Some(entry) = request.entry {
if request.ban_type == "IP" {
if let Ok(ip) = entry.target.parse::<std::net::IpAddr>() {
let mut list = server.data.banned_ip_list.write().await;
if request.remove {
list.banned_ips.retain(|e| e.ip != ip);
} else {
list.banned_ips.retain(|e| e.ip != ip);
let expires = if entry.expires > 0 {
time::OffsetDateTime::from_unix_timestamp(entry.expires).ok()
} else {
None
};
list.banned_ips
.push(pumpkin::data::banlist_serializer::BannedIpEntry {
ip,
created: time::OffsetDateTime::now_utc(),
source: entry.source,
expires,
reason: entry.reason,
});
}
}
} else {
let mut list = server.data.banned_player_list.write().await;
let target_name = entry.target.clone();
if let Some(entry) = request.entry {
if request.ban_type == "IP" {
if let Ok(ip) = entry.target.parse::<std::net::IpAddr>() {
let mut list = server
.data
.banned_ip_list
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if request.remove {
list.banned_players
.retain(|e| !e.name.eq_ignore_ascii_case(&target_name));
list.banned_ips.retain(|e| e.ip != ip);
} else {
list.banned_players
.retain(|e| !e.name.eq_ignore_ascii_case(&target_name));
list.banned_ips.retain(|e| e.ip != ip);
let expires = if entry.expires > 0 {
time::OffsetDateTime::from_unix_timestamp(entry.expires).ok()
} else {
None
};
list.banned_players.push(
pumpkin::data::banlist_serializer::BannedPlayerEntry {
uuid: uuid::Uuid::nil(),
name: target_name,
list.banned_ips
.push(pumpkin::data::banlist_serializer::BannedIpEntry {
ip,
created: time::OffsetDateTime::now_utc(),
source: entry.source,
expires,
reason: entry.reason,
},
);
});
}
}
} else {
let mut list = server
.data
.banned_player_list
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let target_name = entry.target.clone();
if request.remove {
list.banned_players
.retain(|e| !e.name.eq_ignore_ascii_case(&target_name));
} else {
list.banned_players
.retain(|e| !e.name.eq_ignore_ascii_case(&target_name));
let expires = if entry.expires > 0 {
time::OffsetDateTime::from_unix_timestamp(entry.expires).ok()
} else {
None
};
list.banned_players
.push(pumpkin::data::banlist_serializer::BannedPlayerEntry {
uuid: uuid::Uuid::nil(),
name: target_name,
created: time::OffsetDateTime::now_utc(),
source: entry.source,
expires,
reason: entry.reason,
});
}
}
});
}
Some(())
}

View File

@ -71,18 +71,14 @@ pub fn ffi_native_bridge_player_play_sound_impl(request: PlayerPlaySoundRequest)
let position = request.location?.position?;
let position: Vector3<f64> = Vector3::new(position.x, position.y, position.z);
ctx.runtime.spawn(async move {
player
.play_sound(
pumpkin_sound as u16,
category,
&position,
request.volume,
request.pitch,
seed,
)
.await;
});
player.play_sound(
pumpkin_sound as u16,
category,
&position,
request.volume,
request.pitch,
seed,
);
Some(())
}

View File

@ -109,11 +109,7 @@ pub fn ffi_native_bridge_set_block_data_impl(request: SetBlockDataRequest) -> Op
} else {
pumpkin::world::BlockFlags::NOTIFY_LISTENERS
};
tokio::task::block_in_place(|| {
ctx.runtime.block_on(async {
world.set_block_state(&pos, state_id, flags).await;
})
});
world.set_block_state(&pos, state_id, flags);
Some(())
}
@ -178,8 +174,11 @@ pub fn ffi_native_bridge_set_world_border_impl(request: SetWorldBorderRequest) -
.cloned()
.or_else(|| worlds.first().cloned())?;
ctx.runtime.spawn(async move {
let mut wb = world.worldborder.lock().await;
{
let mut wb = world
.worldborder
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
wb.center_x = border_data.center_x;
wb.center_z = border_data.center_z;
wb.old_diameter = border_data.size;
@ -190,7 +189,7 @@ pub fn ffi_native_bridge_set_world_border_impl(request: SetWorldBorderRequest) -
wb.damage_per_block = border_data.damage_per_block as f32;
wb.buffer = border_data.damage_buffer as f32;
wb.portal_teleport_boundary = border_data.max_center_coordinate;
});
}
Some(())
}
@ -480,7 +479,7 @@ pub fn ffi_native_bridge_spawn_world_entity_impl(
_ => &pumpkin_data::entity::EntityType::PIG,
};
let entity = pumpkin::entity::r#type::from_type(entity_type, pos, &w, new_uuid);
w.spawn_entity(entity).await;
w.spawn_entity(entity);
});
Some(SpawnWorldEntityResponse {
@ -513,10 +512,7 @@ pub fn ffi_native_bridge_create_world_explosion_impl(
pumpkin::world::ExplosionInteraction::None
};
let w = world.clone();
ctx.runtime.spawn(async move {
w.explode(pos, power, interaction).await;
});
world.explode(pos, power, interaction);
Some(())
}