mirror of
https://github.com/G2-Games/minecraft_alpha_server.git
synced 2025-04-18 23:03:00 -05:00
Flat world generation works
This commit is contained in:
parent
ca67f15d46
commit
afd0a48527
5 changed files with 253 additions and 181 deletions
61
Cargo.lock
generated
61
Cargo.lock
generated
|
@ -78,15 +78,6 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
|
@ -135,26 +126,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.2"
|
||||
|
@ -188,16 +159,6 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
|
@ -239,15 +200,6 @@ version = "0.4.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "md2"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4f0f3ed25ff4f8d8d102288d92f900efc202661c884cf67dfe4f0d07c43d1f"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.7.0"
|
||||
|
@ -269,7 +221,6 @@ dependencies = [
|
|||
"colog",
|
||||
"flate2",
|
||||
"log",
|
||||
"md2",
|
||||
"md5",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
|
@ -402,12 +353,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
|
@ -420,12 +365,6 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
|
|
@ -9,7 +9,6 @@ byteorder = "1.5.0"
|
|||
colog = "1.3.0"
|
||||
flate2 = "1.0.34"
|
||||
log = "0.4.22"
|
||||
md2 = "0.10.2"
|
||||
md5 = "0.7.0"
|
||||
num-derive = "0.4.2"
|
||||
num-traits = "0.2.19"
|
||||
|
|
39
src/chunk.rs
39
src/chunk.rs
|
@ -62,6 +62,45 @@ impl BlockArray {
|
|||
compressed_data: output_buf,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_superflat() -> Self {
|
||||
let mut block_vec = vec![0; 16 * 16 * 128];
|
||||
|
||||
for x in 0..16 {
|
||||
for y in 0..128 {
|
||||
for z in 0..16 {
|
||||
let pos = y + (z * (128)) + (x * (128) * (16));
|
||||
if y == 7 {
|
||||
block_vec[pos] = BlockType::Grass as u8;
|
||||
} else if y > 0 && y < 7 {
|
||||
block_vec[pos] = BlockType::Dirt as u8;
|
||||
} else if y == 0 {
|
||||
block_vec[pos] = BlockType::Bedrock as u8;
|
||||
} else {
|
||||
block_vec[pos] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _ in 0..(16 * 128 * 16) / 2 {
|
||||
block_vec.push(0);
|
||||
}
|
||||
for _ in 0..(16 * 128 * 16) / 2 {
|
||||
block_vec.push(0);
|
||||
}
|
||||
for _ in 0..(16 * 128 * 16) / 2 {
|
||||
block_vec.push(0xFF);
|
||||
}
|
||||
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
encoder.write(&block_vec).unwrap();
|
||||
let output_buf = encoder.finish().unwrap();
|
||||
|
||||
Self {
|
||||
compressed_size: output_buf.len() as i32,
|
||||
compressed_data: output_buf,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
|
|
196
src/main.rs
196
src/main.rs
|
@ -1,8 +1,9 @@
|
|||
mod utils;
|
||||
mod byte_ops;
|
||||
mod chunk;
|
||||
mod position;
|
||||
|
||||
use std::{io::{self, Read, Write}, net::{TcpListener, TcpStream}};
|
||||
use std::{cell::LazyCell, io::{self, Write}, net::{TcpListener, TcpStream}};
|
||||
|
||||
use base16ct::lower::encode_string;
|
||||
use chunk::{BlockArray, MapChunk, PreChunk};
|
||||
|
@ -11,9 +12,23 @@ use byteorder::{ReadBytesExt, WriteBytesExt, BE};
|
|||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use byte_ops::ToBytes;
|
||||
use position::{PlayerLook, PlayerPosition, PlayerPositionAndLook};
|
||||
use utils::{MCString, ReadMCString, WriteMCString};
|
||||
use rand::random;
|
||||
|
||||
const CHUNKS: LazyCell<Vec<MapChunk>> = LazyCell::new(|| {
|
||||
let mut mapchunk = Vec::new();
|
||||
for i in -10..10 {
|
||||
for o in -10..10 {
|
||||
let x = i * 16;
|
||||
let z = o * 16;
|
||||
|
||||
mapchunk.push(MapChunk::new(x, z, BlockArray::new_superflat()));
|
||||
}
|
||||
}
|
||||
|
||||
mapchunk
|
||||
});
|
||||
|
||||
fn main() {
|
||||
colog::default_builder()
|
||||
|
@ -26,7 +41,9 @@ fn main() {
|
|||
info!("Connected to client @ {}", connection.peer_addr().unwrap());
|
||||
while let Some(cmd) = connection.read_u8().ok() {
|
||||
let command = Command::from_u8(cmd);
|
||||
if command.is_none() {
|
||||
info!("COMMAND: {command:?} (0x{cmd:02X?})");
|
||||
}
|
||||
handle_command(&mut connection, command.unwrap()).unwrap();
|
||||
}
|
||||
warn!("Lost connection to client");
|
||||
|
@ -35,7 +52,6 @@ fn main() {
|
|||
|
||||
fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<(), io::Error> {
|
||||
match command {
|
||||
Command::KeepAlive => todo!(),
|
||||
Command::Handshake => {
|
||||
let username = connection.read_mcstring()?;
|
||||
let random_number = random::<u128>();
|
||||
|
@ -61,10 +77,10 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
info!("Dimension: {dimension}");
|
||||
|
||||
let login_packet = ServerLoginPacket {
|
||||
entity_id: 1200,
|
||||
entity_id: 1,
|
||||
unknown1: MCString::default(),
|
||||
unknown2: MCString::default(),
|
||||
map_seed: 1715505462032542147,
|
||||
map_seed: 0,
|
||||
dimension: 0,
|
||||
};
|
||||
connection.write_u8(Command::Login as u8).unwrap();
|
||||
|
@ -72,16 +88,16 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
|
||||
info!("Responded to auth request");
|
||||
|
||||
for i in 0..7 {
|
||||
for o in 0..7 {
|
||||
let x = (-4 + i) * 16;
|
||||
let z = (-5 + o) * 16;
|
||||
for i in -10..10 {
|
||||
for o in -10..10 {
|
||||
let x = i * 16;
|
||||
let z = o * 16;
|
||||
|
||||
connection.write_u8(Command::PreChunk as u8).unwrap();
|
||||
connection.write_all(&PreChunk::new_load(x, z).to_bytes()).unwrap();
|
||||
|
||||
connection.write_u8(Command::MapChunk as u8)?;
|
||||
connection.write_all(&MapChunk::new(x, z, BlockArray::new_air()).to_bytes())?;
|
||||
connection.write_all(&MapChunk::new(x, z, BlockArray::new_superflat()).to_bytes())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,29 +107,74 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
connection.write_u32::<BE>(0)?;
|
||||
|
||||
let playerpos = PlayerPositionAndLook {
|
||||
position_x: 0.0,
|
||||
position: PlayerPosition {
|
||||
position_x: 1.0,
|
||||
stance: 0.0,
|
||||
position_y: 70.0,
|
||||
position_z: 0.0,
|
||||
position_y: 9.63,
|
||||
position_z: 1.0,
|
||||
},
|
||||
look: PlayerLook {
|
||||
yaw: 0.0,
|
||||
pitch: 0.0,
|
||||
on_ground: true,
|
||||
},
|
||||
};
|
||||
connection.write_u8(Command::PlayerPositionAndLook as u8)?;
|
||||
connection.write_all(&playerpos.to_bytes())?;
|
||||
},
|
||||
Command::PlayerPositionAndLook => {
|
||||
let _poslook = PlayerPositionAndLook::from_bytes(&mut connection);
|
||||
Command::ChatMessage => {
|
||||
info!("Chat Message Recieved: {}", connection.read_mcstring().unwrap());
|
||||
}
|
||||
Command::Player => {
|
||||
connection.read_u8()?;
|
||||
},
|
||||
Command::PlayerLook => {
|
||||
let _look = PlayerLook::from_bytes(&mut connection);
|
||||
}
|
||||
Command::PlayerPosition => {
|
||||
let _pos = PlayerPosition::from_bytes(&mut connection);
|
||||
}
|
||||
Command::PlayerPositionAndLook => {
|
||||
let _poslook = PlayerPositionAndLook::from_bytes(&mut connection);
|
||||
}
|
||||
Command::PlayerDigging => {
|
||||
let status = DiggingStatus::from_u8(connection.read_u8()?).unwrap();
|
||||
let pos_x = connection.read_i32::<BE>()?;
|
||||
let pos_y = connection.read_u8()?;
|
||||
let pos_z = connection.read_i32::<BE>()?;
|
||||
let face = connection.read_u8()?;
|
||||
}
|
||||
Command::ArmAnimation => {
|
||||
let eid = connection.read_i32::<BE>()?;
|
||||
let animate = connection.read_u8()? != 0;
|
||||
}
|
||||
Command::Disconnect => {
|
||||
let disconnect_string = connection.read_mcstring()?;
|
||||
info!("Disconnecting client: {disconnect_string}");
|
||||
connection.shutdown(std::net::Shutdown::Both)?;
|
||||
}
|
||||
Command::KeepAlive => {
|
||||
let _ = connection.write_u8(0x00);
|
||||
// TODO: Feed keepalive watchdog for client
|
||||
}
|
||||
Command::UpdateHealth => {
|
||||
connection.read_u8()?;
|
||||
}
|
||||
c => unimplemented!("This command ({c:?}) is probably `Server -> Client` only")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(FromPrimitive)]
|
||||
enum DiggingStatus {
|
||||
StartedDigging = 0,
|
||||
Digging = 1,
|
||||
StoppedDigging = 2,
|
||||
BlockBroken = 3,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(FromPrimitive)]
|
||||
|
@ -127,18 +188,17 @@ enum Command {
|
|||
SpawnPosition = 0x06,
|
||||
UpdateHealth = 0x08,
|
||||
Respawn = 0x09,
|
||||
PlayerPositionAndLook = 0x0D,
|
||||
Player = 0x0A,
|
||||
PlayerPosition = 0x0B,
|
||||
PlayerLook = 0x0C,
|
||||
PlayerPositionAndLook = 0x0D,
|
||||
PlayerDigging = 0x0E,
|
||||
ArmAnimation = 0x12,
|
||||
PreChunk = 0x32,
|
||||
MapChunk = 0x33,
|
||||
Disconnect = 0xFF,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct CommandError {
|
||||
_id: u8,
|
||||
}
|
||||
|
||||
struct ServerLoginPacket {
|
||||
entity_id: i32,
|
||||
unknown1: MCString,
|
||||
|
@ -161,97 +221,3 @@ impl ToBytes for ServerLoginPacket {
|
|||
out_buf
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct PlayerPositionAndLook {
|
||||
position_x: f64,
|
||||
stance: f64,
|
||||
position_y: f64,
|
||||
position_z: f64,
|
||||
yaw: f32,
|
||||
pitch: f32,
|
||||
on_ground: bool,
|
||||
}
|
||||
|
||||
impl ToBytes for PlayerPositionAndLook {
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
fn to_bytes(self) -> Self::Bytes {
|
||||
let mut out_buf = Vec::new();
|
||||
out_buf.write_f64::<BE>(self.position_x).unwrap();
|
||||
out_buf.write_f64::<BE>(self.stance).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position_y).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position_z).unwrap();
|
||||
out_buf.write_f32::<BE>(self.yaw).unwrap();
|
||||
out_buf.write_f32::<BE>(self.pitch).unwrap();
|
||||
out_buf.write_u8(self.on_ground as u8).unwrap();
|
||||
|
||||
out_buf
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerPositionAndLook {
|
||||
fn from_bytes<R: Read>(stream: &mut R) -> Self {
|
||||
let position_x = stream.read_f64::<BE>().unwrap();
|
||||
let position_y = stream.read_f64::<BE>().unwrap();
|
||||
let stance = stream.read_f64::<BE>().unwrap();
|
||||
let position_z = stream.read_f64::<BE>().unwrap();
|
||||
|
||||
let yaw = stream.read_f32::<BE>().unwrap();
|
||||
let pitch = stream.read_f32::<BE>().unwrap();
|
||||
let on_ground = stream.read_u8().unwrap() != 0;
|
||||
|
||||
Self {
|
||||
position_x,
|
||||
stance,
|
||||
position_y,
|
||||
position_z,
|
||||
yaw,
|
||||
pitch,
|
||||
on_ground
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct PlayerPosition {
|
||||
position_x: f64,
|
||||
position_y: f64,
|
||||
stance: f64,
|
||||
position_z: f64,
|
||||
on_ground: bool,
|
||||
}
|
||||
|
||||
impl ToBytes for PlayerPosition {
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
fn to_bytes(self) -> Self::Bytes {
|
||||
let mut out_buf = Vec::new();
|
||||
out_buf.write_f64::<BE>(self.position_x).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position_y).unwrap();
|
||||
out_buf.write_f64::<BE>(self.stance).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position_z).unwrap();
|
||||
out_buf.write_u8(self.on_ground as u8).unwrap();
|
||||
|
||||
out_buf
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerPosition {
|
||||
fn from_bytes<R: Read>(stream: &mut R) -> Self {
|
||||
let position_x = stream.read_f64::<BE>().unwrap();
|
||||
let position_y = stream.read_f64::<BE>().unwrap();
|
||||
let stance = stream.read_f64::<BE>().unwrap();
|
||||
let position_z = stream.read_f64::<BE>().unwrap();
|
||||
|
||||
let on_ground = stream.read_u8().unwrap() != 0;
|
||||
|
||||
Self {
|
||||
position_x,
|
||||
stance,
|
||||
position_y,
|
||||
position_z,
|
||||
on_ground
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
129
src/position.rs
Normal file
129
src/position.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
use std::io::Read;
|
||||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt, BE};
|
||||
|
||||
use crate::byte_ops::ToBytes;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PlayerPositionAndLook {
|
||||
pub position: PlayerPosition,
|
||||
pub look: PlayerLook,
|
||||
}
|
||||
|
||||
impl ToBytes for PlayerPositionAndLook {
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
fn to_bytes(self) -> Self::Bytes {
|
||||
let mut out_buf = Vec::new();
|
||||
out_buf.write_f64::<BE>(self.position.position_x).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position.position_y).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position.stance).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position.position_z).unwrap();
|
||||
out_buf.write_f32::<BE>(self.look.yaw).unwrap();
|
||||
out_buf.write_f32::<BE>(self.look.pitch).unwrap();
|
||||
out_buf.write_u8(true as u8).unwrap();
|
||||
|
||||
out_buf
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerPositionAndLook {
|
||||
pub fn from_bytes<R: Read>(stream: &mut R) -> Self {
|
||||
let position_x = stream.read_f64::<BE>().unwrap();
|
||||
let position_y = stream.read_f64::<BE>().unwrap();
|
||||
let stance = stream.read_f64::<BE>().unwrap();
|
||||
let position_z = stream.read_f64::<BE>().unwrap();
|
||||
|
||||
let yaw = stream.read_f32::<BE>().unwrap();
|
||||
let pitch = stream.read_f32::<BE>().unwrap();
|
||||
|
||||
let _on_ground = stream.read_u8().unwrap();
|
||||
|
||||
Self {
|
||||
position: PlayerPosition {
|
||||
position_x,
|
||||
stance,
|
||||
position_y,
|
||||
position_z,
|
||||
},
|
||||
look: PlayerLook {
|
||||
yaw,
|
||||
pitch,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PlayerPosition {
|
||||
pub position_x: f64,
|
||||
pub position_y: f64,
|
||||
pub stance: f64,
|
||||
pub position_z: f64,
|
||||
}
|
||||
|
||||
impl ToBytes for PlayerPosition {
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
fn to_bytes(self) -> Self::Bytes {
|
||||
let mut out_buf = Vec::new();
|
||||
out_buf.write_f64::<BE>(self.position_x).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position_y).unwrap();
|
||||
out_buf.write_f64::<BE>(self.stance).unwrap();
|
||||
out_buf.write_f64::<BE>(self.position_z).unwrap();
|
||||
out_buf.write_u8(1).unwrap();
|
||||
|
||||
out_buf
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerPosition {
|
||||
pub fn from_bytes<R: Read>(stream: &mut R) -> Self {
|
||||
let position_x = stream.read_f64::<BE>().unwrap();
|
||||
let position_y = stream.read_f64::<BE>().unwrap();
|
||||
let stance = stream.read_f64::<BE>().unwrap();
|
||||
let position_z = stream.read_f64::<BE>().unwrap();
|
||||
|
||||
let _on_ground = stream.read_u8().unwrap() != 0;
|
||||
|
||||
Self {
|
||||
position_x,
|
||||
stance,
|
||||
position_y,
|
||||
position_z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PlayerLook {
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
}
|
||||
|
||||
impl ToBytes for PlayerLook {
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
fn to_bytes(self) -> Self::Bytes {
|
||||
let mut out_buf = Vec::new();
|
||||
out_buf.write_f32::<BE>(self.yaw).unwrap();
|
||||
out_buf.write_f32::<BE>(self.pitch).unwrap();
|
||||
out_buf.write_u8(1).unwrap();
|
||||
|
||||
out_buf
|
||||
}
|
||||
}
|
||||
|
||||
impl PlayerLook {
|
||||
pub fn from_bytes<R: Read>(stream: &mut R) -> Self {
|
||||
let yaw = stream.read_f32::<BE>().unwrap();
|
||||
let pitch = stream.read_f32::<BE>().unwrap();
|
||||
|
||||
let _on_ground = stream.read_u8().unwrap() != 0;
|
||||
|
||||
Self {
|
||||
yaw,
|
||||
pitch,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue