Add more console support for some commands (#821)

* add console command support

* refactor

* fix: fixed an rare attempt to subtract with overflow case
This commit is contained in:
qwixck
2025-05-19 18:15:51 +03:00
committed by GitHub
parent f449b693c7
commit 9fbaee04d6
5 changed files with 90 additions and 60 deletions

View File

@@ -27,7 +27,7 @@ impl CommandExecutor for Executor {
async fn execute<'a>(
&self,
sender: &mut CommandSender,
_server: &crate::server::Server,
server: &crate::server::Server,
args: &ConsumedArgs<'a>,
) -> Result<(), CommandError> {
let particle = ParticleArgumentConsumer::find_arg(args, ARG_NAME)?;
@@ -36,26 +36,44 @@ impl CommandExecutor for Executor {
let speed = BoundedNumArgumentConsumer::<f32>::find_arg(args, ARG_SPEED);
let count = BoundedNumArgumentConsumer::<i32>::find_arg(args, ARG_COUNT);
// TODO: Make this work in console
if let Some(player) = sender.as_player() {
let pos = pos.unwrap_or(player.living_entity.entity.pos.load());
let delta = delta.unwrap_or(Vector3::new(0.0, 0.0, 0.0));
let delta: Vector3<f32> = Vector3::new(delta.x as f32, delta.y as f32, delta.z as f32);
let speed = speed.unwrap_or(Ok(0.0))?;
let count = count.unwrap_or(Ok(0))?;
let delta = delta.unwrap_or(Vector3::new(0.0, 0.0, 0.0));
let delta: Vector3<f32> = Vector3::new(delta.x as f32, delta.y as f32, delta.z as f32);
let speed = speed.unwrap_or(Ok(0.0))?;
let count = count.unwrap_or(Ok(0))?;
let (world, pos) = match sender {
CommandSender::Console | CommandSender::Rcon(_) => {
let guard = server.worlds.read().await;
let world = guard
.first()
.cloned()
.ok_or(CommandError::InvalidRequirement)?;
let info = &world.level_info;
// default position for spawning a player, in this case for particle
let pos = pos.unwrap_or(Vector3::new(
f64::from(info.spawn_x),
f64::from(info.spawn_y) + 1.0,
f64::from(info.spawn_z),
));
player
.world()
.await
.spawn_particle(pos, delta, speed, count, *particle)
.await;
sender
.send_message(TextComponent::translate(
"commands.particle.success",
[TextComponent::text(format!("{particle:?}"))],
))
.await;
}
(world, pos)
}
CommandSender::Player(player) => {
let pos = pos.unwrap_or(player.living_entity.entity.pos.load());
(player.world().await, pos)
}
};
world
.spawn_particle(pos, delta, speed, count, *particle)
.await;
sender
.send_message(TextComponent::translate(
"commands.particle.success",
[TextComponent::text(format!("{particle:?}"))],
))
.await;
Ok(())
}

View File

@@ -35,19 +35,24 @@ impl CommandExecutor for Executor {
async fn execute<'a>(
&self,
sender: &mut CommandSender,
_server: &crate::server::Server,
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 world = match sender {
CommandSender::Console | CommandSender::Rcon(_) => {
let guard = server.worlds.read().await;
guard
.first()
.cloned()
.ok_or(CommandError::InvalidRequirement)?
}
CommandSender::Player(player) => player.world().await,
};
let success = match mode {
Mode::Destroy => {
world

View File

@@ -32,39 +32,38 @@ impl CommandExecutor for Executor {
) -> Result<(), CommandError> {
let entity = SummonableEntitiesArgumentConsumer::find_arg(args, ARG_ENTITY)?;
let pos = Position3DArgumentConsumer::find_arg(args, ARG_POS);
match sender {
let (world, pos) = match sender {
CommandSender::Console | CommandSender::Rcon(_) => {
if let Some(world) = server.worlds.read().await.first() {
let info = &world.level_info;
// default position for spawning a player, in this case for mob
let pos = pos.unwrap_or(Vector3::new(
f64::from(info.spawn_x),
f64::from(info.spawn_y) + 1.0,
f64::from(info.spawn_z),
));
let mob = mob::from_type(entity, pos, world).await;
world.spawn_entity(mob).await;
sender
.send_message(TextComponent::translate(
"commands.summon.success",
[TextComponent::text(format!("{entity:?}"))],
))
.await;
}
let guard = server.worlds.read().await;
let world = guard
.first()
.cloned()
.ok_or(CommandError::InvalidRequirement)?;
let info = &world.level_info;
// default position for spawning a player, in this case for mob
let pos = pos.unwrap_or(Vector3::new(
f64::from(info.spawn_x),
f64::from(info.spawn_y) + 1.0,
f64::from(info.spawn_z),
));
(world, pos)
}
CommandSender::Player(player) => {
let pos = pos.unwrap_or(player.living_entity.entity.pos.load());
let mob = mob::from_type(entity, pos, &player.world().await).await;
player.world().await.spawn_entity(mob).await;
sender
.send_message(TextComponent::translate(
"commands.summon.success",
[TextComponent::text(format!("{entity:?}"))],
))
.await;
(player.world().await, pos)
}
}
};
let mob = mob::from_type(entity, pos, &world).await;
world.spawn_entity(mob).await;
sender
.send_message(TextComponent::translate(
"commands.summon.success",
[TextComponent::text(format!("{entity:?}"))],
))
.await;
Ok(())
}

View File

@@ -27,14 +27,18 @@ impl CommandExecutor for Executor {
async fn execute<'a>(
&self,
sender: &mut CommandSender,
_server: &crate::server::Server,
server: &crate::server::Server,
args: &ConsumedArgs<'a>,
) -> Result<(), CommandError> {
let world = sender
.world()
.await
.ok_or(CommandError::InvalidRequirement)?;
let duration = TimeArgumentConsumer::find_arg(args, ARG_DURATION).unwrap_or(6000);
let world = {
let guard = server.worlds.read().await;
guard
.first()
.cloned()
.ok_or(CommandError::InvalidRequirement)?
};
let mut weather = world.weather.lock().await;
match self.mode {

View File

@@ -31,7 +31,11 @@ impl PortalManager {
self.ticks_in_portal += 1;
self.ticks_in_portal >= self.portal_delay
} else {
self.ticks_in_portal -= 4;
if self.ticks_in_portal < 4 {
self.ticks_in_portal = 0;
} else {
self.ticks_in_portal -= 4;
}
false
}
}