Update to 1.3 protocol, sha1 digest still needs work

This commit is contained in:
Ammar Askar 2012-09-06 00:28:55 +05:00
parent fb7b22b771
commit f18c6496b8
3 changed files with 184 additions and 81 deletions

22
Utils.py Normal file
View File

@ -0,0 +1,22 @@
import array
def stringToByteArray(string):
return array.array('B', string.decode("hex"))
def TwosCompliment(hash):
hash = array.array('B', hash.decode("hex"))
carry = True
for i in range((hash.__len__() - 1), 0, -1):
if(carry):
carry = hash[i] == 0xFF
hash[i] += 1
return hash
def trimStart(string, character):
for c in string:
if (c == character):
string = string[1:]
else:
break
return string

View File

@ -2,10 +2,12 @@ import socket
import wx import wx
import PacketListenerManager import PacketListenerManager
import urllib2 import urllib2
import urllib
import traceback import traceback
import threading import threading
import hashlib import hashlib
import string import string
import Utils
from networking import PacketSenderManager from networking import PacketSenderManager
from Crypto.Random import _UserFriendlyRNG from Crypto.Random import _UserFriendlyRNG
from Crypto.Util import asn1 from Crypto.Util import asn1
@ -65,28 +67,34 @@ class ServerConnection(threading.Thread):
packetFD = PacketListenerManager.handleFD(self.FileObject) packetFD = PacketListenerManager.handleFD(self.FileObject)
#Import the server's public key #Import the server's public key
print "#Import the server's public key"
self.pubkey = RSA.importKey(packetFD['Public Key']) self.pubkey = RSA.importKey(packetFD['Public Key'])
#Generate a 16 byte (128 bit) shared secret #Generate a 16 byte (128 bit) shared secret
print "#Generate a 16 byte (128 bit) shared secret"
self.sharedSecret = _UserFriendlyRNG.get_random_bytes(16) self.sharedSecret = _UserFriendlyRNG.get_random_bytes(16)
#Grab the server id #Grab the server id
print "#Grab the server id"
serverid = packetFD['ServerID']
sha1 = hashlib.sha1() sha1 = hashlib.sha1()
sha1.update(serverid) sha1.update(packetFD['ServerID'])
sha1.update(str(self.sharedSecret)) sha1.update(self.sharedSecret)
sha1.update(str(self.pubkey)) sha1.update(packetFD['Public Key'])
serverid = sha1.hexdigest() #lovely java style hex digest by SirCmpwn
sha1 = sha1.hexdigest()
negative = (int(sha1[0], 16) & 0x80) == 0x80
if(negative):
sha1 = Utils.TwosCompliment(sha1.digest())
#else:
# sha1 = sha1.digest()
Utils.trimStart(str(sha1), '0')
if (negative):
sha1 = '-' + sha1
serverid = sha1
#Authenticate the server from sessions.minecraft.net #Authenticate the server from sessions.minecraft.net
print "#Authenticate the server from sessions.minecraft.net"
if(serverid != '-'): if(serverid != '-'):
try: try:
#Open up the url with the appropriate get parameters #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 url = "http://session.minecraft.net/game/joinserver.jsp?user=" + self.username + "&sessionId=" + self.sessionID + "&serverId=" + serverid
print url
response = urllib2.urlopen(url).read() response = urllib2.urlopen(url).read()
if(response != "OK"): if(response != "OK"):
@ -99,20 +107,16 @@ class ServerConnection(threading.Thread):
return False return False
#Success \o/ We can now begin sending our stuff to the server #Success \o/ We can now begin sending our stuff to the server
print "#Success \o/ We can now begin sending our stuff to the server"
#Instantiate our main packet listener #Instantiate our main packet listener
print "#Instantiate our main packet listener"
PacketListener(self, self.window, self.socket, self.FileObject).start() PacketListener(self, self.window, self.socket, self.FileObject).start()
#Encrypt the verification token from earlier along with our shared secret with the server's rsa key #Encrypt the verification token from earlier along with our shared secret with the server's rsa key
print "#Encrypt the verification token from earlier along with our shared secret"
self.RSACipher = PKCS1_v1_5.new(self.pubkey) self.RSACipher = PKCS1_v1_5.new(self.pubkey)
encryptedSanityToken = self.RSACipher.encrypt(str(packetFD['Token'])) encryptedSanityToken = self.RSACipher.encrypt(str(packetFD['Token']))
encryptedSharedSecret = self.RSACipher.encrypt(str(self.sharedSecret)) encryptedSharedSecret = self.RSACipher.encrypt(str(self.sharedSecret))
#Send out a a packet FC to the server #Send out a a packet FC to the server
print "#Send out a a packet FC to the server"
PacketSenderManager.sendFC(self.socket, encryptedSharedSecret, encryptedSanityToken) PacketSenderManager.sendFC(self.socket, encryptedSharedSecret, encryptedSanityToken)
#GUI handling #GUI handling
@ -151,7 +155,9 @@ class EncryptedFileObjectHandler():
self.cipher = cipher self.cipher = cipher
def read(self, length): def read(self, length):
return self.cipher.decrypt(self.fileobject.read(length)) rawData = self.fileobject.read(length)
unencryptedData = self.cipher.decrypt(rawData)
return unencryptedData
class EncryptedSocketObjectHandler(): class EncryptedSocketObjectHandler():
@ -161,9 +167,6 @@ class EncryptedSocketObjectHandler():
def send(self, stuff): def send(self, stuff):
self.socket.send(self.cipher.encrypt(stuff)) self.socket.send(self.cipher.encrypt(stuff))
def recv(self, length):
return self.cipher.decrypt(self.socket.recv(length))
def close(self): def close(self):
self.socket.close() self.socket.close()
@ -180,14 +183,13 @@ class PacketListener(threading.Thread):
def enableEncryption(self): def enableEncryption(self):
#Create an AES cipher from the previously obtained public key #Create an AES cipher from the previously obtained public key
print "#Create an AES cipher from the previously generated shared secret" self.cipher = AES.new(self.connection.sharedSecret, AES.MODE_CFB, IV=self.connection.sharedSecret)
self.cipher = AES.new(str(self.connection.sharedSecret), AES.MODE_CFB, IV=self.connection.sharedSecret, segment_size=8) self.decipher = AES.new(self.connection.sharedSecret, AES.MODE_CFB, IV=self.connection.sharedSecret)
self.rawsocket = self.socket self.rawsocket = self.socket
self.socket = EncryptedSocketObjectHandler(self.rawsocket, self.cipher) self.socket = EncryptedSocketObjectHandler(self.rawsocket, self.cipher)
self.rawFileObject = self.FileObject self.rawFileObject = self.FileObject
self.FileObject = EncryptedFileObjectHandler(self.rawFileObject, self.cipher) self.FileObject = EncryptedFileObjectHandler(self.rawFileObject, self.decipher)
self.encryptedConnection = True self.encryptedConnection = True
print "#Encryption enabled"
def run(self): def run(self):
while True: while True:
@ -202,11 +204,11 @@ class PacketListener(threading.Thread):
print "Ping timeout" print "Ping timeout"
traceback.print_exc() traceback.print_exc()
break break
print hex(ord(response))
if(response == "\x00"): if(response == "\x00"):
PacketListenerManager.handle00(self.FileObject, self.socket) PacketListenerManager.handle00(self.FileObject, self.socket)
elif(response == "\x01"): elif(response == "\x01"):
PacketListenerManager.handle01(self.FileObject) packet01 = PacketListenerManager.handle01(self.FileObject)
print "Logged in \o/ Received an entity id of " + str(packet01['EntityID'])
elif(response == "\x03"): elif(response == "\x03"):
message = PacketListenerManager.handle03(self.FileObject) message = PacketListenerManager.handle03(self.FileObject)
if(self.connection.NoGUI): if(self.connection.NoGUI):
@ -275,8 +277,6 @@ class PacketListener(threading.Thread):
PacketListenerManager.handle2A(self.FileObject) PacketListenerManager.handle2A(self.FileObject)
elif(response == "\x2B"): elif(response == "\x2B"):
PacketListenerManager.handle2B(self.FileObject) PacketListenerManager.handle2B(self.FileObject)
elif(response == "\x32"):
PacketListenerManager.handle32(self.FileObject)
elif(response == "\x33"): elif(response == "\x33"):
PacketListenerManager.handle33(self.FileObject) PacketListenerManager.handle33(self.FileObject)
elif(response == "\x34"): elif(response == "\x34"):
@ -285,10 +285,16 @@ class PacketListener(threading.Thread):
PacketListenerManager.handle35(self.FileObject) PacketListenerManager.handle35(self.FileObject)
elif(response == "\x36"): elif(response == "\x36"):
PacketListenerManager.handle36(self.FileObject) PacketListenerManager.handle36(self.FileObject)
elif(response == "\x37"):
PacketListenerManager.handle37(self.FileObject)
elif(response == "\x38"):
PacketListenerManager.handle38(self.FileObject)
elif(response == "\x3C"): elif(response == "\x3C"):
PacketListenerManager.handle3C(self.FileObject) PacketListenerManager.handle3C(self.FileObject)
elif(response == "\x3D"): elif(response == "\x3D"):
PacketListenerManager.handle3D(self.FileObject) PacketListenerManager.handle3D(self.FileObject)
elif(response == "\x3E"):
PacketListenerManager.handle3E(self.FileObject)
elif(response == "\x46"): elif(response == "\x46"):
PacketListenerManager.handle46(self.FileObject) PacketListenerManager.handle46(self.FileObject)
elif(response == "\x47"): elif(response == "\x47"):
@ -300,7 +306,7 @@ class PacketListener(threading.Thread):
elif(response == "\x67"): elif(response == "\x67"):
PacketListenerManager.handle67(self.FileObject) PacketListenerManager.handle67(self.FileObject)
elif(response == "\x68"): elif(response == "\x68"):
PacketListenerManager.handle68(self.FileObject) print PacketListenerManager.handle68(self.FileObject)
elif(response == "\x69"): elif(response == "\x69"):
PacketListenerManager.handle69(self.FileObject) PacketListenerManager.handle69(self.FileObject)
elif(response == "\x6A"): elif(response == "\x6A"):
@ -316,9 +322,11 @@ class PacketListener(threading.Thread):
elif(response == "\xC8"): elif(response == "\xC8"):
PacketListenerManager.handleC8(self.FileObject) PacketListenerManager.handleC8(self.FileObject)
elif(response == "\xC9"): elif(response == "\xC9"):
PacketListenerManager.handleC9(self.FileObject) print PacketListenerManager.handleC9(self.FileObject)
elif(response == "\xCA"): elif(response == "\xCA"):
PacketListenerManager.handleCA(self.FileObject) PacketListenerManager.handleCA(self.FileObject)
elif(response == "\xCB"):
PacketListenerManager.handleCB(self.FileObject)
elif(response == "\xFA"): elif(response == "\xFA"):
PacketListenerManager.handleFA(self.FileObject) PacketListenerManager.handleFA(self.FileObject)
elif(response == "\xFC"): elif(response == "\xFC"):

