Browse code

Merge origin/master

Conflicts:
pom.xml

devnewton authored on 15/02/2014 12:48:55
Showing 13 changed files
... ...
@@ -1,3 +1,5 @@
1 1
 libtiled-jpurexml is a java library to parse [Tiled](http://www.mapeditor.org) tmx maps.
2 2
 
3
-It use [jpurexml](https://github.com/asilvestre/jpurexml), a pure java xml parser in order to be usable with [gwt](http://www.gwtproject.org/) compiler.
4 3
\ No newline at end of file
4
+It use [jpurexml](https://github.com/asilvestre/jpurexml), a pure java xml parser in order to be usable with [gwt](http://www.gwtproject.org/) compiler.
5
+
6
+Usage sample: [TestTmxLoader.java](src/test/java/im/bci/test/TestTmxLoader.java)
5 7
\ No newline at end of file
... ...
@@ -20,8 +20,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 20
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 21
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 22
 THE SOFTWARE. -->
23
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
24
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
23
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
25 24
     <modelVersion>4.0.0</modelVersion>
26 25
     <parent>
27 26
         <groupId>org.sonatype.oss</groupId>
... ...
@@ -30,7 +29,7 @@ THE SOFTWARE. -->
30 29
     </parent>
31 30
     <groupId>im.bci</groupId>
32 31
     <artifactId>libtiled-jpurexml</artifactId>
33
-    <version>0.2-SNAPSHOT</version>
32
+    <version>0.3-SNAPSHOT</version>
34 33
     <name>libtiled-jpurexml</name>
35 34
     <packaging>jar</packaging>
36 35
     <description>libtiled-jpurexml is a java library to parse [Tiled](http://www.mapeditor.org) tmx maps.</description>
... ...
@@ -39,7 +38,8 @@ THE SOFTWARE. -->
39 38
         <connection>scm:git:git@github.com:devnewton/libtiled-jpurexml.git</connection>
40 39
         <developerConnection>scm:git:git@github.com:devnewton/libtiled-jpurexml.git</developerConnection>
41 40
         <url>git@github.com:devnewton/libtiled-jpurexml.git</url>
42
-    </scm>
41
+      <tag>HEAD</tag>
42
+  </scm>
43 43
     <licenses>
44 44
         <license>
45 45
             <name>MIT</name>
... ...
@@ -63,6 +63,12 @@ THE SOFTWARE. -->
63 63
             <artifactId>jpurexml</artifactId>
64 64
             <version>0.10</version>
65 65
         </dependency>
66
+        <dependency>
67
+            <groupId>junit</groupId>
68
+            <artifactId>junit</artifactId>
69
+            <version>4.10</version>
70
+            <scope>test</scope>
71
+        </dependency>
66 72
     </dependencies>
67 73
     <build>
68 74
         <resources>
... ...
@@ -23,8 +23,6 @@
23 23
  */
24 24
 package im.bci.tmxloader;
25 25
 
26
-import java.util.Scanner;
27
-
28 26
 /**
29 27
  *
30 28
  * @author devnewton
... ...
@@ -51,24 +49,21 @@ public class TmxData {
51 49
     }
52 50
 
53 51
     public void decodeTo(int width, int height, int[][] data) {
54
-        switch (encoding) {
55
-            case "csv":
56
-                decodeCsvTo(width, height, data);
57
-                break;
58
-            default:
59
-                throw new RuntimeException(
60
-                        "Unsupported tiled layer data encoding: " + encoding);
52
+        if ("csv".equals(encoding)) {
53
+            decodeCsvTo(width, height, data);
54
+        } else {
55
+            throw new RuntimeException(
56
+                    "Unsupported tiled layer data encoding: " + encoding);
61 57
         }
62 58
     }
63 59
 
64 60
     private void decodeCsvTo(int width, int height, int[][] gidArray) {
65
-        try (Scanner scanner = new Scanner(this.data.trim())) {
66
-            scanner.useDelimiter("[\\s]*,[\\s]*");
67
-            for (int y = 0; y < height; ++y) {
68
-                for (int x = 0; x < width; ++x) {
69
-                    String str = scanner.next();
70
-                    gidArray[x][y] = Integer.parseInt(str);
71
-                }
61
+        String[] values = this.data.replaceAll("[\\s]", "").split(",");
62
+        int index = 0;
63
+        for (int y = 0; y < height; ++y) {
64
+            for (int x = 0; x < width; ++x) {
65
+                String str = values[index++];
66
+                gidArray[x][y] = Integer.parseInt(str);
72 67
             }
73 68
         }
74 69
     }
... ...
@@ -36,7 +36,7 @@ public class TmxLayer {
36 36
     private int x, y;
37 37
     private int width;
38 38
     private int height;
39
-    private List<TmxProperty> properties = new ArrayList<>();
39
+    private List<TmxProperty> properties = new ArrayList<TmxProperty>();
40 40
     private TmxData data;
41 41
     private TmxTileInstance tiles[][];
42 42
 
... ...
@@ -27,7 +27,6 @@ import com.github.asilvestre.jpurexml.XmlDoc;
27 27
 import com.github.asilvestre.jpurexml.XmlParseException;
28 28
 import com.github.asilvestre.jpurexml.XmlParser;
29 29
 import com.github.asilvestre.jpurexml.XmlTag;
30
-import java.io.IOException;
31 30
 import java.util.ArrayList;
32 31
 import java.util.EnumSet;
33 32
 import java.util.HashMap;
... ...
@@ -40,54 +39,28 @@ import java.util.ListIterator;
40 39
  */
41 40
 public class TmxLoader {
42 41
 
43
-    public TmxMap load(String xml) {
42
+    public void parseTmx(TmxMap map, String xml) {
44 43
         try {
45 44
             XmlDoc doc = XmlParser.parseXml(xml);
46
-            TmxMap map = new TmxMap();
47 45
             parseMap(doc.root, map);
48 46
             parseTilesets(doc.root, map);
49
-            parseExternalTilesets(map);
50
-            decodeLayerData(map);
51
-            return map;
52
-        } catch (XmlParseException | IOException ex) {
47
+        } catch (XmlParseException ex) {
53 48
             throw new RuntimeException("Cannot load tmx", ex);
54 49
         }
55 50
     }
56 51
 
57
-    private void parseMap(XmlTag xmlMap, TmxMap map) throws NumberFormatException {
58
-        map.setWidth(getMandatoryIntAttribute(xmlMap, "width"));
59
-        map.setHeight(getMandatoryIntAttribute(xmlMap, "height"));
60
-        map.setTilewidth(getMandatoryIntAttribute(xmlMap, "tilewidth"));
61
-        map.setTileheight(getMandatoryIntAttribute(xmlMap, "tileheight"));
62
-        map.setOrientation(TmxMapOrientation.valueOf(xmlMap.attributes.get("orientation").toUpperCase()));
63
-        map.setProperties(parseProperties(findChild(xmlMap, "properties")));
64
-        List<TmxLayer> layers = new ArrayList<>();
65
-        for (XmlTag child : xmlMap.children) {
66
-            if ("layer".equals(child.name)) {
67
-                TmxLayer layer = new TmxLayer();
68
-                parseLayer(child, layer);
69
-                layer.afterUnmarshal();
70
-                layers.add(layer);
71
-            }
72
-        }
73
-        map.setLayers(layers);
74
-    }
75
-
76
-    XmlTag findChild(XmlTag parent, String name) {
77
-        for (XmlTag child : parent.children) {
78
-            if (name.equals(child.name)) {
79
-                return child;
80
-            }
52
+    public void parseTsx(TmxMap map, TmxTileset tileset, String xml) {
53
+        try {
54
+            parseTileset(XmlParser.parseXml(xml).root, map, tileset);
55
+            tileset.afterUnmarshal();
56
+            tileset.setReady(true);
57
+        } catch (XmlParseException ex) {
58
+            throw new RuntimeException("Cannot load tmx", ex);
81 59
         }
82
-        return null;
83
-    }
84
-
85
-    protected String openExternalTileset(String source) {
86
-        throw new RuntimeException("Not implemented");
87 60
     }
88
-
89
-    private void decodeLayerData(TmxMap map) {
90
-        HashMap<TmxTileInstance, TmxTileInstance> tileInstancePool = new HashMap<>();
61
+    
62
+    public void decode(TmxMap map) {
63
+        HashMap<TmxTileInstance, TmxTileInstance> tileInstancePool = new HashMap<TmxTileInstance, TmxTileInstance>();
91 64
         for (TmxLayer layer : map.getLayers()) {
92 65
             int[][] data = new int[layer.getWidth()][layer.getHeight()];
93 66
             layer.getData().decodeTo(layer.getWidth(), layer.getHeight(), data);
... ...
@@ -114,31 +87,46 @@ public class TmxLoader {
114 87
                                     tileInstancePool.put(instance, instance);
115 88
                                 }
116 89
                                 layer.setTileAt(x, y, instance);
90
+                                break;
117 91
                             }
118 92
                         }
119 93
                     }
120 94
                 }
121 95
             }
122 96
         }
97
+        map.setReady(true);
123 98
     }
124 99
 
125
-    private void parseExternalTilesets(TmxMap map) throws IOException, XmlParseException {
126
-        for (TmxTileset tileset : map.getTilesets()) {
127
-            final String source = tileset.getSource();
128
-            if (null != source) {
129
-                parseTileset(XmlParser.parseXml(openExternalTileset(source)).root, map, tileset);
130
-                String tilesetDir = source.substring(0, source.lastIndexOf('/') + 1);
131
-                final TmxImage image = tileset.getImage();
132
-                if (null != image) {
133
-                    tileset.getImage().setSource(tilesetDir + image.getSource());
134
-                }
135
-                tileset.afterUnmarshal();
100
+    private void parseMap(XmlTag xmlMap, TmxMap map) throws NumberFormatException {
101
+        map.setWidth(getMandatoryIntAttribute(xmlMap, "width"));
102
+        map.setHeight(getMandatoryIntAttribute(xmlMap, "height"));
103
+        map.setTilewidth(getMandatoryIntAttribute(xmlMap, "tilewidth"));
104
+        map.setTileheight(getMandatoryIntAttribute(xmlMap, "tileheight"));
105
+        map.setOrientation(TmxMapOrientation.valueOf(xmlMap.attributes.get("orientation").toUpperCase()));
106
+        map.setProperties(parseProperties(findChild(xmlMap, "properties")));
107
+        List<TmxLayer> layers = new ArrayList<TmxLayer>();
108
+        for (XmlTag child : xmlMap.children) {
109
+            if ("layer".equals(child.name)) {
110
+                TmxLayer layer = new TmxLayer();
111
+                parseLayer(child, layer);
112
+                layer.afterUnmarshal();
113
+                layers.add(layer);
136 114
             }
137 115
         }
116
+        map.setLayers(layers);
117
+    }
118
+
119
+    private XmlTag findChild(XmlTag parent, String name) {
120
+        for (XmlTag child : parent.children) {
121
+            if (name.equals(child.name)) {
122
+                return child;
123
+            }
124
+        }
125
+        return null;
138 126
     }
139 127
 
140 128
     private List<TmxProperty> parseProperties(XmlTag xmlProperties) {
141
-        List<TmxProperty> properties = new ArrayList<>();
129
+        List<TmxProperty> properties = new ArrayList<TmxProperty>();
142 130
         if (null != xmlProperties) {
143 131
             for (XmlTag child : xmlProperties.children) {
144 132
                 if ("property".equals(child.name)) {
... ...
@@ -153,22 +141,22 @@ public class TmxLoader {
153 141
     }
154 142
 
155 143
     private void parseTilesets(XmlTag xmlMap, TmxMap map) throws XmlParseException {
156
-        List<TmxTileset> tilesets = new ArrayList<>();
144
+        List<TmxTileset> tilesets = new ArrayList<TmxTileset>();
157 145
         for (XmlTag child : xmlMap.children) {
158 146
             if ("tileset".equals(child.name)) {
159 147
                 TmxTileset tileset = new TmxTileset();
160 148
                 String source = child.attributes.get("source");
149
+                tileset.setFirstgid(getMandatoryIntAttribute(child, "firstgid"));
161 150
                 if (null != source) {
162
-                    tileset.setFirstgid(getMandatoryIntAttribute(child, "firstgid"));
163 151
                     tileset.setSource(source);
164 152
                 } else {
165 153
                     parseTileset(child, map, tileset);
166 154
                     tileset.afterUnmarshal();
155
+                    tileset.setReady(true);
167 156
                 }
168 157
                 tilesets.add(tileset);
169 158
             }
170 159
         }
171
-
172 160
         map.setTilesets(tilesets);
173 161
     }
174 162
 
... ...
@@ -180,7 +168,7 @@ public class TmxLoader {
180 168
         tileset.setTileheight(getIntAttribute(xmlTileset, "tileheight", map.getTileheight()));
181 169
         tileset.setProperties(parseProperties(findChild(xmlTileset, "properties")));
182 170
         tileset.setImage(parseImage(findChild(xmlTileset, "image")));
183
-        List<TmxTile> tiles = new ArrayList<>();
171
+        List<TmxTile> tiles = new ArrayList<TmxTile>();
184 172
         for (XmlTag child : xmlTileset.children) {
185 173
             if ("tile".equals(child.name)) {
186 174
                 tiles.add(parseTile(tileset, child));
... ...
@@ -32,14 +32,15 @@ import java.util.List;
32 32
  */
33 33
 public class TmxMap {
34 34
 
35
+    private boolean ready;
35 36
     private int width;
36 37
     private int height;
37 38
     private int tilewidth;
38 39
     private int tileheight;
39 40
     private TmxMapOrientation orientation;
40
-    private List<TmxTileset> tilesets = new ArrayList<>();
41
-    private List<TmxProperty> properties = new ArrayList<>();
42
-    private List<TmxLayer> layers = new ArrayList<>();
41
+    private List<TmxTileset> tilesets = new ArrayList<TmxTileset>();
42
+    private List<TmxProperty> properties = new ArrayList<TmxProperty>();
43
+    private List<TmxLayer> layers = new ArrayList<TmxLayer>();
43 44
 
44 45
     public TmxMapOrientation getOrientation() {
45 46
         return orientation;
... ...
@@ -108,4 +109,21 @@ public class TmxMap {
108 109
     public String getProperty(String name, String defaultValue) {
109 110
         return TmxUtils.getProperty(properties, name, defaultValue);
110 111
     }
112
+
113
+    public boolean isReady() {
114
+        return ready;
115
+    }
116
+
117
+    public void setReady(boolean ready) {
118
+        this.ready = ready;
119
+    }
120
+    
121
+    public boolean canDecode() {
122
+        for(TmxTileset ts : tilesets) {
123
+            if(!ts.isReady()) {
124
+                return false;
125
+            }
126
+        }
127
+        return true;
128
+    }
111 129
 }
... ...
@@ -33,7 +33,7 @@ import java.util.List;
33 33
 public class TmxTile {
34 34
 
35 35
     private int id;
36
-    private List<TmxProperty> properties = new ArrayList<>();
36
+    private List<TmxProperty> properties = new ArrayList<TmxProperty>();
37 37
     private TmxFrame frame;
38 38
 
39 39
     public int getId() {
... ...
@@ -24,8 +24,6 @@
24 24
 package im.bci.tmxloader;
25 25
 
26 26
 import java.util.EnumSet;
27
-import java.util.Objects;
28
-
29 27
 /**
30 28
  *
31 29
  * @author devnewton
... ...
@@ -51,8 +49,8 @@ public class TmxTileInstance {
51 49
     @Override
52 50
     public int hashCode() {
53 51
         int hash = 7;
54
-        hash = 89 * hash + Objects.hashCode(this.tile);
55
-        hash = 89 * hash + Objects.hashCode(this.effect);
52
+        hash = 89 * hash + (this.tile != null ? this.tile.hashCode() : 0);
53
+        hash = 89 * hash + (this.effect != null ? this.effect.hashCode() : 0);
56 54
         return hash;
57 55
     }
58 56
 
... ...
@@ -65,10 +63,10 @@ public class TmxTileInstance {
65 63
             return false;
66 64
         }
67 65
         final TmxTileInstance other = (TmxTileInstance) obj;
68
-        if (!Objects.equals(this.tile, other.tile)) {
66
+        if (!TmxUtils.equals(this.tile, other.tile)) {
69 67
             return false;
70 68
         }
71
-        if (!Objects.equals(this.effect, other.effect)) {
69
+        if (!TmxUtils.equals(this.effect, other.effect)) {
72 70
             return false;
73 71
         }
74 72
         return true;
... ...
@@ -38,12 +38,20 @@ public class TmxTileset {
38 38
     private int tilewidth;
39 39
     private int tileheight;
40 40
     private int spacing, margin;
41
-    private List<TmxProperty> properties = new ArrayList<>();
41
+    private List<TmxProperty> properties = new ArrayList<TmxProperty>();
42 42
     private TmxImage image;
43 43
     private int firstgid;
44
-    private final TreeMap<Integer/*id*/, TmxTile> tilesById = new TreeMap<>();
45
-    private List<TmxTile> tiles = new ArrayList<>();
44
+    private final TreeMap<Integer/*id*/, TmxTile> tilesById = new TreeMap<Integer/*id*/, TmxTile>();
45
+    private List<TmxTile> tiles = new ArrayList<TmxTile>();
46
+    private boolean ready;
47
+    
48
+    public boolean isReady() {
49
+        return ready;
50
+    }
46 51
 
52
+    public void setReady(boolean ready) {
53
+        this.ready = ready;
54
+    }
47 55
     public String getSource() {
48 56
         return source;
49 57
     }
... ...
@@ -42,4 +42,8 @@ public class TmxUtils {
42 42
         }
43 43
         return defaultValue;
44 44
     }
45
+    
46
+    public static boolean equals(Object a, Object b) {
47
+        return (a == b) || (a != null && a.equals(b));
48
+    }
45 49
 }
46 50
new file mode 100644
... ...
@@ -0,0 +1,88 @@
1
+/*
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2014 devnewton <devnewton@bci.im>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
+ */
24
+package im.bci.test;
25
+
26
+import im.bci.tmxloader.TmxLoader;
27
+import im.bci.tmxloader.TmxMap;
28
+import im.bci.tmxloader.TmxTile;
29
+import im.bci.tmxloader.TmxTileset;
30
+import java.io.File;
31
+import java.io.FileInputStream;
32
+import java.io.IOException;
33
+import java.io.InputStream;
34
+import java.util.Scanner;
35
+import org.junit.Test;
36
+import org.junit.Assert;
37
+
38
+/**
39
+ *
40
+ * @author devnewton
41
+ */
42
+public class TestTmxLoader {
43
+
44
+    @Test
45
+    public void simpleTmx() throws IOException {
46
+        final File mapFile = new File("test-data/desert.tmx");
47
+        final File mapParentDir = mapFile.getParentFile().getCanonicalFile();
48
+        TmxLoader loader = new TmxLoader();
49
+        TmxMap map = new TmxMap();
50
+        loader.parseTmx(map, loadText(mapFile));
51
+        for (TmxTileset tileset : map.getTilesets()) {
52
+            File tilesetParentDir;
53
+            if (null != tileset.getSource()) {
54
+                final File tilesetFile = new File(mapParentDir, tileset.getSource());
55
+                tilesetParentDir = tilesetFile.getParentFile().getCanonicalFile();
56
+                loader.parseTsx(map, tileset, loadText(tilesetFile));
57
+            } else {
58
+                tilesetParentDir = mapParentDir;
59
+            }
60
+            if (null != tileset.getImage()) {
61
+                tileset.getImage().setSource(convertRelativeToAbsolutePath(tilesetParentDir, tileset.getImage().getSource()));
62
+            }
63
+            for (TmxTile tile : tileset.getTiles()) {
64
+                tile.getFrame().getImage().setSource(convertRelativeToAbsolutePath(tilesetParentDir, tile.getFrame().getImage().getSource()));
65
+            }
66
+        }
67
+        loader.decode(map);
68
+
69
+        Assert.assertEquals(40, map.getWidth());
70
+        Assert.assertEquals(40, map.getHeight());
71
+        Assert.assertEquals(32, map.getTilewidth());
72
+        Assert.assertEquals(32, map.getTileheight());
73
+        Assert.assertEquals(1, map.getLayers().size());
74
+    }
75
+    
76
+    private String convertRelativeToAbsolutePath(File parentDir, String relativePath) throws IOException {
77
+        if(new File(relativePath).isAbsolute()) {
78
+            return relativePath;
79
+        }
80
+        return new File(parentDir, relativePath).getCanonicalPath();        
81
+    }
82
+
83
+    private String loadText(File f) throws IOException {
84
+        try (InputStream is = new FileInputStream(f); Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\Z")) {
85
+            return s.next();
86
+        }
87
+    }
88
+}
0 89
new file mode 100644
... ...
@@ -0,0 +1,50 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<map version="1.0" orientation="orthogonal" width="40" height="40" tilewidth="32" tileheight="32">
3
+ <tileset firstgid="1" name="Desert" tilewidth="32" tileheight="32" spacing="1" margin="1">
4
+  <image source="tmw_desert_spacing.png" width="265" height="199"/>
5
+ </tileset>
6
+ <layer name="Ground" width="40" height="40">
7
+  <data encoding="csv">
8
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,14,15,16,30,30,30,30,30,30,30,30,30,30,30,30,30,
9
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,46,14,15,16,30,31,30,30,30,30,30,30,30,30,30,30,30,
10
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,14,15,16,30,30,30,30,30,30,30,30,30,30,30,30,30,
11
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,31,22,23,24,30,30,30,30,30,30,30,30,30,30,30,30,30,
12
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,1,2,3,30,30,31,30,30,30,30,30,30,30,30,30,30,
13
+30,30,30,30,30,30,30,30,30,30,30,25,26,26,26,26,26,26,26,26,26,26,26,27,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
14
+30,30,30,30,30,30,30,30,30,30,30,33,34,34,34,34,34,34,34,34,34,34,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
15
+30,30,30,30,30,30,40,30,30,30,30,33,34,36,42,37,34,34,34,34,34,34,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
16
+30,30,30,30,30,30,30,30,30,30,30,33,34,35,30,33,34,34,34,34,34,34,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
17
+30,30,30,30,30,30,30,30,38,30,30,33,34,35,30,33,34,34,34,34,34,34,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
18
+30,30,30,30,30,48,38,30,30,30,30,33,34,44,26,45,34,34,34,34,34,34,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
19
+30,30,30,40,30,30,30,40,30,30,30,33,34,34,34,34,34,34,34,36,42,37,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
20
+40,30,30,30,30,40,38,30,30,38,30,33,34,34,34,34,34,34,34,44,26,45,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
21
+30,39,30,30,30,38,30,40,30,30,30,33,34,34,34,34,34,34,34,34,34,34,34,35,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
22
+30,30,30,39,30,30,30,30,30,30,30,41,42,42,42,42,42,42,42,42,42,42,42,43,9,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
23
+7,7,8,1,2,2,2,2,2,2,2,2,3,1,2,2,2,2,2,2,2,2,2,2,29,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
24
+15,15,16,9,10,10,10,10,10,10,10,10,11,9,10,10,10,10,10,10,10,10,10,10,10,10,11,30,30,30,30,30,30,30,30,30,30,30,30,30,
25
+23,23,24,17,18,18,18,18,18,18,18,18,19,17,18,18,18,18,18,18,18,18,18,18,18,18,19,30,30,30,30,30,30,30,30,30,30,30,30,30,
26
+30,30,39,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,31,
27
+30,30,30,30,39,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,
28
+39,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,25,26,26,26,26,26,26,26,26,26,26,26,27,30,
29
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,46,30,33,34,34,34,34,34,34,34,34,36,42,37,35,30,
30
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,33,34,34,34,34,34,34,34,34,35,48,33,35,30,
31
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,47,33,34,34,34,34,34,34,34,34,35,48,33,35,30,
32
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,39,30,30,30,33,34,34,34,34,34,34,34,34,35,48,33,35,30,
33
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,33,34,34,34,34,34,34,34,34,44,26,45,35,30,
34
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,47,30,33,34,34,34,34,34,34,34,34,34,34,34,35,30,
35
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,33,34,34,34,34,34,34,34,34,34,34,34,35,48,
36
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,33,34,34,34,34,34,34,34,34,34,34,34,35,30,
37
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,41,42,42,42,42,42,42,42,42,42,42,42,43,30,
38
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
39
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,30,30,30,
40
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
41
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,30,30,30,31,30,30,30,30,
42
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32,30,30,
43
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
44
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
45
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
46
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
47
+30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30
48
+</data>
49
+ </layer>
50
+</map>
0 51
new file mode 100644
1 52
Binary files /dev/null and b/test-data/tmw_desert_spacing.png differ