Update to 1.19.3 (#171)

Closes #165
This commit is contained in:
Ryan Johnson 2022-12-28 00:42:54 -08:00 committed by GitHub
parent 6de5de57a5
commit 5d3364d452
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 187649 additions and 168495 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "valence" name = "valence"
version = "0.1.0+mc1.19.2" version = "0.2.0+mc1.19.3"
edition = "2021" edition = "2021"
description = "A framework for building Minecraft servers in Rust." description = "A framework for building Minecraft servers in Rust."
repository = "https://github.com/rj00a/valence" repository = "https://github.com/rj00a/valence"

View file

@ -126,6 +126,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -35,6 +35,7 @@ struct Field {
enum Value { enum Value {
Byte(u8), Byte(u8),
Integer(i32), Integer(i32),
Long(i64),
Float(f32), Float(f32),
String(String), String(String),
TextComponent(String), TextComponent(String),
@ -85,27 +86,28 @@ impl Value {
match self { match self {
Value::Byte(_) => 0, Value::Byte(_) => 0,
Value::Integer(_) => 1, Value::Integer(_) => 1,
Value::Float(_) => 2, Value::Long(_) => 2,
Value::String(_) => 3, Value::Float(_) => 3,
Value::TextComponent(_) => 4, Value::String(_) => 4,
Value::OptionalTextComponent(_) => 5, Value::TextComponent(_) => 5,
Value::ItemStack(_) => 6, Value::OptionalTextComponent(_) => 6,
Value::Boolean(_) => 7, Value::ItemStack(_) => 7,
Value::Rotation { .. } => 8, Value::Boolean(_) => 8,
Value::BlockPos(_) => 9, Value::Rotation { .. } => 9,
Value::OptionalBlockPos(_) => 10, Value::BlockPos(_) => 10,
Value::Facing(_) => 11, Value::OptionalBlockPos(_) => 11,
Value::OptionalUuid(_) => 12, Value::Facing(_) => 12,
Value::OptionalBlockState(_) => 13, Value::OptionalUuid(_) => 13,
Value::NbtCompound(_) => 14, Value::OptionalBlockState(_) => 14,
Value::Particle(_) => 15, Value::NbtCompound(_) => 15,
Value::VillagerData { .. } => 16, Value::Particle(_) => 16,
Value::OptionalInt(_) => 17, Value::VillagerData { .. } => 17,
Value::EntityPose(_) => 18, Value::OptionalInt(_) => 18,
Value::CatVariant(_) => 19, Value::EntityPose(_) => 19,
Value::FrogVariant(_) => 20, Value::CatVariant(_) => 20,
Value::OptionalGlobalPos(_) => 21, Value::FrogVariant(_) => 21,
Value::PaintingVariant(_) => 22, Value::OptionalGlobalPos(_) => 22,
Value::PaintingVariant(_) => 23,
} }
} }
@ -113,6 +115,7 @@ impl Value {
match self { match self {
Value::Byte(_) => quote!(u8), Value::Byte(_) => quote!(u8),
Value::Integer(_) => quote!(i32), Value::Integer(_) => quote!(i32),
Value::Long(_) => quote!(i64),
Value::Float(_) => quote!(f32), Value::Float(_) => quote!(f32),
Value::String(_) => quote!(Box<str>), Value::String(_) => quote!(Box<str>),
Value::TextComponent(_) => quote!(Text), Value::TextComponent(_) => quote!(Text),
@ -161,6 +164,7 @@ impl Value {
match self { match self {
Value::Byte(b) => quote!(#b), Value::Byte(b) => quote!(#b),
Value::Integer(i) => quote!(#i), Value::Integer(i) => quote!(#i),
Value::Long(l) => quote!(#l),
Value::Float(f) => quote!(#f), Value::Float(f) => quote!(#f),
Value::String(s) => quote!(#s.to_owned().into_boxed_str()), Value::String(s) => quote!(#s.to_owned().into_boxed_str()),
Value::TextComponent(_) => quote!(Text::default()), // TODO Value::TextComponent(_) => quote!(Text::default()), // TODO

View file

@ -176,6 +176,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -123,6 +123,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -155,6 +155,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -147,6 +147,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }
@ -169,13 +170,15 @@ impl Config for Game {
let index = position.x as usize + position.z as usize * SIZE_X; let index = position.x as usize + position.z as usize * SIZE_X;
if !server.state.board[index] { if !server.state.board[index] {
client.play_sound( // client.play_sound(
Ident::new("minecraft:block.note_block.banjo").unwrap(), // Ident::new("minecraft:block.note_block.
SoundCategory::Block, // banjo").unwrap(),
Vec3::new(position.x, position.y, position.z).as_(), // SoundCategory::Block,
0.5f32, // Vec3::new(position.x, position.y,
1f32, // position.z).as_(),
); // 0.5f32,
// 1f32,
// );
} }
server.state.board[index] = true; server.state.board[index] = true;
@ -208,13 +211,13 @@ impl Config for Game {
let sneaking = data.get_pose() == Pose::Sneaking; let sneaking = data.get_pose() == Pose::Sneaking;
if sneaking != server.state.paused { if sneaking != server.state.paused {
server.state.paused = sneaking; server.state.paused = sneaking;
client.play_sound( // client.play_sound(
Ident::new("block.note_block.pling").unwrap(), // Ident::new("block.note_block.pling").unwrap(),
SoundCategory::Block, // SoundCategory::Block,
client.position(), // client.position(),
0.5, // 0.5,
if sneaking { 0.5 } else { 1.0 }, // if sneaking { 0.5 } else { 1.0 },
); // );
} }
} }

View file

@ -146,6 +146,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }
} }

View file

@ -164,6 +164,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
client.set_respawn_screen(true); client.set_respawn_screen(true);

View file

@ -247,6 +247,7 @@ impl Config for Game {
GameMode::Survival, GameMode::Survival,
0, 0,
None, None,
true,
); );
let (_, e) = server let (_, e) = server
@ -360,6 +361,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -147,6 +147,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }
@ -210,14 +211,17 @@ fn play_note(client: &mut Client<Game>, player: &mut Entity<Game>, clicked_slot:
let pitch = (clicked_slot - SLOT_MIN) as f32 * (PITCH_MAX - PITCH_MIN) let pitch = (clicked_slot - SLOT_MIN) as f32 * (PITCH_MAX - PITCH_MIN)
/ (SLOT_MAX - SLOT_MIN) as f32 / (SLOT_MAX - SLOT_MIN) as f32
+ PITCH_MIN; + PITCH_MIN;
client.send_message(format!("playing note with pitch: {}", pitch));
client.play_sound( client.send_message(format!("playing note with pitch: {pitch}"));
Ident::new("block.note_block.harp").unwrap(),
SoundCategory::Block, let _ = player;
player.position(), // client.play_sound(
10.0, // Ident::new("block.note_block.harp").unwrap(),
pitch, // SoundCategory::Block,
); // player.position(),
// 10.0,
// pitch,
// );
} else if clicked_slot == 44 { } else if clicked_slot == 44 {
client.set_game_mode(match client.game_mode() { client.set_game_mode(match client.game_mode() {
GameMode::Survival => GameMode::Creative, GameMode::Survival => GameMode::Creative,

View file

@ -14,7 +14,7 @@ pub fn main() -> ShutdownResult {
Game { Game {
player_count: AtomicUsize::new(0), player_count: AtomicUsize::new(0),
}, },
ServerState { player_list: None }, None,
) )
} }
@ -22,10 +22,6 @@ struct Game {
player_count: AtomicUsize, player_count: AtomicUsize,
} }
struct ServerState {
player_list: Option<PlayerListId>,
}
#[derive(Default)] #[derive(Default)]
struct ChunkState { struct ChunkState {
keep_loaded: bool, keep_loaded: bool,
@ -57,7 +53,7 @@ const BLOCK_TYPES: [BlockState; 7] = [
#[async_trait] #[async_trait]
impl Config for Game { impl Config for Game {
type ServerState = ServerState; type ServerState = Option<PlayerListId>;
type ClientState = ClientState; type ClientState = ClientState;
type EntityState = (); type EntityState = ();
type WorldState = (); type WorldState = ();
@ -81,7 +77,7 @@ impl Config for Game {
} }
fn init(&self, server: &mut Server<Self>) { fn init(&self, server: &mut Server<Self>) {
server.state.player_list = Some(server.player_lists.insert(()).0); server.state = Some(server.player_lists.insert(()).0);
} }
fn update(&self, server: &mut Server<Self>) { fn update(&self, server: &mut Server<Self>) {
@ -125,11 +121,7 @@ impl Config for Game {
} }
} }
client.respawn(world_id); if let Some(id) = &server.state {
client.set_flat(true);
client.set_player_list(server.state.player_list.clone());
if let Some(id) = &server.state.player_list {
server.player_lists[id].insert( server.player_lists[id].insert(
client.uuid(), client.uuid(),
client.username(), client.username(),
@ -137,9 +129,14 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }
client.respawn(world_id);
client.set_flat(true);
client.set_player_list(server.state.clone());
client.send_message("Welcome to epic infinite parkour game!".italic()); client.send_message("Welcome to epic infinite parkour game!".italic());
client.set_game_mode(GameMode::Adventure); client.set_game_mode(GameMode::Adventure);
reset(client, world); reset(client, world);
@ -200,19 +197,21 @@ impl Config for Game {
client.combo = 0 client.combo = 0
} }
let pitch = 0.9 + ((client.combo as f32) - 1.0) * 0.05; // let pitch = 0.9 + ((client.combo as f32) - 1.0) * 0.05;
for _ in 0..index { for _ in 0..index {
generate_next_block(client, world, true) generate_next_block(client, world, true)
} }
client.play_sound( // TODO: add sounds again.
Ident::new("minecraft:block.note_block.bass").unwrap(), // client.play_sound(
SoundCategory::Master, // Ident::new("minecraft:block.note_block.bass").unwrap(),
client.position(), // SoundCategory::Master,
1f32, // client.position(),
pitch, // 1f32,
); // pitch,
// );
client.set_title( client.set_title(
"", "",
client.score.to_string().color(Color::LIGHT_PURPLE).bold(), client.score.to_string().color(Color::LIGHT_PURPLE).bold(),
@ -239,10 +238,10 @@ impl Config for Game {
if client.is_disconnected() { if client.is_disconnected() {
self.player_count.fetch_sub(1, Ordering::SeqCst); self.player_count.fetch_sub(1, Ordering::SeqCst);
player.set_deleted(true); if let Some(id) = &server.state {
if let Some(id) = &server.state.player_list {
server.player_lists[id].remove(client.uuid()); server.player_lists[id].remove(client.uuid());
} }
player.set_deleted(true);
server.worlds.remove(world_id); server.worlds.remove(world_id);
return false; return false;
} }

View file

@ -137,6 +137,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -116,6 +116,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -11,113 +11,114 @@
"boat": 8, "boat": 8,
"chest_boat": 9, "chest_boat": 9,
"cat": 10, "cat": 10,
"cave_spider": 11, "camel": 11,
"chicken": 12, "cave_spider": 12,
"cod": 13, "chicken": 13,
"cow": 14, "cod": 14,
"creeper": 15, "cow": 15,
"dolphin": 16, "creeper": 16,
"donkey": 17, "dolphin": 17,
"dragon_fireball": 18, "donkey": 18,
"drowned": 19, "dragon_fireball": 19,
"elder_guardian": 20, "drowned": 20,
"end_crystal": 21, "elder_guardian": 21,
"ender_dragon": 22, "end_crystal": 22,
"enderman": 23, "ender_dragon": 23,
"endermite": 24, "enderman": 24,
"evoker": 25, "endermite": 25,
"evoker_fangs": 26, "evoker": 26,
"experience_orb": 27, "evoker_fangs": 27,
"eye_of_ender": 28, "experience_orb": 28,
"falling_block": 29, "eye_of_ender": 29,
"firework_rocket": 30, "falling_block": 30,
"fox": 31, "firework_rocket": 31,
"frog": 32, "fox": 32,
"ghast": 33, "frog": 33,
"giant": 34, "ghast": 34,
"glow_item_frame": 35, "giant": 35,
"glow_squid": 36, "glow_item_frame": 36,
"goat": 37, "glow_squid": 37,
"guardian": 38, "goat": 38,
"hoglin": 39, "guardian": 39,
"horse": 40, "hoglin": 40,
"husk": 41, "horse": 41,
"illusioner": 42, "husk": 42,
"iron_golem": 43, "illusioner": 43,
"item": 44, "iron_golem": 44,
"item_frame": 45, "item": 45,
"fireball": 46, "item_frame": 46,
"leash_knot": 47, "fireball": 47,
"lightning_bolt": 48, "leash_knot": 48,
"llama": 49, "lightning_bolt": 49,
"llama_spit": 50, "llama": 50,
"magma_cube": 51, "llama_spit": 51,
"marker": 52, "magma_cube": 52,
"minecart": 53, "marker": 53,
"chest_minecart": 54, "minecart": 54,
"command_block_minecart": 55, "chest_minecart": 55,
"furnace_minecart": 56, "command_block_minecart": 56,
"hopper_minecart": 57, "furnace_minecart": 57,
"spawner_minecart": 58, "hopper_minecart": 58,
"tnt_minecart": 59, "spawner_minecart": 59,
"mule": 60, "tnt_minecart": 60,
"mooshroom": 61, "mule": 61,
"ocelot": 62, "mooshroom": 62,
"painting": 63, "ocelot": 63,
"panda": 64, "painting": 64,
"parrot": 65, "panda": 65,
"phantom": 66, "parrot": 66,
"pig": 67, "phantom": 67,
"piglin": 68, "pig": 68,
"piglin_brute": 69, "piglin": 69,
"pillager": 70, "piglin_brute": 70,
"polar_bear": 71, "pillager": 71,
"tnt": 72, "polar_bear": 72,
"pufferfish": 73, "tnt": 73,
"rabbit": 74, "pufferfish": 74,
"ravager": 75, "rabbit": 75,
"salmon": 76, "ravager": 76,
"sheep": 77, "salmon": 77,
"shulker": 78, "sheep": 78,
"shulker_bullet": 79, "shulker": 79,
"silverfish": 80, "shulker_bullet": 80,
"skeleton": 81, "silverfish": 81,
"skeleton_horse": 82, "skeleton": 82,
"slime": 83, "skeleton_horse": 83,
"small_fireball": 84, "slime": 84,
"snow_golem": 85, "small_fireball": 85,
"snowball": 86, "snow_golem": 86,
"spectral_arrow": 87, "snowball": 87,
"spider": 88, "spectral_arrow": 88,
"squid": 89, "spider": 89,
"stray": 90, "squid": 90,
"strider": 91, "stray": 91,
"tadpole": 92, "strider": 92,
"egg": 93, "tadpole": 93,
"ender_pearl": 94, "egg": 94,
"experience_bottle": 95, "ender_pearl": 95,
"potion": 96, "experience_bottle": 96,
"trident": 97, "potion": 97,
"trader_llama": 98, "trident": 98,
"tropical_fish": 99, "trader_llama": 99,
"turtle": 100, "tropical_fish": 100,
"vex": 101, "turtle": 101,
"villager": 102, "vex": 102,
"vindicator": 103, "villager": 103,
"wandering_trader": 104, "vindicator": 104,
"warden": 105, "wandering_trader": 105,
"witch": 106, "warden": 106,
"wither": 107, "witch": 107,
"wither_skeleton": 108, "wither": 108,
"wither_skull": 109, "wither_skeleton": 109,
"wolf": 110, "wither_skull": 110,
"zoglin": 111, "wolf": 111,
"zombie": 112, "zoglin": 112,
"zombie_horse": 113, "zombie": 113,
"zombie_villager": 114, "zombie_horse": 114,
"zombified_piglin": 115, "zombie_villager": 115,
"player": 116, "zombified_piglin": 116,
"fishing_bobber": 117 "player": 117,
"fishing_bobber": 118
}, },
"statuses": { "statuses": {
"add_sprinting_particles_or_reset_spawner_minecart_spawn_delay": 1, "add_sprinting_particles_or_reset_spawner_minecart_spawn_delay": 1,
@ -406,10 +407,11 @@
"dying": 7, "dying": 7,
"croaking": 8, "croaking": 8,
"using_tongue": 9, "using_tongue": 9,
"roaring": 10, "sitting": 10,
"sniffing": 11, "roaring": 11,
"emerging": 12, "sniffing": 12,
"digging": 13 "emerging": 13,
"digging": 14
}, },
"particle_types": { "particle_types": {
"ambient_entity_effect": 0, "ambient_entity_effect": 0,

File diff suppressed because it is too large Load diff

View file

@ -32,111 +32,111 @@
"id": 5 "id": 5
}, },
{ {
"name": "RequestChatPreviewC2SPacket", "name": "ClientStatusC2SPacket",
"id": 6 "id": 6
}, },
{ {
"name": "ClientStatusC2SPacket", "name": "ClientSettingsC2SPacket",
"id": 7 "id": 7
}, },
{ {
"name": "ClientSettingsC2SPacket", "name": "RequestCommandCompletionsC2SPacket",
"id": 8 "id": 8
}, },
{ {
"name": "RequestCommandCompletionsC2SPacket", "name": "ButtonClickC2SPacket",
"id": 9 "id": 9
}, },
{ {
"name": "ButtonClickC2SPacket", "name": "ClickSlotC2SPacket",
"id": 10 "id": 10
}, },
{ {
"name": "ClickSlotC2SPacket", "name": "CloseHandledScreenC2SPacket",
"id": 11 "id": 11
}, },
{ {
"name": "CloseHandledScreenC2SPacket", "name": "CustomPayloadC2SPacket",
"id": 12 "id": 12
}, },
{ {
"name": "CustomPayloadC2SPacket", "name": "BookUpdateC2SPacket",
"id": 13 "id": 13
}, },
{ {
"name": "BookUpdateC2SPacket", "name": "QueryEntityNbtC2SPacket",
"id": 14 "id": 14
}, },
{ {
"name": "QueryEntityNbtC2SPacket", "name": "PlayerInteractEntityC2SPacket",
"id": 15 "id": 15
}, },
{ {
"name": "PlayerInteractEntityC2SPacket", "name": "JigsawGeneratingC2SPacket",
"id": 16 "id": 16
}, },
{ {
"name": "JigsawGeneratingC2SPacket", "name": "KeepAliveC2SPacket",
"id": 17 "id": 17
}, },
{ {
"name": "KeepAliveC2SPacket", "name": "UpdateDifficultyLockC2SPacket",
"id": 18 "id": 18
}, },
{ {
"name": "UpdateDifficultyLockC2SPacket", "name": "PositionAndOnGround",
"id": 19 "id": 19
}, },
{ {
"name": "PositionAndOnGround", "name": "Full",
"id": 20 "id": 20
}, },
{ {
"name": "Full", "name": "LookAndOnGround",
"id": 21 "id": 21
}, },
{ {
"name": "LookAndOnGround", "name": "OnGroundOnly",
"id": 22 "id": 22
}, },
{ {
"name": "OnGroundOnly", "name": "VehicleMoveC2SPacket",
"id": 23 "id": 23
}, },
{ {
"name": "VehicleMoveC2SPacket", "name": "BoatPaddleStateC2SPacket",
"id": 24 "id": 24
}, },
{ {
"name": "BoatPaddleStateC2SPacket", "name": "PickFromInventoryC2SPacket",
"id": 25 "id": 25
}, },
{ {
"name": "PickFromInventoryC2SPacket", "name": "CraftRequestC2SPacket",
"id": 26 "id": 26
}, },
{ {
"name": "CraftRequestC2SPacket", "name": "UpdatePlayerAbilitiesC2SPacket",
"id": 27 "id": 27
}, },
{ {
"name": "UpdatePlayerAbilitiesC2SPacket", "name": "PlayerActionC2SPacket",
"id": 28 "id": 28
}, },
{ {
"name": "PlayerActionC2SPacket", "name": "ClientCommandC2SPacket",
"id": 29 "id": 29
}, },
{ {
"name": "ClientCommandC2SPacket", "name": "PlayerInputC2SPacket",
"id": 30 "id": 30
}, },
{ {
"name": "PlayerInputC2SPacket", "name": "PlayPongC2SPacket",
"id": 31 "id": 31
}, },
{ {
"name": "PlayPongC2SPacket", "name": "PlayerSessionC2SPacket",
"id": 32 "id": 32
}, },
{ {
@ -289,388 +289,384 @@
"id": 11 "id": 11
}, },
{ {
"name": "ChatPreviewS2CPacket", "name": "ClearTitleS2CPacket",
"id": 12 "id": 12
}, },
{ {
"name": "ClearTitleS2CPacket", "name": "CommandSuggestionsS2CPacket",
"id": 13 "id": 13
}, },
{ {
"name": "CommandSuggestionsS2CPacket", "name": "CommandTreeS2CPacket",
"id": 14 "id": 14
}, },
{ {
"name": "CommandTreeS2CPacket", "name": "CloseScreenS2CPacket",
"id": 15 "id": 15
}, },
{ {
"name": "CloseScreenS2CPacket", "name": "InventoryS2CPacket",
"id": 16 "id": 16
}, },
{ {
"name": "InventoryS2CPacket", "name": "ScreenHandlerPropertyUpdateS2CPacket",
"id": 17 "id": 17
}, },
{ {
"name": "ScreenHandlerPropertyUpdateS2CPacket", "name": "ScreenHandlerSlotUpdateS2CPacket",
"id": 18 "id": 18
}, },
{ {
"name": "ScreenHandlerSlotUpdateS2CPacket", "name": "CooldownUpdateS2CPacket",
"id": 19 "id": 19
}, },
{ {
"name": "CooldownUpdateS2CPacket", "name": "ChatSuggestionsS2CPacket",
"id": 20 "id": 20
}, },
{ {
"name": "ChatSuggestionsS2CPacket", "name": "CustomPayloadS2CPacket",
"id": 21 "id": 21
}, },
{ {
"name": "CustomPayloadS2CPacket", "name": "RemoveMessageS2CPacket",
"id": 22 "id": 22
}, },
{ {
"name": "PlaySoundIdS2CPacket", "name": "DisconnectS2CPacket",
"id": 23 "id": 23
}, },
{ {
"name": "HideMessageS2CPacket", "name": "ProfilelessChatMessageS2CPacket",
"id": 24 "id": 24
}, },
{ {
"name": "DisconnectS2CPacket", "name": "EntityStatusS2CPacket",
"id": 25 "id": 25
}, },
{ {
"name": "EntityStatusS2CPacket", "name": "ExplosionS2CPacket",
"id": 26 "id": 26
}, },
{ {
"name": "ExplosionS2CPacket", "name": "UnloadChunkS2CPacket",
"id": 27 "id": 27
}, },
{ {
"name": "UnloadChunkS2CPacket", "name": "GameStateChangeS2CPacket",
"id": 28 "id": 28
}, },
{ {
"name": "GameStateChangeS2CPacket", "name": "OpenHorseScreenS2CPacket",
"id": 29 "id": 29
}, },
{ {
"name": "OpenHorseScreenS2CPacket", "name": "WorldBorderInitializeS2CPacket",
"id": 30 "id": 30
}, },
{ {
"name": "WorldBorderInitializeS2CPacket", "name": "KeepAliveS2CPacket",
"id": 31 "id": 31
}, },
{ {
"name": "KeepAliveS2CPacket", "name": "ChunkDataS2CPacket",
"id": 32 "id": 32
}, },
{ {
"name": "ChunkDataS2CPacket", "name": "WorldEventS2CPacket",
"id": 33 "id": 33
}, },
{ {
"name": "WorldEventS2CPacket", "name": "ParticleS2CPacket",
"id": 34 "id": 34
}, },
{ {
"name": "ParticleS2CPacket", "name": "LightUpdateS2CPacket",
"id": 35 "id": 35
}, },
{ {
"name": "LightUpdateS2CPacket", "name": "GameJoinS2CPacket",
"id": 36 "id": 36
}, },
{ {
"name": "GameJoinS2CPacket", "name": "MapUpdateS2CPacket",
"id": 37 "id": 37
}, },
{ {
"name": "MapUpdateS2CPacket", "name": "SetTradeOffersS2CPacket",
"id": 38 "id": 38
}, },
{ {
"name": "SetTradeOffersS2CPacket", "name": "MoveRelative",
"id": 39 "id": 39
}, },
{ {
"name": "MoveRelative", "name": "RotateAndMoveRelative",
"id": 40 "id": 40
}, },
{ {
"name": "RotateAndMoveRelative", "name": "Rotate",
"id": 41 "id": 41
}, },
{ {
"name": "Rotate", "name": "VehicleMoveS2CPacket",
"id": 42 "id": 42
}, },
{ {
"name": "VehicleMoveS2CPacket", "name": "OpenWrittenBookS2CPacket",
"id": 43 "id": 43
}, },
{ {
"name": "OpenWrittenBookS2CPacket", "name": "OpenScreenS2CPacket",
"id": 44 "id": 44
}, },
{ {
"name": "OpenScreenS2CPacket", "name": "SignEditorOpenS2CPacket",
"id": 45 "id": 45
}, },
{ {
"name": "SignEditorOpenS2CPacket", "name": "PlayPingS2CPacket",
"id": 46 "id": 46
}, },
{ {
"name": "PlayPingS2CPacket", "name": "CraftFailedResponseS2CPacket",
"id": 47 "id": 47
}, },
{ {
"name": "CraftFailedResponseS2CPacket", "name": "PlayerAbilitiesS2CPacket",
"id": 48 "id": 48
}, },
{ {
"name": "PlayerAbilitiesS2CPacket", "name": "ChatMessageS2CPacket",
"id": 49 "id": 49
}, },
{ {
"name": "MessageHeaderS2CPacket", "name": "EndCombatS2CPacket",
"id": 50 "id": 50
}, },
{ {
"name": "ChatMessageS2CPacket", "name": "EnterCombatS2CPacket",
"id": 51 "id": 51
}, },
{ {
"name": "EndCombatS2CPacket", "name": "DeathMessageS2CPacket",
"id": 52 "id": 52
}, },
{ {
"name": "EnterCombatS2CPacket", "name": "PlayerRemoveS2CPacket",
"id": 53 "id": 53
}, },
{ {
"name": "DeathMessageS2CPacket", "name": "PlayerListS2CPacket",
"id": 54 "id": 54
}, },
{ {
"name": "PlayerListS2CPacket", "name": "LookAtS2CPacket",
"id": 55 "id": 55
}, },
{ {
"name": "LookAtS2CPacket", "name": "PlayerPositionLookS2CPacket",
"id": 56 "id": 56
}, },
{ {
"name": "PlayerPositionLookS2CPacket", "name": "UnlockRecipesS2CPacket",
"id": 57 "id": 57
}, },
{ {
"name": "UnlockRecipesS2CPacket", "name": "EntitiesDestroyS2CPacket",
"id": 58 "id": 58
}, },
{ {
"name": "EntitiesDestroyS2CPacket", "name": "RemoveEntityStatusEffectS2CPacket",
"id": 59 "id": 59
}, },
{ {
"name": "RemoveEntityStatusEffectS2CPacket", "name": "ResourcePackSendS2CPacket",
"id": 60 "id": 60
}, },
{ {
"name": "ResourcePackSendS2CPacket", "name": "PlayerRespawnS2CPacket",
"id": 61 "id": 61
}, },
{ {
"name": "PlayerRespawnS2CPacket", "name": "EntitySetHeadYawS2CPacket",
"id": 62 "id": 62
}, },
{ {
"name": "EntitySetHeadYawS2CPacket", "name": "ChunkDeltaUpdateS2CPacket",
"id": 63 "id": 63
}, },
{ {
"name": "ChunkDeltaUpdateS2CPacket", "name": "SelectAdvancementTabS2CPacket",
"id": 64 "id": 64
}, },
{ {
"name": "SelectAdvancementTabS2CPacket", "name": "ServerMetadataS2CPacket",
"id": 65 "id": 65
}, },
{ {
"name": "ServerMetadataS2CPacket", "name": "OverlayMessageS2CPacket",
"id": 66 "id": 66
}, },
{ {
"name": "OverlayMessageS2CPacket", "name": "WorldBorderCenterChangedS2CPacket",
"id": 67 "id": 67
}, },
{ {
"name": "WorldBorderCenterChangedS2CPacket", "name": "WorldBorderInterpolateSizeS2CPacket",
"id": 68 "id": 68
}, },
{ {
"name": "WorldBorderInterpolateSizeS2CPacket", "name": "WorldBorderSizeChangedS2CPacket",
"id": 69 "id": 69
}, },
{ {
"name": "WorldBorderSizeChangedS2CPacket", "name": "WorldBorderWarningTimeChangedS2CPacket",
"id": 70 "id": 70
}, },
{ {
"name": "WorldBorderWarningTimeChangedS2CPacket", "name": "WorldBorderWarningBlocksChangedS2CPacket",
"id": 71 "id": 71
}, },
{ {
"name": "WorldBorderWarningBlocksChangedS2CPacket", "name": "SetCameraEntityS2CPacket",
"id": 72 "id": 72
}, },
{ {
"name": "SetCameraEntityS2CPacket", "name": "UpdateSelectedSlotS2CPacket",
"id": 73 "id": 73
}, },
{ {
"name": "UpdateSelectedSlotS2CPacket", "name": "ChunkRenderDistanceCenterS2CPacket",
"id": 74 "id": 74
}, },
{ {
"name": "ChunkRenderDistanceCenterS2CPacket", "name": "ChunkLoadDistanceS2CPacket",
"id": 75 "id": 75
}, },
{ {
"name": "ChunkLoadDistanceS2CPacket", "name": "PlayerSpawnPositionS2CPacket",
"id": 76 "id": 76
}, },
{ {
"name": "PlayerSpawnPositionS2CPacket", "name": "ScoreboardDisplayS2CPacket",
"id": 77 "id": 77
}, },
{ {
"name": "ChatPreviewStateChangeS2CPacket", "name": "EntityTrackerUpdateS2CPacket",
"id": 78 "id": 78
}, },
{ {
"name": "ScoreboardDisplayS2CPacket", "name": "EntityAttachS2CPacket",
"id": 79 "id": 79
}, },
{ {
"name": "EntityTrackerUpdateS2CPacket", "name": "EntityVelocityUpdateS2CPacket",
"id": 80 "id": 80
}, },
{ {
"name": "EntityAttachS2CPacket", "name": "EntityEquipmentUpdateS2CPacket",
"id": 81 "id": 81
}, },
{ {
"name": "EntityVelocityUpdateS2CPacket", "name": "ExperienceBarUpdateS2CPacket",
"id": 82 "id": 82
}, },
{ {
"name": "EntityEquipmentUpdateS2CPacket", "name": "HealthUpdateS2CPacket",
"id": 83 "id": 83
}, },
{ {
"name": "ExperienceBarUpdateS2CPacket", "name": "ScoreboardObjectiveUpdateS2CPacket",
"id": 84 "id": 84
}, },
{ {
"name": "HealthUpdateS2CPacket", "name": "EntityPassengersSetS2CPacket",
"id": 85 "id": 85
}, },
{ {
"name": "ScoreboardObjectiveUpdateS2CPacket", "name": "TeamS2CPacket",
"id": 86 "id": 86
}, },
{ {
"name": "EntityPassengersSetS2CPacket", "name": "ScoreboardPlayerUpdateS2CPacket",
"id": 87 "id": 87
}, },
{ {
"name": "TeamS2CPacket", "name": "SimulationDistanceS2CPacket",
"id": 88 "id": 88
}, },
{ {
"name": "ScoreboardPlayerUpdateS2CPacket", "name": "SubtitleS2CPacket",
"id": 89 "id": 89
}, },
{ {
"name": "SimulationDistanceS2CPacket", "name": "WorldTimeUpdateS2CPacket",
"id": 90 "id": 90
}, },
{ {
"name": "SubtitleS2CPacket", "name": "TitleS2CPacket",
"id": 91 "id": 91
}, },
{ {
"name": "WorldTimeUpdateS2CPacket", "name": "TitleFadeS2CPacket",
"id": 92 "id": 92
}, },
{ {
"name": "TitleS2CPacket", "name": "PlaySoundFromEntityS2CPacket",
"id": 93 "id": 93
}, },
{ {
"name": "TitleFadeS2CPacket", "name": "PlaySoundS2CPacket",
"id": 94 "id": 94
}, },
{ {
"name": "PlaySoundFromEntityS2CPacket", "name": "StopSoundS2CPacket",
"id": 95 "id": 95
}, },
{ {
"name": "PlaySoundS2CPacket", "name": "GameMessageS2CPacket",
"id": 96 "id": 96
}, },
{ {
"name": "StopSoundS2CPacket", "name": "PlayerListHeaderS2CPacket",
"id": 97 "id": 97
}, },
{ {
"name": "GameMessageS2CPacket", "name": "NbtQueryResponseS2CPacket",
"id": 98 "id": 98
}, },
{ {
"name": "PlayerListHeaderS2CPacket", "name": "ItemPickupAnimationS2CPacket",
"id": 99 "id": 99
}, },
{ {
"name": "NbtQueryResponseS2CPacket", "name": "EntityPositionS2CPacket",
"id": 100 "id": 100
}, },
{ {
"name": "ItemPickupAnimationS2CPacket", "name": "AdvancementUpdateS2CPacket",
"id": 101 "id": 101
}, },
{ {
"name": "EntityPositionS2CPacket", "name": "EntityAttributesS2CPacket",
"id": 102 "id": 102
}, },
{ {
"name": "AdvancementUpdateS2CPacket", "name": "FeaturesS2CPacket",
"id": 103 "id": 103
}, },
{ {
"name": "EntityAttributesS2CPacket", "name": "EntityStatusEffectS2CPacket",
"id": 104 "id": 104
}, },
{ {
"name": "EntityStatusEffectS2CPacket", "name": "SynchronizeRecipesS2CPacket",
"id": 105 "id": 105
}, },
{
"name": "SynchronizeRecipesS2CPacket",
"id": 106
},
{ {
"name": "SynchronizeTagsS2CPacket", "name": "SynchronizeTagsS2CPacket",
"id": 107 "id": 106
} }
], ],
"status": [ "status": [

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,9 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.19.2 minecraft_version=1.19.3
yarn_mappings=1.19.2+build.8 yarn_mappings=1.19.3+build.3
loader_version=0.14.9 loader_version=0.14.11
# Mod Properties # Mod Properties
mod_version = 1.0.0 mod_version = 1.0.0
@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G
archives_base_name = valence-extractor archives_base_name = valence-extractor
# Dependencies # Dependencies
fabric_version=0.60.0+1.19.2 fabric_version=0.69.1+1.19.3

View file

@ -27,7 +27,7 @@ public class DummyPlayerEntity extends PlayerEntity {
} }
private DummyPlayerEntity(World world, BlockPos pos, float yaw, GameProfile gameProfile, @Nullable PlayerPublicKey publicKey) { private DummyPlayerEntity(World world, BlockPos pos, float yaw, GameProfile gameProfile, @Nullable PlayerPublicKey publicKey) {
super(world, pos, yaw, gameProfile, publicKey); super(world, pos, yaw, gameProfile);
} }
@Override @Override

View file

@ -7,6 +7,11 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.item.map.MapState; import net.minecraft.item.map.MapState;
import net.minecraft.recipe.RecipeManager; import net.minecraft.recipe.RecipeManager;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.resource.featuretoggle.FeatureFlags;
import net.minecraft.resource.featuretoggle.FeatureSet;
import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
@ -15,9 +20,6 @@ import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.util.profiler.Profiler; import net.minecraft.util.profiler.Profiler;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.RegistryEntry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.Difficulty; import net.minecraft.world.Difficulty;
import net.minecraft.world.GameRules; import net.minecraft.world.GameRules;
import net.minecraft.world.MutableWorldProperties; import net.minecraft.world.MutableWorldProperties;
@ -63,13 +65,18 @@ public class DummyWorld extends World {
} }
@Override
public void playSound(@Nullable PlayerEntity except, double x, double y, double z, RegistryEntry<SoundEvent> sound, SoundCategory category, float volume, float pitch, long seed) {
}
@Override @Override
public void playSound(@Nullable PlayerEntity except, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch, long seed) { public void playSound(@Nullable PlayerEntity except, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch, long seed) {
} }
@Override @Override
public void playSoundFromEntity(@Nullable PlayerEntity except, Entity entity, SoundEvent sound, SoundCategory category, float volume, float pitch, long seed) { public void playSoundFromEntity(@Nullable PlayerEntity except, Entity entity, RegistryEntry<SoundEvent> sound, SoundCategory category, float volume, float pitch, long seed) {
} }
@ -150,6 +157,11 @@ public class DummyWorld extends World {
return null; return null;
} }
@Override
public FeatureSet getEnabledFeatures() {
return FeatureSet.of(FeatureFlags.VANILLA, FeatureFlags.BUNDLE, FeatureFlags.UPDATE_1_20);
}
@Override @Override
public float getBrightness(Direction direction, boolean shaded) { public float getBrightness(Direction direction, boolean shaded) {
return 0; return 0;

View file

@ -4,8 +4,8 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.EmptyBlockView; import net.minecraft.world.EmptyBlockView;
import rs.valence.extractor.Main; import rs.valence.extractor.Main;
@ -31,12 +31,12 @@ public class Blocks implements Main.Extractor {
var shapes = new LinkedHashMap<Shape, Integer>(); var shapes = new LinkedHashMap<Shape, Integer>();
for (var block : Registry.BLOCK) { for (var block : Registries.BLOCK) {
var blockJson = new JsonObject(); var blockJson = new JsonObject();
blockJson.addProperty("id", Registry.BLOCK.getRawId(block)); blockJson.addProperty("id", Registries.BLOCK.getRawId(block));
blockJson.addProperty("name", Registry.BLOCK.getId(block).getPath()); blockJson.addProperty("name", Registries.BLOCK.getId(block).getPath());
blockJson.addProperty("translation_key", block.getTranslationKey()); blockJson.addProperty("translation_key", block.getTranslationKey());
blockJson.addProperty("item_id", Registry.ITEM.getRawId(block.asItem())); blockJson.addProperty("item_id", Registries.ITEM.getRawId(block.asItem()));
var propsJson = new JsonArray(); var propsJson = new JsonArray();
for (var prop : block.getStateManager().getProperties()) { for (var prop : block.getStateManager().getProperties()) {

View file

@ -3,7 +3,7 @@ package rs.valence.extractor.extractors;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.util.registry.Registry; import net.minecraft.registry.Registries;
import rs.valence.extractor.Main; import rs.valence.extractor.Main;
public class Enchants implements Main.Extractor { public class Enchants implements Main.Extractor {
@ -19,11 +19,11 @@ public class Enchants implements Main.Extractor {
public JsonElement extract() { public JsonElement extract() {
var enchantsJson = new JsonArray(); var enchantsJson = new JsonArray();
for (var enchant : Registry.ENCHANTMENT) { for (var enchant : Registries.ENCHANTMENT) {
var enchantJson = new JsonObject(); var enchantJson = new JsonObject();
enchantJson.addProperty("id", Registry.ENCHANTMENT.getRawId(enchant)); enchantJson.addProperty("id", Registries.ENCHANTMENT.getRawId(enchant));
enchantJson.addProperty("name", Registry.ENCHANTMENT.getId(enchant).getPath()); enchantJson.addProperty("name", Registries.ENCHANTMENT.getId(enchant).getPath());
enchantJson.addProperty("translation_key", enchant.getTranslationKey()); enchantJson.addProperty("translation_key", enchant.getTranslationKey());
enchantJson.addProperty("min_level", enchant.getMinLevel()); enchantJson.addProperty("min_level", enchant.getMinLevel());

View file

@ -11,12 +11,12 @@ import net.minecraft.entity.passive.CatVariant;
import net.minecraft.entity.passive.FrogVariant; import net.minecraft.entity.passive.FrogVariant;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleEffect;
import net.minecraft.registry.Registries;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.EulerAngle; import net.minecraft.util.math.EulerAngle;
import net.minecraft.util.math.GlobalPos; import net.minecraft.util.math.GlobalPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryEntry;
import net.minecraft.village.VillagerData; import net.minecraft.village.VillagerData;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import rs.valence.extractor.ClassComparator; import rs.valence.extractor.ClassComparator;
@ -150,6 +150,8 @@ public class Entities implements Main.Extractor {
return new Pair<>("byte", new JsonPrimitive((Byte) val)); return new Pair<>("byte", new JsonPrimitive((Byte) val));
} else if (handler == TrackedDataHandlerRegistry.INTEGER) { } else if (handler == TrackedDataHandlerRegistry.INTEGER) {
return new Pair<>("integer", new JsonPrimitive((Integer) val)); return new Pair<>("integer", new JsonPrimitive((Integer) val));
} else if (handler == TrackedDataHandlerRegistry.LONG) {
return new Pair<>("long", new JsonPrimitive((Long) val));
} else if (handler == TrackedDataHandlerRegistry.FLOAT) { } else if (handler == TrackedDataHandlerRegistry.FLOAT) {
return new Pair<>("float", new JsonPrimitive((Float) val)); return new Pair<>("float", new JsonPrimitive((Float) val));
} else if (handler == TrackedDataHandlerRegistry.STRING) { } else if (handler == TrackedDataHandlerRegistry.STRING) {
@ -201,13 +203,13 @@ public class Entities implements Main.Extractor {
// TODO: base64 binary representation or SNBT? // TODO: base64 binary representation or SNBT?
return new Pair<>("nbt_compound", new JsonPrimitive(val.toString())); return new Pair<>("nbt_compound", new JsonPrimitive(val.toString()));
} else if (handler == TrackedDataHandlerRegistry.PARTICLE) { } else if (handler == TrackedDataHandlerRegistry.PARTICLE) {
var id = Registry.PARTICLE_TYPE.getId(((ParticleEffect) val).getType()); var id = Registries.PARTICLE_TYPE.getId(((ParticleEffect) val).getType());
return new Pair<>("particle", new JsonPrimitive(id.getPath())); return new Pair<>("particle", new JsonPrimitive(id.getPath()));
} else if (handler == TrackedDataHandlerRegistry.VILLAGER_DATA) { } else if (handler == TrackedDataHandlerRegistry.VILLAGER_DATA) {
var vd = (VillagerData) val; var vd = (VillagerData) val;
var json = new JsonObject(); var json = new JsonObject();
var type = Registry.VILLAGER_TYPE.getId(vd.getType()).getPath(); var type = Registries.VILLAGER_TYPE.getId(vd.getType()).getPath();
var profession = Registry.VILLAGER_PROFESSION.getId(vd.getProfession()).getPath(); var profession = Registries.VILLAGER_PROFESSION.getId(vd.getProfession()).getPath();
json.addProperty("type", type); json.addProperty("type", type);
json.addProperty("profession", profession); json.addProperty("profession", profession);
json.addProperty("level", vd.getLevel()); json.addProperty("level", vd.getLevel());
@ -218,9 +220,9 @@ public class Entities implements Main.Extractor {
} else if (handler == TrackedDataHandlerRegistry.ENTITY_POSE) { } else if (handler == TrackedDataHandlerRegistry.ENTITY_POSE) {
return new Pair<>("entity_pose", new JsonPrimitive(((EntityPose) val).name().toLowerCase(Locale.ROOT))); return new Pair<>("entity_pose", new JsonPrimitive(((EntityPose) val).name().toLowerCase(Locale.ROOT)));
} else if (handler == TrackedDataHandlerRegistry.CAT_VARIANT) { } else if (handler == TrackedDataHandlerRegistry.CAT_VARIANT) {
return new Pair<>("cat_variant", new JsonPrimitive(Registry.CAT_VARIANT.getId((CatVariant) val).getPath())); return new Pair<>("cat_variant", new JsonPrimitive(Registries.CAT_VARIANT.getId((CatVariant) val).getPath()));
} else if (handler == TrackedDataHandlerRegistry.FROG_VARIANT) { } else if (handler == TrackedDataHandlerRegistry.FROG_VARIANT) {
return new Pair<>("frog_variant", new JsonPrimitive(Registry.FROG_VARIANT.getId((FrogVariant) val).getPath())); return new Pair<>("frog_variant", new JsonPrimitive(Registries.FROG_VARIANT.getId((FrogVariant) val).getPath()));
} else if (handler == TrackedDataHandlerRegistry.OPTIONAL_GLOBAL_POS) { } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_GLOBAL_POS) {
return new Pair<>("optional_global_pos", ((Optional<?>) val).map(o -> { return new Pair<>("optional_global_pos", ((Optional<?>) val).map(o -> {
var gp = (GlobalPos) o; var gp = (GlobalPos) o;
@ -239,7 +241,7 @@ public class Entities implements Main.Extractor {
var variant = ((RegistryEntry<?>) val).getKey().map(k -> k.getValue().getPath()).orElse(""); var variant = ((RegistryEntry<?>) val).getKey().map(k -> k.getValue().getPath()).orElse("");
return new Pair<>("painting_variant", new JsonPrimitive(variant)); return new Pair<>("painting_variant", new JsonPrimitive(variant));
} else { } else {
throw new IllegalArgumentException("Unexpected tracked data type " + handler); throw new IllegalArgumentException("Unexpected tracked data type");
} }
} }
@ -284,6 +286,7 @@ public class Entities implements Main.Extractor {
// To obtain this, we create a dummy world to spawn the entities into and read the data tracker field from the base entity class. // To obtain this, we create a dummy world to spawn the entities into and read the data tracker field from the base entity class.
// We also handle player entities specially since they cannot be spawned with EntityType#create. // We also handle player entities specially since they cannot be spawned with EntityType#create.
final var entityInstance = entityType.equals(EntityType.PLAYER) ? DummyPlayerEntity.INSTANCE : entityType.create(DummyWorld.INSTANCE); final var entityInstance = entityType.equals(EntityType.PLAYER) ? DummyPlayerEntity.INSTANCE : entityType.create(DummyWorld.INSTANCE);
final var dataTracker = (DataTracker) dataTrackerField.get(entityInstance); final var dataTracker = (DataTracker) dataTrackerField.get(entityInstance);
while (entitiesMap.get(entityClass) == null) { while (entitiesMap.get(entityClass) == null) {
@ -297,7 +300,7 @@ public class Entities implements Main.Extractor {
} }
if (entityType != null) { if (entityType != null) {
entityJson.addProperty("type", Registry.ENTITY_TYPE.getId(entityType).getPath()); entityJson.addProperty("type", Registries.ENTITY_TYPE.getId(entityType).getPath());
entityJson.add("translation_key", new JsonPrimitive(entityType.getTranslationKey())); entityJson.add("translation_key", new JsonPrimitive(entityType.getTranslationKey()));
} }
@ -332,6 +335,17 @@ public class Entities implements Main.Extractor {
} }
entityJson.add("fields", fieldsJson); entityJson.add("fields", fieldsJson);
var bb = entityInstance.getBoundingBox();
if (bb != null) {
var boundingBoxJson = new JsonObject();
boundingBoxJson.addProperty("size_x", bb.getXLength());
boundingBoxJson.addProperty("size_y", bb.getYLength());
boundingBoxJson.addProperty("size_z", bb.getZLength());
entityJson.add("default_bounding_box", boundingBoxJson);
}
entitiesMap.put(entityClass, entityJson); entitiesMap.put(entityClass, entityJson);
if (!hasParent) { if (!hasParent) {

View file

@ -5,8 +5,8 @@ import com.google.gson.JsonObject;
import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityStatuses; import net.minecraft.entity.EntityStatuses;
import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket; import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
import rs.valence.extractor.Main; import rs.valence.extractor.Main;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -23,8 +23,8 @@ public class EntityData implements Main.Extractor {
var dataJson = new JsonObject(); var dataJson = new JsonObject();
var typesJson = new JsonObject(); var typesJson = new JsonObject();
for (var type : Registry.ENTITY_TYPE) { for (var type : Registries.ENTITY_TYPE) {
typesJson.addProperty(Registry.ENTITY_TYPE.getId(type).getPath(), Registry.ENTITY_TYPE.getRawId(type)); typesJson.addProperty(Registries.ENTITY_TYPE.getId(type).getPath(), Registries.ENTITY_TYPE.getRawId(type));
} }
dataJson.add("types", typesJson); dataJson.add("types", typesJson);
@ -50,36 +50,36 @@ public class EntityData implements Main.Extractor {
dataJson.add("animations", animationsJson); dataJson.add("animations", animationsJson);
var villagerTypesJson = new JsonObject(); var villagerTypesJson = new JsonObject();
for (var type : Registry.VILLAGER_TYPE) { for (var type : Registries.VILLAGER_TYPE) {
villagerTypesJson.addProperty(Registry.VILLAGER_TYPE.getId(type).getPath(), Registry.VILLAGER_TYPE.getRawId(type)); villagerTypesJson.addProperty(Registries.VILLAGER_TYPE.getId(type).getPath(), Registries.VILLAGER_TYPE.getRawId(type));
} }
dataJson.add("villager_types", villagerTypesJson); dataJson.add("villager_types", villagerTypesJson);
var villagerProfessionsJson = new JsonObject(); var villagerProfessionsJson = new JsonObject();
for (var profession : Registry.VILLAGER_PROFESSION) { for (var profession : Registries.VILLAGER_PROFESSION) {
villagerProfessionsJson.addProperty(profession.id(), Registry.VILLAGER_PROFESSION.getRawId(profession)); villagerProfessionsJson.addProperty(profession.id(), Registries.VILLAGER_PROFESSION.getRawId(profession));
} }
dataJson.add("villager_professions", villagerProfessionsJson); dataJson.add("villager_professions", villagerProfessionsJson);
var catVariantsJson = new JsonObject(); var catVariantsJson = new JsonObject();
for (var variant : Registry.CAT_VARIANT) { for (var variant : Registries.CAT_VARIANT) {
catVariantsJson.addProperty(Registry.CAT_VARIANT.getId(variant).getPath(), Registry.CAT_VARIANT.getRawId(variant)); catVariantsJson.addProperty(Registries.CAT_VARIANT.getId(variant).getPath(), Registries.CAT_VARIANT.getRawId(variant));
} }
dataJson.add("cat_variants", catVariantsJson); dataJson.add("cat_variants", catVariantsJson);
var frogVariantsJson = new JsonObject(); var frogVariantsJson = new JsonObject();
for (var variant : Registry.FROG_VARIANT) { for (var variant : Registries.FROG_VARIANT) {
frogVariantsJson.addProperty(Registry.FROG_VARIANT.getId(variant).getPath(), Registry.FROG_VARIANT.getRawId(variant)); frogVariantsJson.addProperty(Registries.FROG_VARIANT.getId(variant).getPath(), Registries.FROG_VARIANT.getRawId(variant));
} }
dataJson.add("frog_variants", frogVariantsJson); dataJson.add("frog_variants", frogVariantsJson);
var paintingVariantsJson = new JsonObject(); var paintingVariantsJson = new JsonObject();
for (var variant : Registry.PAINTING_VARIANT) { for (var variant : Registries.PAINTING_VARIANT) {
var variantJson = new JsonObject(); var variantJson = new JsonObject();
variantJson.addProperty("id", Registry.PAINTING_VARIANT.getRawId(variant)); variantJson.addProperty("id", Registries.PAINTING_VARIANT.getRawId(variant));
variantJson.addProperty("width", variant.getWidth()); variantJson.addProperty("width", variant.getWidth());
variantJson.addProperty("height", variant.getHeight()); variantJson.addProperty("height", variant.getHeight());
paintingVariantsJson.add(Registry.PAINTING_VARIANT.getId(variant).getPath(), variantJson); paintingVariantsJson.add(Registries.PAINTING_VARIANT.getId(variant).getPath(), variantJson);
} }
dataJson.add("painting_variants", paintingVariantsJson); dataJson.add("painting_variants", paintingVariantsJson);
@ -97,8 +97,8 @@ public class EntityData implements Main.Extractor {
dataJson.add("poses", posesJson); dataJson.add("poses", posesJson);
var particleTypesJson = new JsonObject(); var particleTypesJson = new JsonObject();
for (var type : Registry.PARTICLE_TYPE) { for (var type : Registries.PARTICLE_TYPE) {
particleTypesJson.addProperty(Registry.PARTICLE_TYPE.getId(type).getPath(), Registry.PARTICLE_TYPE.getRawId(type)); particleTypesJson.addProperty(Registries.PARTICLE_TYPE.getId(type).getPath(), Registries.PARTICLE_TYPE.getRawId(type));
} }
dataJson.add("particle_types", particleTypesJson); dataJson.add("particle_types", particleTypesJson);

View file

@ -3,7 +3,7 @@ package rs.valence.extractor.extractors;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.util.registry.Registry; import net.minecraft.registry.Registries;
import rs.valence.extractor.Main; import rs.valence.extractor.Main;
public class Items implements Main.Extractor { public class Items implements Main.Extractor {
@ -19,10 +19,10 @@ public class Items implements Main.Extractor {
public JsonElement extract() throws Exception { public JsonElement extract() throws Exception {
var itemsJson = new JsonArray(); var itemsJson = new JsonArray();
for (var item : Registry.ITEM) { for (var item : Registries.ITEM) {
var itemJson = new JsonObject(); var itemJson = new JsonObject();
itemJson.addProperty("id", Registry.ITEM.getRawId(item)); itemJson.addProperty("id", Registries.ITEM.getRawId(item));
itemJson.addProperty("name", Registry.ITEM.getId(item).getPath()); itemJson.addProperty("name", Registries.ITEM.getId(item).getPath());
itemJson.addProperty("translation_key", item.getTranslationKey()); itemJson.addProperty("translation_key", item.getTranslationKey());
itemJson.addProperty("max_stack", item.getMaxCount()); itemJson.addProperty("max_stack", item.getMaxCount());
itemJson.addProperty("max_durability", item.getMaxDamage()); itemJson.addProperty("max_durability", item.getMaxDamage());

View file

@ -14,17 +14,16 @@ use tokio::sync::OwnedSemaphorePermit;
use tracing::{info, warn}; use tracing::{info, warn};
use uuid::Uuid; use uuid::Uuid;
use valence_protocol::packets::s2c::play::{ use valence_protocol::packets::s2c::play::{
AcknowledgeBlockChange, ClearTitles, CloseContainerS2c, CombatDeath, CustomSoundEffect, AcknowledgeBlockChange, ClearTitles, CloseContainerS2c, CombatDeath, DisconnectPlay,
DisconnectPlay, EntityAnimationS2c, EntityEvent, GameEvent, KeepAliveS2c, LoginPlayOwned, EntityAnimationS2c, EntityEvent, GameEvent, KeepAliveS2c, LoginPlayOwned, OpenScreen,
OpenScreen, PluginMessageS2c, RemoveEntitiesEncode, ResourcePackS2c, RespawnOwned, PluginMessageS2c, RemoveEntitiesEncode, ResourcePackS2c, RespawnOwned, SetActionBarText,
SetActionBarText, SetCenterChunk, SetContainerContentEncode, SetContainerSlotEncode, SetCenterChunk, SetContainerContentEncode, SetContainerSlotEncode, SetDefaultSpawnPosition,
SetDefaultSpawnPosition, SetEntityMetadata, SetEntityVelocity, SetExperience, SetHealth, SetEntityMetadata, SetEntityVelocity, SetExperience, SetHealth, SetRenderDistance,
SetRenderDistance, SetSubtitleText, SetTitleAnimationTimes, SetTitleText, SetSubtitleText, SetTitleAnimationTimes, SetTitleText, SynchronizePlayerPosition,
SynchronizePlayerPosition, SystemChatMessage, UnloadChunk, UpdateAttributes, UpdateTime, SystemChatMessage, UnloadChunk, UpdateAttributes, UpdateTime,
}; };
use valence_protocol::types::{ use valence_protocol::types::{
AttributeProperty, DisplayedSkinParts, GameMode, GameStateChangeReason, SoundCategory, AttributeProperty, DisplayedSkinParts, GameMode, GameStateChangeReason, SyncPlayerPosLookFlags,
SyncPlayerPosLookFlags,
}; };
use valence_protocol::{ use valence_protocol::{
BlockPos, EncodePacket, Ident, ItemStack, RawBytes, Text, Username, VarInt, BlockPos, EncodePacket, Ident, ItemStack, RawBytes, Text, Username, VarInt,
@ -576,25 +575,6 @@ impl<C: Config> Client<C> {
}); });
} }
/// Plays a sound to the client at a given position.
pub fn play_sound(
&mut self,
name: Ident<&str>,
category: SoundCategory,
pos: Vec3<f64>,
volume: f32,
pitch: f32,
) {
self.queue_packet(&CustomSoundEffect {
name,
category,
position: (pos.as_() * 8).into_array(),
volume,
pitch,
seed: rand::random(),
});
}
/// Sets the title this client sees. /// Sets the title this client sees.
/// ///
/// A title is a large piece of text displayed in the center of the screen /// A title is a large piece of text displayed in the center of the screen
@ -1033,6 +1013,13 @@ impl<C: Config> Client<C> {
.map(|(id, pos)| (id.dimension_name(), pos)), .map(|(id, pos)| (id.dimension_name(), pos)),
})?; })?;
/*
// TODO: enable all the features?
send.append_packet(&FeatureFlags {
features: vec![Ident::new("vanilla").unwrap()],
})?;
*/
if let Some(id) = &self.player_list { if let Some(id) = &self.player_list {
player_lists[id].write_init_packets(&mut *send)?; player_lists[id].write_init_packets(&mut *send)?;
} }
@ -1378,6 +1365,15 @@ impl<C: Config> Client<C> {
})?; })?;
} }
if self.bits.created_this_tick() {
// This closes the "downloading terrain" screen.
// Send this after the initial chunks are loaded.
send.append_packet(&SetDefaultSpawnPosition {
position: BlockPos::at(self.position.into_array()),
angle: self.yaw,
})?;
}
// Update the client's own player metadata. // Update the client's own player metadata.
self.scratch.clear(); self.scratch.clear();
self.player_data.updated_tracked_data(&mut self.scratch); self.player_data.updated_tracked_data(&mut self.scratch);

View file

@ -188,6 +188,12 @@ pub enum ClientEvent {
Pong { Pong {
id: i32, id: i32,
}, },
PlayerSession {
session_id: Uuid,
expires_at: i64,
public_key_data: Box<[u8]>,
key_signature: Box<[u8]>,
},
ChangeRecipeBookSettings { ChangeRecipeBookSettings {
book_id: RecipeBookId, book_id: RecipeBookId,
book_open: bool, book_open: bool,
@ -336,7 +342,6 @@ pub(super) fn next_event_fallible<C: Config>(
message: p.message.into(), message: p.message.into(),
timestamp: p.timestamp, timestamp: p.timestamp,
}, },
C2sPlayPacket::ChatPreviewC2s(_) => ClientEvent::ChatPreview,
C2sPlayPacket::ClientCommand(p) => match p { C2sPlayPacket::ClientCommand(p) => match p {
ClientCommand::PerformRespawn => ClientEvent::PerformRespawn, ClientCommand::PerformRespawn => ClientEvent::PerformRespawn,
ClientCommand::RequestStats => ClientEvent::RequestStats, ClientCommand::RequestStats => ClientEvent::RequestStats,
@ -553,6 +558,12 @@ pub(super) fn next_event_fallible<C: Config>(
unmount: p.flags.unmount(), unmount: p.flags.unmount(),
}, },
C2sPlayPacket::PongPlay(p) => ClientEvent::Pong { id: p.id }, C2sPlayPacket::PongPlay(p) => ClientEvent::Pong { id: p.id },
C2sPlayPacket::PlayerSession(p) => ClientEvent::PlayerSession {
session_id: p.session_id,
expires_at: p.expires_at,
public_key_data: p.public_key_data.into(),
key_signature: p.key_signature.into(),
},
C2sPlayPacket::ChangeRecipeBookSettings(p) => ClientEvent::ChangeRecipeBookSettings { C2sPlayPacket::ChangeRecipeBookSettings(p) => ClientEvent::ChangeRecipeBookSettings {
book_id: p.book_id, book_id: p.book_id,
book_open: p.book_open, book_open: p.book_open,

View file

@ -517,6 +517,7 @@ impl<C: Config> Entity<C> {
TrackedData::Bee(e) => baby(e.get_child(), [0.7, 0.6, 0.7]), TrackedData::Bee(e) => baby(e.get_child(), [0.7, 0.6, 0.7]),
TrackedData::Blaze(_) => [0.6, 1.8, 0.6], TrackedData::Blaze(_) => [0.6, 1.8, 0.6],
TrackedData::Boat(_) => [1.375, 0.5625, 1.375], TrackedData::Boat(_) => [1.375, 0.5625, 1.375],
TrackedData::Camel(e) => baby(e.get_child(), [1.7, 2.375, 1.7]),
TrackedData::Cat(_) => [0.6, 0.7, 0.6], TrackedData::Cat(_) => [0.6, 0.7, 0.6],
TrackedData::CaveSpider(_) => [0.7, 0.5, 0.7], TrackedData::CaveSpider(_) => [0.7, 0.5, 0.7],
TrackedData::Chicken(e) => baby(e.get_child(), [0.4, 0.7, 0.4]), TrackedData::Chicken(e) => baby(e.get_child(), [0.4, 0.7, 0.4]),

View file

@ -4,10 +4,10 @@ use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::ops::{Deref, DerefMut, Index, IndexMut};
use bitfield_struct::bitfield;
use uuid::Uuid; use uuid::Uuid;
use valence_protocol::packets::s2c::play::{PlayerInfo, SetTabListHeaderAndFooter}; use valence_protocol::packets::s2c::play::{PlayerInfoRemove, SetTabListHeaderAndFooter};
use valence_protocol::types::{GameMode, PlayerInfoAddPlayer, SignedProperty}; use valence_protocol::player_list::{Actions, Entry as PacketEntry, PlayerInfoUpdate};
use valence_protocol::types::{GameMode, SignedProperty};
use valence_protocol::Text; use valence_protocol::Text;
use crate::config::Config; use crate::config::Config;
@ -76,7 +76,7 @@ impl<C: Config> PlayerLists<C> {
pub(crate) fn update_caches(&mut self, compression_threshold: Option<u32>) { pub(crate) fn update_caches(&mut self, compression_threshold: Option<u32>) {
let mut scratch = vec![]; let mut scratch = vec![];
// Cache the update packets. // Cache the update packets for each player list.
for pl in self.slab.iter_mut() { for pl in self.slab.iter_mut() {
pl.cached_update_packets.clear(); pl.cached_update_packets.clear();
@ -88,87 +88,111 @@ impl<C: Config> PlayerLists<C> {
if !pl.removed.is_empty() { if !pl.removed.is_empty() {
writer writer
.write_packet(&PlayerInfo::RemovePlayer( .write_packet(&PlayerInfoRemove(pl.removed.iter().cloned().collect()))
pl.removed.iter().cloned().collect(),
))
.unwrap(); .unwrap();
} }
let mut add_player = vec![];
let mut game_mode = vec![];
let mut ping = vec![];
let mut display_name = vec![];
for (&uuid, entry) in pl.entries.iter_mut() { for (&uuid, entry) in pl.entries.iter_mut() {
if entry.bits.created_this_tick() { if entry.created_this_tick {
let mut properties = vec![]; // Send packets to initialize this entry.
if let Some(textures) = &entry.textures {
properties.push(SignedProperty { let mut actions = Actions::new().with_add_player(true);
name: "textures",
value: textures.payload(), // We don't need to send data for fields if they have the default values.
signature: Some(textures.signature()),
}); if entry.listed {
actions.set_update_listed(true);
} }
add_player.push(PlayerInfoAddPlayer { // Negative pings indicate absence.
uuid, if entry.ping >= 0 {
actions.set_update_latency(true);
}
if entry.game_mode != GameMode::default() {
actions.set_update_game_mode(true);
}
if entry.display_name.is_some() {
actions.set_update_display_name(true);
}
// Don't forget to clear modified flags.
entry.old_listed = entry.listed;
entry.modified_ping = false;
entry.modified_game_mode = false;
entry.modified_display_name = false;
entry.created_this_tick = false;
let entries = vec![PacketEntry {
player_uuid: uuid,
username: &entry.username, username: &entry.username,
properties, properties: entry
.textures
.as_ref()
.map(|textures| SignedProperty {
name: "textures",
value: textures.payload(),
signature: Some(textures.signature()),
})
.into_iter()
.collect(),
chat_data: None,
listed: entry.listed,
ping: entry.ping,
game_mode: entry.game_mode, game_mode: entry.game_mode,
ping: entry.ping.into(),
display_name: entry.display_name.clone(), display_name: entry.display_name.clone(),
sig_data: None, }];
});
writer
.write_packet(&PlayerInfoUpdate { actions, entries })
.unwrap();
} else { } else {
if entry.bits.modified_game_mode() { let mut actions = Actions::new();
game_mode.push((uuid, entry.game_mode));
if entry.modified_ping {
entry.modified_ping = false;
actions.set_update_latency(true);
} }
if entry.bits.modified_ping() { if entry.modified_game_mode {
ping.push((uuid, entry.ping.into())); entry.modified_game_mode = false;
actions.set_update_game_mode(true);
} }
if entry.bits.modified_display_name() { if entry.old_listed != entry.listed {
display_name.push((uuid, entry.display_name.clone())); entry.old_listed = entry.listed;
actions.set_update_listed(true);
}
if entry.modified_ping {
entry.modified_ping = false;
actions.set_update_latency(true);
}
if entry.modified_display_name {
entry.modified_display_name = false;
actions.set_update_display_name(true);
}
if u8::from(actions) != 0 {
writer
.write_packet(&PlayerInfoUpdate {
actions,
entries: vec![PacketEntry {
player_uuid: uuid,
username: &entry.username,
properties: vec![],
chat_data: None,
listed: entry.listed,
ping: entry.ping,
game_mode: entry.game_mode,
display_name: entry.display_name.clone(),
}],
})
.unwrap();
} }
} }
entry.bits = EntryBits::new();
}
if !add_player.is_empty() {
writer
.write_packet(&PlayerInfo::AddPlayer(add_player))
.unwrap();
}
if !game_mode.is_empty() {
writer
.write_packet(&PlayerInfo::UpdateGameMode(game_mode))
.unwrap();
}
if !ping.is_empty() {
writer
.write_packet(&PlayerInfo::UpdateLatency(ping))
.unwrap();
}
if !display_name.is_empty() {
writer
.write_packet(&PlayerInfo::UpdateDisplayName(display_name))
.unwrap();
}
if pl.modified_header_or_footer {
pl.modified_header_or_footer = false;
writer
.write_packet(&SetTabListHeaderAndFooter {
header: pl.header.clone(),
footer: pl.footer.clone(),
})
.unwrap();
} }
} }
} }
@ -206,6 +230,7 @@ pub struct PlayerList<C: Config> {
pub state: C::PlayerListState, pub state: C::PlayerListState,
cached_update_packets: Vec<u8>, cached_update_packets: Vec<u8>,
entries: HashMap<Uuid, PlayerListEntry>, entries: HashMap<Uuid, PlayerListEntry>,
/// Contains entries that need to be removed.
removed: HashSet<Uuid>, removed: HashSet<Uuid>,
header: Text, header: Text,
footer: Text, footer: Text,
@ -231,6 +256,7 @@ impl<C: Config> PlayerList<C> {
/// ///
/// If the given UUID conflicts with an existing entry, the entry is /// If the given UUID conflicts with an existing entry, the entry is
/// overwritten and `false` is returned. Otherwise, `true` is returned. /// overwritten and `false` is returned. Otherwise, `true` is returned.
#[allow(clippy::too_many_arguments)]
pub fn insert( pub fn insert(
&mut self, &mut self,
uuid: Uuid, uuid: Uuid,
@ -239,6 +265,7 @@ impl<C: Config> PlayerList<C> {
game_mode: GameMode, game_mode: GameMode,
ping: i32, ping: i32,
display_name: Option<Text>, display_name: Option<Text>,
listed: bool,
) -> bool { ) -> bool {
match self.entries.entry(uuid) { match self.entries.entry(uuid) {
Entry::Occupied(mut oe) => { Entry::Occupied(mut oe) => {
@ -246,7 +273,9 @@ impl<C: Config> PlayerList<C> {
let username = username.into(); let username = username.into();
if e.username() != username || e.textures != textures { if e.username() != username || e.textures != textures {
if !e.bits.created_this_tick() { // Entries created this tick haven't been initialized by clients yet, so there
// is nothing to remove.
if !e.created_this_tick {
self.removed.insert(*oe.key()); self.removed.insert(*oe.key());
} }
@ -256,13 +285,20 @@ impl<C: Config> PlayerList<C> {
game_mode, game_mode,
ping, ping,
display_name, display_name,
bits: EntryBits::new().with_created_this_tick(true), old_listed: listed,
listed,
created_this_tick: true,
modified_game_mode: false,
modified_ping: false,
modified_display_name: false,
}); });
} else { } else {
e.set_game_mode(game_mode); e.set_game_mode(game_mode);
e.set_ping(ping); e.set_ping(ping);
e.set_display_name(display_name); e.set_display_name(display_name);
e.set_listed(listed);
} }
false false
} }
Entry::Vacant(ve) => { Entry::Vacant(ve) => {
@ -272,8 +308,14 @@ impl<C: Config> PlayerList<C> {
game_mode, game_mode,
ping, ping,
display_name, display_name,
bits: EntryBits::new().with_created_this_tick(true), old_listed: listed,
listed,
created_this_tick: true,
modified_game_mode: false,
modified_ping: false,
modified_display_name: false,
}); });
true true
} }
} }
@ -363,43 +405,50 @@ impl<C: Config> PlayerList<C> {
/// Writes the packets needed to completely initialize this player list. /// Writes the packets needed to completely initialize this player list.
pub(crate) fn write_init_packets(&self, mut writer: impl WritePacket) -> anyhow::Result<()> { pub(crate) fn write_init_packets(&self, mut writer: impl WritePacket) -> anyhow::Result<()> {
let add_player: Vec<_> = self let actions = Actions::new()
.with_add_player(true)
.with_update_game_mode(true)
.with_update_listed(true)
.with_update_latency(true)
.with_update_display_name(true);
let entries: Vec<_> = self
.entries .entries
.iter() .iter()
.map(|(&uuid, entry)| PlayerInfoAddPlayer { .map(|(&uuid, entry)| {
uuid, let properties = entry
username: &entry.username, .textures
properties: { .as_ref()
let mut properties = vec![]; .map(|textures| SignedProperty {
if let Some(textures) = &entry.textures { name: "textures",
properties.push(SignedProperty { value: textures.payload(),
name: "textures", signature: Some(textures.signature()),
value: textures.payload(), })
signature: Some(textures.signature()), .into_iter()
}); .collect();
}
properties PacketEntry {
}, player_uuid: uuid,
game_mode: entry.game_mode, username: entry.username(),
ping: entry.ping.into(), properties,
display_name: entry.display_name.clone(), chat_data: None,
sig_data: None, listed: entry.listed,
ping: entry.ping,
game_mode: entry.game_mode,
display_name: entry.display_name.clone(),
}
}) })
.collect(); .collect();
if !add_player.is_empty() { if !entries.is_empty() {
writer writer.write_packet(&PlayerInfoUpdate { actions, entries })?;
.write_packet(&PlayerInfo::AddPlayer(add_player))
.unwrap();
} }
if self.header.is_empty() || self.footer.is_empty() { if !self.header.is_empty() || !self.footer.is_empty() {
writer writer.write_packet(&SetTabListHeaderAndFooter {
.write_packet(&SetTabListHeaderAndFooter { header: self.header.clone(),
header: self.header.clone(), footer: self.footer.clone(),
footer: self.footer.clone(), })?;
})
.unwrap();
} }
Ok(()) Ok(())
@ -420,7 +469,7 @@ impl<C: Config> PlayerList<C> {
.chain(self.removed.iter().cloned()) .chain(self.removed.iter().cloned())
.collect(); .collect();
writer.write_packet(&PlayerInfo::RemovePlayer(uuids)) writer.write_packet(&PlayerInfoRemove(uuids))
} }
} }
@ -431,17 +480,12 @@ pub struct PlayerListEntry {
game_mode: GameMode, game_mode: GameMode,
ping: i32, ping: i32,
display_name: Option<Text>, display_name: Option<Text>,
bits: EntryBits, old_listed: bool,
} listed: bool,
#[bitfield(u8)]
struct EntryBits {
created_this_tick: bool, created_this_tick: bool,
modified_game_mode: bool, modified_game_mode: bool,
modified_ping: bool, modified_ping: bool,
modified_display_name: bool, modified_display_name: bool,
#[bits(4)]
_pad: u8,
} }
impl PlayerListEntry { impl PlayerListEntry {
@ -464,7 +508,8 @@ impl PlayerListEntry {
pub fn set_game_mode(&mut self, game_mode: GameMode) { pub fn set_game_mode(&mut self, game_mode: GameMode) {
if self.game_mode != game_mode { if self.game_mode != game_mode {
self.game_mode = game_mode; self.game_mode = game_mode;
self.bits.set_modified_game_mode(true); // TODO: replace modified_game_mode with old_game_mode
self.modified_game_mode = true;
} }
} }
@ -477,7 +522,7 @@ impl PlayerListEntry {
pub fn set_ping(&mut self, ping: i32) { pub fn set_ping(&mut self, ping: i32) {
if self.ping != ping { if self.ping != ping {
self.ping = ping; self.ping = ping;
self.bits.set_modified_ping(true); self.modified_ping = true;
} }
} }
@ -491,7 +536,17 @@ impl PlayerListEntry {
let display_name = display_name.into(); let display_name = display_name.into();
if self.display_name != display_name { if self.display_name != display_name {
self.display_name = display_name; self.display_name = display_name;
self.bits.set_modified_display_name(true); self.modified_display_name = true;
} }
} }
/// If this entry is visible on the player list.
pub fn is_listed(&self) -> bool {
self.listed
}
/// Sets if this entry is visible on the player list.
pub fn set_listed(&mut self, listed: bool) {
self.listed = listed;
}
} }

View file

@ -693,7 +693,6 @@ async fn handle_login(
let LoginStart { let LoginStart {
username, username,
sig_data: _, // TODO
profile_id: _, // TODO profile_id: _, // TODO
} = mngr.recv_packet().await?; } = mngr.recv_packet().await?;

View file

@ -19,7 +19,7 @@ use valence_protocol::packets::c2s::login::{EncryptionResponse, LoginPluginRespo
use valence_protocol::packets::s2c::login::{ use valence_protocol::packets::s2c::login::{
DisconnectLogin, EncryptionRequest, LoginPluginRequest, DisconnectLogin, EncryptionRequest, LoginPluginRequest,
}; };
use valence_protocol::types::{MsgSigOrVerifyToken, SignedProperty, SignedPropertyOwned}; use valence_protocol::types::{SignedProperty, SignedPropertyOwned};
use valence_protocol::{translation_key, Decode, Ident, RawBytes, Text, Username, VarInt}; use valence_protocol::{translation_key, Decode, Ident, RawBytes, Text, Username, VarInt};
use crate::config::Config; use crate::config::Config;
@ -31,13 +31,13 @@ use crate::server::{NewClientData, SharedServer};
/// [`ConnectionMode::Online`](crate::config::ConnectionMode). /// [`ConnectionMode::Online`](crate::config::ConnectionMode).
pub(super) async fn online( pub(super) async fn online(
server: &SharedServer<impl Config>, server: &SharedServer<impl Config>,
ctrl: &mut InitialPacketManager<OwnedReadHalf, OwnedWriteHalf>, mngr: &mut InitialPacketManager<OwnedReadHalf, OwnedWriteHalf>,
remote_addr: SocketAddr, remote_addr: SocketAddr,
username: Username<String>, username: Username<String>,
) -> anyhow::Result<NewClientData> { ) -> anyhow::Result<NewClientData> {
let my_verify_token: [u8; 16] = rand::random(); let my_verify_token: [u8; 16] = rand::random();
ctrl.send_packet(&EncryptionRequest { mngr.send_packet(&EncryptionRequest {
server_id: "", // Always empty server_id: "", // Always empty
public_key: &server.0.public_key_der, public_key: &server.0.public_key_der,
verify_token: &my_verify_token, verify_token: &my_verify_token,
@ -46,8 +46,8 @@ pub(super) async fn online(
let EncryptionResponse { let EncryptionResponse {
shared_secret, shared_secret,
sig_or_token, verify_token: encrypted_verify_token,
} = ctrl.recv_packet().await?; } = mngr.recv_packet().await?;
let shared_secret = server let shared_secret = server
.0 .0
@ -55,28 +55,23 @@ pub(super) async fn online(
.decrypt(PaddingScheme::PKCS1v15Encrypt, shared_secret) .decrypt(PaddingScheme::PKCS1v15Encrypt, shared_secret)
.context("failed to decrypt shared secret")?; .context("failed to decrypt shared secret")?;
match sig_or_token { let verify_token = server
MsgSigOrVerifyToken::VerifyToken(encrypted_verify_token) => { .0
let verify_token = server .rsa_key
.0 .decrypt(PaddingScheme::PKCS1v15Encrypt, encrypted_verify_token)
.rsa_key .context("failed to decrypt verify token")?;
.decrypt(PaddingScheme::PKCS1v15Encrypt, encrypted_verify_token)
.context("failed to decrypt verify token")?;
ensure!( ensure!(
my_verify_token.as_slice() == verify_token, my_verify_token.as_slice() == verify_token,
"verify tokens do not match" "verify tokens do not match"
); );
}
MsgSigOrVerifyToken::MsgSig { .. } => {}
};
let crypt_key: [u8; 16] = shared_secret let crypt_key: [u8; 16] = shared_secret
.as_slice() .as_slice()
.try_into() .try_into()
.context("shared secret has the wrong length")?; .context("shared secret has the wrong length")?;
ctrl.enable_encryption(&crypt_key); mngr.enable_encryption(&crypt_key);
let hash = Sha1::new() let hash = Sha1::new()
.chain(&shared_secret) .chain(&shared_secret)
@ -99,7 +94,7 @@ pub(super) async fn online(
translation_key::MULTIPLAYER_DISCONNECT_UNVERIFIED_USERNAME, translation_key::MULTIPLAYER_DISCONNECT_UNVERIFIED_USERNAME,
[], [],
); );
ctrl.send_packet(&DisconnectLogin { reason }).await?; mngr.send_packet(&DisconnectLogin { reason }).await?;
bail!("session server could not verify username"); bail!("session server could not verify username");
} }
status => { status => {
@ -131,8 +126,8 @@ pub(super) async fn online(
Ok(NewClientData { Ok(NewClientData {
uuid, uuid,
username, username,
textures: Some(textures),
ip: remote_addr.ip(), ip: remote_addr.ip(),
textures: Some(textures),
}) })
} }
@ -197,17 +192,17 @@ fn auth_digest(bytes: &[u8]) -> String {
} }
pub(super) async fn velocity( pub(super) async fn velocity(
ctrl: &mut InitialPacketManager<OwnedReadHalf, OwnedWriteHalf>, mngr: &mut InitialPacketManager<OwnedReadHalf, OwnedWriteHalf>,
username: Username<String>, username: Username<String>,
velocity_secret: &str, velocity_secret: &str,
) -> anyhow::Result<NewClientData> { ) -> anyhow::Result<NewClientData> {
const VELOCITY_MIN_SUPPORTED_VERSION: u8 = 1; const VELOCITY_MIN_SUPPORTED_VERSION: u8 = 1;
const VELOCITY_MODERN_FORWARDING_WITH_KEY_V2: i32 = 3; const VELOCITY_MODERN_FORWARDING_WITH_KEY_V2: i32 = 3;
let message_id = 0; let message_id: i32 = 0; // TODO: make this random?
// Send Player Info Request into the Plugin Channel // Send Player Info Request into the Plugin Channel
ctrl.send_packet(&LoginPluginRequest { mngr.send_packet(&LoginPluginRequest {
message_id: VarInt(message_id), message_id: VarInt(message_id),
channel: Ident::new("velocity:player_info").unwrap(), channel: Ident::new("velocity:player_info").unwrap(),
data: RawBytes(&[VELOCITY_MIN_SUPPORTED_VERSION]), data: RawBytes(&[VELOCITY_MIN_SUPPORTED_VERSION]),
@ -215,7 +210,7 @@ pub(super) async fn velocity(
.await?; .await?;
// Get Response // Get Response
let plugin_response: LoginPluginResponse = ctrl.recv_packet().await?; let plugin_response: LoginPluginResponse = mngr.recv_packet().await?;
ensure!( ensure!(
plugin_response.message_id.0 == message_id, plugin_response.message_id.0 == message_id,
@ -290,7 +285,7 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn auth_digest_correct() { fn auth_digest_usernames() {
assert_eq!( assert_eq!(
auth_digest(&Sha1::digest("Notch")), auth_digest(&Sha1::digest("Notch")),
"4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48" "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48"

View file

@ -15,7 +15,7 @@ byteorder = "1.4.3"
flate2 = "1.0.25" flate2 = "1.0.25"
thiserror = "1.0.37" thiserror = "1.0.37"
num-integer = "0.1.45" # TODO: remove when div_ceil is stabilized. num-integer = "0.1.45" # TODO: remove when div_ceil is stabilized.
valence = { version = "0.1.0", path = "..", optional = true } valence = { version = "0.2.0", path = "..", optional = true }
valence_nbt = { version = "0.5.0", path = "../valence_nbt" } valence_nbt = { version = "0.5.0", path = "../valence_nbt" }
[dev-dependencies] [dev-dependencies]
@ -23,7 +23,7 @@ anyhow = "1.0.68"
criterion = "0.4.0" criterion = "0.4.0"
fs_extra = "1.2.0" fs_extra = "1.2.0"
tempfile = "3.3.0" tempfile = "3.3.0"
valence = { version = "0.1.0", path = ".." } valence = { version = "0.2.0", path = ".." }
valence_anvil = { version = "0.1.0", path = ".", features = ["valence"] } valence_anvil = { version = "0.1.0", path = ".", features = ["valence"] }
zip = "0.6.3" zip = "0.6.3"

View file

@ -130,6 +130,7 @@ impl Config for Game {
client.game_mode(), client.game_mode(),
0, 0,
None, None,
true,
); );
} }

View file

@ -135,6 +135,12 @@ impl Decode<'_> for u64 {
} }
} }
impl Encode for i64 {
fn encode(&self, mut w: impl Write) -> Result<()> {
Ok(w.write_i64::<BigEndian>(*self)?)
}
}
impl Decode<'_> for i64 { impl Decode<'_> for i64 {
fn decode(r: &mut &[u8]) -> Result<Self> { fn decode(r: &mut &[u8]) -> Result<Self> {
Ok(r.read_i64::<BigEndian>()?) Ok(r.read_i64::<BigEndian>()?)
@ -165,12 +171,6 @@ impl Decode<'_> for i128 {
} }
} }
impl Encode for i64 {
fn encode(&self, mut w: impl Write) -> Result<()> {
Ok(w.write_i64::<BigEndian>(*self)?)
}
}
impl Encode for f32 { impl Encode for f32 {
fn encode(&self, mut w: impl Write) -> Result<()> { fn encode(&self, mut w: impl Write) -> Result<()> {
ensure!( ensure!(

View file

@ -90,11 +90,11 @@ pub use var_long::VarLong;
pub use {uuid, valence_nbt as nbt}; pub use {uuid, valence_nbt as nbt};
/// The Minecraft protocol version this library currently targets. /// The Minecraft protocol version this library currently targets.
pub const PROTOCOL_VERSION: i32 = 760; pub const PROTOCOL_VERSION: i32 = 761;
/// The stringified name of the Minecraft version this library currently /// The stringified name of the Minecraft version this library currently
/// targets. /// targets.
pub const MINECRAFT_VERSION: &str = "1.19.2"; pub const MINECRAFT_VERSION: &str = "1.19.3";
mod array; mod array;
pub mod block; pub mod block;
@ -109,6 +109,7 @@ mod impls;
mod inventory; mod inventory;
mod item; mod item;
pub mod packets; pub mod packets;
pub mod player_list;
mod raw_bytes; mod raw_bytes;
pub mod text; pub mod text;
pub mod translation_key; pub mod translation_key;

View file

@ -62,7 +62,7 @@ macro_rules! packet_enum {
<$packet as crate::DecodePacket>::PACKET_ID => <$packet as crate::DecodePacket>::PACKET_ID =>
Self::$packet($packet::decode(r)?), Self::$packet($packet::decode(r)?),
)* )*
id => anyhow::bail!("unknown packet id {}", id), id => anyhow::bail!("unknown packet ID {:#02x} while decoding {}", id, stringify!($enum_name)),
}) })
} }
} }
@ -126,7 +126,7 @@ macro_rules! packet_enum {
<$packet as crate::DecodePacket>::PACKET_ID => <$packet as crate::DecodePacket>::PACKET_ID =>
Self::$packet($packet::decode(r)?), Self::$packet($packet::decode(r)?),
)* )*
id => anyhow::bail!("unknown packet id {}", id), id => anyhow::bail!("unknown packet ID {:#02x} while decoding {}", id, stringify!($enum_name)),
}) })
} }
} }

View file

@ -8,9 +8,9 @@ use crate::raw_bytes::RawBytes;
use crate::types::{ use crate::types::{
Action, ChatMode, ClickContainerMode, CommandArgumentSignature, CommandBlockFlags, Action, ChatMode, ClickContainerMode, CommandArgumentSignature, CommandBlockFlags,
CommandBlockMode, Difficulty, DiggingStatus, DisplayedSkinParts, EntityInteraction, Hand, CommandBlockMode, Difficulty, DiggingStatus, DisplayedSkinParts, EntityInteraction, Hand,
HandshakeNextState, MainHand, MessageAcknowledgment, MsgSigOrVerifyToken, PlayerInputFlags, HandshakeNextState, MainHand, MessageAcknowledgment, PlayerInputFlags, RecipeBookId,
PublicKeyData, RecipeBookId, StructureBlockAction, StructureBlockFlags, StructureBlockMirror, StructureBlockAction, StructureBlockFlags, StructureBlockMirror, StructureBlockMode,
StructureBlockMode, StructureBlockRotation, StructureBlockRotation,
}; };
use crate::username::Username; use crate::username::Username;
use crate::var_int::VarInt; use crate::var_int::VarInt;
@ -75,7 +75,6 @@ pub mod login {
#[packet_id = 0x00] #[packet_id = 0x00]
pub struct LoginStart<'a> { pub struct LoginStart<'a> {
pub username: Username<&'a str>, pub username: Username<&'a str>,
pub sig_data: Option<PublicKeyData<'a>>,
pub profile_id: Option<Uuid>, pub profile_id: Option<Uuid>,
} }
@ -83,7 +82,7 @@ pub mod login {
#[packet_id = 0x01] #[packet_id = 0x01]
pub struct EncryptionResponse<'a> { pub struct EncryptionResponse<'a> {
pub shared_secret: &'a [u8], pub shared_secret: &'a [u8],
pub sig_or_token: MsgSigOrVerifyToken<'a>, pub verify_token: &'a [u8],
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
@ -151,19 +150,13 @@ pub mod play {
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x06] #[packet_id = 0x06]
pub struct ChatPreviewC2s {
// TODO
}
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x07]
pub enum ClientCommand { pub enum ClientCommand {
PerformRespawn, PerformRespawn,
RequestStats, RequestStats,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x08] #[packet_id = 0x07]
pub struct ClientInformation<'a> { pub struct ClientInformation<'a> {
pub locale: &'a str, pub locale: &'a str,
pub view_distance: u8, pub view_distance: u8,
@ -176,21 +169,21 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x09] #[packet_id = 0x08]
pub struct CommandSuggestionsRequest<'a> { pub struct CommandSuggestionsRequest<'a> {
pub transaction_id: VarInt, pub transaction_id: VarInt,
pub text: &'a str, pub text: &'a str,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0a] #[packet_id = 0x09]
pub struct ClickContainerButton { pub struct ClickContainerButton {
pub window_id: i8, pub window_id: i8,
pub button_id: i8, pub button_id: i8,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0b] #[packet_id = 0x0a]
pub struct ClickContainer { pub struct ClickContainer {
pub window_id: u8, pub window_id: u8,
pub state_id: VarInt, pub state_id: VarInt,
@ -202,20 +195,20 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0c] #[packet_id = 0x0b]
pub struct CloseContainerC2s { pub struct CloseContainerC2s {
pub window_id: i8, pub window_id: i8,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0d] #[packet_id = 0x0c]
pub struct PluginMessageC2s<'a> { pub struct PluginMessageC2s<'a> {
pub channel: Ident<&'a str>, pub channel: Ident<&'a str>,
pub data: RawBytes<'a>, pub data: RawBytes<'a>,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0e] #[packet_id = 0x0d]
pub struct EditBook<'a> { pub struct EditBook<'a> {
pub slot: VarInt, pub slot: VarInt,
pub entries: Vec<&'a str>, pub entries: Vec<&'a str>,
@ -223,14 +216,14 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0f] #[packet_id = 0x0e]
pub struct QueryEntityTag { pub struct QueryEntityTag {
pub transaction_id: VarInt, pub transaction_id: VarInt,
pub entity_id: VarInt, pub entity_id: VarInt,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x10] #[packet_id = 0x0f]
pub struct Interact { pub struct Interact {
pub entity_id: VarInt, pub entity_id: VarInt,
pub interact: EntityInteraction, pub interact: EntityInteraction,
@ -238,7 +231,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x11] #[packet_id = 0x10]
pub struct JigsawGenerate { pub struct JigsawGenerate {
pub position: BlockPos, pub position: BlockPos,
pub levels: VarInt, pub levels: VarInt,
@ -246,24 +239,24 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x12] #[packet_id = 0x11]
pub struct KeepAliveC2s { pub struct KeepAliveC2s {
pub id: u64, pub id: u64,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x13] #[packet_id = 0x12]
pub struct LockDifficulty(pub bool); pub struct LockDifficulty(pub bool);
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x14] #[packet_id = 0x13]
pub struct SetPlayerPosition { pub struct SetPlayerPosition {
pub position: [f64; 3], pub position: [f64; 3],
pub on_ground: bool, pub on_ground: bool,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x15] #[packet_id = 0x14]
pub struct SetPlayerPositionAndRotation { pub struct SetPlayerPositionAndRotation {
pub position: [f64; 3], pub position: [f64; 3],
pub yaw: f32, pub yaw: f32,
@ -272,7 +265,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x16] #[packet_id = 0x15]
pub struct SetPlayerRotation { pub struct SetPlayerRotation {
pub yaw: f32, pub yaw: f32,
pub pitch: f32, pub pitch: f32,
@ -280,11 +273,11 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x17] #[packet_id = 0x16]
pub struct SetPlayerOnGround(pub bool); pub struct SetPlayerOnGround(pub bool);
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x18] #[packet_id = 0x17]
pub struct MoveVehicleC2s { pub struct MoveVehicleC2s {
pub position: [f64; 3], pub position: [f64; 3],
pub yaw: f32, pub yaw: f32,
@ -292,20 +285,20 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x19] #[packet_id = 0x18]
pub struct PaddleBoat { pub struct PaddleBoat {
pub left_paddle_turning: bool, pub left_paddle_turning: bool,
pub right_paddle_turning: bool, pub right_paddle_turning: bool,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1a] #[packet_id = 0x19]
pub struct PickItem { pub struct PickItem {
pub slot_to_use: VarInt, pub slot_to_use: VarInt,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1b] #[packet_id = 0x1a]
pub struct PlaceRecipe<'a> { pub struct PlaceRecipe<'a> {
pub window_id: i8, pub window_id: i8,
pub recipe: Ident<&'a str>, pub recipe: Ident<&'a str>,
@ -313,7 +306,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1c] #[packet_id = 0x1b]
pub enum PlayerAbilitiesC2s { pub enum PlayerAbilitiesC2s {
#[tag = 0b00] #[tag = 0b00]
StopFlying, StopFlying,
@ -322,7 +315,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1d] #[packet_id = 0x1c]
pub struct PlayerAction { pub struct PlayerAction {
pub status: DiggingStatus, pub status: DiggingStatus,
pub position: BlockPos, pub position: BlockPos,
@ -331,7 +324,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1e] #[packet_id = 0x1d]
pub struct PlayerCommand { pub struct PlayerCommand {
pub entity_id: VarInt, pub entity_id: VarInt,
pub action_id: Action, pub action_id: Action,
@ -339,7 +332,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1f] #[packet_id = 0x1e]
pub struct PlayerInput { pub struct PlayerInput {
pub sideways: f32, pub sideways: f32,
pub forward: f32, pub forward: f32,
@ -347,11 +340,21 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x20] #[packet_id = 0x1f]
pub struct PongPlay { pub struct PongPlay {
pub id: i32, pub id: i32,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x20]
pub struct PlayerSession<'a> {
pub session_id: Uuid,
// Public key
pub expires_at: i64,
pub public_key_data: &'a [u8],
pub key_signature: &'a [u8],
}
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x21] #[packet_id = 0x21]
pub struct ChangeRecipeBookSettings { pub struct ChangeRecipeBookSettings {
@ -503,7 +506,6 @@ pub mod play {
MessageAcknowledgmentC2s<'a>, MessageAcknowledgmentC2s<'a>,
ChatCommand<'a>, ChatCommand<'a>,
ChatMessage<'a>, ChatMessage<'a>,
ChatPreviewC2s,
ClientCommand, ClientCommand,
ClientInformation<'a>, ClientInformation<'a>,
CommandSuggestionsRequest<'a>, CommandSuggestionsRequest<'a>,
@ -530,6 +532,7 @@ pub mod play {
PlayerCommand, PlayerCommand,
PlayerInput, PlayerInput,
PongPlay, PongPlay,
PlayerSession<'a>,
ChangeRecipeBookSettings, ChangeRecipeBookSettings,
SetSeenRecipe<'a>, SetSeenRecipe<'a>,
RenameItem<'a>, RenameItem<'a>,

View file

@ -9,8 +9,8 @@ use crate::item::ItemStack;
use crate::raw_bytes::RawBytes; use crate::raw_bytes::RawBytes;
use crate::text::Text; use crate::text::Text;
use crate::types::{ use crate::types::{
AttributeProperty, BossBarAction, ChunkDataBlockEntity, DeathLocation, Difficulty, GameMode, AttributeProperty, BossBarAction, ChunkDataBlockEntity, Difficulty, GameMode,
GameStateChangeReason, PlayerInfoAddPlayer, SignedProperty, SoundCategory, GameStateChangeReason, GlobalPos, PlayerAbilitiesFlags, SignedProperty, SoundCategory,
SyncPlayerPosLookFlags, SyncPlayerPosLookFlags,
}; };
use crate::username::Username; use crate::username::Username;
@ -95,6 +95,7 @@ pub mod login {
pub mod play { pub mod play {
use super::*; use super::*;
pub use crate::player_list::PlayerInfoUpdate;
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x00] #[packet_id = 0x00]
@ -181,20 +182,20 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x0d] #[packet_id = 0x0c]
pub struct ClearTitles { pub struct ClearTitles {
pub reset: bool, pub reset: bool,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x10] #[packet_id = 0x0f]
pub struct CloseContainerS2c { pub struct CloseContainerS2c {
/// Ignored by notchian clients. /// Ignored by notchian clients.
pub window_id: u8, pub window_id: u8,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x11] #[packet_id = 0x10]
pub struct SetContainerContent { pub struct SetContainerContent {
pub window_id: u8, pub window_id: u8,
pub state_id: VarInt, pub state_id: VarInt,
@ -203,7 +204,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket)]
#[packet_id = 0x11] #[packet_id = 0x10]
pub struct SetContainerContentEncode<'a> { pub struct SetContainerContentEncode<'a> {
pub window_id: u8, pub window_id: u8,
pub state_id: VarInt, pub state_id: VarInt,
@ -212,7 +213,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x12] #[packet_id = 0x11]
pub struct SetContainerProperty { pub struct SetContainerProperty {
pub window_id: u8, pub window_id: u8,
pub property: i16, pub property: i16,
@ -220,7 +221,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x13] #[packet_id = 0x12]
pub struct SetContainerSlot { pub struct SetContainerSlot {
pub window_id: i8, pub window_id: i8,
pub state_id: VarInt, pub state_id: VarInt,
@ -229,7 +230,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket)] #[derive(Clone, Debug, Encode, EncodePacket)]
#[packet_id = 0x13] #[packet_id = 0x12]
pub struct SetContainerSlotEncode<'a> { pub struct SetContainerSlotEncode<'a> {
pub window_id: i8, pub window_id: i8,
pub state_id: VarInt, pub state_id: VarInt,
@ -238,59 +239,48 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x14] #[packet_id = 0x13]
pub struct SetCooldown { pub struct SetCooldown {
pub item_id: VarInt, pub item_id: VarInt,
pub cooldown_ticks: VarInt, pub cooldown_ticks: VarInt,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x16] #[packet_id = 0x15]
pub struct PluginMessageS2c<'a> { pub struct PluginMessageS2c<'a> {
pub channel: Ident<&'a str>, pub channel: Ident<&'a str>,
pub data: RawBytes<'a>, pub data: RawBytes<'a>,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x17]
pub struct CustomSoundEffect<'a> {
pub name: Ident<&'a str>,
pub category: SoundCategory,
pub position: [i32; 3],
pub volume: f32,
pub pitch: f32,
pub seed: u64,
}
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x19] #[packet_id = 0x17]
pub struct DisconnectPlay { pub struct DisconnectPlay {
pub reason: Text, pub reason: Text,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1a] #[packet_id = 0x19]
pub struct EntityEvent { pub struct EntityEvent {
pub entity_id: i32, pub entity_id: i32,
pub entity_status: u8, pub entity_status: u8,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1c] #[packet_id = 0x1b]
pub struct UnloadChunk { pub struct UnloadChunk {
pub chunk_x: i32, pub chunk_x: i32,
pub chunk_z: i32, pub chunk_z: i32,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1d] #[packet_id = 0x1c]
pub struct GameEvent { pub struct GameEvent {
pub reason: GameStateChangeReason, pub reason: GameStateChangeReason,
pub value: f32, pub value: f32,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x1f] #[packet_id = 0x1e]
pub struct WorldBorderInitialize { pub struct WorldBorderInitialize {
pub x: f64, pub x: f64,
pub z: f64, pub z: f64,
@ -303,13 +293,13 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x20] #[packet_id = 0x1f]
pub struct KeepAliveS2c { pub struct KeepAliveS2c {
pub id: u64, pub id: u64,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x21] #[packet_id = 0x20]
pub struct ChunkDataAndUpdateLight<'a> { pub struct ChunkDataAndUpdateLight<'a> {
pub chunk_x: i32, pub chunk_x: i32,
pub chunk_z: i32, pub chunk_z: i32,
@ -326,7 +316,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket)] #[derive(Clone, Debug, Encode, EncodePacket)]
#[packet_id = 0x21] #[packet_id = 0x20]
pub struct ChunkDataAndUpdateLightEncode<'a> { pub struct ChunkDataAndUpdateLightEncode<'a> {
pub chunk_x: i32, pub chunk_x: i32,
pub chunk_z: i32, pub chunk_z: i32,
@ -343,7 +333,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x23] #[packet_id = 0x22]
pub struct ParticleS2c<'a> { pub struct ParticleS2c<'a> {
pub particle_id: VarInt, pub particle_id: VarInt,
pub long_distance: bool, pub long_distance: bool,
@ -355,7 +345,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x25] #[packet_id = 0x24]
pub struct LoginPlay<'a> { pub struct LoginPlay<'a> {
pub entity_id: i32, pub entity_id: i32,
pub is_hardcore: bool, pub is_hardcore: bool,
@ -374,12 +364,12 @@ pub mod play {
pub enable_respawn_screen: bool, pub enable_respawn_screen: bool,
pub is_debug: bool, pub is_debug: bool,
pub is_flat: bool, pub is_flat: bool,
pub last_death_location: Option<DeathLocation<'a>>, pub last_death_location: Option<GlobalPos<'a>>,
} }
// TODO: remove this. // TODO: remove this.
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x25] #[packet_id = 0x24]
pub struct LoginPlayOwned { pub struct LoginPlayOwned {
pub entity_id: i32, pub entity_id: i32,
pub is_hardcore: bool, pub is_hardcore: bool,
@ -401,7 +391,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x28] #[packet_id = 0x27]
pub struct UpdateEntityPosition { pub struct UpdateEntityPosition {
pub entity_id: VarInt, pub entity_id: VarInt,
pub delta: [i16; 3], pub delta: [i16; 3],
@ -409,7 +399,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x29] #[packet_id = 0x28]
pub struct UpdateEntityPositionAndRotation { pub struct UpdateEntityPositionAndRotation {
pub entity_id: VarInt, pub entity_id: VarInt,
pub delta: [i16; 3], pub delta: [i16; 3],
@ -419,7 +409,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x2a] #[packet_id = 0x29]
pub struct UpdateEntityRotation { pub struct UpdateEntityRotation {
pub entity_id: VarInt, pub entity_id: VarInt,
pub yaw: ByteAngle, pub yaw: ByteAngle,
@ -428,7 +418,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x2d] #[packet_id = 0x2c]
pub struct OpenScreen { pub struct OpenScreen {
pub window_id: VarInt, pub window_id: VarInt,
pub window_type: VarInt, pub window_type: VarInt,
@ -436,14 +426,22 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x33] #[packet_id = 0x30]
pub struct PlayerAbilitiesS2c {
pub flags: PlayerAbilitiesFlags,
pub flying_speed: f32,
pub fov_modifier: f32,
}
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x31]
pub struct PlayerChatMessage<'a> { pub struct PlayerChatMessage<'a> {
// TODO: A _lot_ of fields // TODO: A bunch of crap.
pub data: RawBytes<'a>, pub data: RawBytes<'a>,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x36] #[packet_id = 0x34]
pub struct CombatDeath { pub struct CombatDeath {
pub player_id: VarInt, pub player_id: VarInt,
/// Killer's entity ID, -1 if no killer /// Killer's entity ID, -1 if no killer
@ -452,17 +450,11 @@ pub mod play {
} }
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x37] #[packet_id = 0x35]
pub enum PlayerInfo<'a> { pub struct PlayerInfoRemove(pub Vec<Uuid>);
AddPlayer(Vec<PlayerInfoAddPlayer<'a>>),
UpdateGameMode(Vec<(Uuid, GameMode)>),
UpdateLatency(Vec<(Uuid, VarInt)>),
UpdateDisplayName(Vec<(Uuid, Option<Text>)>),
RemovePlayer(Vec<Uuid>),
}
#[derive(Copy, Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x39] #[packet_id = 0x38]
pub struct SynchronizePlayerPosition { pub struct SynchronizePlayerPosition {
pub position: [f64; 3], pub position: [f64; 3],
pub yaw: f32, pub yaw: f32,
@ -473,19 +465,19 @@ pub mod play {
} }
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x3b] #[packet_id = 0x3a]
pub struct RemoveEntities { pub struct RemoveEntities {
pub entity_ids: Vec<VarInt>, pub entity_ids: Vec<VarInt>,
} }
#[derive(Copy, Clone, PartialEq, Debug, Encode, EncodePacket)] #[derive(Copy, Clone, PartialEq, Debug, Encode, EncodePacket)]
#[packet_id = 0x3b] #[packet_id = 0x3a]
pub struct RemoveEntitiesEncode<'a> { pub struct RemoveEntitiesEncode<'a> {
pub entity_ids: &'a [VarInt], pub entity_ids: &'a [VarInt],
} }
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x3d] #[packet_id = 0x3c]
pub struct ResourcePackS2c<'a> { pub struct ResourcePackS2c<'a> {
pub url: &'a str, pub url: &'a str,
pub hash: &'a str, pub hash: &'a str,
@ -494,7 +486,7 @@ pub mod play {
} }
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x3e] #[packet_id = 0x3d]
pub struct Respawn<'a> { pub struct Respawn<'a> {
pub dimension_type_name: Ident<&'a str>, pub dimension_type_name: Ident<&'a str>,
pub dimension_name: Ident<&'a str>, pub dimension_name: Ident<&'a str>,
@ -504,12 +496,12 @@ pub mod play {
pub is_debug: bool, pub is_debug: bool,
pub is_flat: bool, pub is_flat: bool,
pub copy_metadata: bool, pub copy_metadata: bool,
pub last_death_location: Option<DeathLocation<'a>>, pub last_death_location: Option<GlobalPos<'a>>,
} }
// TODO: remove // TODO: remove
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x3e] #[packet_id = 0x3d]
pub struct RespawnOwned { pub struct RespawnOwned {
pub dimension_type_name: Ident<String>, pub dimension_type_name: Ident<String>,
pub dimension_name: Ident<String>, pub dimension_name: Ident<String>,
@ -523,14 +515,14 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x3f] #[packet_id = 0x3e]
pub struct SetHeadRotation { pub struct SetHeadRotation {
pub entity_id: VarInt, pub entity_id: VarInt,
pub head_yaw: ByteAngle, pub head_yaw: ByteAngle,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x40] #[packet_id = 0x3f]
pub struct UpdateSectionBlocks { pub struct UpdateSectionBlocks {
pub chunk_section_position: i64, pub chunk_section_position: i64,
pub invert_trust_edges: bool, pub invert_trust_edges: bool,
@ -538,7 +530,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket)] #[derive(Clone, Debug, Encode, EncodePacket)]
#[packet_id = 0x40] #[packet_id = 0x3f]
pub struct UpdateSectionBlocksEncode<'a> { pub struct UpdateSectionBlocksEncode<'a> {
pub chunk_section_position: i64, pub chunk_section_position: i64,
pub invert_trust_edges: bool, pub invert_trust_edges: bool,
@ -546,49 +538,49 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x43] #[packet_id = 0x42]
pub struct SetActionBarText(pub Text); pub struct SetActionBarText(pub Text);
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x4a] #[packet_id = 0x49]
pub struct SetHeldItemS2c { pub struct SetHeldItemS2c {
pub slot: u8, pub slot: u8,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x4b] #[packet_id = 0x4a]
pub struct SetCenterChunk { pub struct SetCenterChunk {
pub chunk_x: VarInt, pub chunk_x: VarInt,
pub chunk_z: VarInt, pub chunk_z: VarInt,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x4c] #[packet_id = 0x4b]
pub struct SetRenderDistance(pub VarInt); pub struct SetRenderDistance(pub VarInt);
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x4d] #[packet_id = 0x4c]
pub struct SetDefaultSpawnPosition { pub struct SetDefaultSpawnPosition {
pub position: BlockPos, pub position: BlockPos,
pub angle: f32, pub angle: f32,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x50] #[packet_id = 0x4e]
pub struct SetEntityMetadata<'a> { pub struct SetEntityMetadata<'a> {
pub entity_id: VarInt, pub entity_id: VarInt,
pub metadata: RawBytes<'a>, pub metadata: RawBytes<'a>,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x52] #[packet_id = 0x50]
pub struct SetEntityVelocity { pub struct SetEntityVelocity {
pub entity_id: VarInt, pub entity_id: VarInt,
pub velocity: [i16; 3], pub velocity: [i16; 3],
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x54] #[packet_id = 0x52]
pub struct SetExperience { pub struct SetExperience {
pub bar: f32, pub bar: f32,
pub level: VarInt, pub level: VarInt,
@ -596,7 +588,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x55] #[packet_id = 0x53]
pub struct SetHealth { pub struct SetHealth {
pub health: f32, pub health: f32,
pub food: VarInt, pub food: VarInt,
@ -604,11 +596,11 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x5b] #[packet_id = 0x59]
pub struct SetSubtitleText(pub Text); pub struct SetSubtitleText(pub Text);
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x5c] #[packet_id = 0x5a]
pub struct UpdateTime { pub struct UpdateTime {
/// The age of the world in 1/20ths of a second. /// The age of the world in 1/20ths of a second.
pub world_age: i64, pub world_age: i64,
@ -619,11 +611,11 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x5d] #[packet_id = 0x5b]
pub struct SetTitleText(pub Text); pub struct SetTitleText(pub Text);
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x5e] #[packet_id = 0x5c]
pub struct SetTitleAnimationTimes { pub struct SetTitleAnimationTimes {
/// Ticks to spend fading in. /// Ticks to spend fading in.
pub fade_in: i32, pub fade_in: i32,
@ -634,7 +626,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x5f] #[packet_id = 0x5d]
pub struct EntitySoundEffect { pub struct EntitySoundEffect {
pub id: VarInt, pub id: VarInt,
pub category: SoundCategory, pub category: SoundCategory,
@ -644,7 +636,7 @@ pub mod play {
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x60] #[packet_id = 0x5e]
pub struct SoundEffect { pub struct SoundEffect {
pub id: VarInt, pub id: VarInt,
pub category: SoundCategory, pub category: SoundCategory,
@ -655,7 +647,7 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x62] #[packet_id = 0x60]
pub struct SystemChatMessage { pub struct SystemChatMessage {
pub chat: Text, pub chat: Text,
/// Index into the chat type registry. /// Index into the chat type registry.
@ -663,14 +655,14 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x63] #[packet_id = 0x61]
pub struct SetTabListHeaderAndFooter { pub struct SetTabListHeaderAndFooter {
pub header: Text, pub header: Text,
pub footer: Text, pub footer: Text,
} }
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x66] #[packet_id = 0x64]
pub struct TeleportEntity { pub struct TeleportEntity {
pub entity_id: VarInt, pub entity_id: VarInt,
pub position: [f64; 3], pub position: [f64; 3],
@ -680,12 +672,18 @@ pub mod play {
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)] #[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x68] #[packet_id = 0x66]
pub struct UpdateAttributes<'a> { pub struct UpdateAttributes<'a> {
pub entity_id: VarInt, pub entity_id: VarInt,
pub properties: Vec<AttributeProperty<'a>>, pub properties: Vec<AttributeProperty<'a>>,
} }
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
#[packet_id = 0x67]
pub struct FeatureFlags<'a> {
pub features: Vec<Ident<&'a str>>,
}
packet_enum! { packet_enum! {
#[derive(Clone)] #[derive(Clone)]
S2cPlayPacket<'a> { S2cPlayPacket<'a> {
@ -706,7 +704,6 @@ pub mod play {
SetContainerSlot, SetContainerSlot,
SetCooldown, SetCooldown,
PluginMessageS2c<'a>, PluginMessageS2c<'a>,
CustomSoundEffect<'a>,
DisconnectPlay, DisconnectPlay,
EntityEvent, EntityEvent,
UnloadChunk, UnloadChunk,
@ -720,9 +717,11 @@ pub mod play {
UpdateEntityPositionAndRotation, UpdateEntityPositionAndRotation,
UpdateEntityRotation, UpdateEntityRotation,
OpenScreen, OpenScreen,
PlayerAbilitiesS2c,
PlayerChatMessage<'a>, PlayerChatMessage<'a>,
CombatDeath, CombatDeath,
PlayerInfo<'a>, PlayerInfoRemove,
PlayerInfoUpdate<'a>,
SynchronizePlayerPosition, SynchronizePlayerPosition,
RemoveEntities, RemoveEntities,
ResourcePackS2c<'a>, ResourcePackS2c<'a>,
@ -748,6 +747,7 @@ pub mod play {
SetTabListHeaderAndFooter, SetTabListHeaderAndFooter,
TeleportEntity, TeleportEntity,
UpdateAttributes<'a>, UpdateAttributes<'a>,
FeatureFlags<'a>,
} }
} }
} }

View file

@ -0,0 +1,126 @@
use std::io::Write;
use bitfield_struct::bitfield;
use uuid::Uuid;
use crate::types::{GameMode, SignedProperty};
use crate::{Decode, DecodePacket, Encode, EncodePacket, Text, VarInt};
#[derive(Clone, Debug, EncodePacket, DecodePacket)]
#[packet_id = 0x36]
pub struct PlayerInfoUpdate<'a> {
pub actions: Actions,
pub entries: Vec<Entry<'a>>,
}
#[bitfield(u8)]
pub struct Actions {
pub add_player: bool,
pub initialize_chat: bool,
pub update_game_mode: bool,
pub update_listed: bool,
pub update_latency: bool,
pub update_display_name: bool,
#[bits(2)]
_pad: u8,
}
#[derive(Clone, Default, Debug)]
pub struct Entry<'a> {
pub player_uuid: Uuid,
pub username: &'a str,
pub properties: Vec<SignedProperty<'a>>,
pub chat_data: Option<ChatData<'a>>,
pub listed: bool,
pub ping: i32,
pub game_mode: GameMode,
pub display_name: Option<Text>,
}
#[derive(Clone, PartialEq, Debug, Encode, Decode)]
pub struct ChatData<'a> {
pub session_id: Uuid,
/// Unix timestamp in milliseconds.
pub key_expiry_time: i64,
pub public_key: &'a [u8],
pub public_key_signature: &'a [u8],
}
impl<'a> Encode for PlayerInfoUpdate<'a> {
fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
self.actions.0.encode(&mut w)?;
// Write number of entries.
VarInt(self.entries.len() as i32).encode(&mut w)?;
for entry in &self.entries {
entry.player_uuid.encode(&mut w)?;
if self.actions.add_player() {
entry.username.encode(&mut w)?;
entry.properties.encode(&mut w)?;
}
if self.actions.initialize_chat() {
entry.chat_data.encode(&mut w)?;
}
if self.actions.update_game_mode() {
entry.game_mode.encode(&mut w)?;
}
if self.actions.update_listed() {
entry.listed.encode(&mut w)?;
}
if self.actions.update_latency() {
VarInt(entry.ping).encode(&mut w)?;
}
if self.actions.update_display_name() {
entry.display_name.encode(&mut w)?;
}
}
Ok(())
}
}
impl<'a> Decode<'a> for PlayerInfoUpdate<'a> {
fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
let actions = Actions(u8::decode(r)?);
let mut entries = vec![];
for _ in 0..VarInt::decode(r)?.0 {
let mut entry = Entry {
player_uuid: Uuid::decode(r)?,
..Default::default()
};
if actions.add_player() {
entry.username = Decode::decode(r)?;
}
if actions.initialize_chat() {
entry.chat_data = Decode::decode(r)?;
}
if actions.update_game_mode() {
entry.game_mode = Decode::decode(r)?;
}
if actions.update_latency() {
entry.ping = VarInt::decode(r)?.0;
}
if actions.update_display_name() {
entry.display_name = Decode::decode(r)?;
}
entries.push(entry);
}
Ok(Self { actions, entries })
}
}

View file

@ -22,12 +22,6 @@ pub struct PublicKeyData<'a> {
pub signature: &'a [u8], pub signature: &'a [u8],
} }
#[derive(Copy, Clone, Debug, Encode, Decode)]
pub enum MsgSigOrVerifyToken<'a> {
MsgSig { salt: u64, sig: &'a [u8] },
VerifyToken(&'a [u8]),
}
#[derive(Clone, Debug, Encode, Decode)] #[derive(Clone, Debug, Encode, Decode)]
pub struct MessageAcknowledgment<'a> { pub struct MessageAcknowledgment<'a> {
pub last_seen: Vec<MessageAcknowledgmentEntry<'a>>, pub last_seen: Vec<MessageAcknowledgmentEntry<'a>>,
@ -271,8 +265,9 @@ pub struct ChunkDataBlockEntity {
pub data: Compound, pub data: Compound,
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encode, Decode)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Encode, Decode)]
pub enum GameMode { pub enum GameMode {
#[default]
Survival, Survival,
Creative, Creative,
Adventure, Adventure,
@ -280,7 +275,7 @@ pub enum GameMode {
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encode, Decode)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub struct DeathLocation<'a> { pub struct GlobalPos<'a> {
pub dimension_name: Ident<&'a str>, pub dimension_name: Ident<&'a str>,
pub position: BlockPos, pub position: BlockPos,
} }
@ -299,17 +294,6 @@ pub struct AttributeModifier {
pub operation: u8, pub operation: u8,
} }
#[derive(Clone, PartialEq, Debug, Encode, Decode)]
pub struct PlayerInfoAddPlayer<'a> {
pub uuid: Uuid,
pub username: &'a str,
pub properties: Vec<SignedProperty<'a>>,
pub game_mode: GameMode,
pub ping: VarInt,
pub display_name: Option<Text>,
pub sig_data: Option<PublicKeyData<'a>>,
}
#[bitfield(u8)] #[bitfield(u8)]
#[derive(PartialEq, Eq, Encode, Decode)] #[derive(PartialEq, Eq, Encode, Decode)]
pub struct DisplayedSkinParts { pub struct DisplayedSkinParts {
@ -363,3 +347,14 @@ pub struct SyncPlayerPosLookFlags {
#[bits(3)] #[bits(3)]
_pad: u8, _pad: u8,
} }
#[bitfield(u8)]
#[derive(PartialEq, Eq, Encode, Decode)]
pub struct PlayerAbilitiesFlags {
pub invulnerable: bool,
pub flying: bool,
pub allow_flying: bool,
pub instant_break: bool,
#[bits(4)]
_pad: u8,
}