diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | Cargo.toml | 9 | ||||
-rw-r--r-- | packetorder.txt | 159 | ||||
-rw-r--r-- | rust-toolchain.toml | 2 | ||||
-rw-r--r-- | src/main.rs | 179 |
5 files changed, 335 insertions, 15 deletions
@@ -104,7 +104,6 @@ dependencies = [ [[package]] name = "craftio-rs" version = "0.1.0" -source = "git+https://github.com/romangraef/craftio-rs.git?branch=fix/read_packet_len#565eb610bd4da8110eabcb79bd06b66c1c815384" dependencies = [ "aes", "async-trait", @@ -22,12 +22,11 @@ version = "*" version = "*" features = ["default", "v1_19_3"] +[patch.crates-io.craftio-rs] +# git = "https://github.com/Twister915/craftio-rs.git" +path = "../craftio-rs" + [patch.crates-io.mcproto-rs] # git = "https://github.com/Web-44/mcproto-rs.git" path = "../mcproto-rs" -[patch.crates-io.craftio-rs] -git = "https://github.com/romangraef/craftio-rs.git" -branch = "fix/read_packet_len" - - diff --git a/packetorder.txt b/packetorder.txt new file mode 100644 index 0000000..89c9f4d --- /dev/null +++ b/packetorder.txt @@ -0,0 +1,159 @@ +0 0x0 ClientboundAddEntityPacket +1 0x1 ClientboundAddExperienceOrbPacket +2 0x2 ClientboundAddPlayerPacket +3 0x3 ClientboundAnimatePacket +4 0x4 ClientboundAwardStatsPacket +5 0x5 ClientboundBlockChangedAckPacket +6 0x6 ClientboundBlockDestructionPacket +7 0x7 ClientboundBlockEntityDataPacket +8 0x8 ClientboundBlockEventPacket +9 0x9 ClientboundBlockUpdatePacket +10 0xa ClientboundBossEventPacket +11 0xb ClientboundChangeDifficultyPacket +12 0xc ClientboundClearTitlesPacket +13 0xd ClientboundCommandSuggestionsPacket +14 0xe ClientboundCommandsPacket +15 0xf ClientboundContainerClosePacket +16 0x10 ClientboundContainerSetContentPacket +17 0x11 ClientboundContainerSetDataPacket +18 0x12 ClientboundContainerSetSlotPacket +19 0x13 ClientboundCooldownPacket +20 0x14 ClientboundCustomChatCompletionsPacket +21 0x15 ClientboundCustomPayloadPacket +22 0x16 ClientboundDeleteChatPacket +23 0x17 ClientboundDisconnectPacket +24 0x18 ClientboundDisguisedChatPacket +25 0x19 ClientboundEntityEventPacket +26 0x1a ClientboundExplodePacket +27 0x1b ClientboundForgetLevelChunkPacket +28 0x1c ClientboundGameEventPacket +29 0x1d ClientboundHorseScreenOpenPacket +30 0x1e ClientboundInitializeBorderPacket +31 0x1f ClientboundKeepAlivePacket +32 0x20 ClientboundLevelChunkWithLightPacket +33 0x21 ClientboundLevelEventPacket +34 0x22 ClientboundLevelParticlesPacket +35 0x23 ClientboundLightUpdatePacket +36 0x24 ClientboundLoginPacket +37 0x25 ClientboundMapItemDataPacket +38 0x26 ClientboundMerchantOffersPacket +39 0x27 ClientboundMoveEntityPacket +40 0x28 ClientboundMoveEntityPacket +41 0x29 ClientboundMoveEntityPacket +42 0x2a ClientboundMoveVehiclePacket +43 0x2b ClientboundOpenBookPacket +44 0x2c ClientboundOpenScreenPacket +45 0x2d ClientboundOpenSignEditorPacket +46 0x2e ClientboundPingPacket +47 0x2f ClientboundPlaceGhostRecipePacket +48 0x30 ClientboundPlayerAbilitiesPacket +49 0x31 ClientboundPlayerChatPacket +50 0x32 ClientboundPlayerCombatEndPacket +51 0x33 ClientboundPlayerCombatEnterPacket +52 0x34 ClientboundPlayerCombatKillPacket +53 0x35 ClientboundPlayerInfoRemovePacket +54 0x36 ClientboundPlayerInfoUpdatePacket +55 0x37 ClientboundPlayerLookAtPacket +56 0x38 ClientboundPlayerPositionPacket +57 0x39 ClientboundRecipePacket +58 0x3a ClientboundRemoveEntitiesPacket +59 0x3b ClientboundRemoveMobEffectPacket +60 0x3c ClientboundResourcePackPacket +61 0x3d ClientboundRespawnPacket +62 0x3e ClientboundRotateHeadPacket +63 0x3f ClientboundSectionBlocksUpdatePacket +64 0x40 ClientboundSelectAdvancementsTabPacket +65 0x41 ClientboundServerDataPacket +66 0x42 ClientboundSetActionBarTextPacket +67 0x43 ClientboundSetBorderCenterPacket +68 0x44 ClientboundSetBorderLerpSizePacket +69 0x45 ClientboundSetBorderSizePacket +70 0x46 ClientboundSetBorderWarningDelayPacket +71 0x47 ClientboundSetBorderWarningDistancePacket +72 0x48 ClientboundSetCameraPacket +73 0x49 ClientboundSetCarriedItemPacket +74 0x4a ClientboundSetChunkCacheCenterPacket +75 0x4b ClientboundSetChunkCacheRadiusPacket +76 0x4c ClientboundSetDefaultSpawnPositionPacket +77 0x4d ClientboundSetDisplayObjectivePacket +78 0x4e ClientboundSetEntityDataPacket +79 0x4f ClientboundSetEntityLinkPacket +80 0x50 ClientboundSetEntityMotionPacket +81 0x51 ClientboundSetEquipmentPacket +82 0x52 ClientboundSetExperiencePacket +83 0x53 ClientboundSetHealthPacket +84 0x54 ClientboundSetObjectivePacket +85 0x55 ClientboundSetPassengersPacket +86 0x56 ClientboundSetPlayerTeamPacket +87 0x57 ClientboundSetScorePacket +88 0x58 ClientboundSetSimulationDistancePacket +89 0x59 ClientboundSetSubtitleTextPacket +90 0x5a ClientboundSetTimePacket +91 0x5b ClientboundSetTitleTextPacket +92 0x5c ClientboundSetTitlesAnimationPacket +93 0x5d ClientboundSoundEntityPacket +94 0x5e ClientboundSoundPacket +95 0x5f ClientboundStopSoundPacket +96 0x60 ClientboundSystemChatPacket +97 0x61 ClientboundTabListPacket +98 0x62 ClientboundTagQueryPacket +99 0x63 ClientboundTakeItemEntityPacket +100 0x64 ClientboundTeleportEntityPacket +101 0x65 ClientboundUpdateAdvancementsPacket +102 0x66 ClientboundUpdateAttributesPacket +103 0x67 ClientboundUpdateEnabledFeaturesPacket +104 0x68 ClientboundUpdateMobEffectPacket +105 0x69 ClientboundUpdateRecipesPacket +106 0x6a ClientboundUpdateTagsPacket + +0 0x0 ServerboundAcceptTeleportationPacket +1 0x1 ServerboundBlockEntityTagQuery +2 0x2 ServerboundChangeDifficultyPacket +3 0x3 ServerboundChatAckPacket +4 0x4 ServerboundChatCommandPacket +5 0x5 ServerboundChatPacket +6 0x6 ServerboundClientCommandPacket +7 0x7 ServerboundClientInformationPacket +8 0x8 ServerboundCommandSuggestionPacket +9 0x9 ServerboundContainerButtonClickPacket +10 0xa ServerboundContainerClickPacket +11 0xb ServerboundContainerClosePacket +12 0xc ServerboundCustomPayloadPacket +13 0xd ServerboundEditBookPacket +14 0xe ServerboundEntityTagQuery +15 0xf ServerboundInteractPacket +16 0x10 ServerboundJigsawGeneratePacket +17 0x11 ServerboundKeepAlivePacket +18 0x12 ServerboundLockDifficultyPacket +19 0x13 ServerboundMovePlayerPacket +20 0x14 ServerboundMovePlayerPacket +21 0x15 ServerboundMovePlayerPacket +22 0x16 ServerboundMovePlayerPacket +23 0x17 ServerboundMoveVehiclePacket +24 0x18 ServerboundPaddleBoatPacket +25 0x19 ServerboundPickItemPacket +26 0x1a ServerboundPlaceRecipePacket +27 0x1b ServerboundPlayerAbilitiesPacket +28 0x1c ServerboundPlayerActionPacket +29 0x1d ServerboundPlayerCommandPacket +30 0x1e ServerboundPlayerInputPacket +31 0x1f ServerboundPongPacket +32 0x20 ServerboundChatSessionUpdatePacket +33 0x21 ServerboundRecipeBookChangeSettingsPacket +34 0x22 ServerboundRecipeBookSeenRecipePacket +35 0x23 ServerboundRenameItemPacket +36 0x24 ServerboundResourcePackPacket +37 0x25 ServerboundSeenAdvancementsPacket +38 0x26 ServerboundSelectTradePacket +39 0x27 ServerboundSetBeaconPacket +40 0x28 ServerboundSetCarriedItemPacket +41 0x29 ServerboundSetCommandBlockPacket +42 0x2a ServerboundSetCommandMinecartPacket +43 0x2b ServerboundSetCreativeModeSlotPacket +44 0x2c ServerboundSetJigsawBlockPacket +45 0x2d ServerboundSetStructureBlockPacket +46 0x2e ServerboundSignUpdatePacket +47 0x2f ServerboundSwingPacket +48 0x30 ServerboundTeleportToEntityPacket +49 0x31 ServerboundUseItemOnPacket +50 0x32 ServerboundUseItemPacket
\ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/main.rs b/src/main.rs index 80dea19..1e1c306 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,16 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, TcpStream}; +use std::time::Duration; use anyhow::Result; use craftio_rs::{CraftIo, CraftSyncReader, CraftSyncWriter, CraftTcpConnection}; -use mcproto_rs::nbt::{NamedTag, Tag}; +use mcproto_rs::nbt::Tag; use mcproto_rs::protocol::{HasPacketKind, State}; +use mcproto_rs::Serializer; use mcproto_rs::status::{StatusPlayersSpec, StatusSpec, StatusVersionSpec}; -use mcproto_rs::types::{Chat, NamedNbtTag}; +use mcproto_rs::types::{BytesSerializer, Chat, IntPosition, ItemStack, NamedNbtTag, Slot, Vec3}; use mcproto_rs::uuid::UUID4; -use mcproto_rs::v1_19_3::{GameMode, HandshakeNextState, LoginPlaySpec, LoginSuccessSpec, - Packet761, Packet761Kind, PingRequestSpec, PingResponseSpec, - PreviousGameMode, RawPacket761, StatusResponseSpec}; +use mcproto_rs::v1_19_3::{BitSet, BlobArray, BookSettings, ChunkDataAndUpdateLightSpec, ChunkDataSpec, ChunkSection, CommandNode, CommandNodeSpec, CommandsSpec, EntityEventSpec, InitializeWorldBorderSpec, KeepAliveClientBoundSpec, LightDataSpec, PalettedContainer, RecipeBookAction, RecipeBookInitSpec, SetCenterChunkSpec, SetContainerContentSpec, SetDefaultSpawnPositionSpec, SynchronizePlayerPositionSpec, TagType, TypedTagList, UpdateRecipeBookSpec}; +use mcproto_rs::v1_19_3::{GameMode, HandshakeNextState, LoginPlaySpec, LoginSuccessSpec, Packet761, Packet761Kind, PingRequestSpec, PingResponseSpec, PreviousGameMode, RawPacket761, SetHeldItemClientSpec, StatusResponseSpec, UpdateRecipesSpec, UpdateTagsSpec}; use tokio; pub struct MinecraftClient { @@ -197,6 +198,12 @@ async fn handle_conn(mut client: MinecraftClient) -> Result<()> { properties: vec![].into(), })) .await?; + let min_build_height = -64i32; + let max_build_height = 256i32; + let world_height = max_build_height - min_build_height; + let min_world_section = min_build_height >> 4; + let max_world_section = ((max_build_height - 1) >> 4) + 1; + let section_count = max_world_section - min_world_section; let overworld_spec = nbt! { "id" :: (0), "name" :: ("minecraft:overworld"), @@ -208,10 +215,10 @@ async fn handle_conn(mut client: MinecraftClient) -> Result<()> { "has_ceiling" :: (false), "has_skylight" :: (true), "has_raids" :: (false), - "height" :: (384), + "height" :: (world_height), "infiniburn" :: ("#minecraft:infiniburn_overworld"), - "logical_height" :: (384), - "min_y" :: (-64), + "logical_height" :: (world_height), + "min_y" :: (min_build_height), "monster_spawn_block_light_limit" :: (0), "monster_spawn_light_level" :: { "type" :: ("minecraft:uniform"), @@ -287,7 +294,161 @@ async fn handle_conn(mut client: MinecraftClient) -> Result<()> { .await?; let client_information = await_packet!(ClientInformation, client); println!("Client Information: {:?}", client_information); - anyhow::bail!("TODO"); + client.send_packet(Packet761::SetHeldItemClient(SetHeldItemClientSpec { + selected_slot: 0, + })).await?; + client.send_packet(Packet761::UpdateRecipes(UpdateRecipesSpec { recipes: vec![].into() })).await?; + client.send_packet(Packet761::UpdateTags(UpdateTagsSpec { + tags: vec![ + TypedTagList { + tag_type: TagType::Block, + tags: vec![].into(), + }, + TypedTagList { + tag_type: TagType::Item, + tags: vec![].into(), + }, + TypedTagList { + tag_type: TagType::EntityType, + tags: vec![].into(), + }, + TypedTagList { + tag_type: TagType::GameEvent, + tags: vec![].into(), + }, + TypedTagList { + tag_type: TagType::Fluid, + tags: vec![].into(), + }, + ].into(), + })).await?; + client.send_packet(Packet761::EntityEvent(EntityEventSpec { + entity_id: 0, + entity_status: 24 /* OP permission level = 0 */, + })).await?; + client.send_packet(Packet761::Commands(CommandsSpec { + nodes: vec![ + CommandNodeSpec { + children_indices: vec![].into(), + redirect_node: None, + is_executable: false, + node: CommandNode::Root, + } + ].into(), + root_index: 0.into(), + })).await?; + client.send_packet(Packet761::UpdateRecipeBook(UpdateRecipeBookSpec { + action: RecipeBookAction::Init(RecipeBookInitSpec { + book_settings: BookSettings::default(), + known_recipes: vec![].into(), + highlighted_recipes: vec![].into(), + }) + })).await?; + client.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, + })).await?; + client.send_packet(Packet761::SetCenterChunk(SetCenterChunkSpec { + chunk_x: 0.into(), + chunk_z: 0.into(), + })).await?; + 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..section_count { + 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(§ion)?; + } + let chunk_column_bytes = chunk_dat_serializer.into_bytes(); + client.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(), + }, + })).await?; + } + } + client.send_packet(Packet761::InitializeWorldBorder(InitializeWorldBorderSpec { + x: 0.0, + z: 0.0, + old_diameter: 10000000.0, + new_diameter: 10000000.0, + speed: 0.into(), + portal_teleport_boundary: 29999984.into(), + warning_blocks: 0.into(), + warning_time: 0.into(), + })).await?; + client.send_packet(Packet761::SetDefaultSpawnPosition(SetDefaultSpawnPositionSpec { + location: IntPosition { + x: 0, + y: 0, + z: 0, + }, + angle: 0.0, + })).await?; + client.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, + })).await?; + client.send_packet(Packet761::SetContainerContent(SetContainerContentSpec { + window_id: 0, + state_id: 0.into(), + slot_data: vec![Some(ItemStack { + item_id: 1.into(), + item_count: 1, + nbt: None, + }); 45].into(), + carried_item: None, + })); + let mut i = 0; + loop { + client.send_packet(Packet761::KeepAliveClientBound(KeepAliveClientBoundSpec { + keep_alive_id: i, + })).await?; + i += 1; + tokio::time::sleep(Duration::from_secs(10)).await; + } } else if hs.next_state == HandshakeNextState::Status { return handle_status(client).await; } else { |