Return to Snippet

Revision: 32312
at September 22, 2010 08:23 by ElStevo


Initial Code
from __future__ import division
from __future__ import print_function

import os
import subprocess
import urllib2
import time
import re
import tarfile
from PIL import Image


# Note: don't put trailing slashes on any filepaths or URLs

# Where all the files and maps are saved
MAP_DIRECTORY = "C:/Cartograph"

# The filepath to Cartograph
APP_PATH = "F:/Programs/Minecraft/Alpha/Cartograph"
APP_NAME = "Cartograph.exe"

# The arguments to pass to Cartograph. Check the Cartograph help for more info
APP_ARGUMENTS_1 = "normal 0 0 0 0"
APP_ARGUMENTS_2 = "obliqueangle 0 0 0 0 0"

# The map name(s)
MAP_NAME_1 = "top_down"
MAP_NAME_2 = "oblique_angled"

# Delete the archive after extracting?
DELETE_ARCHIVE = True

# Where the backups are downloaded from. Leave this as it is
BASEURL = "http://rps.fragwith.us/backups"


_CHUNK_SIZE = 1024 * 8
_MB = 1024 * 1024

def main():
    curTime = time.time()

    print("Finding most recent backup...")

    for i in range(-1, 5):
        date = _subtractDays(curTime, i)
        try:
            html = urllib2.urlopen(BASEURL + '/' + date + '/')
        except urllib2.HTTPError:
            continue

        archivename = re.findall('<a href="world\..*\.tar\.gz">',
          html.read())[-1].split('"')[1]
        print("Most recent backup is {0}.".format(archivename))
        datetimestring = archivename.split('.')[1]
        datetime = time.strptime(datetimestring, '%d-%m-%Y_%H%M%S')
        filepath = "{0}/{1}/".format(MAP_DIRECTORY,
          time.strftime('%Y-%m-%d_%H-%M-%S', datetime))
        if not os.path.exists(filepath):
            os.mkdir(filepath)

        print("Downloading {0} to {1}".format(archivename, filepath))
        startTime = time.time()
        download(BASEURL + '/' + date + '/' + archivename, filepath +
          archivename)
        print("Downloaded in {0}.".format(_timeTaken(startTime, time.time())))

        print("Extracting contents from archive...")
        startTime = time.time()
        extract(filepath, archivename)
        print("Extracted in {0}.".format(_timeTaken(startTime, time.time())))

        if DELETE_ARCHIVE:
            print("Deleting archive...")
            os.remove(filepath + archivename)
            print("Archive deleted.")

        map(filepath)

        break

def download(url, filepath):
    bytesSoFar = 0
    percent = -1
    partfile = filepath + '.part'
    opener = urllib2.build_opener()
    response = opener.open(url)

    totalSize = response.info().getheader("Content-Length")
    if totalSize is not None:
        totalSize = int(totalSize.strip())

    if not os.path.exists(filepath):
        fp = open(partfile, 'wb')

        chunk = True
        while chunk:
            chunk = response.read(_CHUNK_SIZE)
            bytesSoFar += len(chunk)
            fp.write(chunk)
            percent = _percentageDone(bytesSoFar, totalSize, percent)

        print("")
        fp.close()
        response.close()
        os.rename(partfile, filepath)
    else:
        print("{0} already exists".format(filepath))

def extract(filepath, filename):
    tar = tarfile.open(filepath + filename, 'r')
    tar.extractall(filepath)

def map(path):
    os.chdir(APP_PATH)

    inputPath = path + "world"
    print("Generating map 1...")
    outputPath = path + MAP_NAME_1 + ".png"
    startTime = time.time()
    app = subprocess.Popen('{0} 6 {1} "{2}" "{3}"'.format(APP_NAME,
      APP_ARGUMENTS_1, outputPath, inputPath))
    app.wait()
    print("Map generated in {0}.".format(_timeTaken(startTime, time.time())))
    print("Map 1 generated.")
    # Rotate the image so that north is actually north. Obviously this won't
    # work on oblique maps.
    print("Rotating...")
    _rotateImage(outputPath)
    print("Map 1 finished.")

    # Map 2 generation commented out because oblique mode crashes on my system
    # for very large maps. YMMV.

    # print("Generating map 2...")
    # outputPath = path + '/' + MAP_NAME_2 + ".png"
    # app = subprocess.Popen('{0} 6 {1} "{2}" "{3}"'.format(APP_NAME,
      # APP_ARGUMENTS_2, outputPath, inputPath))
    # app.wait()
    # print("Map 2 generated.")
    # print("Map 2 finished.")

def _rotateImage(file):
    im = Image.open(file)
    im = im.rotate(-90)
    im.save(file)

def _percentageDone(bytesSoFar, totalSize, curPercent):
    if totalSize == 0 or totalSize is None:
        return -1
    percent = (bytesSoFar / totalSize) * 100
    if int(percent) > int(curPercent):
        print("\n {0:3}% downloaded ({1:6.2f}MB of {2:6.2f}MB)".format(
          int(percent), bytesSoFar/_MB, totalSize/_MB), end='')
    if int(percent * 10) > int(curPercent * 10) and int(percent) < 100:
        print('.', end='')
    return percent

def _subtractDays(t, n):
    t -= (n * 86400)
    date = time.strftime("%d-%m-%Y", time.localtime(t))
    return date

def _timeTaken(start, finish):
    timeTaken = int(finish - start)

    numHours = timeTaken // 3600
    timeTaken %= 3600

    numMins = timeTaken // 60
    timeTaken %= 60

    numSecs = timeTaken

    ret = ""

    if numHours == 1:
        ret += "{0} hour, ".format(numHours)
    elif numHours > 1:
        ret += "{0} hours, ".format(numHours)

    if numMins == 1:
        ret += "{0} minute and ".format(numMins)
    elif numMins > 1 or numHours > 0:
        ret += "{0} minutes and ".format(numMins)

    if numSecs == 1:
        ret += "{0} second".format(numSecs)
    else:
        ret += "{0} seconds".format(numSecs)

    return ret

if __name__ == "__main__":
    main()

Initial URL


Initial Description
Downloads the latest backup of the Unofficial RPS Minecraft server and generates a map using Cartograph. You will need to modify MAP DIRECTORY and APP PATH to point to the relevant places on your machine.

Initial Title
Unofficial RPS Minecraft server automapper

Initial Tags


Initial Language
Python