#!/usr/bin/env python from __future__ import print_function import threading import importlib import getpass import sys import os import re import time from optparse import OptionParser import bot from minecraft import authentication from minecraft.exceptions import YggdrasilError from minecraft.networking.connection import Connection from minecraft.networking.packets import Packet, clientbound, serverbound from minecraft.compat import input get_mod_time = lambda: os.path.getmtime('bot.py') class PlayerInfo: eid = None pos = None mcdata = None chunks = None player_info = PlayerInfo() def get_options(): parser = OptionParser() parser.add_option("-u", "--username", dest="username", default=None, help="username to log in with") parser.add_option("-p", "--password", dest="password", default=None, help="password to log in with") parser.add_option("-s", "--server", dest="server", default=None, help="server host or host:port " "(enclose IPv6 addresses in square brackets)") parser.add_option("-o", "--offline", dest="offline", action="store_true", help="connect to a server in offline mode " "(no password required)") parser.add_option("-d", "--dump-packets", dest="dump_packets", action="store_true", help="print sent and received packets to standard error") (options, args) = parser.parse_args() if not options.username: options.username = input("Enter your username: ") if not options.password and not options.offline: options.password = getpass.getpass("Enter your password (leave " "blank for offline mode): ") options.offline = options.offline or (options.password == "") if not options.server: options.server = input("Enter server host or host:port " "(enclose IPv6 addresses in square brackets): ") # Try to split out port and address match = re.match(r"((?P[^\[\]:]+)|\[(?P[^\[\]]+)\])" r"(:(?P\d+))?$", options.server) if match is None: raise ValueError("Invalid server address: '%s'." % options.server) options.address = match.group("host") or match.group("addr") options.port = int(match.group("port") or 25565) return options def main(): global last_mod_time options = get_options() if options.offline: print("Connecting in offline mode...") connection = Connection( options.address, options.port, username=options.username) else: auth_token = authentication.AuthenticationToken() try: auth_token.authenticate(options.username, options.password) except YggdrasilError as e: print(e) sys.exit() print("Logged in as %s..." % auth_token.username) connection = Connection( options.address, options.port, auth_token=auth_token) if options.dump_packets: def print_incoming(packet): if type(packet) is Packet: # This is a direct instance of the base Packet type, meaning # that it is a packet of unknown type, so we do not print it. return print('--> %s' % packet, file=sys.stderr) def print_outgoing(packet): print('<-- %s' % packet, file=sys.stderr) connection.register_packet_listener( print_incoming, Packet, early=True) connection.register_packet_listener( print_outgoing, Packet, outgoing=True) connection.connect() while True: try: importlib.reload(bot) bot.main(connection, player_info) except KeyboardInterrupt: print("Bye!") sys.exit() except BaseException as e: import traceback print(traceback.format_exc()) last_mod_time = get_mod_time() print('locking') while get_mod_time() == last_mod_time: time.sleep(0.1) if __name__ == "__main__": main()