Lay down the foundations for a complete rewrite, the new framework is far more easy to maintain

This commit is contained in:
Ammar Askar 2014-06-07 01:47:34 +02:00
parent 59e4706b25
commit 85112fba1d
17 changed files with 607 additions and 2135 deletions

View File

@ -1,86 +0,0 @@
import re
import urllib2
import urllib
import threading
from hashlib import sha1
# This function courtesy of barneygale
def javaHexDigest(digest):
d = long(digest.hexdigest(), 16)
if d >> 39 * 4 & 0x8:
d = "-%x" % ((-d) & (2 ** (40 * 4) - 1))
else:
d = "%x" % d
return d
def translate_escape(m):
c = m.group(1).lower()
if c == "0": return "\x1b[30m\x1b[21m" # black
elif c == "1": return "\x1b[34m\x1b[21m" # dark blue
elif c == "2": return "\x1b[32m\x1b[21m" # dark green
elif c == "3": return "\x1b[36m\x1b[21m" # dark cyan
elif c == "4": return "\x1b[31m\x1b[21m" # dark red
elif c == "5": return "\x1b[35m\x1b[21m" # purple
elif c == "6": return "\x1b[33m\x1b[21m" # gold
elif c == "7": return "\x1b[37m\x1b[21m" # gray
elif c == "8": return "\x1b[30m\x1b[1m" # dark gray
elif c == "9": return "\x1b[34m\x1b[1m" # blue
elif c == "a": return "\x1b[32m\x1b[1m" # bright green
elif c == "b": return "\x1b[36m\x1b[1m" # cyan
elif c == "c": return "\x1b[31m\x1b[1m" # red
elif c == "d": return "\x1b[35m\x1b[1m" # pink
elif c == "e": return "\x1b[33m\x1b[1m" # yellow
elif c == "f": return "\x1b[37m\x1b[1m" # white
elif c == "k": return "\x1b[5m" # random
elif c == "l": return "\x1b[1m" # bold
elif c == "m": return "\x1b[9m" # strikethrough (escape code not widely supported)
elif c == "n": return "\x1b[4m" # underline
elif c == "o": return "\x1b[3m" # italic (escape code not widely supported)
elif c == "r": return "\x1b[0m" # reset
return ""
def translate_escapes(s):
return re.sub(ur"\xa7([0-9a-zA-Z])", translate_escape, s) + "\x1b[0m"
def loginToMinecraft(username, password):
try:
url = 'https://login.minecraft.net'
header = {'Content-Type': 'application/x-www-form-urlencoded'}
data = {'user': username,
'password': password,
'version': '13'}
data = urllib.urlencode(data)
req = urllib2.Request(url, data, header)
opener = urllib2.build_opener()
response = opener.open(req, None, 10)
response = response.read()
except urllib2.URLError:
return {'Response': "Can't connect to minecraft.net"}
if (not "deprecated" in response.lower()):
return {'Response': response}
response = response.split(":")
sessionid = response[3]
toReturn = {'Response': "Good to go!",
'Username': response[2],
'SessionID': sessionid
}
return toReturn
class MinecraftLoginThread(threading.Thread):
def __init__(self, username, password):
threading.Thread.__init__(self)
self.username = username
self.password = password
def run(self):
self.response = loginToMinecraft(self.username, self.password)
def getResponse(self):
return self.response

View File

@ -0,0 +1 @@
from auth import *

82
authentication/auth.py Normal file
View File

@ -0,0 +1,82 @@
import urllib2
import urllib
import json
BASE_URL = 'https://authserver.mojang.com/'
AGENT_INFO = {"name": "Minecraft", "version": 1}
"""Class to hold responses from Yggdrasil
"""
class Response:
error = False
def make_request(url, payload):
"""Makes http requests to the Yggdrasil authentication service
Returns a Response object with an error boolean, if there is an error
then it will also contain `error` and `human_error` fields
otherwise a `payload` field will be returned with the actual response
from Yggdrasil
"""
response = Response()
try:
header = {'Content-Type': 'application/json'}
data = json.dumps(payload)
req = urllib2.Request(url, data, header)
opener = urllib2.build_opener()
http_response = opener.open(req, None, 10)
http_response = http_response.read()
except urllib2.HTTPError, e:
error = e.read()
error = json.loads(error)
response.error = True
response.human_error = error['errorMessage']
response.error = error['error']
return response
except urllib2.URLError, e:
response.error = True
response.human_error = e.reason
return response
# ohey, everything didn't end up crashing and burning
json_response = json.loads(http_response)
response.payload = json_response
return response
"""Yet another container class, this time to hold login info since it'll probably
be need to passed around a lot afterwards
"""
class LoginResponse:
pass
def login_to_minecraft(username, password):
"""Logs in to mineraft
Returns a LoginResponse object containing a boolean `error` field.
If there is an error, it will be accompanied with a `human_error` field.
Otherwise `access_token`, `profile_id` and `username` fields will be present in the response.
"""
payload = { "username": username, "password": password, "agent": AGENT_INFO }
response = make_request(BASE_URL + "authenticate", payload)
login_response = LoginResponse()
if response.error:
login_response.error = True
login_response.human_error = response.human_error
else:
payload = response.payload
login_response.error = False
login_response.access_token = payload["accessToken"]
login_response.profile_id = payload["selectedProfile"]["id"]
login_response.username = payload["selectedProfile"]["name"]
return login_response

173
network/connection.py Normal file
View File

@ -0,0 +1,173 @@
from packets import *
from start import PROTOCOL_VERSION
from collections import deque
from threading import Lock
from types import VarInt
import threading
import socket
import time
import select
class Connection:
"""This class represents a connection to a minecraft
server, it handles everything from connecting, sending packets,
handling default network behaviour
"""
outgoing_packet_queue = deque()
write_lock = Lock()
networking_thread = None
def __init__(self, address, port, login_response):
self.address = address
self.port = port
self.login_response = login_response
self.reactor = HandshakeReactor(self)
def _start_network_thread(self):
self.networking_thread = NetworkingThread(self)
self.networking_thread.start()
def write_packet(self, packet, force=False):
if force:
self.write_lock.acquire()
packet.write(self.socket)
self.write_lock.release()
else:
self.outgoing_packet_queue.append(packet)
# Mostly a convenience function, caller should make sure they have the
# write lock acquired to avoid issues caused by asynchronous access to the socket.
# This should be the only method that removes elements from the outbound queue
def _pop_packet(self):
if len(self.outgoing_packet_queue) == 0:
return False
else:
packet = self.outgoing_packet_queue.popleft()
print "Writing out: " + hex(packet.id) + " / " + packet.name
packet.write(self.socket)
return True
def status(self):
self._connect()
self._handshake(1)
self._start_network_thread()
self.reactor = StatusReactor(self)
request_packet = RequestPacket()
self.write_packet(request_packet)
def connect(self):
self._connect()
self._handshake()
def _connect(self):
#Connect a socket to the server and create a file object from the socket
#The file object is used to read any and all data from the socket since it's "guaranteed"
#to read the number of bytes specified, the socket itself will mostly be
#used to write data upstream to the server
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(20.0)
self.socket.connect(( self.address, self.port ))
self.file_object = self.socket.makefile()
def _handshake(self, next_state=2):
handshake = HandShakePacket()
handshake.protocol_version = PROTOCOL_VERSION
handshake.server_address = self.address
handshake.server_port = self.port
handshake.next_state = next_state
handshake.write(self.socket)
class NetworkingThread(threading.Thread):
interrupt = False
def __init__(self, connection):
threading.Thread.__init__(self)
self.connection = connection
self.name = "Networking Thread"
self.daemon = True
def run(self):
while True:
if self.interrupt:
break
# Attempt to write out as many as 300 packets as possible every 0.05 seconds (20 ticks per second)
num_packets = 0
self.connection.write_lock.acquire()
while self.connection._pop_packet():
self.connection._pop_packet()
num_packets += 1
if num_packets >= 300:
break
self.connection.write_lock.release()
# Read and react to as many as 50 packets
num_packets = 0
packet = self.connection.reactor.read_packet(self.connection.socket, self.connection.file_object)
while packet:
num_packets += 1
self.connection.reactor.react(packet)
if num_packets >= 50:
break
packet = self.connection.reactor.read_packet(self.connection.socket, self.connection.file_object)
time.sleep(0.05)
class PacketReactor:
state_name = None
clientbound_packets = None
TIME_OUT = 0.5
def __init__(self, connection):
self.connection = connection
def read_packet(self, socket, stream):
ready = select.select([self.connection.socket], [], [], 0.5)
if ready[0]:
length = VarInt.read(stream)
packet_id = VarInt.read(stream)
if packet_id in self.clientbound_packets:
packet = self.clientbound_packets[packet_id]()
packet.read(stream)
return packet
else:
print "Unkown packet: " + str(packet_id) + " / " + hex(packet_id)
return Packet()
else:
return None
def react(self, packet):
pass
class HandshakeReactor(PacketReactor):
clientbound_packets = state_handshake_clientbound
class StatusReactor(PacketReactor):
clientbound_packets = state_status_clientbound
def react(self, packet):
if packet.name == "response":
import json
print json.loads(packet.json_response)
ping_packet = PingPacket()
ping_packet.time = int(time.time())
self.connection.write_packet(ping_packet)
self.connection.networking_thread.interrupt = True
# TODO: More shutdown? idk