View File

@ -9,8 +9,8 @@ def handle01(FileObject):
Eid = struct.unpack('!i', FileObject.read(4))[0] Eid = struct.unpack('!i', FileObject.read(4))[0]
length = struct.unpack('!h', FileObject.read(2))[0] * 2 length = struct.unpack('!h', FileObject.read(2))[0] * 2
world = FileObject.read(length).decode('utf-16be') world = FileObject.read(length).decode('utf-16be')
mode = struct.unpack('!i', FileObject.read(4))[0] mode = struct.unpack('!b', FileObject.read(1))[0]
dimension = struct.unpack('!i', FileObject.read(4))[0] dimension = struct.unpack('!b', FileObject.read(1))[0]
difficulty = struct.unpack('!b', FileObject.read(1))[0] difficulty = struct.unpack('!b', FileObject.read(1))[0]
FileObject.read(1) FileObject.read(1)
maxplayers = struct.unpack('!B', FileObject.read(1))[0] maxplayers = struct.unpack('!B', FileObject.read(1))[0]
@ -29,6 +29,12 @@ def handle02(FileObject):
message = message.decode('utf-16be', 'strict') message = message.decode('utf-16be', 'strict')
return message return message
def handle03(FileObject):
length = struct.unpack('!h', FileObject.read(2))[0] * 2
message = FileObject.read(length)
message = message.decode('utf-16be','strict')
return message
def handle04(FileObject): def handle04(FileObject):
time = struct.unpack('!q', FileObject.read(8))[0] time = struct.unpack('!q', FileObject.read(8))[0]
return time return time
@ -140,7 +146,6 @@ def handle14(FileObject):
'curItem' : curItem, 'curItem' : curItem,
'Metadata' : metadata 'Metadata' : metadata
} }
print toReturn
return toReturn return toReturn
def handle15(FileObject): def handle15(FileObject):
@ -211,6 +216,9 @@ def handle18(FileObject):
Yaw = struct.unpack('!b', FileObject.read(1))[0] Yaw = struct.unpack('!b', FileObject.read(1))[0]
Pitch = struct.unpack('!b', FileObject.read(1))[0] Pitch = struct.unpack('!b', FileObject.read(1))[0]
HeadYaw = struct.unpack('!b', FileObject.read(1))[0] HeadYaw = struct.unpack('!b', FileObject.read(1))[0]
VelocityX = struct.unpack('!h', FileObject.read(2))[0]
VelocityY = struct.unpack('!h', FileObject.read(2))[0]
VelocityZ = struct.unpack('!h', FileObject.read(2))[0]
metadata = readEntityMetadata(FileObject) metadata = readEntityMetadata(FileObject)
return {'EntityID' : EntityID, return {'EntityID' : EntityID,
@ -221,7 +229,10 @@ def handle18(FileObject):
'Yaw' : Yaw, 'Yaw' : Yaw,
'Pitch' : Pitch, 'Pitch' : Pitch,
'HeadYaw' : HeadYaw, 'HeadYaw' : HeadYaw,
'Metadata' : metadata 'Metadata' : metadata,
'VelocityX' : VelocityX,
'VelocityY' : VelocityY,
'VelocityZ' : VelocityZ
} }
def handle19(FileObject): def handle19(FileObject):
@ -266,8 +277,11 @@ def handle1C(FileObject):
} }
def handle1D(FileObject): def handle1D(FileObject):
EntityID = struct.unpack('!i', FileObject.read(4))[0] EntityArrayLength = struct.unpack('!b', FileObject.read(1))[0]
return EntityID Entities = []
for i in range(EntityArrayLength):
Entities.append(struct.unpack('!i', FileObject.read(4))[0])
return Entities
def handle1E(FileObject): def handle1E(FileObject):
EntityID = struct.unpack('!i', FileObject.read(4))[0] EntityID = struct.unpack('!i', FileObject.read(4))[0]
@ -377,16 +391,6 @@ def handle2B(FileObject):
'Level' : Level, 'Level' : Level,
'TotalExp' : TotalExp 'TotalExp' : TotalExp
} }
def handle32(FileObject):
X = struct.unpack('!i', FileObject.read(4))[0]
raw = FileObject.read(4)
Z = struct.unpack('!i', raw)[0]
Mode = struct.unpack('?', FileObject.read(1))[0]
return {'x' : X,
'z' : Z,
'Mode' : Mode
}
def handle33(FileObject): def handle33(FileObject):
X = struct.unpack('!i', FileObject.read(4))[0] X = struct.unpack('!i', FileObject.read(4))[0]
@ -395,7 +399,6 @@ def handle33(FileObject):
PrimaryBitMap = struct.unpack('!H', FileObject.read(2))[0] PrimaryBitMap = struct.unpack('!H', FileObject.read(2))[0]
AddBitMap = struct.unpack('!H', FileObject.read(2))[0] AddBitMap = struct.unpack('!H', FileObject.read(2))[0]
CompressedSize = struct.unpack('!i', FileObject.read(4))[0] CompressedSize = struct.unpack('!i', FileObject.read(4))[0]
FileObject.read(4) #unused int
FileObject.read(CompressedSize) #not going to be deflating and using this data until I know how to :3 FileObject.read(CompressedSize) #not going to be deflating and using this data until I know how to :3
return {'x' : X, return {'x' : X,
'z' : Z 'z' : Z
@ -416,7 +419,7 @@ def handle35(FileObject):
X = struct.unpack('!i', FileObject.read(4))[0] X = struct.unpack('!i', FileObject.read(4))[0]
Y = struct.unpack('!b', FileObject.read(1))[0] Y = struct.unpack('!b', FileObject.read(1))[0]
Z = struct.unpack('!i', FileObject.read(4))[0] Z = struct.unpack('!i', FileObject.read(4))[0]
BlockType = struct.unpack('!b', FileObject.read(1))[0] BlockType = struct.unpack('!h', FileObject.read(2))[0]
BlockMetaData = struct.unpack('!b', FileObject.read(1))[0] BlockMetaData = struct.unpack('!b', FileObject.read(1))[0]
return {'x' : X, return {'x' : X,
'y' : Y, 'y' : Y,
@ -431,18 +434,57 @@ def handle36(FileObject):
Z = struct.unpack('!i', FileObject.read(4))[0] Z = struct.unpack('!i', FileObject.read(4))[0]
Byte1 = struct.unpack('!b', FileObject.read(1))[0] Byte1 = struct.unpack('!b', FileObject.read(1))[0]
Byte2 = struct.unpack('!b', FileObject.read(1))[0] Byte2 = struct.unpack('!b', FileObject.read(1))[0]
BlockID = struct.unpack('!h', FileObject.read(2))[0]
return {'x' : X, return {'x' : X,
'y' : Y, 'y' : Y,
'z' : Z, 'z' : Z,
'Byte1' : Byte1, 'Byte1' : Byte1,
'Byte2' : Byte2 'Byte2' : Byte2,
'BlockID' : BlockID
}
def handle37(FileObject):
#int - EntityID
EntityID = struct.unpack('!i', FileObject.read(4))[0]
#int - X cord
x = struct.unpack('!i', FileObject.read(4))[0]
#int - Y cord
y = struct.unpack('!i', FileObject.read(4))[0]
#int - Z cord
z = struct.unpack('!i', FileObject.read(4))[0]
#byte - Stage
DestroyedStage = struct.unpack('!b', FileObject.read(1))[0]
return {'EntityID' : EntityID,
'x' : x,
'y' : y,
'z' : z,
'DestroyedStage' : DestroyedStage
}
def handle38(FileObject):
#short - number of chunks
ChunkCount = struct.unpack('!h', FileObject.read(2))[0]
#int - chunk data length
ChunkDataLength = struct.unpack('!i', FileObject.read(4))[0]
FileObject.read(ChunkDataLength) #just gonna ignore this for now
#metadata - ignoring this
for i in range(ChunkCount):
FileObject.read(12)
return {'ChunkCount' : ChunkCount
} }
def handle3C(FileObject): def handle3C(FileObject):
X = struct.unpack('!d', FileObject.read(8))[0] X = struct.unpack('!d', FileObject.read(8))[0]
Y = struct.unpack('!d', FileObject.read(8))[0] Y = struct.unpack('!d', FileObject.read(8))[0]
Z = struct.unpack('!d', FileObject.read(8))[0] Z = struct.unpack('!d', FileObject.read(8))[0]
FileObject.read(4) #Unknown what this float does Radius = struct.unpack('!f', FileObject.read(4))[0]
RecordCount = struct.unpack('!i', FileObject.read(4))[0] RecordCount = struct.unpack('!i', FileObject.read(4))[0]
AffectedBlocks = [] AffectedBlocks = []
for i in range((RecordCount * 3)): for i in range((RecordCount * 3)):
@ -450,9 +492,15 @@ def handle3C(FileObject):
y = struct.unpack('!b', FileObject.read(1))[0] y = struct.unpack('!b', FileObject.read(1))[0]
z = struct.unpack('!b', FileObject.read(1))[0] z = struct.unpack('!b', FileObject.read(1))[0]
AffectedBlocks.append({'x' : x, 'y' : y, 'z' : z}) AffectedBlocks.append({'x' : x, 'y' : y, 'z' : z})
return {'X' : X, #---Unknown what these floats do
'Y' : Y, FileObject.read(4)
'Z' : Z, FileObject.read(4)
FileObject.read(4)
#---
return {'x' : X,
'y' : Y,
'z' : Z,
'Raidus' : Radius,
'AffectedBlocks' : AffectedBlocks 'AffectedBlocks' : AffectedBlocks
} }
@ -469,6 +517,22 @@ def handle3D(FileObject):
'Data' : Data 'Data' : Data
} }
def handle3E(FileObject):
length = struct.unpack('!h', FileObject.read(2))[0] * 2
Sound = FileObject.read(length).decode('utf-16be')
x = struct.unpack('!i', FileObject.read(4))[0]
y = struct.unpack('!i', FileObject.read(4))[0]
z = struct.unpack('!i', FileObject.read(4))[0]
Volume = struct.unpack('!f', FileObject.read(4))[0]
Pitch = struct.unpack('!b', FileObject.read(1))[0]
return {'Sound' : Sound,
'x' : x,
'y' : y,
'z' : z,
'Volume' : Volume,
'Pitch' : Pitch
}
def handle46(FileObject): def handle46(FileObject):
Reason = struct.unpack('!b', FileObject.read(1))[0] Reason = struct.unpack('!b', FileObject.read(1))[0]
GameMode = struct.unpack('!b', FileObject.read(1))[0] GameMode = struct.unpack('!b', FileObject.read(1))[0]
@ -519,7 +583,6 @@ def handle68(FileObject):
Slots = [] Slots = []
for i in range(Count): for i in range(Count):
SlotData = decodeSlotData(FileObject) SlotData = decodeSlotData(FileObject)
SlotData["index"] = i
Slots.append(SlotData) Slots.append(SlotData)
return {'WindowID' : WindowID, return {'WindowID' : WindowID,
'Count' : Count, 'Count' : Count,
@ -555,7 +618,7 @@ def handle82(FileObject):
X = struct.unpack('!i', FileObject.read(4))[0] X = struct.unpack('!i', FileObject.read(4))[0]
Y = struct.unpack('!h', FileObject.read(2))[0] Y = struct.unpack('!h', FileObject.read(2))[0]
Z = struct.unpack('!i', FileObject.read(4))[0] Z = struct.unpack('!i', FileObject.read(4))[0]
length = struct.unpack('!i', FileObject.read(2))[0] * 2 length = struct.unpack('!h', FileObject.read(2))[0] * 2
Line1 = FileObject.read(length).decode("utf-16be") Line1 = FileObject.read(length).decode("utf-16be")
length = struct.unpack('!h', FileObject.read(2))[0] * 2 length = struct.unpack('!h', FileObject.read(2))[0] * 2
Line2 = FileObject.read(length).decode("utf-16be") Line2 = FileObject.read(length).decode("utf-16be")
@ -587,16 +650,19 @@ def handle84(FileObject):
Y = struct.unpack('!h', FileObject.read(2))[0] Y = struct.unpack('!h', FileObject.read(2))[0]
Z = struct.unpack('!i', FileObject.read(4))[0] Z = struct.unpack('!i', FileObject.read(4))[0]
Action = struct.unpack('!b', FileObject.read(1))[0] Action = struct.unpack('!b', FileObject.read(1))[0]
Custom1 = struct.unpack('!i', FileObject.read(4))[0] DataLength = struct.unpack('!h', FileObject.read(2))[0]
Custom2 = struct.unpack('!i', FileObject.read(4))[0] if (DataLength != -1):
Custom3 = struct.unpack('!i', FileObject.read(4))[0] NBTData = struct.unpack(str(DataLength) + "s", FileObject.read(DataLength))[0]
return {'x' : X,
'y' : Y,
'z' : Z,
'Action' : Action,
'NBTData' : NBTData
}
return {'x' : X, return {'x' : X,
'y' : Y, 'y' : Y,
'z' : Z, 'z' : Z,
'Action' : Action, 'Action' : Action
'Custom1' : Custom1,
'Custom2' : Custom2,
'Custom3': Custom3
} }
def handleC8(FileObject): def handleC8(FileObject):
@ -617,16 +683,24 @@ def handleC9(FileObject):
} }
def handleCA(FileObject): def handleCA(FileObject):
Invulnerable = struct.unpack('?', FileObject.read(1))[0] #byte - flags
IsFlying = struct.unpack('?', FileObject.read(1))[0] Flags = struct.unpack('!b', FileObject.read(1))[0]
CanFly = struct.unpack('?', FileObject.read(1))[0]
InstantDestroy = struct.unpack('?', FileObject.read(1))[0] #byte - fly speed
return {'Invulnerable' : Invulnerable, FlySpeed = struct.unpack('!b', FileObject.read(1))[0]
'IsFlying' : IsFlying,
'CanFly' : CanFly, #byte - walk speed
'InstantDestroy' : InstantDestroy WalkSpeed = struct.unpack('!b', FileObject.read(1))[0]
return {'Flags' : Flags,
'Fly Speed' : FlySpeed,
'Walk Speed' : WalkSpeed
} }
def handleCB(FileObject):
length = struct.unpack('!h', FileObject.read(2))[0] * 2
text = FileObject.read(length).decode("utf-16be")
return {'Text' : text}
def handleFA(FileObject): def handleFA(FileObject):
length = struct.unpack('!h', FileObject.read(2))[0] * 2 length = struct.unpack('!h', FileObject.read(2))[0] * 2
Channel = FileObject.read(length).decode("utf-16be") Channel = FileObject.read(length).decode("utf-16be")
@ -716,22 +790,21 @@ def decodeSlotData(FileObject):
BlockID = struct.unpack('!h', FileObject.read(2))[0] BlockID = struct.unpack('!h', FileObject.read(2))[0]
if(BlockID != -1): if(BlockID != -1):
ItemCount = struct.unpack('!b', FileObject.read(1))[0] ItemCount = struct.unpack('!b', FileObject.read(1))[0]
MetaData = struct.unpack('!h', FileObject.read(2))[0] Damage = struct.unpack('!h', FileObject.read(2))[0]
if((256 <= BlockID and BlockID <= 259) or (267 <= BlockID and BlockID <= 279) or (283 <= BlockID and BlockID <= 286) or (290 <= BlockID and BlockID <= 294) or (298 <= BlockID and BlockID <= 317) or BlockID == 261 or BlockID == 359 or BlockID == 346): MetadataLength = struct.unpack('!h', FileObject.read(2))[0]
IncomingDataLength = struct.unpack('!h', FileObject.read(2))[0] if(MetadataLength != -1):
if(IncomingDataLength != -1): raw = FileObject.read(MetadataLength)
raw = FileObject.read(IncomingDataLength) ByteArray = struct.unpack(str(MetadataLength) + "s", raw)[0]
ByteArray = struct.unpack(str(IncomingDataLength) + "s", raw)[0] Data = zlib.decompress(ByteArray, 15+32)
Data = zlib.decompress(ByteArray, 15+32) return {'BlockID' : BlockID,
return {'BlockID' : BlockID, 'ItemCount' : ItemCount,
'ItemCount' : ItemCount, 'Damage' : Damage,
'MetaData' : MetaData, 'Data' : Data
'Data' : Data }
}
return {'BlockID' : BlockID, return {'BlockID' : BlockID,
'ItemCount' : ItemCount, 'ItemCount' : ItemCount,
'MetaData' : MetaData 'Damage' : Damage
} }
return {'BlockID' : -1, return {'BlockID' : -1,
'ItemCount' : -1 'ItemCount' : 0
} }