mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
257 lines
9.0 KiB
Rust
257 lines
9.0 KiB
Rust
use crate::command::argument_builder::{ArgumentBuilder, argument, command, literal};
|
|
use crate::command::argument_types::core::integer::IntegerArgumentType;
|
|
use crate::command::argument_types::objective::ObjectiveArgumentType;
|
|
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::world::scoreboard::ScoreboardScore;
|
|
use pumpkin_data::translation;
|
|
use pumpkin_protocol::codec::var_int::VarInt;
|
|
use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry};
|
|
use pumpkin_util::text::TextComponent;
|
|
|
|
const DESCRIPTION: &str = "Modifies a trigger scoreboard objective.";
|
|
const PERMISSION: &str = "minecraft:command.trigger";
|
|
|
|
const ARG_OBJECTIVE: &str = "objective";
|
|
const ARG_VALUE: &str = "value";
|
|
|
|
const INVALID_TRIGGER_ERROR: CommandErrorType<0> = CommandErrorType::new(
|
|
translation::java::COMMANDS_TRIGGER_FAILED_INVALID,
|
|
translation::java::COMMANDS_TRIGGER_FAILED_INVALID,
|
|
);
|
|
|
|
const UNPRIMED_TRIGGER_ERROR: CommandErrorType<0> = CommandErrorType::new(
|
|
translation::java::COMMANDS_TRIGGER_FAILED_UNPRIMED,
|
|
translation::java::COMMANDS_TRIGGER_FAILED_UNPRIMED,
|
|
);
|
|
|
|
struct SimpleTriggerExecutor;
|
|
|
|
impl CommandExecutor for SimpleTriggerExecutor {
|
|
fn execute<'a>(&'a self, context: &'a CommandContext) -> CommandExecutorResult<'a> {
|
|
Box::pin(async move {
|
|
let player = context.source.player_or_err()?;
|
|
let player_name = &player.gameprofile.name;
|
|
let objective_name = ObjectiveArgumentType::get(context, ARG_OBJECTIVE)?;
|
|
|
|
let world = context.world();
|
|
let mut scoreboard = world.scoreboard.lock().await;
|
|
|
|
let objective = scoreboard
|
|
.get_objectives()
|
|
.get(objective_name)
|
|
.ok_or_else(|| INVALID_TRIGGER_ERROR.create_without_context())?;
|
|
|
|
if objective.criterion != "trigger" {
|
|
return Err(INVALID_TRIGGER_ERROR.create_without_context());
|
|
}
|
|
|
|
let objective_display_name = objective.display_name.clone();
|
|
|
|
let is_locked = scoreboard
|
|
.get_scores()
|
|
.get(objective_name)
|
|
.and_then(|m| m.get(player_name))
|
|
.is_none_or(|s| s.locked);
|
|
|
|
if is_locked {
|
|
return Err(UNPRIMED_TRIGGER_ERROR.create_without_context());
|
|
}
|
|
|
|
let current_value = scoreboard
|
|
.get_scores()
|
|
.get(objective_name)
|
|
.and_then(|m| m.get(player_name))
|
|
.map_or(0, |s| s.value.0);
|
|
|
|
let new_value = current_value + 1;
|
|
|
|
let updated_score = ScoreboardScore {
|
|
entity_name: player_name.clone(),
|
|
objective_name: objective_name.to_string(),
|
|
value: VarInt(new_value),
|
|
display_name: None,
|
|
number_format: None,
|
|
locked: true,
|
|
};
|
|
|
|
scoreboard.update_score(world, updated_score).await;
|
|
|
|
context
|
|
.source
|
|
.send_feedback(
|
|
TextComponent::translate_cross(
|
|
translation::java::COMMANDS_TRIGGER_SIMPLE_SUCCESS,
|
|
translation::java::COMMANDS_TRIGGER_SIMPLE_SUCCESS,
|
|
[objective_display_name],
|
|
),
|
|
false,
|
|
)
|
|
.await;
|
|
|
|
Ok(new_value)
|
|
})
|
|
}
|
|
}
|
|
|
|
struct AddTriggerExecutor;
|
|
|
|
impl CommandExecutor for AddTriggerExecutor {
|
|
fn execute<'a>(&'a self, context: &'a CommandContext) -> CommandExecutorResult<'a> {
|
|
Box::pin(async move {
|
|
let player = context.source.player_or_err()?;
|
|
let player_name = &player.gameprofile.name;
|
|
let objective_name = ObjectiveArgumentType::get(context, ARG_OBJECTIVE)?;
|
|
let value = IntegerArgumentType::get(context, ARG_VALUE)?;
|
|
|
|
let world = context.world();
|
|
let mut scoreboard = world.scoreboard.lock().await;
|
|
|
|
let objective = scoreboard
|
|
.get_objectives()
|
|
.get(objective_name)
|
|
.ok_or_else(|| INVALID_TRIGGER_ERROR.create_without_context())?;
|
|
|
|
if objective.criterion != "trigger" {
|
|
return Err(INVALID_TRIGGER_ERROR.create_without_context());
|
|
}
|
|
|
|
let objective_display_name = objective.display_name.clone();
|
|
|
|
let is_locked = scoreboard
|
|
.get_scores()
|
|
.get(objective_name)
|
|
.and_then(|m| m.get(player_name))
|
|
.is_none_or(|s| s.locked);
|
|
|
|
if is_locked {
|
|
return Err(UNPRIMED_TRIGGER_ERROR.create_without_context());
|
|
}
|
|
|
|
let current_value = scoreboard
|
|
.get_scores()
|
|
.get(objective_name)
|
|
.and_then(|m| m.get(player_name))
|
|
.map_or(0, |s| s.value.0);
|
|
|
|
let new_value = current_value + value;
|
|
|
|
let updated_score = ScoreboardScore {
|
|
entity_name: player_name.clone(),
|
|
objective_name: objective_name.to_string(),
|
|
value: VarInt(new_value),
|
|
display_name: None,
|
|
number_format: None,
|
|
locked: true,
|
|
};
|
|
|
|
scoreboard.update_score(world, updated_score).await;
|
|
|
|
context
|
|
.source
|
|
.send_feedback(
|
|
TextComponent::translate_cross(
|
|
translation::java::COMMANDS_TRIGGER_ADD_SUCCESS,
|
|
translation::java::COMMANDS_TRIGGER_ADD_SUCCESS,
|
|
[
|
|
objective_display_name,
|
|
TextComponent::text(value.to_string()),
|
|
],
|
|
),
|
|
false,
|
|
)
|
|
.await;
|
|
|
|
Ok(new_value)
|
|
})
|
|
}
|
|
}
|
|
|
|
struct SetTriggerExecutor;
|
|
|
|
impl CommandExecutor for SetTriggerExecutor {
|
|
fn execute<'a>(&'a self, context: &'a CommandContext) -> CommandExecutorResult<'a> {
|
|
Box::pin(async move {
|
|
let player = context.source.player_or_err()?;
|
|
let player_name = &player.gameprofile.name;
|
|
let objective_name = ObjectiveArgumentType::get(context, ARG_OBJECTIVE)?;
|
|
let value = IntegerArgumentType::get(context, ARG_VALUE)?;
|
|
|
|
let world = context.world();
|
|
let mut scoreboard = world.scoreboard.lock().await;
|
|
|
|
let objective = scoreboard
|
|
.get_objectives()
|
|
.get(objective_name)
|
|
.ok_or_else(|| INVALID_TRIGGER_ERROR.create_without_context())?;
|
|
|
|
if objective.criterion != "trigger" {
|
|
return Err(INVALID_TRIGGER_ERROR.create_without_context());
|
|
}
|
|
|
|
let objective_display_name = objective.display_name.clone();
|
|
|
|
let is_locked = scoreboard
|
|
.get_scores()
|
|
.get(objective_name)
|
|
.and_then(|m| m.get(player_name))
|
|
.is_none_or(|s| s.locked);
|
|
|
|
if is_locked {
|
|
return Err(UNPRIMED_TRIGGER_ERROR.create_without_context());
|
|
}
|
|
|
|
let updated_score = ScoreboardScore {
|
|
entity_name: player_name.clone(),
|
|
objective_name: objective_name.to_string(),
|
|
value: VarInt(value),
|
|
display_name: None,
|
|
number_format: None,
|
|
locked: true,
|
|
};
|
|
|
|
scoreboard.update_score(world, updated_score).await;
|
|
|
|
context
|
|
.source
|
|
.send_feedback(
|
|
TextComponent::translate_cross(
|
|
translation::java::COMMANDS_TRIGGER_SET_SUCCESS,
|
|
translation::java::COMMANDS_TRIGGER_SET_SUCCESS,
|
|
[
|
|
objective_display_name,
|
|
TextComponent::text(value.to_string()),
|
|
],
|
|
),
|
|
false,
|
|
)
|
|
.await;
|
|
|
|
Ok(value)
|
|
})
|
|
}
|
|
}
|
|
|
|
pub fn register(dispatcher: &mut CommandDispatcher, registry: &mut PermissionRegistry) {
|
|
registry.register_permission_or_panic(Permission::new(
|
|
PERMISSION,
|
|
DESCRIPTION,
|
|
PermissionDefault::Allow,
|
|
));
|
|
|
|
dispatcher.register(
|
|
command("trigger", DESCRIPTION).requires(PERMISSION).then(
|
|
argument(ARG_OBJECTIVE, ObjectiveArgumentType)
|
|
.executes(SimpleTriggerExecutor)
|
|
.then(literal("add").then(
|
|
argument(ARG_VALUE, IntegerArgumentType::any()).executes(AddTriggerExecutor),
|
|
))
|
|
.then(literal("set").then(
|
|
argument(ARG_VALUE, IntegerArgumentType::any()).executes(SetTriggerExecutor),
|
|
)),
|
|
),
|
|
);
|
|
}
|