143
network/packets.py Normal file
View File

@ -0,0 +1,143 @@
from types import *
from io import BytesIO
class PacketBuffer:
b = BytesIO()
def send(self, value):
self.b.write(value)
def get_writable(self):
return self.b.getvalue()
class Packet:
name = "base"
definition = []
def read(self, file_object):
for field in self.definition:
for var_name, data_type in field.iteritems():
setattr(self, var_name, data_type.read(file_object))
def write(self, socket):
# buffer the data since we need to know the length of each packet's payload
packet_buffer = PacketBuffer()
# write off the id right off the bat
VarInt.send(self.id, packet_buffer)
for field in self.definition:
for var_name, data_type in field.iteritems():
data = getattr(self, var_name)
data_type.send(data, packet_buffer)
VarInt.send(len(packet_buffer.get_writable()), socket) # Packet Size
socket.send(packet_buffer.get_writable()) # Packet Payload
# Handshake State
#==============
class HandShakePacket(Packet):
id = 0x00
name = "handshake"
definition = [
{'protocol_version': VarInt},
{'server_address': String},
{'server_port': UnsignedShort},
{'next_state': VarInt}]
state_handshake_clientbound = {
}
state_handshake_serverbound = {
0x00: HandShakePacket
}
# Status State
#==============
class ResponsePacket(Packet):
id = 0x00
name = "response"
definition = [
{'json_response': String}]
class PingPacket(Packet):
id = 0x01
name = "ping"
definition = [
{'time': Long}]
state_status_clientbound = {
0x00: ResponsePacket,
0x01: PingPacket
}
class RequestPacket(Packet):
id = 0x00
name = "request"
definition = []
class PingPacket(Packet):
id = 0x01
name = "ping"
definition = [
{'time': Long}]
state_status_serverbound = {
0x00: RequestPacket,
0x01: PingPacket
}
# Login State
#==============
class DisconnectPacket(Packet):
id = 0x00
name = "disconnect"
definition = [
{'json_data': String}]
class EncryptionRequestPacket(Packet):
id = 0x01
name = "encryption request"
definition = [
{'server_id': String},
{'public_key': ByteArray},
{'verify_token': ByteArray}]
class LoginSucessPacket(Packet):
id = 0x02
name = "login success"
definition = [
{'UUID': String},
{'Username': String}]
state_login_clientbound = {
0x00: DisconnectPacket,
0x01: EncryptionRequestPacket,
0x02: LoginSucessPacket
}
class LoginStartPacket(Packet):
id = 0x00
name = "login start"
definition = [
{'name': String}]
class EncryptionResponsePacket(Packet):
id = 0x01
name = "encryption response"
definition = [
{'shared_secret': ByteArray},
{'verify_token': ByteArray}]
state_login_serverbound = {
0x00: LoginStartPacket,
0x01: EncryptionResponsePacket
}

166
network/types.py Normal file
View File

@ -0,0 +1,166 @@
"""Contains definitions for minecraft's different data types
Each type has a method which is used to read and write it.
These definitions and methods are used by the packet definitions
"""
import struct
class Type:
@staticmethod
def read(file_object):
pass
@staticmethod
def send(value, socket):
pass
#=========================================================
class Boolean(Type):
@staticmethod
def read(file_object):
return struct.unpack('?', file_object.read(1))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('?', value))
class Byte(Type):
@staticmethod
def read(file_object):
return struct.unpack('>b', file_object.read(1))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('>b', value))
class Short(Type):
@staticmethod
def read(file_object):
return struct.unpack('>h', file_object.read(2))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('>h', value))
class UnsignedShort(Type):
@staticmethod
def read(file_object):
return struct.unpack('>H', file_object.read(2))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('>H', value))
class Integer(Type):
@staticmethod
def read(file_object):
return struct.unpack('>i', file_object.read(4))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('>i', value))
class VarInt(Type):
@staticmethod
def read_socket(s):
d = 0
for i in range(5):
b = ord(s.recv(1))
d |= (b & 0x7F) << 7 * i
if not b & 0x80:
break
return d
@staticmethod
def read(file_object):
d = 0
for i in range(5):
b = ord(file_object.read(1))
d |= (b & 0x7F) << 7 * i
if not b & 0x80:
break
return d
@staticmethod
def send(value, socket):
o = ""
while True:
b = value & 0x7F
value >>= 7
o += struct.pack("B", b | (0x80 if value > 0 else 0))
if value == 0:
break
socket.send(o)
class Long(Type):
@staticmethod
def read(file_object):
return struct.unpack('>q', file_object.read(8))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('>q', value))
class Float(Type):
@staticmethod
def read(file_object):
return struct.unpack('>f', file_object.read(4))[0]
@staticmethod
def send(svalue, socket):
socket.send(struct.pack('>f', value))
class Double(Type):
@staticmethod
def read(file_object):
return struct.unpack('>d', file_object.read(8))[0]
@staticmethod
def send(value, socket):
socket.send(struct.pack('>d', value))
class ByteArray(Type):
@staticmethod
def read(file_object, length=None):
if length is None:
length = Short.read(file_object)
return struct.unpack(str(length) + "s", file_object.read(length))[0]
@staticmethod
def send(value, socket):
Short.send(len(value), socket)
socket.send(value)
class String(Type):
@staticmethod
def read(file_object):
length = VarInt.read(file_object)
return unicode(file_object.read(length), "utf-8")
@staticmethod
def send(value, socket):
value = unicode(value).encode('utf-8')
VarInt.send(len(value), socket)
socket.send(value)

View File

@ -1,147 +0,0 @@
import struct
import types
from io import BytesIO
from pynbt import NBTFile
def readBoolean(FileObject):
return struct.unpack('?', FileObject.read(1))[0]
def readByte(FileObject):
return struct.unpack('>b', FileObject.read(1))[0]
def readUnsignedByte(FileObject):
return struct.unpack('>B', FileObject.read(1))[0]
def readShort(FileObject):
return struct.unpack('>h', FileObject.read(2))[0]
def readUnsignedShort(FileObject):
return struct.unpack('>H', FileObject.read(2))[0]
def readInt(FileObject):
return struct.unpack('>i', FileObject.read(4))[0]
def readFloat(FileObject):
return struct.unpack('>f', FileObject.read(4))[0]
def readLong(FileObject):
return struct.unpack('>q', FileObject.read(8))[0]
def readDouble(FileObject):
return struct.unpack('>d', FileObject.read(8))[0]
def readByteArray(FileObject, length):
return struct.unpack(str(length) + "s", FileObject.read(length))[0]
def readString(FileObject):
length = readShort(FileObject) * 2
return unicode(FileObject.read(length), "utf-16be")
def sendBoolean(socket, value):
assert type(value) is types.BooleanType, "value is not a boolean: %r" % value
socket.send(struct.pack('?', value))
def sendByte(socket, value):
socket.send(struct.pack('>b', value))
def sendUnsignedByte(socket, value):
socket.send(struct.pack('>B', value))
def sendShort(socket, value):
socket.send(struct.pack('>h', value))
def sendUnsignedShort(socket, value):
socket.send(struct.pack('>H', value))
def sendInt(socket, value):
assert type(value) is types.IntType, "value is not an integer: %r" % value
socket.send(struct.pack('>i', value))
def sendFloat(socket, value):
socket.send(struct.pack('>f', value))
def sendLong(socket, value):
socket.send(struct.pack('>q', value))
def sendDouble(socket, value):
socket.send(struct.pack('>d', value))
def sendString(socket, value):
value = unicode(value).encode('utf-16be')
socket.send(struct.pack('>h', len(value) / 2))
socket.send(value)
def readEntityMetadata(FileObject):
metadata = {}
byte = readUnsignedByte(FileObject)
while byte != 127:
index = byte & 0x1F # Lower 5 bits
ty = byte >> 5 # Upper 3 bits
if ty == 0: val = readByte(FileObject)
if ty == 1: val = readShort(FileObject)
if ty == 2: val = readInt(FileObject)
if ty == 3: val = readFloat(FileObject)
if ty == 4:
val = readString(FileObject)
if ty == 5:
val = {}
val["id"] = readShort(FileObject)
if (val["id"] != -1):
val["count"] = readByte(FileObject)
val["damage"] = readShort(FileObject)
nbtDataLength = readShort(FileObject)
if (nbtDataLength != -1):
val["NBT"] = NBTFile(BytesIO(readByteArray(FileObject, nbtDataLength)),
compression=NBTFile.Compression.GZIP)
if ty == 6:
val = []
for i in range(3):
val.append(readInt(FileObject))
metadata[index] = (ty, val)
byte = readUnsignedByte(FileObject)
return metadata
def readSlotData(FileObject):
BlockID = readShort(FileObject)
if (BlockID != -1):
ItemCount = readByte(FileObject)
Damage = readShort(FileObject)
MetadataLength = readShort(FileObject)
if (MetadataLength != -1):
ByteArray = readByteArray(FileObject, MetadataLength)
NBTData = NBTFile(BytesIO(ByteArray), compression=NBTFile.Compression.GZIP)
return {'BlockID': BlockID,
'ItemCount': ItemCount,
'Damage': Damage,
'Data': NBTData
}
return {'BlockID': BlockID,
'ItemCount': ItemCount,
'Damage': Damage
}
return {'BlockID': -1,
'ItemCount': 0
}

