diff --git a/pumpkin/src/command/commands/teleport.rs b/pumpkin/src/command/commands/teleport.rs index 4f7afcf77..b4d384392 100644 --- a/pumpkin/src/command/commands/teleport.rs +++ b/pumpkin/src/command/commands/teleport.rs @@ -12,6 +12,7 @@ use crate::command::args::rotation::RotationArgumentConsumer; use crate::command::tree::CommandTree; use crate::command::tree::builder::{argument, literal}; use crate::command::{CommandExecutor, CommandSender}; +use crate::world::World; const NAMES: [&str; 2] = ["teleport", "tp"]; const DESCRIPTION: &str = "Teleports entities, including players."; // todo @@ -63,7 +64,11 @@ impl CommandExecutor for EntitiesToEntityExecutor { let destination = EntityArgumentConsumer::find_arg(args, ARG_DESTINATION)?; let pos = destination.living_entity.entity.pos.load(); - + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } for target in targets { let yaw = target.living_entity.entity.yaw.load(); let pitch = target.living_entity.entity.pitch.load(); @@ -87,7 +92,11 @@ impl CommandExecutor for EntitiesToPosFacingPosExecutor { let targets = EntitiesArgumentConsumer::find_arg(args, ARG_TARGETS)?; let pos = Position3DArgumentConsumer::find_arg(args, ARG_LOCATION)?; - + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } let facing_pos = Position3DArgumentConsumer::find_arg(args, ARG_FACING_LOCATION)?; let (yaw, pitch) = yaw_pitch_facing_position(&pos, &facing_pos); @@ -112,7 +121,11 @@ impl CommandExecutor for EntitiesToPosFacingEntityExecutor { let targets = EntitiesArgumentConsumer::find_arg(args, ARG_TARGETS)?; let pos = Position3DArgumentConsumer::find_arg(args, ARG_LOCATION)?; - + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } let facing_entity = &EntityArgumentConsumer::find_arg(args, ARG_FACING_ENTITY)? .living_entity .entity; @@ -139,7 +152,11 @@ impl CommandExecutor for EntitiesToPosWithRotationExecutor { let targets = EntitiesArgumentConsumer::find_arg(args, ARG_TARGETS)?; let pos = Position3DArgumentConsumer::find_arg(args, ARG_LOCATION)?; - + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } let (yaw, pitch) = RotationArgumentConsumer::find_arg(args, ARG_ROTATION)?; for target in targets { @@ -163,7 +180,11 @@ impl CommandExecutor for EntitiesToPosExecutor { let targets = EntitiesArgumentConsumer::find_arg(args, ARG_TARGETS)?; let pos = Position3DArgumentConsumer::find_arg(args, ARG_LOCATION)?; - + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } for target in targets { let yaw = target.living_entity.entity.yaw.load(); let pitch = target.living_entity.entity.pitch.load(); @@ -191,6 +212,11 @@ impl CommandExecutor for SelfToEntityExecutor { CommandSender::Player(player) => { let yaw = player.living_entity.entity.yaw.load(); let pitch = player.living_entity.entity.pitch.load(); + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } player.teleport(pos, yaw, pitch).await; } _ => { @@ -203,7 +229,6 @@ impl CommandExecutor for SelfToEntityExecutor { Ok(()) } } - struct SelfToPosExecutor; #[async_trait] @@ -219,6 +244,11 @@ impl CommandExecutor for SelfToPosExecutor { let pos = Position3DArgumentConsumer::find_arg(args, ARG_LOCATION)?; let yaw = player.living_entity.entity.yaw.load(); let pitch = player.living_entity.entity.pitch.load(); + if !World::is_valid(pos) { + return Err(CommandError::CommandFailed(Box::new( + TextComponent::translate("argument.pos.outofbounds", []), + ))); + } player.teleport(pos, yaw, pitch).await; } _ => { diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 700508ec1..0b581ad13 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -203,7 +203,7 @@ impl World { players: Arc::new(RwLock::new(HashMap::new())), entities: Arc::new(RwLock::new(HashMap::new())), scoreboard: Mutex::new(Scoreboard::new()), - worldborder: Mutex::new(Worldborder::new(0.0, 0.0, 29_999_984.0, 0, 0, 0)), + worldborder: Mutex::new(Worldborder::new(0.0, 0.0, 30_000_000.0, 0, 0, 0)), level_time: Mutex::new(LevelTime::new()), dimension_type, weather: Mutex::new(Weather::new()), @@ -1983,7 +1983,19 @@ impl World { self.broadcast_packet_all(&CWorldEvent::new(world_event as i32, position, data, false)) .await; } - + #[must_use] + pub fn is_valid(dest: Vector3) -> bool { + Self::is_valid_horizontally(dest) && Self::is_valid_vertically(dest.y) + } + #[must_use] + pub fn is_valid_horizontally(dest: Vector3) -> bool { + (-30_000_000.0..=30_000_000.0).contains(&dest.x) + && (-30_000_000.0..=30_000_000.0).contains(&dest.z) + } + #[must_use] + pub fn is_valid_vertically(y: f64) -> bool { + (-20_000_000.0..=20_000_000.0).contains(&y) + } /// Gets a `Block` from the block registry. Returns `Block::AIR` if the block was not found. pub async fn get_block(&self, position: &BlockPos) -> &'static pumpkin_data::Block { let id = self.get_block_state_id(position).await;