summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs87
-rw-r--r--src/nbtdsl.rs6
-rw-r--r--src/player.rs48
-rw-r--r--src/world.rs74
4 files changed, 139 insertions, 76 deletions
diff --git a/src/main.rs b/src/main.rs
index 24666d0..a697b08 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,14 +1,14 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+use std::sync::Arc;
use std::time::Duration;
use anyhow::Result;
-use mcproto_rs::nbt::Tag;
use mcproto_rs::protocol::State;
use mcproto_rs::Serializer;
use mcproto_rs::status::{StatusPlayersSpec, StatusSpec, StatusVersionSpec};
-use mcproto_rs::types::{BytesSerializer, Chat, IntPosition, ItemStack, NamedNbtTag, RemainingBytes, Vec3};
+use mcproto_rs::types::{BytesSerializer, Chat, IntPosition, ItemStack, RemainingBytes, Vec3};
use mcproto_rs::uuid::UUID4;
-use mcproto_rs::v1_19_3::{BitSet, BlobArray, ChunkDataAndUpdateLightSpec, ChunkDataSpec, ChunkSection, EntityEventSpec, InitializeWorldBorderSpec, KeepAliveClientBoundSpec, LightDataSpec, PalettedContainer, PluginMessageSpec, SetCenterChunkSpec, SetContainerContentSpec, SetDefaultSpawnPositionSpec, SynchronizePlayerPositionSpec};
+use mcproto_rs::v1_19_3::{EntityEventSpec, InitializeWorldBorderSpec, KeepAliveClientBoundSpec, PluginMessageSpec, SetContainerContentSpec, SetDefaultSpawnPositionSpec};
use mcproto_rs::v1_19_3::{HandshakeNextState, LoginSuccessSpec, Packet761, Packet761Kind, PingRequestSpec, PingResponseSpec, SetHeldItemClientSpec, StatusResponseSpec};
use tokio;
use tokio::net::TcpStream;
@@ -18,11 +18,13 @@ use tokio::sync::broadcast::Receiver;
use tokio::task::JoinHandle;
use crate::connect::MinecraftClient;
+use crate::world::DebugWorld;
pub mod connect;
pub mod nbtdsl;
pub mod player;
pub mod convention;
+pub mod world;
#[tokio::main]
async fn main() -> Result<()> {
@@ -113,18 +115,13 @@ async fn handle_login(mut client: MinecraftClient) -> Result<()> {
properties: vec![].into(),
}))?;
client.set_state(State::Play)?;
- let mut player = player::Player {
- client,
- name: loginstart.name.clone(),
- position: Vec3 {
- x: 0.0,
- y: 100.0,
- z: 0.0,
- },
- yaw: 0.0,
- pitch: 0.0,
- };
- let universe = convention::Universe::default_meta(-64, 256);
+ let mut player = player::Player::new(client, loginstart.name.clone(), Vec3 {
+ x: 0.0,
+ y: 0.0,
+ z: 0.0,
+ }, 0.0, 0.0);
+ let universe = Arc::new(convention::Universe::default_meta(-64, 256));
+ let world = DebugWorld::new(universe.clone());
player.send_packet(universe.create_login_play_packet())?;
let client_information = await_packet!(ClientInformation, player.client);
@@ -143,51 +140,8 @@ async fn handle_login(mut client: MinecraftClient) -> Result<()> {
player.send_packet(universe.empty_commands())?;
player.send_packet(universe.init_empty_recipe_book())?;
player.send_packet(player.create_teleport_packet())?;
- player.send_packet(Packet761::SetCenterChunk(SetCenterChunkSpec {
- chunk_x: 0.into(),
- chunk_z: 0.into(),
- }))?;
- for i in -7..7 {
- for j in -7..7 {
- let mut heightmap = BlobArray::new(9);
- for cx in 0..(16 * 16) {
- heightmap.set_entry(cx, 2)
- }
- let mut chunk_dat_serializer = BytesSerializer::default();
- for i in 0..(universe.max_world_section - universe.min_world_section) {
- let section = ChunkSection {
- block_count: if i < 4 { 16 * 16 * 16 } else { 0 },
- block_state: PalettedContainer { singular_value: if i < 4 { 1.into() } else { 0.into() } },
- biomes: PalettedContainer { singular_value: 0.into() },
- };
- chunk_dat_serializer.serialize_other(&section)?;
- }
- let chunk_column_bytes = chunk_dat_serializer.into_bytes();
- player.send_packet(Packet761::ChunkDataAndUpdateLight(ChunkDataAndUpdateLightSpec {
- chunk_x: i,
- chunk_z: j,
- chunk_data: ChunkDataSpec {
- heightmaps: NamedNbtTag {
- root: nbt! {
- "MOTION_BLOCKING" :: (Tag::LongArray(heightmap.data.iter().map(|n| n.to_owned() as _).collect())),
- "WORLD_SURFACE" :: (Tag::LongArray(heightmap.data.iter().map(|n| n.to_owned() as _).collect())),
- }.with_name("root")
- },
- buffer: chunk_column_bytes.into(),
- block_entities: vec![].into(),
- },
- light_data: LightDataSpec {
- trust_edges: true,
- sky_y_mask: BitSet::empty(),
- block_y_mask: BitSet::empty(),
- empty_sky_y_mask: BitSet::empty(),
- empty_block_y_mask: BitSet::empty(),
- sky_updates: vec![].into(),
- block_updates: vec![].into(),
- },
- }))?;
- }
- }
+ player.synchronize_center_chunk()?;
+ player.send_all_nearby_chunks(&world).await?;
player.send_packet(Packet761::InitializeWorldBorder(InitializeWorldBorderSpec {
x: 0.0,
z: 0.0,
@@ -206,18 +160,7 @@ async fn handle_login(mut client: MinecraftClient) -> Result<()> {
},
angle: 0.0,
}))?;
- player.send_packet(Packet761::SynchronizePlayerPosition(SynchronizePlayerPositionSpec {
- position: Vec3 {
- x: 0f64,
- y: 100f64,
- z: 0f64,
- },
- yaw: 0.0,
- pitch: 0.0,
- flags: Default::default(),
- teleport_id: 0.into(),
- dismount_vehicle: false,
- }))?;
+ player.send_packet(player.create_teleport_packet())?;
player.send_packet(Packet761::SetContainerContent(SetContainerContentSpec {
window_id: 0,
state_id: 0.into(),
diff --git a/src/nbtdsl.rs b/src/nbtdsl.rs
index 86b2116..4e4baa4 100644
--- a/src/nbtdsl.rs
+++ b/src/nbtdsl.rs
@@ -55,21 +55,21 @@ impl ShittyToNbt for f64 {
#[macro_export]
macro_rules! nbt {
( {$($name:literal :: $value:tt),* $(,)? } ) => {
- Tag::Compound(vec![
+ mcproto_rs::nbt::Tag::Compound(vec![
$(
nbt!($value).with_name($name)
),*
])
};
{ $($name:literal :: $value:tt),* $(,)? } => {
- Tag::Compound(vec![
+ mcproto_rs::nbt::Tag::Compound(vec![
$(
nbt!($value).with_name($name)
),*
])
};
([ $($value:tt),* $(,)? ]) => {
- Tag::List(vec![
+ mcproto_rs::nbt::Tag::List(vec![
$(
nbt!($value)
),*
diff --git a/src/player.rs b/src/player.rs
index 7b99c16..e63c8a4 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -1,8 +1,9 @@
use anyhow::Result;
use mcproto_rs::types::Vec3;
-use mcproto_rs::v1_19_3::{Packet761, SynchronizePlayerPositionSpec};
+use mcproto_rs::v1_19_3::{Packet761, SetCenterChunkSpec, SynchronizePlayerPositionSpec};
use crate::connect::MinecraftClient;
+use crate::world::World;
pub struct Player {
pub client: MinecraftClient,
@@ -10,10 +11,23 @@ pub struct Player {
pub position: Vec3<f64>,
pub yaw: f32,
pub pitch: f32,
+ last_center_chunk: Option<(i32, i32)>,
+
}
impl Player {
+ pub fn new(client: MinecraftClient, name: String, position: Vec3<f64>, yaw: f32, pitch: f32) -> Player {
+ Player {
+ client,
+ name,
+ position,
+ yaw,
+ pitch,
+ last_center_chunk: None,
+ }
+ }
+
pub fn create_teleport_packet(&self) -> Packet761 {
Packet761::SynchronizePlayerPosition(SynchronizePlayerPositionSpec {
position: self.position.clone(),
@@ -33,6 +47,38 @@ impl Player {
Ok(())
}
+ pub fn chunk_x(&self) -> i32 {
+ self.position.x.ceil() as i32 / 16
+ }
+
+ pub fn chunk_z(&self) -> i32 {
+ self.position.z.ceil() as i32 / 16
+ }
+
+ pub fn synchronize_center_chunk(&mut self) -> Result<()> {
+ let cx = self.chunk_x();
+ let cz = self.chunk_z();
+ let tup = Some((cx, cz));
+ if self.last_center_chunk != tup {
+ self.last_center_chunk = tup;
+ self.send_packet(Packet761::SetCenterChunk(SetCenterChunkSpec {
+ chunk_x: cx.into(),
+ chunk_z: cz.into(),
+ }))?;
+ }
+ Ok(())
+ }
+
+ pub async fn send_all_nearby_chunks(&self, world: &(dyn World + Sync + Send)) -> Result<()> {
+ // TODO: proper chunk observing
+ for x_off in -7..7 {
+ for z_off in -7..7 {
+ world.send_chunk(&self, self.chunk_x() + x_off, self.chunk_z() + z_off).await?;
+ }
+ }
+ Ok(())
+ }
+
pub fn send_packet(&self, packet: Packet761) -> Result<()> {
self.client.send_packet(packet)
}
diff --git a/src/world.rs b/src/world.rs
new file mode 100644
index 0000000..a1c7e11
--- /dev/null
+++ b/src/world.rs
@@ -0,0 +1,74 @@
+use std::sync::Arc;
+
+use anyhow::Result;
+use async_trait::async_trait;
+use mcproto_rs::nbt::Tag;
+use mcproto_rs::Serializer;
+use mcproto_rs::types::{BytesSerializer, NamedNbtTag};
+use mcproto_rs::v1_19_3::{BitSet, BlobArray, ChunkDataAndUpdateLightSpec, ChunkDataSpec, ChunkSection, LightDataSpec, Packet761, PalettedContainer};
+
+use crate::convention::Universe;
+use crate::nbt;
+use crate::player::Player;
+
+#[async_trait]
+pub trait World {
+ async fn send_chunk(&self, observer: &Player, chunk_x: i32, chunk_z: i32) -> Result<()>;
+}
+
+pub struct DebugWorld {
+ universe: Arc<Universe>,
+}
+
+impl DebugWorld {
+ pub fn new(universe: Arc<Universe>) -> DebugWorld {
+ DebugWorld { universe }
+ }
+}
+
+#[async_trait]
+impl World for DebugWorld {
+ async fn send_chunk(&self, observer: &Player, chunk_x: i32, chunk_z: i32) -> Result<()> {
+ let mut heightmap = BlobArray::new(9);
+ for cx in 0..(16 * 16) {
+ heightmap.set_entry(cx, 2)
+ }
+ let mut chunk_dat_serializer = BytesSerializer::default();
+ for i in 0..(self.universe.max_world_section - self.universe.min_world_section) {
+ let section = ChunkSection {
+ block_count: if i < 4 { 16 * 16 * 16 } else { 0 },
+ block_state: PalettedContainer { singular_value: if i < 4 { 1.into() } else { 0.into() } },
+ biomes: PalettedContainer { singular_value: 0.into() },
+ };
+ chunk_dat_serializer.serialize_other(&section)?;
+ }
+ let chunk_column_bytes = chunk_dat_serializer.into_bytes();
+ observer.send_packet(Packet761::ChunkDataAndUpdateLight(ChunkDataAndUpdateLightSpec {
+ chunk_x,
+ chunk_z,
+ chunk_data: ChunkDataSpec {
+ heightmaps: NamedNbtTag {
+ root: nbt! {
+ "MOTION_BLOCKING" :: (Tag::LongArray(heightmap.data.iter().map(|n| n.to_owned() as _).collect())),
+ "WORLD_SURFACE" :: (Tag::LongArray(heightmap.data.iter().map(|n| n.to_owned() as _).collect())),
+ }.with_name("root")
+ },
+ buffer: chunk_column_bytes.into(),
+ block_entities: vec![].into(),
+ },
+ light_data: LightDataSpec {
+ trust_edges: true,
+ sky_y_mask: BitSet::empty(),
+ block_y_mask: BitSet::empty(),
+ empty_sky_y_mask: BitSet::empty(),
+ empty_block_y_mask: BitSet::empty(),
+ sky_updates: vec![].into(),
+ block_updates: vec![].into(),
+ },
+ }))?;
+ Ok(())
+ }
+}
+
+
+