View File

@ -1,356 +0,0 @@
import socket
import PacketListenerManager
import urllib2
import traceback
import threading
import hashlib
import string
import unicodedata
import Utils
import sys
from networking import PacketSenderManager
from Crypto.Random import _UserFriendlyRNG
from Crypto.Util import asn1
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto.Cipher import PKCS1_v1_5
from json import loads
EntityID = 0
class ServerConnection(threading.Thread):
def __init__(self, pluginLoader, username, sessionID, server, port, options=None):
threading.Thread.__init__(self)
self.pluginLoader = pluginLoader
self.options = options
self.isConnected = False
self.username = username
self.sessionID = sessionID
self.server = server
self.port = port
def disconnect(self, reason="Disconnected by user"):
PacketSenderManager.sendFF(self.socket, reason)
self.listener.kill = True
self.socket.close()
def setWindow(self, window):
self.window = window
def grabSocket(self):
return self.socket
def run(self):
try:
#Create the socket and fileobject
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect(( self.server, self.port ))
self.FileObject = self.socket.makefile()
#Send out the handshake packet
PacketSenderManager.sendHandshake(self.socket, self.username, self.server, self.port)
#Receive the encryption packet id
packetid = self.socket.recv(1)
if (packetid == "\xFF"):
print PacketListenerManager.handleFF(self.FileObject)
#Sanity check the packet id
assert packetid == "\xFD", "Server didn't respond back to handshake with proper packet!"
#Parse the packet
packetFD = PacketListenerManager.handleFD(self.FileObject)
#Import the server's public key
self.pubkey = RSA.importKey(packetFD['Public Key'])
#Generate a 16 byte (128 bit) shared secret
self.sharedSecret = _UserFriendlyRNG.get_random_bytes(16)
#Authenticate the server from sessions.minecraft.net
if (packetFD['ServerID'] != '-'):
try:
#Grab the server id
sha1 = hashlib.sha1()
sha1.update(packetFD['ServerID'])
sha1.update(self.sharedSecret)
sha1.update(packetFD['Public Key'])
#lovely java style hex digest by barneygale
serverid = Utils.javaHexDigest(sha1)
#Open up the url with the appropriate get parameters
url = "http://session.minecraft.net/game/joinserver.jsp?user=" + self.username + "&sessionId=" + self.sessionID + "&serverId=" + serverid
response = urllib2.urlopen(url).read()
if (response != "OK"):
print "Response from sessions.minecraft.net wasn't OK, it was " + response
return False
#Success \o/ We can now begin sending our serverAddress to the server
#Instantiate our main packet listener
self.listener = PacketListener(self, self.socket, self.FileObject)
self.listener.setDaemon(True)
self.listener.start()
#Encrypt the verification token from earlier along with our shared secret with the server's rsa key
self.RSACipher = PKCS1_v1_5.new(self.pubkey)
encryptedSanityToken = self.RSACipher.encrypt(str(packetFD['Token']))
encryptedSharedSecret = self.RSACipher.encrypt(str(self.sharedSecret))
#Send out a a packet FC to the server
PacketSenderManager.sendFC(self.socket, encryptedSharedSecret, encryptedSanityToken)
self.pluginLoader.notify("onConnect")
except Exception, e:
traceback.print_exc()
else:
print "Server is in offline mode"
#Instantiate our main packet listener
self.listener = PacketListener(self, self.socket, self.FileObject)
self.listener.setDaemon(True)
self.listener.start()
#Encrypt the verification token from earlier along with our shared secret with the server's rsa key
self.RSACipher = PKCS1_v1_5.new(self.pubkey)
encryptedSanityToken = self.RSACipher.encrypt(str(packetFD['Token']))
encryptedSharedSecret = self.RSACipher.encrypt(str(self.sharedSecret))
#Send out a a packet FC to the server
PacketSenderManager.sendFC(self.socket, encryptedSharedSecret, encryptedSanityToken)
self.pluginLoader.notify("onConnect")
except Exception, e:
print "Connection to server failed"
traceback.print_exc()
sys.exit(1)
class EncryptedFileObjectHandler():
def __init__(self, fileobject, cipher):
self.fileobject = fileobject
self.cipher = cipher
self.length = 0
def read(self, length):
rawData = self.fileobject.read(length)
self.length += length
unencryptedData = self.cipher.decrypt(rawData)
return unencryptedData
def tell(self):
return self.length
class EncryptedSocketObjectHandler():
def __init__(self, socket, cipher):
self.socket = socket
self.cipher = cipher
def send(self, serverAddress):
self.socket.send(self.cipher.encrypt(serverAddress))
def close(self):
self.socket.close()
class PacketListener(threading.Thread):
def __init__(self, connection, socket, FileObject):
threading.Thread.__init__(self)
self.connection = connection
self.socket = socket
self.FileObject = FileObject
self.encryptedConnection = False
self.kill = False
def enableEncryption(self):
#Create an AES cipher from the previously obtained public key
self.cipher = AES.new(self.connection.sharedSecret, AES.MODE_CFB, IV=self.connection.sharedSecret)
self.decipher = AES.new(self.connection.sharedSecret, AES.MODE_CFB, IV=self.connection.sharedSecret)
self.rawsocket = self.socket
self.connection.rawsocket = self.connection.socket
self.socket = EncryptedSocketObjectHandler(self.rawsocket, self.cipher)
self.connection.socket = self.socket
self.rawFileObject = self.FileObject
self.connection.rawFileObject = self.connection.FileObject
self.FileObject = EncryptedFileObjectHandler(self.rawFileObject, self.decipher)
self.connection.FileObject = self.FileObject
self.encryptedConnection = True
def run(self):
while True:
if (self.kill):
break
try:
response = self.FileObject.read(1)
if (response == ""):
continue
except Exception, e:
print "Ping timeout"
sys.exit()
break
if (response == "\x00"):
packet = PacketListenerManager.handle00(self.FileObject, self.socket)
elif (response == "\x01"):
packet = PacketListenerManager.handle01(self.FileObject)
print "Logged in \o/ Received an entity id of " + str(packet['EntityID'])
elif (response == "\x03"):
packet = PacketListenerManager.handle03(self.FileObject)
filtered_string = loads(packet['Message'])["text"]
if not self.connection.options.disableAnsiColours:
filtered_string = Utils.translate_escapes(filtered_string)
print filtered_string.decode("unicode-escape")
elif (response == "\x04"):
packet = PacketListenerManager.handle04(self.FileObject)
elif (response == "\x05"):
packet = PacketListenerManager.handle05(self.FileObject)
elif (response == "\x06"):
packet = PacketListenerManager.handle06(self.FileObject)
elif (response == "\x07"):
packet = PacketListenerManager.handle07(self.FileObject)
elif (response == "\x08"):
packet = PacketListenerManager.handle08(self.FileObject)
elif (response == "\x09"):
packet = PacketListenerManager.handle09(self.FileObject)
elif (response == "\x0D"):
packet = PacketListenerManager.handle0D(self.FileObject)
elif (response == "\x10"):
packet = PacketListenerManager.handle10(self.FileObject)
elif (response == "\x11"):
packet = PacketListenerManager.handle11(self.FileObject)
elif (response == "\x12"):
packet = PacketListenerManager.handle12(self.FileObject)
elif (response == "\x14"):
packet = PacketListenerManager.handle14(self.FileObject)
elif (response == "\x15"):
packet = PacketListenerManager.handle15(self.FileObject)
elif (response == "\x16"):
packet = PacketListenerManager.handle16(self.FileObject)
elif (response == "\x17"):
packet = PacketListenerManager.handle17(self.FileObject)
elif (response == "\x18"):
packet = PacketListenerManager.handle18(self.FileObject)
elif (response == "\x19"):
packet = PacketListenerManager.handle19(self.FileObject)
elif (response == "\x1A"):
packet = PacketListenerManager.handle1A(self.FileObject)
elif (response == "\x1C"):
packet = PacketListenerManager.handle1C(self.FileObject)
elif (response == "\x1D"):
packet = PacketListenerManager.handle1D(self.FileObject)
elif (response == "\x1E"):
packet = PacketListenerManager.handle1E(self.FileObject)
elif (response == "\x1F"):
packet = PacketListenerManager.handle1F(self.FileObject)
elif (response == "\x20"):
packet = PacketListenerManager.handle20(self.FileObject)
elif (response == "\x21"):
packet = PacketListenerManager.handle21(self.FileObject)
elif (response == "\x22"):
packet = PacketListenerManager.handle22(self.FileObject)
elif (response == "\x23"):
packet = PacketListenerManager.handle23(self.FileObject)
elif (response == "\x26"):
packet = PacketListenerManager.handle26(self.FileObject)
elif (response == "\x27"):
packet = PacketListenerManager.handle27(self.FileObject)
elif (response == "\x28"):
packet = PacketListenerManager.handle28(self.FileObject)
elif (response == "\x29"):
packet = PacketListenerManager.handle29(self.FileObject)
elif (response == "\x2A"):
packet = PacketListenerManager.handle2A(self.FileObject)
elif (response == "\x2B"):
packet = PacketListenerManager.handle2B(self.FileObject)
elif (response == "\x2C"):
packet = PacketListenerManager.handle2C(self.FileObject)
elif (response == "\x33"):
packet = PacketListenerManager.handle33(self.FileObject)
elif (response == "\x34"):
packet = PacketListenerManager.handle34(self.FileObject)
elif (response == "\x35"):
packet = PacketListenerManager.handle35(self.FileObject)
elif (response == "\x36"):
packet = PacketListenerManager.handle36(self.FileObject)
elif (response == "\x37"):
packet = PacketListenerManager.handle37(self.FileObject)
elif (response == "\x38"):
packet = PacketListenerManager.handle38(self.FileObject)
elif (response == "\x3C"):
packet = PacketListenerManager.handle3C(self.FileObject)
elif (response == "\x3D"):
packet = PacketListenerManager.handle3D(self.FileObject)
elif (response == "\x3E"):
packet = PacketListenerManager.handle3E(self.FileObject)
elif (response == "\x3F"):
packet = PacketListenerManager.handle3F(self.FileObject)
elif (response == "\x46"):
packet = PacketListenerManager.handle46(self.FileObject)
elif (response == "\x47"):
packet = PacketListenerManager.handle47(self.FileObject)
elif (response == "\x64"):
packet = PacketListenerManager.handle64(self.FileObject)
elif (response == "\x65"):
packet = PacketListenerManager.handle65(self.FileObject)
elif (response == "\x67"):
packet = PacketListenerManager.handle67(self.FileObject)
elif (response == "\x68"):
packet = PacketListenerManager.handle68(self.FileObject)
elif (response == "\x69"):
packet = PacketListenerManager.handle69(self.FileObject)
elif (response == "\x6A"):
packet = PacketListenerManager.handle6A(self.FileObject)
elif (response == "\x6B"):
packet = PacketListenerManager.handle6B(self.FileObject)
elif (response == "\x82"):
packet = PacketListenerManager.handle82(self.FileObject)
elif (response == "\x83"):
packet = PacketListenerManager.handle83(self.FileObject)
elif (response == "\x84"):
packet = PacketListenerManager.handle84(self.FileObject)
elif (response == "\x85"):
packet = PacketListenerManager.handle85(self.FileObject)
elif (response == "\xC8"):
packet = PacketListenerManager.handleC8(self.FileObject)
elif (response == "\xC9"):
packet = PacketListenerManager.handleC9(self.FileObject)
elif (response == "\xCA"):
packet = PacketListenerManager.handleCA(self.FileObject)
elif (response == "\xCB"):
packet = PacketListenerManager.handleCB(self.FileObject)
elif (response == "\xCE"):
packet = PacketListenerManager.handleCE(self.FileObject)
elif (response == "\xCF"):
packet = PacketListenerManager.handleCF(self.FileObject)
elif (response == "\xD0"):
packet = PacketListenerManager.handleD0(self.FileObject)
elif (response == "\xD1"):
packet = PacketListenerManager.handleD1(self.FileObject)
elif (response == "\xFA"):
packet = PacketListenerManager.handleFA(self.FileObject)
elif (response == "\xFC"):
packet = PacketListenerManager.handleFC(self.FileObject)
if (not self.encryptedConnection):
self.enableEncryption()
self.connection.isConnected = True
PacketSenderManager.sendCD(self.socket, 0)
elif (response == "\xFF"):
packet = PacketListenerManager.handleFF(self.FileObject)
print "Disconnected: " + packet['Reason']
self.connection.disconnect()
self.connection.pluginLoader.disablePlugins()
sys.exit(1)
break
else:
print "Protocol error: " + hex(ord(response))
self.connection.disconnect("Protocol error, invalid packet: " + hex(ord(response)))
self.connection.pluginLoader.disablePlugins()
sys.exit(1)
break
# Invoke plugin listeners
for listener in self.connection.pluginLoader.getPacketListeners():
listener(response, packet)

