Pumpkin/crates/pumpkin/src/command/commands/op.rs
Alexander Medvedev 61bd8f77b6 chore: swap permissions_manger to dashmap
i need this also PatchBukkit
2026-08-19 19:50:20 +02:00

123 lines
4.4 KiB
Rust

use crate::command::argument_builder::{ArgumentBuilder, argument, command};
use crate::command::argument_types::game_profile::GameProfileArgumentType;
use crate::command::context::command_context::CommandContext;
use crate::command::errors::error_types::CommandErrorType;
use crate::command::node::dispatcher::CommandDispatcher;
use crate::command::node::{CommandExecutor, CommandExecutorResult};
use crate::command::suggestion::provider::{SuggestionProvider, SuggestionProviderResult};
use crate::command::suggestion::suggestions::SuggestionsBuilder;
use crate::data::SaveJSONConfiguration;
use pumpkin_config::op::Op;
use pumpkin_data::translation;
use pumpkin_util::PermissionLvl;
use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry};
use pumpkin_util::text::TextComponent;
pub const ALREADY_OP_ERROR_TYPE: CommandErrorType<0> = CommandErrorType::new(
translation::java::COMMANDS_OP_FAILED,
translation::bedrock::COMMANDS_OP_FAILED,
);
const DESCRIPTION: &str = "Grants operator status to a player.";
const PERMISSION: &str = "minecraft:command.op";
const ARG_TARGETS: &str = "targets";
struct OpCommandExecutor;
impl CommandExecutor for OpCommandExecutor {
fn execute<'a>(&'a self, context: &'a CommandContext) -> CommandExecutorResult<'a> {
Box::pin(async move {
let server = context.server();
let profiles = GameProfileArgumentType::get(context, ARG_TARGETS).await?;
let mut config = server.data.operator_config.write().await;
let mut successes: i32 = 0;
let new_level = server.basic_config.op_permission_level;
for profile in profiles {
let maybe_existing_entry = config.ops.iter_mut().find(|o| o.uuid == profile.id);
if let Some(op) = maybe_existing_entry {
if op.level == new_level {
continue;
}
op.level = new_level;
op.name.clone_from(&profile.name);
} else {
let op_entry = Op::new(profile.id, profile.name.clone(), new_level, false);
config.ops.push(op_entry);
}
if let Some(player) = server.get_player_by_uuid(profile.id) {
let command_dispatcher = server.command_dispatcher.load();
player
.set_permission_lvl(server, new_level, &command_dispatcher)
.await;
}
context
.source
.send_feedback(
TextComponent::translate_cross(
translation::java::COMMANDS_OP_SUCCESS,
translation::bedrock::COMMANDS_OP_SUCCESS,
[TextComponent::text(profile.name.clone())],
),
true,
)
.await;
successes += 1;
}
if successes > 0 {
config.save();
}
if successes == 0 {
Err(ALREADY_OP_ERROR_TYPE.create_without_context())
} else {
Ok(successes)
}
})
}
}
struct OpSuggestionProvider;
impl SuggestionProvider for OpSuggestionProvider {
fn suggest<'a>(
&'a self,
context: &'a CommandContext,
mut builder: SuggestionsBuilder,
) -> SuggestionProviderResult<'a> {
Box::pin(async move {
// Suggest every non-opped player.
let ops = context.server().data.operator_config.read().await;
for player in context.source.server().get_all_players() {
if ops.ops.iter().all(|op| op.uuid != player.gameprofile.id) {
builder = builder.suggest(player.gameprofile.name.clone());
}
}
builder.build()
})
}
}
pub fn register(dispatcher: &mut CommandDispatcher, registry: &PermissionRegistry) {
registry.register_permission_or_panic(Permission::new(
PERMISSION,
DESCRIPTION,
PermissionDefault::Op(PermissionLvl::Three),
));
dispatcher.register(
command("op", DESCRIPTION).requires(PERMISSION).then(
argument(ARG_TARGETS, GameProfileArgumentType)
.suggests(OpSuggestionProvider)
.executes(OpCommandExecutor),
),
);
}