feat(bedrock): add block breaking
This commit is contained in:
parent
e035a5fb58
commit
4616289fbe
@ -4,6 +4,7 @@ pub mod container_close;
|
||||
pub mod interaction;
|
||||
pub mod loading_screen;
|
||||
pub mod login;
|
||||
pub mod player_action;
|
||||
pub mod player_auth_input;
|
||||
pub mod raknet;
|
||||
pub mod request_chunk_radius;
|
||||
|
||||
104
pumpkin-protocol/src/bedrock/server/player_action.rs
Normal file
104
pumpkin-protocol/src/bedrock/server/player_action.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use std::io::{Error, Read};
|
||||
|
||||
use pumpkin_macros::packet;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
use crate::{codec::var_int::VarInt, serial::PacketRead};
|
||||
|
||||
#[derive(Debug, PacketRead)]
|
||||
#[packet(36)]
|
||||
pub struct SPlayerAction {
|
||||
pub runtime_id: VarInt,
|
||||
pub action: Action,
|
||||
pub block_pos: BlockPos,
|
||||
pub result_pos: BlockPos,
|
||||
pub face: VarInt,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(i32)]
|
||||
pub enum Action {
|
||||
StartBreak = 0,
|
||||
AbortBreak = 1,
|
||||
StopBreak = 2,
|
||||
GetUpdatedBlock = 3,
|
||||
DropItem = 4,
|
||||
StartSleeping = 5,
|
||||
StopSleeping = 6,
|
||||
Respawn = 7,
|
||||
Jump = 8,
|
||||
StartSprint = 9,
|
||||
StopSprint = 10,
|
||||
StartSneak = 11,
|
||||
StopSneak = 12,
|
||||
CreativePlayerDestroyBlock = 13,
|
||||
DimensionChangeAck = 14,
|
||||
StartGlide = 15,
|
||||
StopGlide = 16,
|
||||
BuildDenied = 17,
|
||||
CrackBreak = 18,
|
||||
ChangeSkin = 19,
|
||||
SetEnchantmentSeed = 20,
|
||||
Swimming = 21,
|
||||
StopSwimming = 22,
|
||||
StartSpinAttack = 23,
|
||||
StopSpinAttack = 24,
|
||||
InteractBlock = 25,
|
||||
PredictDestroyBlock = 26,
|
||||
ContinueDestroyBlock = 27,
|
||||
StartItemUseOn = 28,
|
||||
StopItemUseOn = 29,
|
||||
HandledTeleport = 30,
|
||||
MissedSwing = 31,
|
||||
StartCrawling = 32,
|
||||
StopCrawling = 33,
|
||||
StartFlying = 34,
|
||||
StopFlying = 35,
|
||||
ClientAckServerData = 36,
|
||||
}
|
||||
|
||||
impl PacketRead for Action {
|
||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let action = VarInt::read(reader)?;
|
||||
match action.0 {
|
||||
0 => Ok(Self::StartBreak),
|
||||
1 => Ok(Self::AbortBreak),
|
||||
2 => Ok(Self::StopBreak),
|
||||
3 => Ok(Self::GetUpdatedBlock),
|
||||
4 => Ok(Self::DropItem),
|
||||
5 => Ok(Self::StartSleeping),
|
||||
6 => Ok(Self::StopSleeping),
|
||||
7 => Ok(Self::Respawn),
|
||||
8 => Ok(Self::Jump),
|
||||
9 => Ok(Self::StartSprint),
|
||||
10 => Ok(Self::StopSprint),
|
||||
11 => Ok(Self::StartSneak),
|
||||
12 => Ok(Self::StopSneak),
|
||||
13 => Ok(Self::CreativePlayerDestroyBlock),
|
||||
14 => Ok(Self::DimensionChangeAck),
|
||||
15 => Ok(Self::StartGlide),
|
||||
16 => Ok(Self::StopGlide),
|
||||
17 => Ok(Self::BuildDenied),
|
||||
18 => Ok(Self::CrackBreak),
|
||||
19 => Ok(Self::ChangeSkin),
|
||||
20 => Ok(Self::SetEnchantmentSeed),
|
||||
21 => Ok(Self::Swimming),
|
||||
22 => Ok(Self::StopSwimming),
|
||||
23 => Ok(Self::StartSpinAttack),
|
||||
24 => Ok(Self::StopSpinAttack),
|
||||
25 => Ok(Self::InteractBlock),
|
||||
26 => Ok(Self::PredictDestroyBlock),
|
||||
27 => Ok(Self::ContinueDestroyBlock),
|
||||
28 => Ok(Self::StartItemUseOn),
|
||||
29 => Ok(Self::StopItemUseOn),
|
||||
30 => Ok(Self::HandledTeleport),
|
||||
31 => Ok(Self::MissedSwing),
|
||||
32 => Ok(Self::StartCrawling),
|
||||
33 => Ok(Self::StopCrawling),
|
||||
34 => Ok(Self::StartFlying),
|
||||
35 => Ok(Self::StopFlying),
|
||||
36 => Ok(Self::ClientAckServerData),
|
||||
_ => Err(Error::other(format!("Invalid action ID: {}", action.0))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,10 +3,13 @@ use std::{
|
||||
net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
|
||||
};
|
||||
|
||||
use pumpkin_util::math::{vector2::Vector2, vector3::Vector3};
|
||||
use pumpkin_util::math::{position::BlockPos, vector2::Vector2, vector3::Vector3};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{codec::var_uint::VarUInt, serial::PacketRead};
|
||||
use crate::{
|
||||
codec::{var_int::VarInt, var_uint::VarUInt},
|
||||
serial::PacketRead,
|
||||
};
|
||||
|
||||
impl PacketRead for bool {
|
||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
@ -187,6 +190,16 @@ impl<T: PacketRead> PacketRead for Vector2<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketRead for BlockPos {
|
||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
Ok(Self(Vector3 {
|
||||
x: VarInt::read(reader)?.0,
|
||||
y: VarInt::read(reader)?.0,
|
||||
z: VarInt::read(reader)?.0,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketRead for SocketAddr {
|
||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
match u8::read(reader)? {
|
||||
|
||||
@ -28,6 +28,7 @@ use pumpkin_protocol::{
|
||||
interaction::SInteraction,
|
||||
loading_screen::SLoadingScreen,
|
||||
login::SLogin,
|
||||
player_action::SPlayerAction,
|
||||
player_auth_input::SPlayerAuthInput,
|
||||
raknet::{
|
||||
connection::{
|
||||
@ -586,6 +587,10 @@ impl BedrockClient {
|
||||
self.handle_chat_command(player, server, SCommandRequest::read(reader)?)
|
||||
.await;
|
||||
}
|
||||
SPlayerAction::PACKET_ID => {
|
||||
self.handle_player_action(player, server, SPlayerAction::read(reader)?)
|
||||
.await;
|
||||
}
|
||||
_ => {
|
||||
warn!("Bedrock: Received Unknown Game packet: {}", packet.id);
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ use pumpkin_protocol::{
|
||||
command_request::SCommandRequest,
|
||||
container_close::SContainerClose,
|
||||
interaction::{Action, SInteraction},
|
||||
player_action::{Action as PlayerAction, SPlayerAction},
|
||||
player_auth_input::{InputData, SPlayerAuthInput},
|
||||
request_chunk_radius::SRequestChunkRadius,
|
||||
text::SText,
|
||||
@ -19,7 +20,9 @@ use pumpkin_protocol::{
|
||||
codec::{var_int::VarInt, var_long::VarLong},
|
||||
java::client::play::CSystemChatMessage,
|
||||
};
|
||||
use pumpkin_util::{math::position::BlockPos, text::TextComponent};
|
||||
use pumpkin_util::{GameMode, math::position::BlockPos, text::TextComponent};
|
||||
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
use crate::{
|
||||
entity::{EntityBase, player::Player},
|
||||
@ -210,6 +213,69 @@ impl BedrockClient {
|
||||
}}
|
||||
}
|
||||
|
||||
pub async fn handle_player_action(
|
||||
&self,
|
||||
player: &Arc<Player>,
|
||||
server: &Server,
|
||||
packet: SPlayerAction,
|
||||
) {
|
||||
if !player.has_client_loaded() {
|
||||
return;
|
||||
}
|
||||
|
||||
match packet.action {
|
||||
PlayerAction::StartBreak | PlayerAction::CreativePlayerDestroyBlock => {
|
||||
let location = packet.block_pos;
|
||||
if !player.can_interact_with_block_at(&location, 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let entity = &player.living_entity.entity;
|
||||
let world = entity.world.load_full();
|
||||
let (block, state) = world.get_block_and_state(&location).await;
|
||||
|
||||
if player.gamemode.load() == GameMode::Creative {
|
||||
let new_state = world
|
||||
.break_block(
|
||||
&location,
|
||||
Some(player.clone()),
|
||||
BlockFlags::NOTIFY_NEIGHBORS | BlockFlags::SKIP_DROPS,
|
||||
)
|
||||
.await;
|
||||
if new_state.is_some() {
|
||||
server
|
||||
.block_registry
|
||||
.broken(&world, block, player, &location, server, state)
|
||||
.await;
|
||||
}
|
||||
} else if !state.is_air() {
|
||||
let speed = crate::block::calc_block_breaking(player, state, block).await;
|
||||
if speed >= 1.0 {
|
||||
let broken_state = world.get_block_state(&location).await;
|
||||
let new_state = world
|
||||
.break_block(
|
||||
&location,
|
||||
Some(player.clone()),
|
||||
BlockFlags::NOTIFY_NEIGHBORS,
|
||||
)
|
||||
.await;
|
||||
if new_state.is_some() {
|
||||
server
|
||||
.block_registry
|
||||
.broken(&world, block, player, &location, server, broken_state)
|
||||
.await;
|
||||
player.apply_tool_damage_for_block_break(broken_state).await;
|
||||
}
|
||||
} else {
|
||||
// TODO: Survival progressive breaking
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_chat_command(
|
||||
&self,
|
||||
player: &Arc<Player>,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user