View File

@ -1,936 +0,0 @@
import DataUtil
import PacketSenderManager
from io import BytesIO
from pynbt import NBTFile
def handle00(FileObject, socket):
KAid = DataUtil.readInt(FileObject)
PacketSenderManager.send00(socket, KAid)
def handle01(FileObject):
Eid = DataUtil.readInt(FileObject)
world = DataUtil.readString(FileObject)
mode = DataUtil.readByte(FileObject)
dimension = DataUtil.readByte(FileObject)
difficulty = DataUtil.readByte(FileObject)
FileObject.read(1)
maxplayers = DataUtil.readByte(FileObject)
return {'EntityID': Eid,
'World': world,
'Mode': mode,
'Dimension': dimension,
'Difficulty': difficulty,
'MaxPlayers': maxplayers
}
def handle02(FileObject):
message = DataUtil.readString(FileObject)
return message
def handle03(FileObject):
message = DataUtil.readString(FileObject)
return {'Message': message}
def handle04(FileObject):
time = DataUtil.readLong(FileObject)
dayTime = DataUtil.readLong(FileObject)
return {'Time': time,
'DayTime': dayTime
}
def handle05(FileObject):
EntityID = DataUtil.readInt(FileObject)
Slot = DataUtil.readShort(FileObject)
Item = DataUtil.readSlotData(FileObject)
return {'EntityID': EntityID,
'Slot': Slot,
'Item': Item
}
def handle06(FileObject):
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
return {'x': x,
'y': y,
'z': z
}
def handle07(FileObject):
userID = DataUtil.readInt(FileObject)
targetID = DataUtil.readInt(FileObject)
mButton = DataUtil.readBoolean(FileObject)
return {'userID': userID,
'targetID': targetID,
'mButton': mButton
}
def handle08(FileObject):
health = DataUtil.readFloat(FileObject)
food = DataUtil.readShort(FileObject)
saturation = DataUtil.readFloat(FileObject)
return {'health': health,
'food': food,
'saturation': saturation
}
def handle09(FileObject):
dimension = DataUtil.readInt(FileObject)
difficulty = DataUtil.readByte(FileObject)
mode = DataUtil.readByte(FileObject)
height = DataUtil.readShort(FileObject)
world = DataUtil.readString(FileObject)
return {'Dimension': dimension,
'Difficulty': difficulty,
'Mode': mode,
'Height': height,
'World': world
}
def handle0D(FileObject):
x = DataUtil.readDouble(FileObject)
stance = DataUtil.readDouble(FileObject)
y = DataUtil.readDouble(FileObject)
z = DataUtil.readDouble(FileObject)
yaw = DataUtil.readFloat(FileObject)
pitch = DataUtil.readFloat(FileObject)
onGround = DataUtil.readBoolean(FileObject)
return {'x': x,
'stance': stance,
'y': y,
'z': z,
'yaw': yaw,
'pitch': pitch,
'onGround': onGround
}
def handle10(FileObject):
slotID = DataUtil.readShort(FileObject)
return {'SlotID': slotID}
def handle11(FileObject):
EntityID = DataUtil.readInt(FileObject)
FileObject.read(1) #Unused
x = DataUtil.readInt(FileObject)
y = DataUtil.readByte(FileObject)
z = DataUtil.readInt(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z
}
def handle12(FileObject):
EntityID = DataUtil.readInt(FileObject)
Animation = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'AnimationID': Animation
}
def handle14(FileObject):
EntityID = DataUtil.readInt(FileObject)
PlayerName = DataUtil.readString(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
yaw = DataUtil.readFloat(FileObject)
pitch = DataUtil.readFloat(FileObject)
curItem = DataUtil.readShort(FileObject)
metadata = DataUtil.readEntityMetadata(FileObject)
toReturn = {'EntityID': EntityID,
'Player Name': PlayerName,
'x': x,
'y': y,
'z': z,
'yaw': yaw,
'pitch': pitch,
'curItem': curItem,
'Metadata': metadata
}
return toReturn
def handle15(FileObject):
EntityID = DataUtil.readInt(FileObject)
ItemID = DataUtil.readShort(FileObject)
if (ItemID != -1):
Count = DataUtil.readByte(FileObject)
Damage = DataUtil.readShort(FileObject)
ArrayLength = DataUtil.readShort(FileObject)
if (ArrayLength != -1):
Array = FileObject.read(ArrayLength) #TODO: find out what this does and do stuff accrodingly
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
Rotation = DataUtil.readByte(FileObject)
Pitch = DataUtil.readByte(FileObject)
Roll = DataUtil.readByte(FileObject)
toReturn = {'EntityID': EntityID,
'ItemID': ItemID,
'x': x,
'y': y,
'z': z,
'Rotation': Rotation,
'Pitch': Pitch,
'Roll': Roll
}
if (ItemID != -1):
toReturn['Count'] = Count
toReturn['Damage'] = Damage
return toReturn
def handle16(FileObject):
CollectedID = DataUtil.readInt(FileObject)
CollectorID = DataUtil.readInt(FileObject)
return {'CollectedID': CollectedID,
'CollectorID': CollectorID
}
def handle17(FileObject):
EntityID = DataUtil.readInt(FileObject)
Type = DataUtil.readByte(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
yaw = DataUtil.readByte(FileObject)
pitch = DataUtil.readByte(FileObject)
data = DataUtil.readInt(FileObject)
if (data > 0):
SpeedX = DataUtil.readShort(FileObject)
SpeedY = DataUtil.readShort(FileObject)
SpeedZ = DataUtil.readShort(FileObject)
return {'EntityID': EntityID,
'Type': Type,
'x': x,
'y': y,
'z': z,
'yaw': yaw,
'pitch': pitch,
'SpeedX': SpeedX,
'SpeedY': SpeedY,
'SpeedZ': SpeedZ
}
else:
return {'EntityID': EntityID,
'Type': Type,
'x': x,
'y': y,
'z': z,
'yaw': yaw,
'pitch': pitch
}
def handle18(FileObject):
EntityID = DataUtil.readInt(FileObject)
Type = DataUtil.readByte(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
Yaw = DataUtil.readByte(FileObject)
Pitch = DataUtil.readByte(FileObject)
HeadYaw = DataUtil.readByte(FileObject)
VelocityX = DataUtil.readShort(FileObject)
VelocityY = DataUtil.readShort(FileObject)
VelocityZ = DataUtil.readShort(FileObject)
metadata = DataUtil.readEntityMetadata(FileObject)
return {'EntityID': EntityID,
'Type': Type,
'x': x,
'y': y,
'z': z,
'Yaw': Yaw,
'Pitch': Pitch,
'HeadYaw': HeadYaw,
'Metadata': metadata,
'VelocityX': VelocityX,
'VelocityY': VelocityY,
'VelocityZ': VelocityZ
}
def handle19(FileObject):
EntityID = DataUtil.readInt(FileObject)
Title = DataUtil.readString(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
Direction = DataUtil.readInt(FileObject)
return {'EntityID': EntityID,
'Title': Title,
'x': x,
'y': y,
'z': z,
'Direction': Direction
}
def handle1A(FileObject):
EntityID = DataUtil.readInt(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
Count = DataUtil.readShort(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z,
'Count': Count
}
def handle1C(FileObject):
EntityID = DataUtil.readInt(FileObject)
VelocityX = DataUtil.readShort(FileObject)
VelocityY = DataUtil.readShort(FileObject)
VelocityZ = DataUtil.readShort(FileObject)
return {'EntityID': EntityID,
'VelocityX': VelocityX,
'VelocityY': VelocityY,
'VelocityZ': VelocityZ
}
def handle1D(FileObject):
EntityArrayLength = DataUtil.readByte(FileObject)
Entities = []
for i in range(EntityArrayLength):
Entities.append(DataUtil.readInt(FileObject))
return Entities
def handle1E(FileObject):
EntityID = DataUtil.readInt(FileObject)
return EntityID
def handle1F(FileObject):
EntityID = DataUtil.readInt(FileObject)
x = DataUtil.readByte(FileObject)
y = DataUtil.readByte(FileObject)
z = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z
}
def handle20(FileObject):
EntityID = DataUtil.readInt(FileObject)
Yaw = DataUtil.readByte(FileObject)
Pitch = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'Yaw': Yaw,
'Pitch': Pitch
}
def handle21(FileObject):
EntityID = DataUtil.readInt(FileObject)
x = DataUtil.readByte(FileObject)
y = DataUtil.readByte(FileObject)
z = DataUtil.readByte(FileObject)
Yaw = DataUtil.readByte(FileObject)
Pitch = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z,
'Yaw': Yaw,
'Pitch': Pitch
}
def handle22(FileObject):
EntityID = DataUtil.readInt(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
Yaw = DataUtil.readByte(FileObject)
Pitch = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z,
'Yaw': Yaw,
'Pitch': Pitch
}
def handle23(FileObject):
EntityID = DataUtil.readInt(FileObject)
HeadYaw = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'HeadYaw': HeadYaw
}
def handle26(FileObject):
EntityID = DataUtil.readInt(FileObject)
Status = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'Status': Status
}
def handle27(FileObject):
EntityID = DataUtil.readInt(FileObject)
VehicleID = DataUtil.readInt(FileObject)
Leash = DataUtil.readBoolean(FileObject)
return {'EntityID': EntityID,
'VehicleID': VehicleID,
'Leash': Leash
}
def handle28(FileObject):
EntityID = DataUtil.readInt(FileObject)
metadata = DataUtil.readEntityMetadata(FileObject)
return {'EntityID': EntityID,
'MetaData': metadata
}
def handle29(FileObject):
EntityID = DataUtil.readInt(FileObject)
EffectID = DataUtil.readByte(FileObject)
Amplifier = DataUtil.readByte(FileObject)
Duration = DataUtil.readShort(FileObject)
return {'EntityID': EntityID,
'EffectID': EffectID,
'Amplifier': Amplifier,
'Duration': Duration
}
def handle2A(FileObject):
EntityID = DataUtil.readInt(FileObject)
EffectID = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'EffectID': EffectID
}
def handle2B(FileObject):
ExperienceBar = DataUtil.readFloat(FileObject)
Level = DataUtil.readShort(FileObject)
TotalExp = DataUtil.readShort(FileObject)
return {'ExpBar': ExperienceBar,
'Level': Level,
'TotalExp': TotalExp
}
def handle2C(FileObject):
EntityID = DataUtil.readInt(FileObject)
PropertiesCount = DataUtil.readInt(FileObject)
Properties = {}
for i in range(PropertiesCount):
key = DataUtil.readString(FileObject)
value = DataUtil.readDouble(FileObject)
Properties[key] = value
len = DataUtil.readShort(FileObject)
for x in range(len):
uuid_msb = DataUtil.readLong(FileObject)
uuid_lsb = DataUtil.readLong(FileObject)
amount = DataUtil.readDouble(FileObject)
operation = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'Properties': Properties
}
def handle33(FileObject):
X = DataUtil.readInt(FileObject)
Z = DataUtil.readInt(FileObject)
GroundUpContinuous = DataUtil.readBoolean(FileObject)
PrimaryBitMap = DataUtil.readShort(FileObject)
AddBitMap = DataUtil.readShort(FileObject)
CompressedSize = DataUtil.readInt(FileObject)
RawData = FileObject.read(CompressedSize)
return {'x': X,
'z': Z,
'GroundUpContinuous': GroundUpContinuous,
'PrimaryBitMap': PrimaryBitMap,
'AddBitMap': AddBitMap,
'RawData': RawData
}
def handle34(FileObject):
ChunkX = DataUtil.readInt(FileObject)
ChunkZ = DataUtil.readInt(FileObject)
AffectedBlocks = DataUtil.readShort(FileObject)
DataSize = DataUtil.readInt(FileObject)
FileObject.read(DataSize) #not going to be using this until I know how to.
return {'ChunkX': ChunkX,
'ChunkZ': ChunkZ,
'AffectedBlocks': AffectedBlocks
}
def handle35(FileObject):
X = DataUtil.readInt(FileObject)
Y = DataUtil.readByte(FileObject)
Z = DataUtil.readInt(FileObject)
BlockType = DataUtil.readShort(FileObject)
BlockMetaData = DataUtil.readByte(FileObject)
return {'x': X,
'y': Y,
'z': Z,
'BlockType': BlockType,
'MetaData': BlockMetaData
}
def handle36(FileObject):
X = DataUtil.readInt(FileObject)
Y = DataUtil.readShort(FileObject)
Z = DataUtil.readInt(FileObject)
Byte1 = DataUtil.readByte(FileObject)
Byte2 = DataUtil.readByte(FileObject)
BlockID = DataUtil.readShort(FileObject)
return {'x': X,
'y': Y,
'z': Z,
'Byte1': Byte1,
'Byte2': Byte2,
'BlockID': BlockID
}
def handle37(FileObject):
#int - EntityID
EntityID = DataUtil.readInt(FileObject)
#int - X cord
x = DataUtil.readInt(FileObject)
#int - Y cord
y = DataUtil.readInt(FileObject)
#int - Z cord
z = DataUtil.readInt(FileObject)
#byte - Stage
DestroyedStage = DataUtil.readByte(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z,
'DestroyedStage': DestroyedStage
}
def handle38(FileObject):
#short - number of chunks
ChunkCount = DataUtil.readShort(FileObject)
#int - chunk data length
ChunkDataLength = DataUtil.readInt(FileObject)
SkyLightSent = DataUtil.readBoolean(FileObject)
RawData = FileObject.read(ChunkDataLength)
metadata = []
for i in range(ChunkCount):
ChunkX = DataUtil.readInt(FileObject)
ChunkZ = DataUtil.readInt(FileObject)
PrimaryBitMap = DataUtil.readUnsignedShort(FileObject)
AddBitMap = DataUtil.readUnsignedShort(FileObject)
metadata.append({'x': ChunkX,
'z': ChunkZ,
'PrimaryBitMap': PrimaryBitMap,
'AddBitMap': AddBitMap
})
return {'ChunkCount': ChunkCount,
'SkyLightSent': SkyLightSent,
'RawData': RawData,
'ChunkMeta': metadata
}
def handle3C(FileObject):
X = DataUtil.readDouble(FileObject)
Y = DataUtil.readDouble(FileObject)
Z = DataUtil.readDouble(FileObject)
Radius = DataUtil.readFloat(FileObject)
RecordCount = DataUtil.readInt(FileObject)
AffectedBlocks = []
for i in range((RecordCount * 3)):
x = DataUtil.readByte(FileObject)
y = DataUtil.readByte(FileObject)
z = DataUtil.readByte(FileObject)
AffectedBlocks.append({'x': x, 'y': y, 'z': z})
#---Unknown what these floats do
FileObject.read(4)
FileObject.read(4)
FileObject.read(4)
#---
return {'x': X,
'y': Y,
'z': Z,
'Raidus': Radius,
'AffectedBlocks': AffectedBlocks
}
def handle3D(FileObject):
EffectID = DataUtil.readInt(FileObject)
X = DataUtil.readInt(FileObject)
Y = DataUtil.readByte(FileObject)
Z = DataUtil.readInt(FileObject)
Data = DataUtil.readInt(FileObject)
NoVolDecrease = DataUtil.readBoolean(FileObject)
return {'EffectID': EffectID,
'X': X,
'Y': Y,
'Z': Z,
'Data': Data,
'NoVolumeDecrease': NoVolDecrease
}
def handle3E(FileObject):
Sound = DataUtil.readString(FileObject)
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
Volume = DataUtil.readFloat(FileObject)
Pitch = DataUtil.readByte(FileObject)
return {'Sound': Sound,
'x': x,
'y': y,
'z': z,
'Volume': Volume,
'Pitch': Pitch
}
def handle3F(FileObject):
name = DataUtil.readString(FileObject)
x = DataUtil.readFloat(FileObject)
y = DataUtil.readFloat(FileObject)
z = DataUtil.readFloat(FileObject)
offsetx = DataUtil.readFloat(FileObject)
offsety = DataUtil.readFloat(FileObject)
offsetz = DataUtil.readFloat(FileObject)
speed = DataUtil.readFloat(FileObject)
num = DataUtil.readInt(FileObject)
return {'Name' : name,
'x' : x,
'y' : y,
'z' : z,
'Offset x' : offsetx,
'Offset y' : offsety,
'Offset z' : offsetz,
'Speed' : speed,
'Number' : num
}
def handle46(FileObject):
Reason = DataUtil.readByte(FileObject)
GameMode = DataUtil.readByte(FileObject)
return {'Reason': Reason,
'GameMode': GameMode
}
def handle47(FileObject):
EntityID = DataUtil.readInt(FileObject)
FileObject.read(1) #Boolean don't do nothing
x = DataUtil.readInt(FileObject)
y = DataUtil.readInt(FileObject)
z = DataUtil.readInt(FileObject)
return {'EntityID': EntityID,
'x': x,
'y': y,
'z': z
}
def handle64(FileObject):
WindowID = DataUtil.readByte(FileObject)
InventoryType = DataUtil.readByte(FileObject)
WindowTitle = DataUtil.readString(FileObject)
NumberOfSlots = DataUtil.readByte(FileObject)
UseName = DataUtil.readBoolean(FileObject)
toReturn = {'WindowID': WindowID,
'InventoryType': InventoryType,
'WindowTitle': WindowTitle,
'NumberOfSlots': NumberOfSlots,
'UseName': UseName
}
if InventoryType == 11:
toReturn['EntityId'] = DataUtil.readInt(FileObject)
return toReturn
def handle65(FileObject):
WindowID = DataUtil.readByte(FileObject)
return WindowID
def handle67(FileObject):
WindowID = DataUtil.readByte(FileObject)
Slot = DataUtil.readShort(FileObject)
SlotData = DataUtil.readSlotData(FileObject)
return {'WindowID': WindowID,
'Slot': Slot,
'SlotData': SlotData
}
def handle68(FileObject):
WindowID = DataUtil.readByte(FileObject)
Count = DataUtil.readShort(FileObject)
Slots = []
for i in range(Count):
SlotData = DataUtil.readSlotData(FileObject)
Slots.append(SlotData)
return {'WindowID': WindowID,
'Count': Count,
'Slots': Slots
}
def handle69(FileObject):
WindowID = DataUtil.readByte(FileObject)
Property = DataUtil.readShort(FileObject)
Value = DataUtil.readShort(FileObject)
return {'WindowID': WindowID,
'Property': Property,
'Value': Value
}
def handle6A(FileObject):
WindowID = DataUtil.readByte(FileObject)
ActionType = DataUtil.readShort(FileObject)
Accepted = DataUtil.readBoolean(FileObject)
return {'WindowID': WindowID,
'ActionType': ActionType,
'Accepted': Accepted
}
def handle6B(FileObject):
Slot = DataUtil.readShort(FileObject)
ClickedItem = DataUtil.readSlotData(FileObject)
return {'Slot': Slot,
'ClickedItem': ClickedItem
}
def handle82(FileObject):
X = DataUtil.readInt(FileObject)
Y = DataUtil.readShort(FileObject)
Z = DataUtil.readInt(FileObject)
Line1 = DataUtil.readString(FileObject)
Line2 = DataUtil.readString(FileObject)
Line3 = DataUtil.readString(FileObject)
Line4 = DataUtil.readString(FileObject)
return {'x': X,
'y': Y,
'z': Z,
'Line1': Line1,
'Line2': Line2,
'Line3': Line3,
'Line4': Line4
}
def handle83(FileObject):
ItemType = DataUtil.readShort(FileObject)
ItemID = DataUtil.readShort(FileObject)
TextLength = DataUtil.readShort(FileObject)
Text = DataUtil.readByteArray(FileObject, TextLength)
return {'ItemType': ItemType,
'ItemID': ItemID,
'Text': Text
}
def handle84(FileObject):
X = DataUtil.readInt(FileObject)
Y = DataUtil.readShort(FileObject)
Z = DataUtil.readInt(FileObject)
Action = DataUtil.readByte(FileObject)
DataLength = DataUtil.readShort(FileObject)
if (DataLength != -1):
ByteArray = DataUtil.readByteArray(FileObject, DataLength)
NBTData = NBTFile(BytesIO(ByteArray), compression=NBTFile.Compression.GZIP)
return {'x': X,
'y': Y,
'z': Z,
'Action': Action,
'NBTData': NBTData
}
return {'x': X,
'y': Y,
'z': Z,
'Action': Action
}
def handle85(FileObject):
EntityID = DataUtil.readByte(FileObject)
X = DataUtil.readInt(FileObject)
Y = DataUtil.readInt(FileObject)
Z = DataUtil.readInt(FileObject)
return {'EntityID': EntityID,
'x': X,
'y': Y,
'z': Z}
def handleC8(FileObject):
StatID = DataUtil.readInt(FileObject)
Amount = DataUtil.readInt(FileObject)
return {'StatID': StatID,
'Amount': Amount
}
def handleC9(FileObject):
PlayerName = DataUtil.readString(FileObject)
Online = DataUtil.readBoolean(FileObject)
Ping = DataUtil.readShort(FileObject)
return {'PlayerName': PlayerName,
'Online': Online,
'Ping': Ping
}
def handleCA(FileObject):
#byte - flags
Flags = DataUtil.readByte(FileObject)
#byte - fly speed
FlySpeed = DataUtil.readFloat(FileObject)
#byte - walk speed
WalkSpeed = DataUtil.readFloat(FileObject)
return {'Flags': Flags,
'Fly Speed': FlySpeed,
'Walk Speed': WalkSpeed
}
def handleCB(FileObject):
text = DataUtil.readString(FileObject)
return {'Text': text}
def handleCE(FileObject):
name = DataUtil.readString(FileObject)
display_text = DataUtil.readString(FileObject)
create_or_remove = DataUtil.readBoolean(FileObject)
return {'Name' : name,
'Display Name' : display_text,
'Remove' : create_or_remove
}
def handleCF(FileObject):
name = DataUtil.readString(FileObject)
remove = DataUtil.readBoolean(FileObject)
score_name = DataUtil.readString(FileObject)
value = DataUtil.readInt(FileObject)
return {'Item Name' : name,
'Remove' : remove,
'Score Name' : score_name,
'Value' : value
}
def handleD0(FileObject):
position = DataUtil.readByte(FileObject)
score = DataUtil.readString(FileObject)
return {'Position' : position,
'Score' : score
}
def handleD1(FileObject):
team = DataUtil.readString(FileObject)
mode = DataUtil.readByte(FileObject)
toReturn = {'Team' : team, 'Mode' : mode}
if mode == 0 or mode == 2:
toReturn['Display Name'] = DataUtil.readString(FileObject)
toReturn['Prefix'] = DataUtil.readString(FileObject)
toReturn['Suffix'] = DataUtil.readString(FileObject)
toReturn['FriendlyFire'] = DataUtil.readByte(FileObject)
if mode == 0 or mode == 3 or mode == 4:
count = DataUtil.readShort(FileObject)
players = []
for i in range(count):
players.append(DataUtil.readString(FileObject))
return toReturn
def handleFA(FileObject):
Channel = DataUtil.readString(FileObject)
length = DataUtil.readShort(FileObject)
message = DataUtil.readByteArray(FileObject, length)
return {'Channel': Channel,
'message': message
}
def handleFC(FileObject):
#short - shared secret length
secretLength = DataUtil.readShort(FileObject)
sharedSecret = DataUtil.readByteArray(FileObject, secretLength) #ignore this data, it doesn't matter
#short - token length
length = DataUtil.readShort(FileObject)
token = DataUtil.readByteArray(FileObject, length) #ignore this data, it doesn't matter
return {'Secret Length': secretLength,
'Shared Secret': sharedSecret,
'Token Length': length,
'Token': token
}
def handleFD(FileObject):
#string - server id
serverid = DataUtil.readString(FileObject)
#short - pub key length
length = DataUtil.readShort(FileObject)
#byte array - pub key
pubkey = DataUtil.readByteArray(FileObject, length)
#short - token length
length = DataUtil.readShort(FileObject)
#byte array - token
token = DataUtil.readByteArray(FileObject, length)
return {'ServerID': serverid,
'Public Key': pubkey,
'Token': token
}
def handleFF(FileObject):
Reason = DataUtil.readString(FileObject)
return {'Reason': Reason}

