使用Python库Quarry搭建Minecraft代理时的协议与端口问题
问题:Quarry代理在Minecraft 1.19.3下的协议包错误、版本设置无效及端口占用问题
问题场景
使用Quarry库的proxy_hide_chat.py示例作为代理对接Minecraft 1.19.3版本服务器时,出现三个核心问题:
- 服务器列表加载时触发协议包识别错误
- 手动设置
factory.protocol_version=761后,客户端仍提示“Unknown protocol version” - 运行代理脚本时出现端口占用错误
错误信息
协议包识别错误
No name known for packet: (761, 'status', 'upstream', 0) Traceback (most recent call last): File "/home/todd/.local/lib/python3.10/site-packages/quarry/net/protocol.py", line 205, in get_packet_name return packets.packet_names[key] KeyError: (761, 'status', 'upstream', 0) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/todd/.local/lib/python3.10/site-packages/quarry/net/protocol.py", line 241, in data_received name = self.get_packet_name(buff.unpack_varint()) File "/home/todd/.local/lib/python3.10/site-packages/quarry/net/protocol.py", line 207, in get_packet_name raise ProtocolError("No name known for packet: %s" % (key,)) quarry.net.protocol.ProtocolError: No name known for packet: (761, 'status', 'upstream', 0)
端口占用错误
^C[todd@todd minecraftProxy]$ python teleport_proxy.py Traceback (most recent call last): File "/home/todd/.local/lib/python3.10/site-packages/twisted/internet/tcp.py", line 1334, in startListening skt.bind(addr) OSError: [Errno 98] Address already in use
客户端提示
连接服务器时,Minecraft客户端弹窗提示:Unknown protocol version
完整代理代码
""" "Quiet mode" example proxy Allows a client to turn on "quiet mode" which hides chat messages This client doesn't handle system messages, and assumes none of them contain chat messages """ from twisted.internet import reactor from quarry.types.uuid import UUID from quarry.net.proxy import DownstreamFactory, Bridge class QuietBridge(Bridge): quiet_mode = False def packet_upstream_chat_command(self, buff): command = buff.unpack_string() if command == "quiet": self.toggle_quiet_mode() buff.discard() else: buff.restore() self.upstream.send_packet("chat_command", buff.read()) def packet_upstream_chat_message(self, buff): buff.save() chat_message = self.read_chat(buff, "upstream") self.logger.info(" >> %s" % chat_message) if chat_message.startswith("/quiet"): self.toggle_quiet_mode() elif self.quiet_mode and not chat_message.startswith("/"): # Don't let the player send chat messages in quiet mode msg = "Can't send messages while in quiet mode" self.send_system(msg) else: # Pass to upstream buff.restore() self.upstream.send_packet("chat_message", buff.read()) def toggle_quiet_mode(self): # Switch mode self.quiet_mode = not self.quiet_mode action = self.quiet_mode and "enabled" or "disabled" msg = "Quiet mode %s" % action self.send_system(msg) def packet_downstream_chat_message(self, buff): chat_message = self.read_chat(buff, "downstream") self.logger.info(" :: %s" % chat_message) # All chat messages on 1.19+ are from players and should be ignored in quiet mode if self.quiet_mode and self.downstream.protocol_version >= 759: return # Ignore message that look like chat when in quiet mode if chat_message is not None and self.quiet_mode and chat_message.startswith("<"): return # Pass to downstream buff.restore() self.downstream.send_packet("chat_message", buff.read()) def read_chat(self, buff, direction): buff.save() if direction == "upstream": p_text = buff.unpack_string() buff.discard() return p_text elif direction == "downstream": # 1.19.1+ if self.downstream.protocol_version >= 760: p_signed_message = buff.unpack_signed_message() buff.unpack_varint() # Filter result p_position = buff.unpack_varint() p_sender_name = buff.unpack_chat() buff.discard() if p_position not in (1, 2): # Ignore system and game info messages # Sender name is sent separately to the message text return ":: <%s> %s" % ( p_sender_name, p_signed_message.unsigned_content or p_signed_message.body.message) return p_text = buff.unpack_chat().to_string() # 1.19+ if self.downstream.protocol_version == 759: p_unsigned_text = buff.unpack_optional(lambda: buff.unpack_chat().to_string()) p_position = buff.unpack_varint() buff.unpack_uuid() # Sender UUID p_sender_name = buff.unpack_chat() buff.discard() if p_position not in (1, 2): # Ignore system and game info messages # Sender name is sent separately to the message text return "<%s> %s" % (p_sender_name, p_unsigned_text or p_text) elif self.downstream.protocol_version >= 47: # 1.8.x+ p_position = buff.unpack('B') buff.discard() if p_position not in (1, 2) and p_text.strip(): # Ignore system and game info messages return p_text else: return p_text def send_system(self, message): if self.downstream.protocol_version >= 760: # 1.19.1+ self.downstream.send_packet("system_message", self.downstream.buff_type.pack_chat(message), self.downstream.buff_type.pack('?', False)) # Overlay false to put in chat elif self.downstream.protocol_version == 759: # 1.19 self.downstream.send_packet("system_message", self.downstream.buff_type.pack_chat(message), self.downstream.buff_type.pack_varint(1)) # Type 1 for system chat message else: self.downstream.send_packet("chat_message", self.downstream.buff_type.pack_chat(message), self.downstream.buff_type.pack('B', 0), self.downstream.buff_type.pack_uuid(UUID(int=0))) class QuietDownstreamFactory(DownstreamFactory): bridge_class = QuietBridge motd = "Proxy Server" def main(argv): # Parse options import argparse parser = argparse.ArgumentParser() parser.add_argument("-a", "--listen-host", default="0.0.0.0", help="address to listen on") parser.add_argument("-p", "--listen-port", default=12345, type=int, help="port to listen on") parser.add_argument("-b", "--connect-host", default="127.0.0.1", help="address to connect to") parser.add_argument("-q", "--connect-port", default=25565, type=int, help="port to connect to") args = parser.parse_args(argv) # Create factory factory = QuietDownstreamFactory() factory.connect_host = args.connect_host factory.connect_port = args.connect_port # Listen factory.protocol_version=761 factory.listen(args.listen_host, args.listen_port) reactor.run() if __name__ == "__main__": import sys main(sys.argv[1:])
解决需求
需解决以下三个问题:
- 协议包
(761, 'status', 'upstream', 0)无法识别的错误 factory.protocol_version=761设置无效,客户端仍提示协议版本未知- 端口占用的OSError异常
内容的提问来源于stack exchange,提问作者Todd Howardson
相关产品推荐
相关产品推荐

