import struct
class BinaryReaderEOFException(Exception):
def __init__(self):
pass
def __str__(self):
return 'Not enough bytes in file to satisfy read request'
class BR:
# Map well-known type names into struct format characters.
typeNames = {
'int8' :'b',
'uint8' :'B',
'int16' :'h',
'uint16' :'H',
'int32' :'i',
'uint32' :'I',
'int64' :'q',
'uint64' :'Q',
'float' :'f',
'double' :'d',
'char' :'s'}
def __init__(self, fileName):
self.file = open(fileName, 'rb')
def read(self, typeName):
typeFormat = BR.typeNames[typeName.lower()]
typeSize = struct.calcsize(typeFormat)
value = self.file.read(typeSize)
if typeSize != len(value):
raise BinaryReaderEOFException
return struct.unpack(typeFormat, value)[0]
def __del__(self):
self.file.close()
NAV_DIR = ["North", "East", "South", "West"]
LADDER_DIRS = ["Up", "Down"]
def read_nav_file(filename):
f = BR(filename)
magic = f.read('uint32')
version = f.read('uint32')
savebspsize = f.read('uint32')
placecount = f.read('uint16')
places = dict()
for placeindex in range(placecount):
placenamesize = f.read('uint16')
placenamechars = list()
for x in range(placenamesize):
placenamechars.append(f.read('char'))
placename = b''.join(placenamechars)
places[placeindex] = placename
areacount = f.read('uint32')
areas = dict()
for areaindex in range(areacount):
areas[areaindex] = dict()
areas[areaindex]["id"] = f.read('uint32')
areas[areaindex]["flags"] = f.read('uint16')
x1 = f.read('float')
y1 = f.read('float')
z1 = f.read('float')
x2 = f.read('float')
y2 = f.read('float')
z2 = f.read('float')
areas[areaindex]["box"] = ((x1, y1, z1), (x2, y2, z2))
NEcornerz = f.read('float')
SWcornerz = f.read('float')
areas[areaindex]["corner"] = dict()
areas[areaindex]["corner"]["NE"] = NEcornerz
areas[areaindex]["corner"]["SW"] = SWcornerz
areas[areaindex]["directions"] = dict()
for index, direction in enumerate(NAV_DIR):
connectioncount = f.read('uint32')
areas[areaindex]["directions"][direction] = {'connectioncount' : connectioncount}
areas[areaindex]["directions"][direction]["connections"] = dict()
for connectionindex in range(connectioncount):
connectingareaindex = f.read('uint32')
areas[areaindex]["directions"][direction]["connections"][connectionindex] = connectingareaindex
hidingspotcount = f.read("uint8")
areas[areaindex]["hidingspotcount"] = hidingspotcount
areas[areaindex]["hidingspots"] = dict()
for hidingspotindex in range(hidingspotcount):
hidingspotid = f.read('uint32')
areas[areaindex]["hidingspots"][hidingspotindex] = {"id" : hidingspotid}
x = f.read('float')
y = f.read('float')
z = f.read('float')
areas[areaindex]["hidingspots"][hidingspotindex]["point"] = (x, y, z)
hidingspotflags = f.read("uint8")
areas[areaindex]["hidingspots"][hidingspotindex]["flags"] = hidingspotflags
approachareacount = f.read("uint8")
areas[areaindex]["approachareacount"] = approachareacount
areas[areaindex]["approachareas"] = dict()
for approachareaindex in range(approachareacount):
approachHereID = f.read('uint32')
approachPrevID = f.read('uint32')
approachType = f.read("uint8")
approachNextID = f.read('uint32')
approachHow = f.read("uint8")
areas[areaindex]["approachareas"][approachareaindex] = {"id": approachHereID, "previd": approachPrevID, "type": approachType, "nextid": approachNextID, "how": approachHow}
encounterPathcount = f.read("uint32")
areas[areaindex]["encounterpathcount"] = encounterPathcount
areas[areaindex]["encounterpaths"] = dict()
for encounterPathindex in range(encounterPathcount):
encounterFromID = f.read('uint32')
encounterFromDirection = f.read("uint8")
encounterToID = f.read('uint32')
encounterToDirection = f.read("uint8")
areas[areaindex]["encounterpaths"][encounterPathindex] = {"fromid": encounterFromID, "toid": encounterToID, "fromdir": encounterFromDirection, "todir": encounterToDirection,}
encounterSpotcount = f.read("uint8")
areas[areaindex]["encounterpaths"][encounterPathindex]["encounterspotcount"] = encounterPathcount
areas[areaindex]["encounterpaths"][encounterPathindex]["encounterspots"] = dict()
for encounterSpotindex in range(encounterSpotcount):
encounterSpotOrderId = f.read('uint32')
encounterSpotT = f.read("uint8")
encounterSpotParametricDistance = encounterSpotT / 255.0
areas[areaindex]["encounterpaths"][encounterPathindex]["encounterspots"][encounterSpotindex] = {"orderid": encounterSpotOrderId, "T": encounterSpotT,"parametricdistance": encounterSpotParametricDistance}
placeID = f.read("uint16")
areas[areaindex]["placeid"] = placeID
for index, direction in enumerate(LADDER_DIRS):
ladderConnectionCount = f.read('uint32')
for ladderconnectionindex in range(ladderConnectionCount):
ladderConnectID = f.read('uint32')
earliestOccupyTimeFirstTeam = f.read('float')
earliestOccupyTimeSecondTeam = f.read('float')
areas[areaindex]["team1eop"] = earliestOccupyTimeFirstTeam
areas[areaindex]["team2eop"] = earliestOccupyTimeSecondTeam
laddercount = f.read('uint32')
return {"areas": areas,
"places": places,
"laddercount": laddercount,
"filename": filename,
"magic": magic,
"version": version,
"savebspsize": savebspsize,
"areacount": areacount,
"placecount": placecount
}
# And ladder stuff goes here