View File

@ -1,59 +0,0 @@
import DataUtil
def send00(socket, KAid):
#packet id
socket.send("\x00")
#int - keep alive id
DataUtil.sendInt(socket, KAid)
def sendHandshake(socket, username, host, port):
#packet id
socket.send("\x02")
#byte - protocol version
DataUtil.sendByte(socket, 78)
#string - username
DataUtil.sendString(socket, username)
#string - server host
DataUtil.sendString(socket, host)
#int - server port
DataUtil.sendInt(socket, port)
def send03(socket, message):
#packet id
socket.send("\x03")
#-----string - message-----#
DataUtil.sendString(socket, message)
def sendCD(socket, payload):
#packet id
socket.send("\xCD")
#payload - byte
DataUtil.sendByte(socket, payload)
def sendFC(socket, secret, token):
#packet id
socket.send("\xFC")
#shared secret
DataUtil.sendShort(socket, secret.__len__()) #length
socket.send(secret)
#token
DataUtil.sendShort(socket, token.__len__())
socket.send(token)
def sendFF(socket, reason):
#string - disconnect reason
DataUtil.sendString(socket, reason)

View File

@ -1,63 +0,0 @@
import os
import imp
class PluginLoader():
path = ""
plugins = {}
listeners = []
def __init__(self, path):
self.path = path
def loadPlugins(self, parser):
for item in os.listdir(self.path):
split = os.path.splitext(item)
if (split[1] == '.py'):
name = split[0]
full_name = split[0].replace(os.path.sep, '.')
m = imp.load_module(full_name, *imp.find_module(name, [self.path]))
pluginClass = None
try:
pluginClass = getattr(m, name)()
self.plugins[name] = pluginClass
try:
pluginClass.onEnable(parser, self)
except AttributeError:
pass
try:
self.listeners.append(pluginClass.packetReceive)
except AttributeError:
pass
except AttributeError:
print "Plugin " + name + " is malformed"
def disablePlugins(self):
for plugin in self.plugins.values():
try:
plugin.onDisable()
except AttributeError:
pass
def notifyOptions(self, options):
for plugin in self.plugins.values():
try:
plugin.optionsParsed(options)
except AttributeError:
pass
def notify(self, methodName):
for plugin in self.plugins.values():
try:
getattr(plugin, methodName)()
except AttributeError:
pass
def getPlugins(self):
return self.plugins.values()
def getPlugin(self, name):
return self.plugins[name]
def getPacketListeners(self):
return self.listeners

