summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2013-12-14 10:24:48 -0800
committerBen Longbons <b.r.longbons@gmail.com>2013-12-14 10:24:48 -0800
commit78875e3c896656458d000c1987b1b0856fdb2bbe (patch)
tree9da2a6949fec98f2f48fc5f3f3799829a139be6c /client
parentbf2e24c6ed00e67466c1dbf967c23eef29aaf73e (diff)
parent709373a850e6c96aa03b56c8e0865a09db91b341 (diff)
downloadtools-78875e3c896656458d000c1987b1b0856fdb2bbe.tar.gz
tools-78875e3c896656458d000c1987b1b0856fdb2bbe.tar.bz2
tools-78875e3c896656458d000c1987b1b0856fdb2bbe.tar.xz
tools-78875e3c896656458d000c1987b1b0856fdb2bbe.zip
Merge remote-tracking branch 'origin/client'
Diffstat (limited to 'client')
-rwxr-xr-xclient/add-git-attributes2
-rw-r--r--client/adler32/.gitignore1
-rw-r--r--client/adler32/Makefile16
-rw-r--r--client/adler32/adler32.c68
-rwxr-xr-xclient/edit-all-to-export-tilesets.sh19
-rwxr-xr-xclient/edit-map-tileset-names.sh15
-rwxr-xr-xclient/formatXML.sh13
-rw-r--r--client/indent.xsl7
-rwxr-xr-xclient/list-tileset-order15
-rwxr-xr-xclient/make-updates125
-rwxr-xr-xclient/map-db.py59
-rwxr-xr-xclient/map-diff.py192
-rwxr-xr-xclient/minimap-render.py167
13 files changed, 699 insertions, 0 deletions
diff --git a/client/add-git-attributes b/client/add-git-attributes
new file mode 100755
index 0000000..80cc30c
--- /dev/null
+++ b/client/add-git-attributes
@@ -0,0 +1,2 @@
+#!/bin/sh
+git config diff.csv2tsv.textconv 'sed s/,/\\t/g'
diff --git a/client/adler32/.gitignore b/client/adler32/.gitignore
new file mode 100644
index 0000000..cfcde45
--- /dev/null
+++ b/client/adler32/.gitignore
@@ -0,0 +1 @@
+/adler32
diff --git a/client/adler32/Makefile b/client/adler32/Makefile
new file mode 100644
index 0000000..42f101a
--- /dev/null
+++ b/client/adler32/Makefile
@@ -0,0 +1,16 @@
+prefix=/usr/local
+bindir=${prefix}/bin
+
+LDLIBS=-lz
+
+all: adler32
+
+adler32: adler32.c
+
+clean:
+ rm -f adler32
+
+install:
+ install -D adler32 ${bindir}/
+
+.PHONY: clean install
diff --git a/client/adler32/adler32.c b/client/adler32/adler32.c
new file mode 100644
index 0000000..5dd7e4c
--- /dev/null
+++ b/client/adler32/adler32.c
@@ -0,0 +1,68 @@
+/*
+ * adler32.c (c) 2006 Bjorn Lindeijer
+ * License: GPL, v2 or later
+ *
+ * Calculates Adler-32 checksums for all files passed as argument.
+ *
+ * Usage: adler32 [file]...
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <zlib.h>
+
+/**
+ * Calculates the Adler-32 checksum for the given file.
+ */
+unsigned long fadler32(FILE *file)
+{
+ // Obtain file size
+ fseek(file, 0, SEEK_END);
+ long fileSize = ftell(file);
+ rewind(file);
+
+ // Calculate Adler-32 checksum
+ char *buffer = (char*) malloc(fileSize);
+ fread(buffer, 1, fileSize, file);
+ unsigned long adler = adler32(0L, Z_NULL, 0);
+ adler = adler32(adler, (Bytef*) buffer, fileSize);
+ free(buffer);
+
+ return adler;
+}
+
+/**
+ * Prints out usage and exists.
+ */
+void print_usage()
+{
+ printf("Usage: adler32 [file]...\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int i; /**< Loops through arguments. */
+
+ if (argc == 1)
+ {
+ print_usage();
+ }
+
+ for (i = 1; i < argc; ++i)
+ {
+ FILE *file = fopen(argv[i], "r");
+
+ if (!file)
+ {
+ printf("Error while opening '%s' for reading!\n", argv[i]);
+ exit(1);
+ }
+
+ unsigned long adler = fadler32(file);
+ printf("%s %lx\n", argv[i], adler);
+ fclose(file);
+ }
+
+ return 0;
+}
diff --git a/client/edit-all-to-export-tilesets.sh b/client/edit-all-to-export-tilesets.sh
new file mode 100755
index 0000000..7be3411
--- /dev/null
+++ b/client/edit-all-to-export-tilesets.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+for MAP in $(ls maps | grep '\.tmx$')
+do
+ TILESETS=$(
+ grep '<tileset' "maps/$MAP" |
+ while read TILESET
+ do
+ TILESET=${TILESET#*name=\"}
+ TILESET=${TILESET%%\"*}
+ echo tilesets/${TILESET}.tsx
+ done
+ )
+ rm -f ${TILESETS}
+ (cd tilesets; tiled ../maps/$MAP;)
+ git add -N tilesets/
+ git add --patch
+done
+
+
diff --git a/client/edit-map-tileset-names.sh b/client/edit-map-tileset-names.sh
new file mode 100755
index 0000000..6c359e2
--- /dev/null
+++ b/client/edit-map-tileset-names.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+for MAP in maps/*.tmx
+do
+ grep '<tileset\|<image' "$MAP" |
+ while read TILESET && read IMAGE
+ do
+ LINE=$TILESET
+ TILESET=${TILESET#*name=\"}
+ TILESET=${TILESET%%\"*}
+ IMAGE=${IMAGE#*source=\"}
+ IMAGE=${IMAGE%%.png\"*}
+ IMAGE=${IMAGE##*/}
+ sed "/$LINE/s/$TILESET/$IMAGE/" -i "$MAP"
+ done
+done
diff --git a/client/formatXML.sh b/client/formatXML.sh
new file mode 100755
index 0000000..c830f30
--- /dev/null
+++ b/client/formatXML.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+cd ..
+
+for f in $(find -name "*.xml")
+do
+ if [ ${f} != "./items.xml" ]; then
+ xsltproc tools/indent.xsl ${f} > ${f}__
+ mv ${f}__ ${f}
+ fi
+done
+xmlindent items.xml > items.xml_
+sed 's/[[:space:]]*$//' items.xml_ > items.xml
diff --git a/client/indent.xsl b/client/indent.xsl
new file mode 100644
index 0000000..7d747ab
--- /dev/null
+++ b/client/indent.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="xml" indent="yes"/>
+ <xsl:strip-space elements="*"/>
+ <xsl:template match="/">
+ <xsl:copy-of select="."/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/client/list-tileset-order b/client/list-tileset-order
new file mode 100755
index 0000000..b8d3f85
--- /dev/null
+++ b/client/list-tileset-order
@@ -0,0 +1,15 @@
+#!/bin/bash
+DIR=${1:-maps}
+for MAP in $(ls "$DIR" | grep '\.tmx$' )
+do
+ echo -n "${MAP%.tmx}:"
+ grep '<tileset' "$DIR/$MAP" |
+ while read TILESET
+ do
+ TILESET=${TILESET#*source=\"}
+ TILESET=${TILESET%%.tsx\"*}
+ TILESET=${TILESET##*/}
+ echo -n " $TILESET"
+ done
+ echo
+done
diff --git a/client/make-updates b/client/make-updates
new file mode 100755
index 0000000..aef0aaf
--- /dev/null
+++ b/client/make-updates
@@ -0,0 +1,125 @@
+#!/bin/bash -e
+# This is a tool to automatically generate and ship client updates.
+# It is entirely self-contained, storing its own state in the git repo.
+# It is called by running 'make updates' in server-data.
+# It also supports manually calls for maintenance work.
+# TODO: make auto-mode work with music too.
+
+# local branch to keep update info on
+# will be created on first run; updated thereafter
+branch=update-zips
+# must already exist
+# must NOT be a relative path
+output=~/www/updates
+
+function apply_function()
+{
+ $1 misc-xml charcreation.xml ea-skills.xml effects.xml emotes.xml hair.xml paths.xml settings.xml skills.xml status-effects.xml units.xml
+ $1 emotes graphics/emotes/
+ $1 images graphics/images/
+ $1 items graphics/items/
+ $1 minimaps graphics/minimaps/
+ $1 particles graphics/particles/
+ $1 skills graphics/skills/
+ $1 sprites graphics/sprites/
+ $1 tiles graphics/tiles/
+ $1 item-xml items.xml
+ $1 map-xml maps.xml
+ $1 maps maps/
+ $1 mob-xml monsters.xml
+ $1 npc-xml npcs.xml
+ $1 sfx sfx/
+ $1 tsx tilesets/
+}
+
+function add_resource()
+{
+ pushd $output >/dev/null
+ adler32 $1 | tee -a resources2.txt | {
+ read name hash
+ chmod a+r $name
+ sed '/<\/updates>/i <update type="data" file="'$name'" hash="'$hash'" />' -i resources.xml
+ }
+ popd >/dev/null
+}
+
+# TODO actually use this
+function add_music()
+{
+ adler32 $1 | {
+ read name hash
+ chmod a+r $name
+ sed '/<\/updates>/i <update type="music" required="no" file="'$name'" hash="'$hash'" />' -i resources.xml
+ }
+}
+
+function do_initial_zip()
+{
+ zip=$1-$this_update.zip; shift
+ git ls-files --with-tree=HEAD -- "$@" \
+ | zip -q $output/$zip -@
+ add_resource $zip
+}
+
+function git_diff_tree()
+{
+ git diff-tree -r --diff-filter=AM "$@"
+}
+
+function do_delta_zip()
+{
+ zip=$1-$last_update..$this_update.zip; shift
+ if git_diff_tree --quiet $last_update $this_update -- "$@"
+ then
+ return
+ fi
+ git_diff_tree --name-only $last_update $this_update -- "$@" \
+ | zip -q $output/$zip -@
+ add_resource $zip
+}
+
+function do_initial_zips()
+{
+ apply_function do_initial_zip
+}
+
+function do_delta_zips()
+{
+ apply_function do_delta_zip
+}
+
+function main()
+{
+ if ! test -d $output
+ then
+ echo 'Fatal error: output directory does not exist'
+ echo "$output"
+ return 1
+ fi
+
+ this_update=$(git rev-parse --short HEAD)
+ if ! last_update=$(git rev-parse --short $branch 2>/dev/null)
+ then
+ echo 'Doing initial updates'
+ do_initial_zips
+ elif test "$this_update" = "$last_update"
+ then
+ echo 'No commits since last update generation ...'
+ else
+ echo 'Doing incremental updates'
+ do_delta_zips
+ fi
+ git branch -f $branch
+}
+
+if test "$0" = "$BASH_SOURCE"
+then
+ echo 'Generating updates automatically'
+ main
+elif test "$0" = 'bash'
+then
+ echo 'sourcing detected - you can do manual updates'
+else
+ echo 'How did you get here?'
+ exit 3
+fi
diff --git a/client/map-db.py b/client/map-db.py
new file mode 100755
index 0000000..5215e72
--- /dev/null
+++ b/client/map-db.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+import sys
+import os
+import subprocess
+import tempfile
+import re
+
+CLIENT_DATA_ROOT = os.path.realpath(
+ os.path.join(
+ os.path.dirname(__file__),
+ u'..',
+ )
+)
+
+MAP_RE = re.compile(r'^(\d{3})-(\d{1})$')
+
+def list_missing_minimaps(maps, minimaps):
+ def minimap_wanted(m):
+ match = MAP_RE.match(m)
+ if match:
+ d = match.group(2)
+ # We ignore indoor maps
+ if not d == '2':
+ return True
+ return False
+
+ missing_minimaps = set([m for m in maps if minimap_wanted(m)]) - set(minimaps)
+ retcode = len(missing_minimaps)
+ print '\n'.join(sorted(missing_minimaps))
+ return retcode
+
+def usage():
+ sys.stderr.write(u'''Usage: %(prgm_name)s CMD
+
+ Where CMD is one of:
+ list-missing-minimaps, lm: Lists all maps which do not
+ have a minimap.
+
+ \n''' % {'prgm_name': sys.argv[0]})
+
+def main():
+ if not len(sys.argv) > 1:
+ usage()
+ return 127
+ action = sys.argv[1].lower()
+ maps = [os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'maps'))]
+ minimaps = [os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps'))]
+ status = 0
+ if action in ('list-missing-minimaps', 'lm'):
+ status = list_missing_minimaps(maps, minimaps)
+ else:
+ usage()
+ return 127
+ return status
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/client/map-diff.py b/client/map-diff.py
new file mode 100755
index 0000000..1da5cde
--- /dev/null
+++ b/client/map-diff.py
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+import sys
+import os
+import subprocess
+import re
+import tempfile
+
+class MapDiff(object):
+
+ @staticmethod
+ def check_programs():
+ """
+ Checks the require programs are available
+ """
+ def which(program):
+ import os
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+ return None
+
+ platform_programs = MapDiff.PROGRAMS.get(sys.platform, MapDiff.PROGRAMS.get('default'))
+ for program in platform_programs.values():
+ if not which(program):
+ raise Exception('The required "%s" program is missing from your PATH.' % program)
+
+ MAP_RE = re.compile(r'^\d{3}-\d{1}(\.tmx)?$')
+ PROGRAMS = {
+ 'default': {
+ 'tmxrasterizer': 'tmxrasterizer',
+ 'im_convert': 'convert',
+ 'im_display': 'display',
+ 'git': 'git',
+ },
+ 'win32': {
+ 'tmxrasterizer': 'tmxrasterizer.exe',
+ 'im_convert': 'convert.exe',
+ 'im_display': 'display.exe',
+ 'git': 'git.exe',
+ },
+ }
+
+ def __init__(self):
+ self.platform_programs = MapDiff.PROGRAMS.get(sys.platform, MapDiff.PROGRAMS.get('default'))
+
+ def _diffmaps(self, tmx1, tmx2, tmxdiffpath):
+ tmxraster1 = self._rastermap(tmx1)
+ tmxraster2 = self._rastermap(tmx2)
+ tmxf, tmxdiff = tempfile.mkstemp(suffix='.png')
+ subprocess.check_call([
+ self.platform_programs.get('im_convert'), tmxraster1, tmxraster2,
+ '-compose', 'Difference',
+ '-auto-level',
+ '-composite',
+ tmxraster2,
+ '-compose', 'Screen',
+ '-composite',
+ tmxdiffpath
+ ])
+ os.unlink(tmxdiff)
+ os.unlink(tmxraster1)
+ os.unlink(tmxraster2)
+ sys.stdout.write((u'Map diff written to %s\n' % tmxdiffpath).encode('utf-8'))
+ subprocess.check_call([self.platform_programs.get('im_display'), tmxdiffpath])
+
+ def _rastermap(self, tmx):
+ tmxf, tmxraster = tempfile.mkstemp(suffix='.png')
+ subprocess.check_call([
+ self.platform_programs.get('tmxrasterizer'),
+ '--scale', '1.0',
+ tmx, tmxraster
+ ])
+ if os.stat(tmxraster).st_size == 0:
+ raise Exception('A problem was encountered when rendering a map')
+ return tmxraster
+
+
+class MapGitRevDiff(MapDiff):
+
+ def __init__(self, map_name):
+ super(MapGitRevDiff, self).__init__()
+ self.map_name = map_name
+
+ def diff(self):
+ if not MapDiff.MAP_RE.match(self.map_name):
+ sys.stderr.write(u'Invalid map name: %s.\n' % self.map_name)
+ return 1
+ if not self.map_name.endswith(u'.tmx'):
+ self.map_name = self.map_name+u'.tmx'
+ self.tmx_path = os.path.join(u'..', u'maps', self.map_name)
+ self.map_number = os.path.splitext(os.path.basename(self.map_name))[0]
+ p = subprocess.Popen([self.platform_programs.get('git'), '--no-pager', 'log', '-n', '2', '--oneline', '--follow', self.tmx_path], stdout=subprocess.PIPE)
+ log = p.communicate()[0].splitlines()
+ if not len(log) == 2:
+ raise Exception('This map has only one version')
+ c1 = log[0].split(' ')[0]
+ c2 = log[1].split(' ')[0]
+
+ # We have the 2 revs to compare. Let's extract the related tmx file
+ p1 = self._mktmx_from_rev(c1)
+ p2 = self._mktmx_from_rev(c2)
+ try:
+ difftmxpath = '%s_%s-%s.png' % (self.map_number, c1, c2)
+ self._diffmaps(p1, p2, difftmxpath)
+ finally:
+ os.unlink(p1)
+ os.unlink(p2)
+
+ def _mktmx_from_rev(self, rev):
+ p = subprocess.Popen([self.platform_programs.get('git'), '--no-pager', 'show', '%s:%s' % (rev, self.tmx_path)], stdout=subprocess.PIPE)
+ contents = p.communicate()[0]
+ revtmx = '%s-%s.tmx' % (self.map_number, rev)
+ f = open(revtmx, 'w')
+ f.write(contents)
+ f.close()
+ return revtmx
+
+
+class MapFileDiff(MapDiff):
+
+ def __init__(self, map1, map2):
+ super(MapFileDiff, self).__init__()
+ self.map1 = map1
+ self.map2 = map2
+
+ def diff(self):
+ b1 = os.path.splitext(os.path.basename(self.map1))[0]
+ b2 = os.path.splitext(os.path.basename(self.map2))[0]
+ difftmxpath = '%s__%s.png' % (b1, b2)
+ self._diffmaps(self.map1, self.map2, difftmxpath)
+
+
+def usage():
+ sys.stderr.write(u'''Usage: %s MAP_NAME
+ %s CHANGED_TMX REFERENCE_TMX
+
+ Example:
+ $ ./map-diff.py 007-1
+ will highlight the changes between the current 007-1 map and its previous version
+
+ $ ./map-diff.py changes-made-by-someone-007-1.tmx ../maps-007-1.tmx
+ will highlight the changes between the two tmx maps.
+ Note that these 2 tmx to compare have to satisfy their dependancies, e.g tilesets.
+ Hence they should be in a sibling directory of the client-data/maps folder.
+ \n''' % (sys.argv[0], sys.argv[0]))
+
+def main():
+ if not len(sys.argv) > 1:
+ usage()
+ return 127
+ if not os.path.basename(os.path.dirname(os.getcwdu())) == u'client-data':
+ sys.stderr.write(u'This script must be run from client-data/tools.\n')
+ return 1
+ try:
+ MapDiff.check_programs()
+ except Exception as e:
+ sys.stderr.write(u'%s\n' % e)
+ return 126
+ if len(sys.argv) == 2:
+ map_name = sys.argv[1]
+ mapdiff = MapGitRevDiff(map_name)
+ try:
+ mapdiff.diff()
+ except Exception as e:
+ sys.stderr.write(u'\x1b[31m\x1b[1mError while generating the diff for map %s: %s\x1b[0m\n' % (map_name, e))
+ return 1
+ else:
+ return 0
+ else:
+ map1 = sys.argv[1]
+ map2 = sys.argv[2]
+ mapdiff = MapFileDiff(map1, map2)
+ try:
+ mapdiff.diff()
+ except Exception as e:
+ sys.stderr.write(u'\x1b[31m\x1b[1mError while generating the diff for %s and %s: %s\x1b[0m\n' % (map1, map2, e))
+ return 1
+ else:
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/client/minimap-render.py b/client/minimap-render.py
new file mode 100755
index 0000000..c9cb4a1
--- /dev/null
+++ b/client/minimap-render.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+import sys
+import os
+import subprocess
+import tempfile
+import re
+
+CLIENT_DATA_ROOT = os.path.realpath(
+ os.path.join(
+ os.path.dirname(__file__),
+ u'..',
+ )
+)
+
+class MinimapRenderer(object):
+
+ MAP_RE = re.compile(r'^\d{3}-\d{1}(\.tmx)?$')
+ PROGRAMS = {
+ 'default': {
+ 'tmxrasterizer': 'tmxrasterizer',
+ 'im_convert': 'convert',
+ },
+ 'win32': {
+ 'tmxrasterizer': 'tmxrasterizer.exe',
+ 'im_convert': 'convert.exe',
+ },
+ }
+
+ def __init__(self, map_name, tilesize, useAntiAliasing):
+ self.map_name = map_name
+ self.tilesize = tilesize
+ self.useAntiAliasing = useAntiAliasing
+
+ def render(self):
+ """
+ Processes a map
+ """
+ if not MinimapRenderer.MAP_RE.match(self.map_name):
+ sys.stderr.write(u'Invalid map name: %s. Skipping.\n' % self.map_name)
+ return 1
+ if not self.map_name.endswith(u'.tmx'):
+ self.map_name = self.map_name+u'.tmx'
+
+ map_number = os.path.splitext(os.path.basename(self.map_name))[0]
+ tmx_file = os.path.join(CLIENT_DATA_ROOT, u'maps', self.map_name)
+ minimap_file = os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps', map_number+u'.png')
+
+ prefix = os.path.commonprefix((tmx_file, minimap_file))
+ sys.stdout.write(u'%s -> %s\n' % (os.path.relpath(tmx_file, prefix), os.path.relpath(minimap_file, prefix)))
+
+ try:
+ self.do_render(tmx_file, minimap_file)
+ except Exception as e:
+ sys.stderr.write(u'\x1b[31m\x1b[1mError while rendering %s: %s\x1b[0m\n' % (self.map_name, e))
+ return 1
+ else:
+ return 0
+
+ def do_render(self, tmx_file, bitmap_file):
+ """
+ The map rendering implementation
+ """
+ platform_programs = MinimapRenderer.PROGRAMS.get(sys.platform, MinimapRenderer.PROGRAMS.get('default'))
+ # tmx rasterize
+ mrf, map_raster = tempfile.mkstemp(suffix='.png')
+ tmxrasterizer_cmd = [
+ platform_programs.get('tmxrasterizer'),
+ '--tilesize', str(self.tilesize),
+ ]
+ if self.useAntiAliasing:
+ tmxrasterizer_cmd.append('--anti-aliasing')
+ tmxrasterizer_cmd += [tmx_file, map_raster]
+ subprocess.check_call(tmxrasterizer_cmd)
+ if os.stat(map_raster).st_size == 0:
+ raise Exception('A problem was encountered when rendering a map')
+ # add cell-shading to the minimap to improve readability
+ ebf, edges_bitmap = tempfile.mkstemp(suffix='.png')
+ subprocess.check_call([
+ platform_programs.get('im_convert'), map_raster,
+ '-set', 'option:convolve:scale', '-1!',
+ '-morphology', 'Convolve', 'Laplacian:0',
+ '-colorspace', 'gray',
+ '-auto-level',
+ '-threshold', '2.8%',
+ '-negate',
+ '-transparent', 'white',
+ edges_bitmap
+ ])
+ subprocess.check_call([
+ platform_programs.get('im_convert'), map_raster, edges_bitmap,
+ '-compose', 'Dissolve',
+ '-define', 'compose:args=35',
+ '-composite',
+ bitmap_file
+ ])
+ os.unlink(map_raster)
+ os.unlink(edges_bitmap)
+
+ @staticmethod
+ def check_programs():
+ """
+ Checks the require programs are available
+ """
+ def which(program):
+ import os
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+ return None
+
+ platform_programs = MinimapRenderer.PROGRAMS.get(sys.platform, MinimapRenderer.PROGRAMS.get('default'))
+ for program in platform_programs.values():
+ if not which(program):
+ raise Exception('The required "%s" program is missing from your PATH.' % program)
+
+def usage():
+ sys.stderr.write(u'''Usage: %s MAP_NAME...
+
+ Example:
+ $ ./minimap-render.py 007-1
+ will render the map at maps/007-1.tmx in the graphics/minimaps directory.
+ $ ./minimap-render.py all
+ will render all existing maps found in the maps directory.
+ $ ./minimap-render.py update
+ will update all existing minimaps found in the graphics/minimaps directory.
+
+ For convenience,
+ $ ./minimap-render.py 007-1.tmx
+ is also accepted.
+ \n''' % sys.argv[0])
+
+def main():
+ if not len(sys.argv) > 1:
+ usage()
+ return 127
+ try:
+ MinimapRenderer.check_programs()
+ except Exception as e:
+ sys.stderr.write(u'%s\n' % e)
+ return 126
+
+ status = 0
+ if sys.argv[1].lower() == 'all':
+ map_names = sorted([os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'maps'))])
+ elif sys.argv[1].lower() == 'update':
+ map_names = sorted([os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps'))])
+ else:
+ map_names = sys.argv[1:]
+
+ for map_name in map_names:
+ # Render tiles at 1 pixel size
+ map_renderer = MinimapRenderer(map_name, 1, True)
+ status += map_renderer.render()
+ return status
+
+if __name__ == '__main__':
+ sys.exit(main())