async def encrypted_login(stream: Stream, packet: Packet) -> tuple: shared_key, auth = await server_auth(packet, stream.remote, login_cache[stream.remote]) del login_cache[stream.remote] # No longer needed if not auth: # If authentication failed, disconnect client stream.write( Buffer.pack_packet( login_packets.LoginDisconnect( "Failed to authenticate your connection."))) await stream.drain() return False, stream # Generate a cipher for that client using the shared key from the client cipher = encryption.gen_aes_cipher(shared_key) # Replace stream with one which auto decrypts + encrypts data when reading/writing stream = EncryptedStream(stream, cipher) if share["comp_thresh"] > 0: # Send set compression packet if needed stream.write( Buffer.pack_packet(LoginSetCompression(share["comp_thresh"]))) await stream.drain() # Send LoginSuccess packet, tells client they've logged in succesfully stream.write( Buffer.pack_packet(login_packets.LoginSuccess(*auth), share["comp_thresh"])) await stream.drain() return True, stream
async def login_start(stream: Stream, packet: Packet) -> tuple: if share["conf"][ "online_mode"]: # Online mode is enabled, so we request encryption lc = login_cache[stream.remote] = { "username": packet.username, "verify": None } packet = login_packets.LoginEncryptionRequest( share["rsa"]["public"].public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo)) lc["verify"] = packet.verify_token stream.write(Buffer.pack_packet(packet)) await stream.drain() else: # No need for encryption since online mode is off, just send login success uuid_ = ( uuid.uuid4() ) # This should be only generated if the player name isn't found in the world data, but no way to do that rn stream.write( Buffer.pack_packet( login_packets.LoginSuccess(uuid_, packet.username), share["comp_thresh"])) await stream.drain() states[stream.remote] = 3 # Update state to play return True, stream
async def finish_join(r: StreamReader, w: StreamWriter, remote: tuple) -> None: lvl_name = share["conf"]["level_name"] entity_id = entity_id_cache.get(remote) if entity_id is None: entity_id = entity_id_cache[remote] = int(time.time()) w.write( Buffer.pack_packet( packets_player.PlayJoinGame( entity_id, share["conf"]["hardcore"], 0, # Shoudl be current gamemode -1, # Should be previous gamemode # Should be actual world names [f"minecraft:{lvl_name}", f"minecraft:{lvl_name}_nether", f"minecraft:{lvl_name}_the_end"], nbt.TAG_Int(name="bruh", value=1), nbt.TAG_Int(name="bruh", value=1), f"minecraft:{lvl_name}", # should be actual current world name seed_hash(share["conf"]["seed"]), share["conf"]["max_players"], share["conf"]["view_distance"], (not share["conf"]["debug"]), True, # should be (not doImmediateRespawn gamerule) False, False, # Should be true if world is superflat ) ) ) await w.drain()
async def send_packet(self, stream: Stream, packet: Packet, comp_thresh=None): self.console.debug(f"OUT: state:-1 | id:0x{packet.id:02X} | packet:{type(packet).__name__}") if comp_thresh is None: comp_thresh = self.comp_thresh stream.write(Buffer.pack_packet(packet, comp_thresh)) await stream.drain()
async def send_status(stream: Stream, packet: Packet) -> tuple: data = { "version": { "name": share["version"], "protocol": share["protocol"] }, "players": { "max": share["conf"]["max_players"], "online": len(share["states"]), "sample": [ { "name": "Iapetus11", "id": "cbcfa252-867d-4bda-a214-776c881cf370" }, { "name": "Sh_wayz", "id": "cbcfa252-867d-4bda-a214-776c881cf370" }, { "name": "emeralddragonmc", "id": "eb86dc19-c3f5-4aef-a50e-a4bf435a7528" }, ], }, "description": { "text": share["conf"]["motd"] }, # a Chat } if share["favicon"]: data["favicon"] = share["favicon"] stream.write(Buffer.pack_packet(status_packets.StatusStatusResponse(data))) await stream.drain() return True, stream
async def send_pong(stream: Stream, packet: Packet) -> tuple: stream.write(Buffer.pack_packet(packet)) await stream.drain() return False, stream