Je ne sais pas ce que ça vaut, mais voici un de mes codes (dégueulasse) :
Cliquez pour révéler
Cliquez pour masquer
from API.data.const import *
from API.data.data import *
class MapLoader():
def __init__(self, fichier='/Applications/Dofus.app/Contents/Data/Dofus.app/Contents/Resources/content/maps/maps0.d2p'):
self.indexes = dict()
self.properties = dict()
self.initStream(fichier)
def load(self, mapId):
index = self.indexes[str(mapId%10)+'/'+str(mapId)+'.dlm']
fs = index['stream']
fs.pos = index['o']
data = Data(fs.readBytes(index['l']))
map = Map()
map.fromRaw(data)
return map
def initStream(self, chemin):
file = chemin
while file:
with open(file,'rb') as f:
fs=Data(f.read())
file = ""
fs.readUnsignedByte() # == 2
fs.readUnsignedByte() # == 1
fs.pos = len(fs)-24
dataOffset = fs.readUnsignedInt()
dataCount = fs.readUnsignedInt()
indexOffset = fs.readUnsignedInt()
indexCount = fs.readUnsignedInt()
propertiesOffset = fs.readUnsignedInt()
propertiesCount = fs.readUnsignedInt()
#print(chemin,dataOffset,dataCount,indexOffset,indexCount,propertiesOffset,propertiesCount,len(fs)-24,len(fs))
fs.pos = propertiesOffset
for i in range(propertiesCount):
propertyName = fs.readUTF()
propertyValue = fs.readUTF()
self.properties[propertyName] = propertyValue
if propertyName == "link":
index = chemin[::-1].find("/")
if index != -1:
chemin = chemin[0:-index-1]+"/"+propertyValue
else:
chemin = propertyValue
file = chemin
fs.pos = indexOffset
for i in range(indexCount):
filePath = fs.readUTF()
fileOffset = fs.readInt()
fileLength = fs.readInt()
self.indexes[filePath] = {"o":fileOffset + dataOffset, "l":fileLength, "stream":fs}
def getMapIdFromCoord(worldId,x,y):
worldIdMax = 2 << 12
mapCoordMax = 2 << 8
if((x > mapCoordMax) or (y > mapCoordMax) or (worldId > worldIdMax)):
return -1
newWorldId = worldId & 4095
newX = abs(x) & 255
if(x < 0):
newX = newX | 256
newY = abs(y) & 255
if(y < 0):
newY = newY | 256
return newWorldId << 18 | newX << 9 | newY
# def getMapUriFromId(mapId):
# return '/Applications/Dofus.app/Contents/Data/Dofus.app/Contents/Resources/content/maps/maps'+str(mapId%10)+'/'+str(mapId)+'.dlm'
class WorldPoint():
WORLD_ID_MAX = 2 << 12
MAP_COORDS_MAX = 2 << 8
def __init__(self):
pass
def fromMapId(mapId):
wp = WorldPoint()
wp._mapId = mapId
wp.setFromMapId()
return wp
def fromCoords(worldId, x, y):
wp = WorldPoint()
wp._worldId = worldId
wp._x = x
wp._y = y
wp.setFromCoords()
return wp
def setFromMapId():
self._worldId = (self._mapId & 1073479680) >> 18
self._x = self._mapId >> 9 & 511
self._y = self._mapId & 511
if((self._x & 256) == 256):
self._x = -(self._x & 255)
if((self._y & 256) == 256):
self._y = -(self._y & 255)
def setFromCoords():
if (self._x > MAP_COORDS_MAX) or (self._y > MAP_COORDS_MAX) or (self._worldId > WORLD_ID_MAX):
raise Exception("Coordinates or world identifier out of range.")
else:
worldValue = self._worldId & 4095
xValue = Math.abs(self._x) & 255
if(self._x < 0):
xValue = xValue | 256
yValue = Math.abs(self._y) & 255
if(self._y < 0):
yValue = yValue | 256
self._mapId = worldValue << 18 | xValue << 9 | yValue
# les raw sont des Data
class Map():
decryptionKey=bytes.fromhex("649ae451ca33ec53bbcbcc33becf15f4")
def __init__(self):
self.topArrowCell = []
self.leftArrowCell = []
self.bottomArrowCell = []
self.rightArrowCell = []
def fromRaw(self,raw):
_oldMvtSystem = 0
header = raw.readByte()
if header != 77:
raw.pos = 0
raw.uncompress()
header = raw.readByte()
if header != 77:
raise Exception('! erreur header ! '+str(header))
self.mapVersion = raw.readByte()
self.id = raw.readUnsignedInt()
if(self.mapVersion >= 7):
self.encrypted = raw.readBoolean()
self.encryptionVersion = raw.readByte()
dataLen = raw.readInt()
if(self.encrypted):
encryptedData = list(raw.readBytes(dataLen))
for i in range(len(encryptedData)):
encryptedData = encryptedData ^ self.decryptionKey[i % len(self.decryptionKey)]
raw = Data(bytes(encryptedData))
self.relativeId = raw.readUnsignedInt()
self.mapType = raw.readByte()
self.subareaId = raw.readInt()
self.topNeighbourId = raw.readInt()
self.bottomNeighbourId = raw.readInt()
self.leftNeighbourId = raw.readInt()
self.rightNeighbourId = raw.readInt()
self.shadowBonusOnEntities = raw.readInt()
if(self.mapVersion >= 3):
self.backgroundRed = raw.readByte()
self.backgroundGreen = raw.readByte()
self.backgroundBlue = raw.readByte()
self.backgroundColor = (self.backgroundRed & 255) << 16 | (self.backgroundGreen & 255) << 8 | self.backgroundBlue & 255
if(self.mapVersion >= 4):
self.zoomScale = raw.readUnsignedShort() / 100
self.zoomOffsetX = raw.readShort()
self.zoomOffsetY = raw.readShort()
if(self.zoomScale < 1):
self.zoomScale = 1
self.zoomOffsetX = self.zoomOffsetY = 0
self.useLowPassFilter = raw.readByte() == 1
self.useReverb = raw.readByte() == 1
if(self.useReverb):
self.presetId = raw.readInt()
else:
self.presetId = -1
self.backgroundsCount = raw.readByte()
self.backgroundFixtures = list()
for i in range(self.backgroundsCount):
bg = Fixture()
bg.fromRaw(raw)
self.backgroundFixtures.append(bg)
self.foregroundsCount = raw.readByte()
self.backgroundFixtures = list()
for i in range(self.backgroundsCount):
fg = Fixture()
fg.fromRaw(raw)
self.backgroundFixtures.append(fg)
self.cellsCount = AtouinConstants.MAP_CELLS_COUNT
raw.readInt()
self.groundCRC = raw.readInt()
self.layersCount = raw.readByte()
self.layers = list()
for i in range(self.layersCount):
la = Layer()
la.fromRaw(raw,self.mapVersion)
self.layers.append(la)
self.cells = list()
for i in range(self.cellsCount):
cd = CellData(self, i)
cd.fromRaw(raw)
if not _oldMvtSystem:
_oldMvtSystem = cd.moveZone
if(cd.moveZone != _oldMvtSystem):
self.isUsingNewMovementSystem = True
self.cells.append(cd)
self._parsed = True
class Fixture():
def __init__(self, map):
pass
def fromRaw(self, raw):
self.fixtureId = raw.readInt()
self.offset = Point()
self.offset.x = raw.readShort()
self.offset.y = raw.readShort()
self.rotation = raw.readShort()
self.xScale = raw.readShort()
self.yScale = raw.readShort()
self.redMultiplier = raw.readByte()
self.greenMultiplier = raw.readByte()
self.blueMultiplier = raw.readByte()
self.hue = self.redMultiplier | self.greenMultiplier | self.blueMultiplier
self.alpha = raw.readUnsignedByte()
class Point():
def __init__(self,x=0,y=0):
self.x = x
self.y = y
class Layer():
def __init__(self):
pass
def fromRaw(self, raw):
self.layerId = raw.readInt()
self.cellsCount = raw.readShort()
self.cells = list()
for i in range(self.cellsCount):
c = Cell()
c.fromRaw(raw,mapVersion)
self.cells.append(c)
class Cell():
def __init__(self):
pass
def fromRaw(self, raw, mapVersion):
self.cellId = raw.readShort()
self.elementsCount = raw.readShort()
self.elements = list()
for i in range(self.elementsCount):
be = BasicElement.getElementFromType(raw.readByte(),self)
be.fromRaw(raw,mapVersion)
self.elements.append(be)
class BasicElement():
def getElementFromType(type):
return {ElementTypesEnum.GRAPHICAL:GraphicalElement(), ElementTypesEnum.SOUND:SoundElement()}[type]
class GraphicalElement():
def fromRaw(self, raw, mapVersion):
self.elementId = raw.readUnsignedInt()
self.hue = ColorMultiplicator(raw.readByte(),raw.readByte(),raw.readByte())
self.shadow = ColorMultiplicator(raw.readByte(),raw.readByte(),raw.readByte())
self.offset = Point()
self.pixelOffset = Point()
if(mapVersion <= 4):
self.offset.x = raw.readByte()
self.offset.y = raw.readByte()
self.pixelOffset.x = self.offset.x * AtouinConstants.CELL_HALF_WIDTH
self.pixelOffset.y = self.offset.y * AtouinConstants.CELL_HALF_HEIGHT
else:
self.pixelOffset.x = raw.readShort()
self.pixelOffset.y = raw.readShort()
self.offset.x = self.pixelOffset.x / AtouinConstants.CELL_HALF_WIDTH
self.offset.y = self.pixelOffset.y / AtouinConstants.CELL_HALF_HEIGHT
self.altitude = raw.readByte()
self.identifier = raw.readUnsignedInt()
self.calculateFinalTeint()
def calculateFinalTeint(self):
r=self.hue.red + self.shadow.red
g=self.hue.green + self.shadow.green
b=self.hue.blue + self.shadow.blue
r = ColorMultiplicator.clamp((r + 128) * 2,0,512)
g = ColorMultiplicator.clamp((g + 128) * 2,0,512)
b = ColorMultiplicator.clamp((b + 128) * 2,0,512)
self.finalTeint = ColorMultiplicator(r,g,b,True)
class SoundElement():
def __init__(self):
pass
def fromRaw(self, raw, mapVersion):
self.soundId = raw.readInt()
self.baseVolume = raw.readShort()
self.fullVolumeDistance = raw.readInt()
self.nullVolumeDistance = raw.readInt()
self.minDelayBetweenLoops = raw.readShort()
self.maxDelayBetweenLoops = raw.readShort()
class ColorMultiplicator():
def __init__(self, redComponent,greenComponent,blueComponent,forceCalculation=False):
self.red = redComponent
self.green = greenComponent
self.blue = blueComponent
if((not forceCalculation) and (redComponent + greenComponent + blueComponent == 0)):
self._isOne = True
def clamp(value,mini,maxi):
if value>maxi:
return maxi
if value<mini:
return mini
return value
class CellData():
def __init__(self, map, cellId):
self.id = cellId
self._map = map
def fromRaw(self, raw):
self._floor = raw.readByte() * 10
self._losmov = raw.readUnsignedByte()
self.speed = raw.readByte()
self.mapChangeData = raw.readUnsignedByte()
if(self._map.mapVersion > 5):
self.moveZone = raw.readUnsignedByte()
if(self._map.mapVersion > 7):
tmpBits = raw.readByte()
self._arrow = 15 & tmpBits
if(self.useTopArrow()):
self._map.topArrowCell.append(self.id)
if(self.useBottomArrow()):
self._map.bottomArrowCell.append(self.id)
if(self.useLeftArrow()):
self._map.leftArrowCell.append(self.id)
if(self.useRightArrow()):
self._map.rightArrowCell.append(self.id)
def useTopArrow(self):
return not ((self._arrow & 1) == 0)
def useBottomArrow(self):
return not ((self._arrow & 2) == 0)
def useRightArrow(self):
return not ((self._arrow & 4) == 0)
def useLeftArrow(self):
return not ((self._arrow & 8) == 0)
Je ne suis pas sûr qu'il fonctionne à 100%, mais en tous cas, il ouvre les d2p.