Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/server_chat_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,14 @@ def player_joined(self):

if self.protocol_version >= 759: # 1.19
join_game.append(self.buff_type.pack("?", False))

# Send "Join Game" packet
self.send_packet("join_game", *join_game)

# 1.19.3+ Send default spawn position, required to hide Loading Terrain screen
if self.protocol_version >= 761:
self.send_packet("spawn_position", self.buff_type.pack("iii", 0, 0, 0))

# Send "Player Position and Look" packet
self.send_packet(
"player_position_and_look",
Expand Down
80 changes: 60 additions & 20 deletions examples/server_chat_room_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,16 @@ def player_joined(self):
# in-game, and does some logging.
ServerProtocol.player_joined(self)

# Send server data packet on 1.19+
if self.protocol_version >= 760:
self.send_packet('server_data',
self.buff_type.pack('????',
False, # Optional description
False, # Optional favicon
False, # Disable chat previews
self.factory.online_mode)) # Enforce chat signing when in online mode
elif self.protocol_version == 759: # 1.19 lacks enforce chat signing field
self.send_packet('server_data', self.buff_type.pack('???', False, False, False))
# Send server data
self.factory.send_server_data(self)

# Send join game packet
self.factory.send_join_game(self)

# 1.19.3+ Send default spawn position, required to hide Loading Terrain screen
if self.protocol_version >= 761:
self.send_packet("spawn_position", self.buff_type.pack("iii", 0, 0, 0))

# Send "Player Position and Look" packet
self.send_packet(
"player_position_and_look",
Expand Down Expand Up @@ -225,6 +221,27 @@ class ChatRoomFactory(ServerFactory):
protocol = ChatRoomProtocol
motd = "Chat Room Server"

def send_server_data(self, player):
# 1.19.3+ removed chat preview field
if player.protocol_version >= 761:
player.send_packet('server_data',
player.buff_type.pack('???',
False,
False,
self.online_mode)) # Enforce chat signing when in online mode

# 1.19 added enforce chat signing field
elif player.protocol_version >= 760:
player.send_packet('server_data',
player.buff_type.pack('????',
False,
False,
False,
self.online_mode)) # Enforce chat signing when in online mode

elif player.protocol_version == 759:
player.send_packet('server_data', self.buff_type.pack('???', False, False, False))

def send_join_game(self, player):
# Build up fields for "Join Game" packet
entity_id = 0
Expand Down Expand Up @@ -375,10 +392,17 @@ def broadcast_player_list_add(self, added: ChatRoomProtocol):

@staticmethod
def send_player_list_add(player: ChatRoomProtocol, added: List[ChatRoomProtocol]):
data = [
player.buff_type.pack_varint(0), # Action - 0 = Player add
player.buff_type.pack_varint(len(added)), # Player entry count
]
data = []

# 1.19.3+ splits the player list into separate remove and update packets (which also add players)
# Update packets use a bitset to indicate which player information is being added/updated
if player.protocol_version >= 761:
data.append(player.buff_type.pack('B', 63)) # Set first 6 bits to indicate all fields are being updated

else: # Older versions have a single packet with a varint for "action", 0 being adding a player
data.append(player.buff_type.pack_varint(0))

data.append(player.buff_type.pack_varint(len(added))) # Player entry count

for entry in added:
if entry.protocol_mode != 'play':
Expand All @@ -387,12 +411,22 @@ def send_player_list_add(player: ChatRoomProtocol, added: List[ChatRoomProtocol]
data.append(player.buff_type.pack_uuid(entry.uuid)) # Player UUID
data.append(player.buff_type.pack_string(entry.display_name)) # Player name
data.append(player.buff_type.pack_varint(0)) # Empty properties list

# 1.19.3+ include the players public key here
if player.protocol_version >= 761:
data.append(player.buff_type.pack('?', False))

data.append(player.buff_type.pack_varint(3)) # Gamemode

# 1.19.3+ includes an extra field for whether to update the tab list
if player.protocol_version >= 761:
data.append(player.buff_type.pack('?', True))

data.append(player.buff_type.pack_varint(0)) # Latency
data.append(player.buff_type.pack('?', False)) # No display name

# Add signature for 1.19+ clients if it exists
if player.protocol_version >= 759:
# 1.19 - 1.19.1 include the players public key here
if 759 <= player.protocol_version < 761:
data.append(player.buff_type.pack_optional(player.buff_type.pack_player_public_key, entry.public_key_data))

player.send_packet('player_list_item', *data)
Expand All @@ -401,10 +435,16 @@ def send_player_list_add(player: ChatRoomProtocol, added: List[ChatRoomProtocol]
def broadcast_player_list_remove(self, removed: ChatRoomProtocol):
for player in self.players:
if player.protocol_mode == 'play' and player != removed:
player.send_packet('player_list_item',
player.buff_type.pack_varint(4), # Action - 4 = Player remove
player.buff_type.pack_varint(1), # Player entry count
player.buff_type.pack_uuid(removed.uuid)) # Player UUID

if player.protocol_version >= 761: # 1.19.3 has separate packet for player list removals
player.send_packet('player_list_remove',
player.buff_type.pack_varint(1), # Player entry count
player.buff_type.pack_uuid(removed.uuid)) # Player UUID
else:
player.send_packet('player_list_item',
player.buff_type.pack_varint(4), # Action - 4 = Player remove
player.buff_type.pack_varint(1), # Player entry count
player.buff_type.pack_uuid(removed.uuid)) # Player UUID


def main(argv):
Expand Down
Binary file added quarry/data/data_packs/0761_1.19.3.nbt
Binary file not shown.
172 changes: 172 additions & 0 deletions quarry/data/packets/0761_1.19.3.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
protocol_mode,packet_direction,packet_name
init,upstream,handshake
play,downstream,spawn_object
play,downstream,spawn_experience_orb
play,downstream,spawn_player
play,downstream,animation
play,downstream,statistics
play,downstream,acknowledge_block_changes
play,downstream,block_break_animation
play,downstream,update_block_entity
play,downstream,block_action
play,downstream,block_change
play,downstream,boss_bar
play,downstream,server_difficulty
play,downstream,clear_titles
play,downstream,tab_complete
play,downstream,declare_commands
play,downstream,close_window
play,downstream,window_items
play,downstream,window_property
play,downstream,set_slot
play,downstream,set_cooldown
play,downstream,custom_chat_completions
play,downstream,plugin_message
play,downstream,delete_chat_message
play,downstream,disconnect
play,downstream,disguised_chat
play,downstream,entity_status
play,downstream,explosion
play,downstream,unload_chunk
play,downstream,change_game_state
play,downstream,open_horse_window
play,downstream,initialize_world_border
play,downstream,keep_alive
play,downstream,chunk_data
play,downstream,effect
play,downstream,particle
play,downstream,update_light
play,downstream,join_game
play,downstream,map
play,downstream,trade_list
play,downstream,entity_relative_move
play,downstream,entity_look_and_relative_move
play,downstream,entity_look
play,downstream,vehicle_move
play,downstream,open_book
play,downstream,open_window
play,downstream,open_sign_editor
play,downstream,ping
play,downstream,craft_recipe_response
play,downstream,player_abilities
play,downstream,chat_message
play,downstream,end_combat_event
play,downstream,enter_combat_event
play,downstream,death_combat_event
play,downstream,player_list_remove
play,downstream,player_list_item
play,downstream,face_player
play,downstream,player_position_and_look
play,downstream,unlock_recipes
play,downstream,destroy_entities
play,downstream,remove_entity_effect
play,downstream,resource_pack_send
play,downstream,respawn
play,downstream,entity_head_look
play,downstream,multi_block_change
play,downstream,select_advancement_tab
play,downstream,server_data
play,downstream,action_bar
play,downstream,world_border_center
play,downstream,world_border_lerp_size
play,downstream,world_border_size
play,downstream,world_border_warning_delay
play,downstream,world_border_warning_reach
play,downstream,camera
play,downstream,held_item_change
play,downstream,update_view_position
play,downstream,update_view_distance
play,downstream,spawn_position
play,downstream,display_scoreboard
play,downstream,entity_metadata
play,downstream,attach_entity
play,downstream,entity_velocity
play,downstream,entity_equipment
play,downstream,set_experience
play,downstream,update_health
play,downstream,scoreboard_objective
play,downstream,set_passengers
play,downstream,teams
play,downstream,update_score
play,downstream,set_simulation_distance
play,downstream,set_title_subtitle
play,downstream,time_update
play,downstream,set_title_text
play,downstream,set_title_time
play,downstream,entity_sound_effect
play,downstream,sound_effect
play,downstream,stop_sound
play,downstream,system_message
play,downstream,player_list_header_footer
play,downstream,block_metadata_response
play,downstream,collect_item
play,downstream,entity_teleport
play,downstream,advancements
play,downstream,entity_properties
play,downstream,update_enabled_features
play,downstream,entity_effect
play,downstream,declare_recipes
play,downstream,tags
play,upstream,teleport_confirm
play,upstream,block_metadata_request
play,upstream,set_difficulty
play,upstream,acknowledge_chat
play,upstream,chat_command
play,upstream,chat_message
play,upstream,client_status
play,upstream,client_settings
play,upstream,tab_complete
play,upstream,confirm_transaction
play,upstream,click_window
play,upstream,close_window
play,upstream,plugin_message
play,upstream,edit_book
play,upstream,entity_metadata_request
play,upstream,use_entity
play,upstream,generate_structure
play,upstream,keep_alive
play,upstream,lock_difficulty
play,upstream,player_position
play,upstream,player_position_and_look
play,upstream,player_look
play,upstream,player
play,upstream,vehicle_move
play,upstream,steer_boat
play,upstream,pick_item
play,upstream,craft_recipe_request
play,upstream,player_abilities
play,upstream,player_digging
play,upstream,entity_action
play,upstream,steer_vehicle
play,upstream,pong
play,upstream,chat_session_update
play,upstream,set_displayed_recipe
play,upstream,set_recipe_book_state
play,upstream,name_item
play,upstream,resource_pack_status
play,upstream,advancement_tab
play,upstream,select_trade
play,upstream,set_beacon_effect
play,upstream,held_item_change
play,upstream,update_command_block
play,upstream,update_command_block_minecart
play,upstream,creative_inventory_action
play,upstream,update_jigsaw_block
play,upstream,update_structure_block
play,upstream,update_sign
play,upstream,animation
play,upstream,spectate
play,upstream,player_block_placement
play,upstream,use_item
status,downstream,status_response
status,downstream,status_pong
status,upstream,status_request
status,upstream,status_ping
login,downstream,login_disconnect
login,downstream,login_encryption_request
login,downstream,login_success
login,downstream,login_set_compression
login,downstream,login_plugin_request
login,upstream,login_start
login,upstream,login_encryption_response
login,upstream,login_plugin_response
14 changes: 9 additions & 5 deletions quarry/net/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,17 @@ def switch_protocol_mode(self, mode):

elif mode == "login":
# Send login start
# TODO: Implement signatures/1.19.1 UUID sending
if self.protocol_version >= 760: # 1.19.1+
# TODO: Implement signature/UUID sending
if self.protocol_version >= 761: # 1.19.3+ sends optional UUID
self.send_packet("login_start",
self.buff_type.pack_string(self.factory.profile.display_name),
self.buff_type.pack("?", False)) # No UUID as we haven't implemented them yet
elif self.protocol_version >= 760: # 1.19.1 sends optional signature and uuid
self.send_packet("login_start",
self.buff_type.pack_string(self.factory.profile.display_name),
self.buff_type.pack("?", False), # No signature as we haven't implemented them here
self.buff_type.pack("?", False)) # No UUID as we haven't implemented them yet
elif self.protocol_version == 759: # 1.19
elif self.protocol_version == 759: # 1.19 sends optional signature
self.send_packet("login_start",
self.buff_type.pack_string(self.factory.profile.display_name),
self.buff_type.pack("?", False)) # No signature as we haven't implemented them here
Expand Down Expand Up @@ -98,8 +102,8 @@ def auth_ok(self, data):
pack_array = lambda d: self.buff_type.pack_varint(
len(d), max_bits=16) + d

# 1.19+
if self.protocol_version >= 759:
# 1.19 - 1.19.2
if 759 <= self.protocol_version < 761:
self.send_packet(
"login_encryption_response",
pack_array(p_shared_secret),
Expand Down
8 changes: 4 additions & 4 deletions quarry/net/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ def packet_login_start(self, buff):
if self.factory.online_mode:
self.login_expecting = 1

# 1.19+ may send a Mojang signed public key which needs to be verified
if self.protocol_version >= 759:
# 1.19 - 1.19.2 may send a Mojang signed public key which needs to be verified
if 759 <= self.protocol_version < 761:
try:
self.public_key_data = buff.unpack_optional(buff.unpack_player_public_key)
except ValueError:
Expand Down Expand Up @@ -246,8 +246,8 @@ def packet_login_encryption_response(self, buff):
p_shared_secret = unpack_array(buff)
salt = None

# 1.19 can now sign the verify token + a salt with the players public key, rather than encrypting the token
if self.protocol_version >= 759:
# 1.19 - 1.19.2 can now sign the verify token + a salt with the players public key, rather than encrypting the token
if 759 <= self.protocol_version < 761:
if buff.unpack("?") is False:
salt = buff.unpack("Q").to_bytes(8, 'big')

Expand Down
2 changes: 2 additions & 0 deletions quarry/types/buffer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class BufferUnderrun(Exception):
from quarry.types.buffer.v1_14 import Buffer1_14
from quarry.types.buffer.v1_19 import Buffer1_19
from quarry.types.buffer.v1_19_1 import Buffer1_19_1
from quarry.types.buffer.v1_19_3 import Buffer1_19_3


# Versioned buffers used after handshaking
Expand All @@ -20,6 +21,7 @@ class BufferUnderrun(Exception):
(477, Buffer1_14),
(759, Buffer1_19),
(760, Buffer1_19_1),
(761, Buffer1_19_3),
]


Expand Down
Loading