View File

@ -1,16 +0,0 @@
class IRC:
options = None
writeFile = None
def onEnable(self, parser, pluginloader):
parser.add_option("-q", "--irc-out-file", dest="ircDump", default="ircdump.txt",
help="file to dump messages to")
def onDisable(self):
if (self.writeFile != None):
self.writeFile.close()
def optionsParsed(self, parsedOptions):
self.options = parsedOptions
if (self.options.ircDump):
self.writeFile = open(self.options.filename, 'w')

View File

@ -1,35 +0,0 @@
import string
import copy
import base64
class PacketDumper:
options = None
writeFile = None
def onEnable(self, parser, pluginloader):
parser.add_option("-d", "--dump-packets",
action="store_true", dest="dumpPackets", default=False,
help="run with this argument to dump packets")
parser.add_option("-o", "--out-file", dest="filename", default="dump.txt",
help="file to dump packets to")
def onDisable(self):
if self.writeFile is not None:
self.writeFile.close()
def optionsParsed(self, parsedOptions):
self.options = parsedOptions
if self.options.dumpPackets:
self.writeFile = open(self.options.filename, 'w')
def packetReceive(self, packetID, receivedPacket):
packet = copy.deepcopy(receivedPacket)
if self.writeFile is not None:
if packetID == "\x33" or packetID == "\x38":
packet['Data'] = base64.b64encode(packet['RawData'])
del packet['RawData']
if packetID == "\x03":
packet['Message'] = filter(lambda x: x in string.printable, packet['Message'])
self.writeFile.write(hex(ord(packetID)) + " : " + str(packet) + '\n')

