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]
name = "valence"
version = "0.1.0+mc1.19.2"
version = "0.2.0+mc1.19.3"
edition = "2021"
description = "A framework for building Minecraft servers in Rust."
repository = "https://github.com/rj00a/valence"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -147,6 +147,7 @@ impl Config for Game {
client.game_mode(),
0,
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)
/ (SLOT_MAX - SLOT_MIN) as f32
+ PITCH_MIN;
client.send_message(format!("playing note with pitch: {}", pitch));
client.play_sound(
Ident::new("block.note_block.harp").unwrap(),
SoundCategory::Block,
player.position(),
10.0,
pitch,
);
client.send_message(format!("playing note with pitch: {pitch}"));
let _ = player;
// client.play_sound(
// Ident::new("block.note_block.harp").unwrap(),
// SoundCategory::Block,
// player.position(),
// 10.0,
// pitch,
// );
} else if clicked_slot == 44 {
client.set_game_mode(match client.game_mode() {
GameMode::Survival => GameMode::Creative,

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,9 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.19.2
yarn_mappings=1.19.2+build.8
loader_version=0.14.9
minecraft_version=1.19.3
yarn_mappings=1.19.3+build.3
loader_version=0.14.11
# Mod Properties
mod_version = 1.0.0
@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G
archives_base_name = valence-extractor
# 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) {
super(world, pos, yaw, gameProfile, publicKey);
super(world, pos, yaw, gameProfile);
}
@Override

View file

@ -7,6 +7,11 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.map.MapState;
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.sound.SoundCategory;
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.random.Random;
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.GameRules;
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
public void playSound(@Nullable PlayerEntity except, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch, long seed) {
}
@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;
}
@Override
public FeatureSet getEnabledFeatures() {
return FeatureSet.of(FeatureFlags.VANILLA, FeatureFlags.BUNDLE, FeatureFlags.UPDATE_1_20);
}
@Override
public float getBrightness(Direction direction, boolean shaded) {
return 0;

View file

@ -4,8 +4,8 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.EmptyBlockView;
import rs.valence.extractor.Main;
@ -31,12 +31,12 @@ public class Blocks implements Main.Extractor {
var shapes = new LinkedHashMap<Shape, Integer>();
for (var block : Registry.BLOCK) {
for (var block : Registries.BLOCK) {
var blockJson = new JsonObject();
blockJson.addProperty("id", Registry.BLOCK.getRawId(block));
blockJson.addProperty("name", Registry.BLOCK.getId(block).getPath());
blockJson.addProperty("id", Registries.BLOCK.getRawId(block));
blockJson.addProperty("name", Registries.BLOCK.getId(block).getPath());
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();
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.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.util.registry.Registry;
import net.minecraft.registry.Registries;
import rs.valence.extractor.Main;
public class Enchants implements Main.Extractor {
@ -19,11 +19,11 @@ public class Enchants implements Main.Extractor {
public JsonElement extract() {
var enchantsJson = new JsonArray();
for (var enchant : Registry.ENCHANTMENT) {
for (var enchant : Registries.ENCHANTMENT) {
var enchantJson = new JsonObject();
enchantJson.addProperty("id", Registry.ENCHANTMENT.getRawId(enchant));
enchantJson.addProperty("name", Registry.ENCHANTMENT.getId(enchant).getPath());
enchantJson.addProperty("id", Registries.ENCHANTMENT.getRawId(enchant));
enchantJson.addProperty("name", Registries.ENCHANTMENT.getId(enchant).getPath());
enchantJson.addProperty("translation_key", enchant.getTranslationKey());
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.item.ItemStack;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.registry.Registries;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.EulerAngle;
import net.minecraft.util.math.GlobalPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryEntry;
import net.minecraft.village.VillagerData;
import org.jetbrains.annotations.Nullable;
import rs.valence.extractor.ClassComparator;
@ -150,6 +150,8 @@ public class Entities implements Main.Extractor {
return new Pair<>("byte", new JsonPrimitive((Byte) val));
} else if (handler == TrackedDataHandlerRegistry.INTEGER) {
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) {
return new Pair<>("float", new JsonPrimitive((Float) val));
} else if (handler == TrackedDataHandlerRegistry.STRING) {
@ -201,13 +203,13 @@ public class Entities implements Main.Extractor {
// TODO: base64 binary representation or SNBT?
return new Pair<>("nbt_compound", new JsonPrimitive(val.toString()));
} 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()));
} else if (handler == TrackedDataHandlerRegistry.VILLAGER_DATA) {
var vd = (VillagerData) val;
var json = new JsonObject();
var type = Registry.VILLAGER_TYPE.getId(vd.getType()).getPath();
var profession = Registry.VILLAGER_PROFESSION.getId(vd.getProfession()).getPath();
var type = Registries.VILLAGER_TYPE.getId(vd.getType()).getPath();
var profession = Registries.VILLAGER_PROFESSION.getId(vd.getProfession()).getPath();
json.addProperty("type", type);
json.addProperty("profession", profession);
json.addProperty("level", vd.getLevel());
@ -218,9 +220,9 @@ public class Entities implements Main.Extractor {
} else if (handler == TrackedDataHandlerRegistry.ENTITY_POSE) {
return new Pair<>("entity_pose", new JsonPrimitive(((EntityPose) val).name().toLowerCase(Locale.ROOT)));
} 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) {
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) {
return new Pair<>("optional_global_pos", ((Optional<?>) val).map(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("");
return new Pair<>("painting_variant", new JsonPrimitive(variant));
} 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.
// 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 dataTracker = (DataTracker) dataTrackerField.get(entityInstance);
while (entitiesMap.get(entityClass) == null) {
@ -297,7 +300,7 @@ public class Entities implements Main.Extractor {
}
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()));
}
@ -332,6 +335,17 @@ public class Entities implements Main.Extractor {
}
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);
if (!hasParent) {

View file

@ -5,8 +5,8 @@ import com.google.gson.JsonObject;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityStatuses;
import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
import rs.valence.extractor.Main;
import java.lang.reflect.Modifier;
@ -23,8 +23,8 @@ public class EntityData implements Main.Extractor {
var dataJson = new JsonObject();
var typesJson = new JsonObject();
for (var type : Registry.ENTITY_TYPE) {
typesJson.addProperty(Registry.ENTITY_TYPE.getId(type).getPath(), Registry.ENTITY_TYPE.getRawId(type));
for (var type : Registries.ENTITY_TYPE) {
typesJson.addProperty(Registries.ENTITY_TYPE.getId(type).getPath(), Registries.ENTITY_TYPE.getRawId(type));
}
dataJson.add("types", typesJson);
@ -50,36 +50,36 @@ public class EntityData implements Main.Extractor {
dataJson.add("animations", animationsJson);
var villagerTypesJson = new JsonObject();
for (var type : Registry.VILLAGER_TYPE) {
villagerTypesJson.addProperty(Registry.VILLAGER_TYPE.getId(type).getPath(), Registry.VILLAGER_TYPE.getRawId(type));
for (var type : Registries.VILLAGER_TYPE) {
villagerTypesJson.addProperty(Registries.VILLAGER_TYPE.getId(type).getPath(), Registries.VILLAGER_TYPE.getRawId(type));
}
dataJson.add("villager_types", villagerTypesJson);
var villagerProfessionsJson = new JsonObject();
for (var profession : Registry.VILLAGER_PROFESSION) {
villagerProfessionsJson.addProperty(profession.id(), Registry.VILLAGER_PROFESSION.getRawId(profession));
for (var profession : Registries.VILLAGER_PROFESSION) {
villagerProfessionsJson.addProperty(profession.id(), Registries.VILLAGER_PROFESSION.getRawId(profession));
}
dataJson.add("villager_professions", villagerProfessionsJson);
var catVariantsJson = new JsonObject();
for (var variant : Registry.CAT_VARIANT) {
catVariantsJson.addProperty(Registry.CAT_VARIANT.getId(variant).getPath(), Registry.CAT_VARIANT.getRawId(variant));
for (var variant : Registries.CAT_VARIANT) {
catVariantsJson.addProperty(Registries.CAT_VARIANT.getId(variant).getPath(), Registries.CAT_VARIANT.getRawId(variant));
}
dataJson.add("cat_variants", catVariantsJson);
var frogVariantsJson = new JsonObject();
for (var variant : Registry.FROG_VARIANT) {
frogVariantsJson.addProperty(Registry.FROG_VARIANT.getId(variant).getPath(), Registry.FROG_VARIANT.getRawId(variant));
for (var variant : Registries.FROG_VARIANT) {
frogVariantsJson.addProperty(Registries.FROG_VARIANT.getId(variant).getPath(), Registries.FROG_VARIANT.getRawId(variant));
}
dataJson.add("frog_variants", frogVariantsJson);
var paintingVariantsJson = new JsonObject();
for (var variant : Registry.PAINTING_VARIANT) {
for (var variant : Registries.PAINTING_VARIANT) {
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("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);
@ -97,8 +97,8 @@ public class EntityData implements Main.Extractor {
dataJson.add("poses", posesJson);
var particleTypesJson = new JsonObject();
for (var type : Registry.PARTICLE_TYPE) {
particleTypesJson.addProperty(Registry.PARTICLE_TYPE.getId(type).getPath(), Registry.PARTICLE_TYPE.getRawId(type));
for (var type : Registries.PARTICLE_TYPE) {
particleTypesJson.addProperty(Registries.PARTICLE_TYPE.getId(type).getPath(), Registries.PARTICLE_TYPE.getRawId(type));
}
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.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.util.registry.Registry;
import net.minecraft.registry.Registries;
import rs.valence.extractor.Main;
public class Items implements Main.Extractor {
@ -19,10 +19,10 @@ public class Items implements Main.Extractor {
public JsonElement extract() throws Exception {
var itemsJson = new JsonArray();
for (var item : Registry.ITEM) {
for (var item : Registries.ITEM) {
var itemJson = new JsonObject();
itemJson.addProperty("id", Registry.ITEM.getRawId(item));
itemJson.addProperty("name", Registry.ITEM.getId(item).getPath());
itemJson.addProperty("id", Registries.ITEM.getRawId(item));
itemJson.addProperty("name", Registries.ITEM.getId(item).getPath());
itemJson.addProperty("translation_key", item.getTranslationKey());
itemJson.addProperty("max_stack", item.getMaxCount());
itemJson.addProperty("max_durability", item.getMaxDamage());

View file

@ -14,17 +14,16 @@ use tokio::sync::OwnedSemaphorePermit;
use tracing::{info, warn};
use uuid::Uuid;
use valence_protocol::packets::s2c::play::{
AcknowledgeBlockChange, ClearTitles, CloseContainerS2c, CombatDeath, CustomSoundEffect,
DisconnectPlay, EntityAnimationS2c, EntityEvent, GameEvent, KeepAliveS2c, LoginPlayOwned,
OpenScreen, PluginMessageS2c, RemoveEntitiesEncode, ResourcePackS2c, RespawnOwned,
SetActionBarText, SetCenterChunk, SetContainerContentEncode, SetContainerSlotEncode,
SetDefaultSpawnPosition, SetEntityMetadata, SetEntityVelocity, SetExperience, SetHealth,
SetRenderDistance, SetSubtitleText, SetTitleAnimationTimes, SetTitleText,
SynchronizePlayerPosition, SystemChatMessage, UnloadChunk, UpdateAttributes, UpdateTime,
AcknowledgeBlockChange, ClearTitles, CloseContainerS2c, CombatDeath, DisconnectPlay,
EntityAnimationS2c, EntityEvent, GameEvent, KeepAliveS2c, LoginPlayOwned, OpenScreen,
PluginMessageS2c, RemoveEntitiesEncode, ResourcePackS2c, RespawnOwned, SetActionBarText,
SetCenterChunk, SetContainerContentEncode, SetContainerSlotEncode, SetDefaultSpawnPosition,
SetEntityMetadata, SetEntityVelocity, SetExperience, SetHealth, SetRenderDistance,
SetSubtitleText, SetTitleAnimationTimes, SetTitleText, SynchronizePlayerPosition,
SystemChatMessage, UnloadChunk, UpdateAttributes, UpdateTime,
};
use valence_protocol::types::{
AttributeProperty, DisplayedSkinParts, GameMode, GameStateChangeReason, SoundCategory,
SyncPlayerPosLookFlags,
AttributeProperty, DisplayedSkinParts, GameMode, GameStateChangeReason, SyncPlayerPosLookFlags,
};
use valence_protocol::{
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.
///
/// 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)),
})?;
/*
// TODO: enable all the features?
send.append_packet(&FeatureFlags {
features: vec![Ident::new("vanilla").unwrap()],
})?;
*/
if let Some(id) = &self.player_list {
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.
self.scratch.clear();
self.player_data.updated_tracked_data(&mut self.scratch);

View file

@ -188,6 +188,12 @@ pub enum ClientEvent {
Pong {
id: i32,
},
PlayerSession {
session_id: Uuid,
expires_at: i64,
public_key_data: Box<[u8]>,
key_signature: Box<[u8]>,
},
ChangeRecipeBookSettings {
book_id: RecipeBookId,
book_open: bool,
@ -336,7 +342,6 @@ pub(super) fn next_event_fallible<C: Config>(
message: p.message.into(),
timestamp: p.timestamp,
},
C2sPlayPacket::ChatPreviewC2s(_) => ClientEvent::ChatPreview,
C2sPlayPacket::ClientCommand(p) => match p {
ClientCommand::PerformRespawn => ClientEvent::PerformRespawn,
ClientCommand::RequestStats => ClientEvent::RequestStats,
@ -553,6 +558,12 @@ pub(super) fn next_event_fallible<C: Config>(
unmount: p.flags.unmount(),
},
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 {
book_id: p.book_id,
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::Blaze(_) => [0.6, 1.8, 0.6],
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::CaveSpider(_) => [0.7, 0.5, 0.7],
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::ops::{Deref, DerefMut, Index, IndexMut};
use bitfield_struct::bitfield;
use uuid::Uuid;
use valence_protocol::packets::s2c::play::{PlayerInfo, SetTabListHeaderAndFooter};
use valence_protocol::types::{GameMode, PlayerInfoAddPlayer, SignedProperty};
use valence_protocol::packets::s2c::play::{PlayerInfoRemove, SetTabListHeaderAndFooter};
use valence_protocol::player_list::{Actions, Entry as PacketEntry, PlayerInfoUpdate};
use valence_protocol::types::{GameMode, SignedProperty};
use valence_protocol::Text;
use crate::config::Config;
@ -76,7 +76,7 @@ impl<C: Config> PlayerLists<C> {
pub(crate) fn update_caches(&mut self, compression_threshold: Option<u32>) {
let mut scratch = vec![];
// Cache the update packets.
// Cache the update packets for each player list.
for pl in self.slab.iter_mut() {
pl.cached_update_packets.clear();
@ -88,87 +88,111 @@ impl<C: Config> PlayerLists<C> {
if !pl.removed.is_empty() {
writer
.write_packet(&PlayerInfo::RemovePlayer(
pl.removed.iter().cloned().collect(),
))
.write_packet(&PlayerInfoRemove(pl.removed.iter().cloned().collect()))
.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() {
if entry.bits.created_this_tick() {
let mut properties = vec![];
if let Some(textures) = &entry.textures {
properties.push(SignedProperty {
name: "textures",
value: textures.payload(),
signature: Some(textures.signature()),
});
if entry.created_this_tick {
// Send packets to initialize this entry.
let mut actions = Actions::new().with_add_player(true);
// We don't need to send data for fields if they have the default values.
if entry.listed {
actions.set_update_listed(true);
}
add_player.push(PlayerInfoAddPlayer {
uuid,
// Negative pings indicate absence.
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,
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,
ping: entry.ping.into(),
display_name: entry.display_name.clone(),
sig_data: None,
});
}];
writer
.write_packet(&PlayerInfoUpdate { actions, entries })
.unwrap();
} else {
if entry.bits.modified_game_mode() {
game_mode.push((uuid, entry.game_mode));
let mut actions = Actions::new();
if entry.modified_ping {
entry.modified_ping = false;
actions.set_update_latency(true);
}
if entry.bits.modified_ping() {
ping.push((uuid, entry.ping.into()));
if entry.modified_game_mode {
entry.modified_game_mode = false;
actions.set_update_game_mode(true);
}
if entry.bits.modified_display_name() {
display_name.push((uuid, entry.display_name.clone()));
if entry.old_listed != entry.listed {
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,
cached_update_packets: Vec<u8>,
entries: HashMap<Uuid, PlayerListEntry>,
/// Contains entries that need to be removed.
removed: HashSet<Uuid>,
header: Text,
footer: Text,
@ -231,6 +256,7 @@ impl<C: Config> PlayerList<C> {
///
/// If the given UUID conflicts with an existing entry, the entry is
/// overwritten and `false` is returned. Otherwise, `true` is returned.
#[allow(clippy::too_many_arguments)]
pub fn insert(
&mut self,
uuid: Uuid,
@ -239,6 +265,7 @@ impl<C: Config> PlayerList<C> {
game_mode: GameMode,
ping: i32,
display_name: Option<Text>,
listed: bool,
) -> bool {
match self.entries.entry(uuid) {
Entry::Occupied(mut oe) => {
@ -246,7 +273,9 @@ impl<C: Config> PlayerList<C> {
let username = username.into();
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());
}
@ -256,13 +285,20 @@ impl<C: Config> PlayerList<C> {
game_mode,
ping,
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 {
e.set_game_mode(game_mode);
e.set_ping(ping);
e.set_display_name(display_name);
e.set_listed(listed);
}
false
}
Entry::Vacant(ve) => {
@ -272,8 +308,14 @@ impl<C: Config> PlayerList<C> {
game_mode,
ping,
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
}
}
@ -363,43 +405,50 @@ impl<C: Config> PlayerList<C> {
/// Writes the packets needed to completely initialize this player list.
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
.iter()
.map(|(&uuid, entry)| PlayerInfoAddPlayer {
uuid,
username: &entry.username,
properties: {
let mut properties = vec![];
if let Some(textures) = &entry.textures {
properties.push(SignedProperty {
name: "textures",
value: textures.payload(),
signature: Some(textures.signature()),
});
}
properties
},
game_mode: entry.game_mode,
ping: entry.ping.into(),
display_name: entry.display_name.clone(),
sig_data: None,
.map(|(&uuid, entry)| {
let properties = entry
.textures
.as_ref()
.map(|textures| SignedProperty {
name: "textures",
value: textures.payload(),
signature: Some(textures.signature()),
})
.into_iter()
.collect();
PacketEntry {
player_uuid: uuid,
username: entry.username(),
properties,
chat_data: None,
listed: entry.listed,
ping: entry.ping,
game_mode: entry.game_mode,
display_name: entry.display_name.clone(),
}
})
.collect();
if !add_player.is_empty() {
writer
.write_packet(&PlayerInfo::AddPlayer(add_player))
.unwrap();
if !entries.is_empty() {
writer.write_packet(&PlayerInfoUpdate { actions, entries })?;
}
if self.header.is_empty() || self.footer.is_empty() {
writer
.write_packet(&SetTabListHeaderAndFooter {
header: self.header.clone(),
footer: self.footer.clone(),
})
.unwrap();
if !self.header.is_empty() || !self.footer.is_empty() {
writer.write_packet(&SetTabListHeaderAndFooter {
header: self.header.clone(),
footer: self.footer.clone(),
})?;
}
Ok(())
@ -420,7 +469,7 @@ impl<C: Config> PlayerList<C> {
.chain(self.removed.iter().cloned())
.collect();
writer.write_packet(&PlayerInfo::RemovePlayer(uuids))
writer.write_packet(&PlayerInfoRemove(uuids))
}
}
@ -431,17 +480,12 @@ pub struct PlayerListEntry {
game_mode: GameMode,
ping: i32,
display_name: Option<Text>,
bits: EntryBits,
}
#[bitfield(u8)]
struct EntryBits {
old_listed: bool,
listed: bool,
created_this_tick: bool,
modified_game_mode: bool,
modified_ping: bool,
modified_display_name: bool,
#[bits(4)]
_pad: u8,
}
impl PlayerListEntry {
@ -464,7 +508,8 @@ impl PlayerListEntry {
pub fn set_game_mode(&mut self, game_mode: GameMode) {
if 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) {
if 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();
if 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 {
username,
sig_data: _, // TODO
profile_id: _, // TODO
} = mngr.recv_packet().await?;

View file

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

View file

@ -15,7 +15,7 @@ byteorder = "1.4.3"
flate2 = "1.0.25"
thiserror = "1.0.37"
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" }
[dev-dependencies]
@ -23,7 +23,7 @@ anyhow = "1.0.68"
criterion = "0.4.0"
fs_extra = "1.2.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"] }
zip = "0.6.3"

View file

@ -130,6 +130,7 @@ impl Config for Game {
client.game_mode(),
0,
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 {
fn decode(r: &mut &[u8]) -> Result<Self> {
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 {
fn encode(&self, mut w: impl Write) -> Result<()> {
ensure!(

View file

@ -90,11 +90,11 @@ pub use var_long::VarLong;
pub use {uuid, valence_nbt as nbt};
/// 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
/// targets.
pub const MINECRAFT_VERSION: &str = "1.19.2";
pub const MINECRAFT_VERSION: &str = "1.19.3";
mod array;
pub mod block;
@ -109,6 +109,7 @@ mod impls;
mod inventory;
mod item;
pub mod packets;
pub mod player_list;
mod raw_bytes;
pub mod text;
pub mod translation_key;

View file

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

View file

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