summaryrefslogblamecommitdiff
path: root/hercules/code/clienttoserver/maps.py
blob: 0cdafb405ec4256fa68ae0e415fb6d9053b8bc97 (plain) (tree)
1
2
3
4
5
6
7
8
9
10





                                 
          


             
               




                            
              
                                   


                          






                                             







                                 












                                                 
                       

                                        


                    
                                    







                                                    
                         
                                                                


                                                                          
 
                         
                                                            
                                                                                






                                                                  





                                                                          









                                                                        



                                            
                                                                       
                                                                            
                                                  




                                                                               






                                                                               
                                                                                    






                                                                                     
 











                                                                        
                                 


                                                                     
 












                                                                      
                                
                         

                                                                                    


                                
# -*- coding: utf8 -*-
#
# Copyright (C) 2014  Evol Online
# Author: Andrei Karas (4144)

import array
import csv
import os
import zlib
import struct
import StringIO
from xml.dom import minidom

from code.fileutils import *

def getTmxFiles(srcDir):
    names = []
    for name in os.listdir(srcDir):
        names.append(name)
    names.sort()
    for name in names:
        fileName = srcDir + name
        if os.path.isfile(fileName) == False:
            continue
        if name.endswith(".tmx") == False:
            continue
        yield fileName

def findFirstGid(tilesets, tile):
    found = -1
    for t in tilesets:
        if t <= tile:
            found = t
            break
    return found

# 0 - walkable ground
# 1 - non walkable wall
# 2 - air allowed            shootable too
# 3 - water allowed          water, shootable too
# 4 - sit, walkable ground
# 5 - none
def convertTileType(tile):
#    if tile == 4:
#        tile = 0;
    if tile > 128 or tile < 0:
        tile = 1
    return tile

def recreateMapCache():
    destDir = "../../server-data/db/re/"
    srcDir = "../../client-data/maps/"
    makeDir(destDir)
    sz = 0L
    mapsCount = 0
    collisionLayerName = "collision"
    with open(destDir + "map_cache.dat", "wb") as w:
        writeInt32(w, 0)  # file size
        writeInt16(w, 0)  # maps count
        writeInt16(w, 0)  # padding
        sz = sz + 8
        for fileName in getTmxFiles(srcDir):
            dom = minidom.parse(fileName)
            root = dom.documentElement
            tilesets = []
            for tileset in root.getElementsByTagName("tileset"):
                tilesets.append(int(tileset.attributes["firstgid"].value))

            tilesets.sort(reverse = True)

            found = False
            for layer in root.getElementsByTagName("layer"):
                if layer.attributes["name"].value.lower() == collisionLayerName:
                    data = layer.getElementsByTagName("data")
                    if data is None or len(data) != 1:
                        continue
                    data = data[0]
                    width = int(layer.attributes["width"].value)
                    height = int(layer.attributes["height"].value)
                    encoding = data.attributes["encoding"].value
                    try:
                        compression = data.attributes["compression"].value
                    except:
                        compression = ""

                    tiles = []
                    if encoding == "base64":
                        binData = data.childNodes[0].data.strip()
                        binData = binData.decode('base64')
                        if compression == "gzip":
                            dc = zlib.decompressobj(16 + zlib.MAX_WBITS)
                        else:
                            dc = zlib.decompressobj()
                        layerData = dc.decompress(binData)
                        arr = array.array("I")
                        arr.fromstring(layerData)
                        for tile in arr:
                            if tile == 0:
                                tileType = 0
                            else:
                                firstgid = findFirstGid(tilesets, tile)
                                tileType = convertTileType(tile - firstgid);
                            tiles.append(tileType)
                    elif encoding == "csv":
                        binData = data.childNodes[0].data.strip()
                        f = StringIO.StringIO(binData)
                        arr = list(csv.reader(f, delimiter=',', quotechar='|'))
                        for row in arr:
                            for item in row:
                                if item != "":
                                    tile = int(item)
                                    if tile == 0:
                                        tileType = 0
                                    else:
                                        firstgid = findFirstGid(tilesets, tile)
                                        tileType = convertTileType(tile - firstgid);
                                    # tmx collision format
                                    # 0 - walkable ground
                                    # 1 - non walkable wall
                                    # 2 - air allowed            shootable too
                                    # 3 - water allowed          water, shootable too
                                    # 4 - sit, walkable ground
                                    # 5 - none

                                    # server collision format
                                    # 000 0 - walkable, shootable
                                    # 001 1 - wall
                                    # 010 2 - same with 0
                                    # 011 3 - walkable, shootable, water
                                    # 100 4 - same with 0
                                    # 101 5 - shootable
                                    # 110 6 - same with 0
                                    # 111 7 - none
                                    if tileType > 128 or tileType < 0:
                                        tileType = 1
                                    tiles.append(tileType)
                        f.close()
                    else:
                        print "map format not supported: " + fileName
                        continue

                    comp = zlib.compressobj()
                    binData = struct.pack(str(len(tiles))+"B", *tiles)
                    binData = zlib.compress(binData)
                    idx = fileName.rfind("/") + 1
                    mapName = fileName[idx:-4]
                    writeMapName(w, mapName)
                    writeInt16(w, width)
                    writeInt16(w, height)
                    writeInt32(w, len(binData))
                    writeData(w, binData)
                    print fileName
                    mapsCount = mapsCount + 1
                    sz = sz + 12 + 8 + len(binData)
                    found = True
                    break
            if found == False:
                print "Error: missing collision layer in file: {0}".format(fileName)
        w.seek(0);
        writeInt32(w, sz)
        writeInt16(w, mapsCount)