View File

@ -1,15 +0,0 @@
# -*- coding: utf8 -*-
from pynbt.nbt import (
NBTFile,
TAG_Byte,
TAG_Short,
TAG_Int,
TAG_Long,
TAG_Float,
TAG_Double,
TAG_Byte_Array,
TAG_String,
TAG_List,
TAG_Compound,
TAG_Int_Array
)

View File

@ -1,354 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
"""
Implements reading & writing for the Minecraft Named Binary Tag (NBT) format,
created by Markus Petersson.
.. moduleauthor:: Tyler Kennedy <tk@tkte.ch>
"""
import gzip
from struct import unpack, pack
class BaseTag(object):
def __init__(self, value, name=None):
self.name = name
self.value = value
@staticmethod
def _read_utf8(read):
"""Reads a length-prefixed UTF-8 string."""
name_length = read('H', 2)[0]
return read.io.read(name_length).decode('utf-8')
@staticmethod
def _write_utf8(write, value):
"""Writes a length-prefixed UTF-8 string."""
write('h', len(value))
write.io.write(value.encode('UTF-8'))
@classmethod
def read(cls, read, has_name=True):
"""
Read the tag in using the reader `rd`.
If `has_name` is `False`, skip reading the tag name.
"""
name = cls._read_utf8(read) if has_name else None
if cls is TAG_Compound:
# A TAG_Compound is almost identical to Python's native dict()
# object, or a Java HashMap.
final = {}
while True:
# Find the type of each tag in a compound in turn.
tag = read('b', 1)[0]
if tag == 0:
# A tag of 0 means we've reached TAG_End, used to terminate
# a TAG_Compound.
break
# We read in each tag in turn, using its name as the key in
# the dict (Since a compound cannot have repeating names,
# this works fine).
tmp = _tags[tag].read(read)
final[tmp.name] = tmp
return cls(final, name=name)
elif cls is TAG_List:
# A TAG_List is a very simple homogeneous array, similar to
# Python's native list() object, but restricted to a single type.
tag_type, length = read('bi', 5)
tag_read = _tags[tag_type].read
return cls(
_tags[tag_type],
[tag_read(read, has_name=False) for x in range(0, length)],
name=name
)
elif cls is TAG_String:
# A simple length-prefixed UTF-8 string.
value = cls._read_utf8(read)
return cls(value, name=name)
elif cls is TAG_Byte_Array:
# A simple array of (signed) bytes.
length = read('i', 4)[0]
return cls(read('{0}b'.format(length), length), name=name)
elif cls is TAG_Int_Array:
# A simple array of (signed) 4-byte integers.
length = read('i', 4)[0]
return cls(read('{0}i'.format(length), length * 4), name=name)
elif cls is TAG_Byte:
# A single (signed) byte.
return cls(read('b', 1)[0], name=name)
elif cls is TAG_Short:
# A single (signed) short.
return cls(read('h', 2)[0], name=name)
elif cls is TAG_Int:
# A signed (signed) 4-byte int.
return cls(read('i', 4)[0], name=name)
elif cls is TAG_Long:
# A single (signed) 8-byte long.
return cls(read('q', 8)[0], name=name)
elif cls is TAG_Float:
# A single single-precision floating point value.
return cls(read('f', 4)[0], name=name)
elif cls is TAG_Double:
# A single double-precision floating point value.
return cls(read('d', 8)[0], name=name)
def write(self, write):
# Only write the name TAG_String if our name is not `None`.
# If you want a blank name, use ''.
if self.name is not None:
if isinstance(self, NBTFile):
write('b', 0x0A)
else:
write('b', _tags.index(self.__class__))
self._write_utf8(write, self.name)
if isinstance(self, TAG_List):
write('bi', _tags.index(self.type_), len(self.value))
for item in self.value:
# If our list item isn't of type self._type, convert
# it before writing.
if not isinstance(item, self.type_):
item = self.type_(item)
item.write(write)
elif isinstance(self, TAG_Compound):
for v in self.value.values():
v.write(write)
# A tag of type 0 (TAg_End) terminates a TAG_Compound.
write('b', 0)
elif isinstance(self, TAG_String):
self._write_utf8(write, self.value)
elif isinstance(self, TAG_Int_Array):
l = len(self.value)
write('i{0}i'.format(l), l, *self.value)
elif isinstance(self, TAG_Byte_Array):
l = len(self.value)
write('i{0}b'.format(l), l, *self.value)
elif isinstance(self, TAG_Byte):
write('b', self.value)
elif isinstance(self, TAG_Short):
write('h', self.value)
elif isinstance(self, TAG_Int):
write('i', self.value)
elif isinstance(self, TAG_Long):
write('q', self.value)
elif isinstance(self, TAG_Float):
write('f', self.value)
elif isinstance(self, TAG_Double):
write('d', self.value)
def pretty(self, indent=0, indent_str=' '):
"""
Pretty-print a tag in the same general style as Markus's example
output.
"""
return '{0}{1}({2!r}): {3!r}'.format(
indent_str * indent,
self.__class__.__name__,
self.name,
self.value
)
def __repr__(self):
return '{0}({1!r}, {2!r})'.format(
self.__class__.__name__, self.value, self.name)
def __str__(self):
return repr(self)
def __unicode__(self):
return unicode(repr(self), 'utf-8')
class TAG_Byte(BaseTag):
pass
class TAG_Short(BaseTag):
pass
class TAG_Int(BaseTag):
pass
class TAG_Long(BaseTag):
pass
class TAG_Float(BaseTag):
pass
class TAG_Double(BaseTag):
pass
class TAG_Byte_Array(BaseTag):
def pretty(self, indent=0, indent_str=' '):
return '{0}TAG_Byte_Array({1!r}): [{2} bytes]'.format(
indent_str * indent, self.name, len(self.value))
class TAG_String(BaseTag):
pass
class TAG_List(BaseTag, list):
def __init__(self, tag_type, value=None, name=None):
"""
Creates a new homogeneous list of `tag_type` items, copying `value`
if provided.
"""
self.name = name
self.value = self
self.type_ = tag_type
if value is not None:
self.extend(value)
def pretty(self, indent=0, indent_str=' '):
t = []
t.append('{0}TAG_List({1!r}): {2} entries'.format(
indent_str * indent, self.name, len(self.value)))
t.append('{0}{{'.format(indent_str * indent))
for v in self.value:
t.append(v.pretty(indent + 1, indent_str))
t.append('{0}}}'.format(indent_str * indent))
return '\n'.join(t)
def __repr__(self):
return '{0}({1!r} entries, {2!r})'.format(
self.__class__.__name__, len(self), self.name)
class TAG_Compound(BaseTag, dict):
def __init__(self, value=None, name=None):
self.name = name
self.value = self
if value is not None:
self.update(value)
def pretty(self, indent=0, indent_str=' '):
t = []
t.append('{0}TAG_Compound({1!r}): {2} entries'.format(
indent_str * indent, self.name, len(self.value)))
t.append('{0}{{'.format(indent_str * indent))
for v in self.values():
t.append(v.pretty(indent + 1, indent_str))
t.append('{0}}}'.format(indent_str * indent))
return '\n'.join(t)
def __repr__(self):
return '{0}({1!r} entries, {2!r})'.format(
self.__class__.__name__, len(self), self.name)
def __setitem__(self, key, value):
"""
Sets the TAG_*'s name if it isn't already set to that of the key
it's being assigned to. This results in cleaner code, as the name
does not need to be specified twice.
"""
if value.name is None:
value.name = key
super(TAG_Compound, self).__setitem__(key, value)
def update(self, *args, **kwargs):
"""See `__setitem__`."""
super(TAG_Compound, self).update(*args, **kwargs)
for key, item in self.items():
if item.name is None:
item.name = key
class TAG_Int_Array(BaseTag):
def pretty(self, indent=0, indent_str=' '):
return '{0}TAG_Int_Array({1!r}): [{2} integers]'.format(
indent_str * indent, self.name, len(self.value))
# The TAG_* types have the convienient property of being continuous.
# The code is written in such a way that if this were to no longer be
# true in the future, _tags can simply be replaced with a dict().
_tags = (
None,
TAG_Byte,
TAG_Short,
TAG_Int,
TAG_Long,
TAG_Float,
TAG_Double,
TAG_Byte_Array,
TAG_String,
TAG_List,
TAG_Compound,
TAG_Int_Array
)
class NBTFile(TAG_Compound):
class Compression(object):
"""
Defines compression schemes to be used for loading and saving
NBT files.
"""
# NONE is simply for the sake of completeness.
NONE = 10
# Use Gzip compression when reading or writing.
GZIP = 20
def __init__(self, io=None, name=None, value=None, compression=None,
little_endian=False):
"""
Creates a new NBTFile or loads one from any file-like object providing
`read()`.
Construction a new NBTFile() is as simple as:
>>> nbt = NBTFile(name='')
Whereas loading an existing one is most often done:
>>> with open('my_file.nbt', rb') as io:
... nbt = NBTFile(io=io, compression=NBTFile.Compression.GZIP)
"""
# No file or path given, so we're creating a new NBTFile.
if io is None:
super(NBTFile, self).__init__(value if value else {}, name)
return
if compression is None or compression == NBTFile.Compression.NONE:
final_io = io
elif compression == NBTFile.Compression.GZIP:
final_io = gzip.GzipFile(fileobj=io, mode='rb')
else:
raise ValueError('Unrecognized compression scheme.')
# The pocket edition uses little-endian NBT files, but annoyingly
# without any kind of header we can't determine that ourselves,
# not even a magic number we could flip.
if little_endian:
read = lambda fmt, size: unpack('<' + fmt, final_io.read(size))
else:
read = lambda fmt, size: unpack('>' + fmt, final_io.read(size))
read.io = final_io
# All valid NBT files will begin with 0x0A, which is a TAG_Compound.
if read('b', 1)[0] != 0x0A:
raise IOError('NBTFile does not begin with 0x0A.')
tmp = TAG_Compound.read(read)
super(NBTFile, self).__init__(tmp, tmp.name)
def save(self, io, compression=None, little_endian=False):
"""
Saves the `NBTFile()` to `io`, which can be any file-like object
providing `write()`.
"""
if compression is None or compression == NBTFile.Compression.NONE:
final_io = io
elif compression == NBTFile.Compression.GZIP:
final_io = gzip.GzipFile(fileobj=io, mode='wb')
if little_endian:
write = lambda fmt, *args: final_io.write(pack('<' + fmt, *args))
else:
write = lambda fmt, *args: final_io.write(pack('>' + fmt, *args))
write.io = final_io
self.write(write)

