100 lines
3.1 KiB
Rust
100 lines
3.1 KiB
Rust
use async_trait::async_trait;
|
|
use pumpkin_util::text::TextComponent;
|
|
|
|
use crate::command::args::block::BlockArgumentConsumer;
|
|
use crate::command::args::position_block::BlockPosArgumentConsumer;
|
|
use crate::command::args::{ConsumedArgs, FindArg};
|
|
use crate::command::tree::CommandTree;
|
|
use crate::command::tree::builder::{argument, literal};
|
|
use crate::command::{CommandError, CommandExecutor, CommandSender};
|
|
|
|
const NAMES: [&str; 1] = ["setblock"];
|
|
|
|
const DESCRIPTION: &str = "Place a block.";
|
|
|
|
const ARG_BLOCK: &str = "block";
|
|
const ARG_BLOCK_POS: &str = "pos";
|
|
|
|
#[derive(Clone, Copy)]
|
|
enum Mode {
|
|
/// with particles + item drops
|
|
Destroy,
|
|
|
|
/// only replaces air
|
|
Keep,
|
|
|
|
/// default; without particles
|
|
Replace,
|
|
}
|
|
|
|
struct Executor(Mode);
|
|
|
|
#[async_trait]
|
|
impl CommandExecutor for Executor {
|
|
async fn execute<'a>(
|
|
&self,
|
|
sender: &mut CommandSender<'a>,
|
|
_server: &crate::server::Server,
|
|
args: &ConsumedArgs<'a>,
|
|
) -> Result<(), CommandError> {
|
|
let block = BlockArgumentConsumer::find_arg(args, ARG_BLOCK)?;
|
|
let block_state_id = block.default_state_id;
|
|
let pos = BlockPosArgumentConsumer::find_arg(args, ARG_BLOCK_POS)?;
|
|
let mode = self.0;
|
|
// TODO: allow console to use the command (seed sender.world)
|
|
let world = sender
|
|
.world()
|
|
.await
|
|
.ok_or(CommandError::InvalidRequirement)?;
|
|
|
|
let success = match mode {
|
|
Mode::Destroy => {
|
|
world.clone().break_block(&pos, None, false).await;
|
|
world.set_block_state(&pos, block_state_id).await;
|
|
true
|
|
}
|
|
Mode::Replace => {
|
|
world.set_block_state(&pos, block_state_id).await;
|
|
true
|
|
}
|
|
Mode::Keep => match world.get_block_state(&pos).await {
|
|
Ok(old_state) if old_state.air => {
|
|
world.set_block_state(&pos, block_state_id).await;
|
|
true
|
|
}
|
|
Ok(_) => false,
|
|
Err(e) => return Err(CommandError::OtherPumpkin(e.into())),
|
|
},
|
|
};
|
|
|
|
sender
|
|
.send_message(if success {
|
|
TextComponent::translate(
|
|
"commands.setblock.success",
|
|
[
|
|
TextComponent::text(pos.0.x.to_string()),
|
|
TextComponent::text(pos.0.y.to_string()),
|
|
TextComponent::text(pos.0.z.to_string()),
|
|
],
|
|
)
|
|
} else {
|
|
TextComponent::translate("commands.setblock.failed", [])
|
|
})
|
|
.await;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub fn init_command_tree() -> CommandTree {
|
|
CommandTree::new(NAMES, DESCRIPTION).then(
|
|
argument(ARG_BLOCK_POS, BlockPosArgumentConsumer).then(
|
|
argument(ARG_BLOCK, BlockArgumentConsumer)
|
|
.then(literal("replace").execute(Executor(Mode::Replace)))
|
|
.then(literal("destroy").execute(Executor(Mode::Destroy)))
|
|
.then(literal("keep").execute(Executor(Mode::Keep)))
|
|
.execute(Executor(Mode::Replace)),
|
|
),
|
|
)
|
|
}
|