Gaming, Hacking, Programming

Animating build progress on a Minecraft server

My Minecraft server is seeing some use again, and I decided to build a life size model of the Philadelphia Museum of Art. I also thought it would be cool to have an animated gif of the build progress as things go.

2014-10-15

Configuring Overviewer

We use Minecraft Overviewer to generate Google-maps style views of our world for the web. I created a config file limiting the render area to the coordinates around the building

worlds["Main"] = "/minecraft/Minecraft/world"

renders["normalrender"] = {
        "world": "Main",
        "title": "Overworld",
        "dimension": "overworld",
        "crop" : (200, -90, 420, 70),
}
outputdir="/minecraft/renders/museum"

Compositing the tiles
I found a script for making composites from google map data, originally written for use with Overviewer, but it was pretty far out of date and written for a different version of python than what I’ve got installed. I used it as a jumping off point for writing my own composite script.

#!/usr/bin/env python

import Image, ImageChops

import os, fnmatch
import os.path
import re

import sys

CHUNK_SIZE = 384

def trim(im):
    bg = Image.new(im.mode, im.size, im.getpixel((0,0)))
    diff = ImageChops.difference(im, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    if bbox:
        return im.crop(bbox)

def find_files(directory, pattern):
    regex = re.compile(pattern)
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if regex.match(basename):
                filename = os.path.join(root, basename)
                yield filename

def getAllFiles(srcdir):
  return find_files(srcdir,  "[0-9]+.png")

def getCoordinates(f):
  return map(lambda x: int(x), re.findall(r'[0-9-]+', f))

def getX(c):
  return {
    0: 0,
    1: 1,
    2: 0,
    3: 1,
  }[c]

def getY(c):
  return {
    0:0,
    1:0,
    2:1,
    3:1,
  }[c]

if len(sys.argv) != 4:
  print "Usage:", sys.argv[0], "<source directory (Dir)> <output file> <zoom level>"
  sys.exit(1)

sourceDirectory = sys.argv[1]
zoomLevel = int(sys.argv[3])
outputName = sys.argv[2]

width = (2**zoomLevel)  * CHUNK_SIZE
height = (2**zoomLevel)  * CHUNK_SIZE
print "Width:", width, "Height:", height

output = Image.new("RGBA", (width, height))

for f in getAllFiles(sourceDirectory):
  coords = getCoordinates(f)
  if len(coords) == zoomLevel:
    chunk = Image.open(os.path.join(sourceDirectory, f))
    #print chunk
    xbin = ""
    ybin = ""
    for c in coords:
      xbin = xbin + str(getX(c))
      ybin = ybin + str(getY(c))
    y = int(ybin,2)
    x = int(xbin,2)
    output.paste(chunk, (x*CHUNK_SIZE, y*CHUNK_SIZE))

print "Map merged, saving..."

output = trim(output)

if outputName[-3:] == "jpg" or outputName[-4:] == "jpeg":
  output.save(outputName, quality=100)
else:
  try:
    output.save(outputName, quality=85, progressive=True, optimize=True)
  except:
    print "Error saving with progressive=True and optimize=True, trying normally..."
    output.save(outputName, quality=85)

print "Done!"

This generates a daily snapshot and puts it in a web-accessible folder. I can then make a gif of all the images in that folder with ImageMagick’s convert utility
convert -delay 80 -loop 0 *jpg animated.gif

Checking for modifications
Originally I ran the script once daily on a cron, but later decided to run the world generator every half hour and only generate an image if there’s something new to see.

#!/bin/bash

rendersecs=$(expr `date +%s` - `stat -c %Y /minecraft/renders/museum/normalrender/3/`)
snapsecs=$(expr `date +%s` - `stat -c %Y /minecraft/renders/museum/last-snapshot`)
if [ "$rendersecs" -lt "$snapsecs" ]; then
  echo "Render was modified $rendersecs secs ago. Last snapshot $snapsecs secondds ago. Updating snapshot."
  /minecraft/renders/merge.py /minecraft/renders/museum /var/www/html/museum/$(date +\%Y-\%m-\%d-\%H\%M).jpg 3
  touch -m /minecraft/renders/museum/last-snapshot
  convert -delay 40 -loop 0 /var/www/html/museum/*jpg /var/www/html/museum/animated.gif
fi

Setting up cron tasks
I put two new jobs in my crontab file: one to generate the terrain and one to run my shell script. I give Overviewer a bit of a head start in case it has a lot of work to do.

*/30 *  * * *  overviewer.py --conifg=/minecraft/overviewer-museum.conf
10,40 *  * * *  /minecraft/update-museum.sh

2 thoughts on “Animating build progress on a Minecraft server”

  1. Stay Ahead of the Market with Our Crypto Signals

    Want to stay ahead in the crypto game Our crypto signals provide you with actionable insights for profitable trades No more uncertainty let us guide you through every market move with precision and accuracy

    Daily signals for top cryptocurrencies
    Trusted by traders worldwide
    Easy-to-use platform
    Join now and get your first signals for free
    [url=https://medium.com/@tavush87654/signal-crypto-team-ea44c89e6377]gignal crypto team[/url]

    [url=http://samorezi.com/vse_novosti/novosti_iz_mira_homyachkov/]Hellcatraz Slot Free Demo Game Review Aug 2024[/url] 20_5b87

  2. [url=https://thunderstruck.lol]thunderstruck[/url]

    Rugby is a highly popular sport in England, with the Six Nations Championship being a highlight of the annual sporting calendar. The England national rugby team is renowned for its strength and competitiveness, having won the Rugby World Cup in 2003. Fans admire the physicality and skill that define the sport.
    [url=http://gonaesea.com/bbs/board.php?bo_table=guest&wr_id=21137]pusatcuan c49e25_

Comments are closed.