110
start.py
View File

@ -1,89 +1,63 @@
import getpass import getpass
import sys import sys
import Utils
from pluginloader import PluginLoader
from networking import PacketSenderManager, NetworkManager
from optparse import OptionParser from optparse import OptionParser
try: import authentication
import colorama
colorama.init()
except ImportError:
pass
if __name__ == "__main__": PROTOCOL_VERSION = 5
def main():
parser = OptionParser() parser = OptionParser()
parser.add_option("-u", "--username", dest="username", default="", parser.add_option("-u", "--username", dest="username", default=None,
help="username to log in with") help="username to log in with")
parser.add_option("-p", "--password", dest="password", default="", parser.add_option("-p", "--password", dest="password", default=None,
help="password to log in with") help="password to log in with")
parser.add_option("-s", "--server", dest="server", default="", parser.add_option("-s", "--server", dest="server", default=None,
help="server to connect to") help="server to connect to")
parser.add_option("-x", "--offline-mode", dest="offlineMode",
action="store_true", default=False,
help="run in offline mode i.e don't attempt to auth via minecraft.net")
parser.add_option("-c", "--disable-console-colours", dest="disableAnsiColours",
action="store_true", default=False,
help="print minecraft chat colours as their equivalent ansi colours")
# pluginLoader
pluginLoader = PluginLoader("plugins")
pluginLoader.loadPlugins(parser)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
pluginLoader.notifyOptions(options)
if not options.username:
options.username = raw_input("Enter your username: ")
if (options.username != ""): if not options.password:
user = options.username options.password = getpass.getpass("Enter your password: ")
else:
user = raw_input("Enter your username: ")
if (options.password != ""):
passwd = options.password
elif (not options.offlineMode):
passwd = getpass.getpass("Enter your password: ")
if (not options.offlineMode): login_response = authentication.login_to_minecraft(options.username, options.password)
loginThread = Utils.MinecraftLoginThread(user, passwd) from pprint import pprint # TODO: remove debug
loginThread.start() pprint(vars(login_response)) # TODO: remove debug
loginThread.join()
loginResponse = loginThread.getResponse()
if (loginResponse['Response'] != "Good to go!"):
print loginResponse['Response']
sys.exit(1)
sessionid = loginResponse['SessionID']
user = loginResponse['Username']
print "Logged in as " + loginResponse['Username'] + "! Your session id is: " + sessionid
else:
sessionid = None
if (options.server != ""): if login_response.error:
serverAddress = options.server print login_response.human_error
return
print("Logged in as " + login_response.username)
if not options.server:
options.server = raw_input("Please enter server address (including port): ")
# Try to split out port and address
if ':' in options.server:
server = options.server.split(":")
address = server[0]
port = int(server[1])
else: else:
serverAddress = raw_input("Enter host and port if any: ") address = options.server
if ':' in serverAddress:
StuffEnteredIntoBox = serverAddress.split(":")
host = StuffEnteredIntoBox[0]
port = int(StuffEnteredIntoBox[1])
else:
host = serverAddress
port = 25565 port = 25565
connection = NetworkManager.ServerConnection(pluginLoader, user, sessionid, host, port, options)
connection.setDaemon(True) from network.connection import Connection
connection.start() connection = Connection(address, port, login_response)
connection.status()
while True: while True:
try: try:
chat_input = raw_input() text = raw_input()
if (connection.isConnected): except KeyboardInterrupt:
PacketSenderManager.send03(connection.grabSocket(), print "Bye!"
chat_input.decode('utf-8')[:100]) sys.exit()
else:
pass
except KeyboardInterrupt, e: if __name__ == "__main__":
connection.disconnect() main()
pluginLoader.disablePlugins()
sys.exit(1)