Gridarta Editor
AbstractMapArchObjectParser.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.model.io;
21 
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
29 import net.sf.gridarta.utils.Size2D;
31 import org.jetbrains.annotations.NotNull;
32 
40 public abstract class AbstractMapArchObjectParser<A extends MapArchObject<A>> implements MapArchObjectParser<A> {
41 
46  @NotNull
47  private static final Pattern TILE_PATH_PATTERN = Pattern.compile("(\\d+) (.+)");
48 
49  @Override
50  public void load(@NotNull final BufferedReader reader, @NotNull final A mapArchObject) throws IOException {
51  final String firstLine = reader.readLine();
52  if (firstLine == null) {
53  throw new IOException("unexpected end of file in map header");
54  }
55 
56  final String trimmedFirstLine = StringUtils.removeTrailingWhitespace(firstLine);
57 
58  if (!trimmedFirstLine.equals("arch map")) {
59  throw new InvalidMapFormatException("unexpected first line of map file: '" + trimmedFirstLine + "', expected 'arch map'");
60  }
61 
62  int width = 0;
63  int height = 0;
64  while (true) {
65  final String line = reader.readLine();
66  if (line == null) {
67  throw new IOException("unexpected end of file in map header");
68  }
69 
70  final String trimmedLine = StringUtils.removeTrailingWhitespace(line);
71 
72  if (parseLine(trimmedLine, mapArchObject, reader)) {
73  // ignore
74  } else if (trimmedLine.equals("msg")) {
75  while (true) {
76  final String msgLine = reader.readLine();
77  if (msgLine == null) {
78  throw new IOException("unexpected end of file in msg...endmsg field");
79  }
80 
81  final String trimmedMsgLine = StringUtils.removeTrailingWhitespace(msgLine);
82 
83  if (trimmedMsgLine.equals("endmsg")) {
84  break;
85  }
86 
87  if (!mapArchObject.getText().isEmpty()) {
88  mapArchObject.addText("\n");
89  }
90  mapArchObject.addText(trimmedMsgLine);
91  }
92  } else if (trimmedLine.equals("end")) {
93  break;
94  } else if (trimmedLine.startsWith("name ")) {
95  mapArchObject.setMapName(trimmedLine.substring(5));
96  } else if (trimmedLine.startsWith("width ")) {
97  width = NumberUtils.parseInt(trimmedLine.substring(6));
98  } else if (trimmedLine.startsWith("height ")) {
99  height = NumberUtils.parseInt(trimmedLine.substring(7));
100  } else if (trimmedLine.startsWith("enter_x ")) {
101  mapArchObject.setEnterX(NumberUtils.parseInt(trimmedLine.substring(8)));
102  } else if (trimmedLine.startsWith("enter_y ")) {
103  mapArchObject.setEnterY(NumberUtils.parseInt(trimmedLine.substring(8)));
104  } else if (trimmedLine.startsWith("reset_timeout ")) {
105  mapArchObject.setResetTimeout(NumberUtils.parseInt(trimmedLine.substring(14)));
106  } else if (trimmedLine.startsWith("swap_time ")) {
107  mapArchObject.setSwapTime(NumberUtils.parseInt(trimmedLine.substring(10)));
108  } else if (trimmedLine.startsWith("difficulty ")) {
109  mapArchObject.setDifficulty(NumberUtils.parseInt(trimmedLine.substring(11)));
110  } else if (trimmedLine.startsWith("darkness ")) {
111  mapArchObject.setDarkness(NumberUtils.parseInt(trimmedLine.substring(9)));
112  } else if (trimmedLine.startsWith("fixed_resettime ")) {
113  if (NumberUtils.parseInt(trimmedLine.substring(16)) != 0) {
114  mapArchObject.setFixedReset(true);
115  }
116  } else if (trimmedLine.startsWith("outdoor ")) {
117  if (NumberUtils.parseInt(trimmedLine.substring(8)) != 0) {
118  mapArchObject.setOutdoor(true);
119  }
120  } else if (trimmedLine.startsWith("tile_path_")) {
121  final Matcher m = TILE_PATH_PATTERN.matcher(trimmedLine.substring(10));
122  if (!m.matches()) {
123  throw new InvalidMapFormatException("unexpected map attribute: '" + trimmedLine + "'");
124  }
125 
126  // get tile path
127  try {
128  final int index = Integer.valueOf(m.group(1));
129  if (index > 0 && index <= Direction.values().length) {
130  mapArchObject.setTilePath(Direction.values()[index - 1], m.group(2));
131  } else {
132  throw new InvalidMapFormatException("unexpected map attribute: '" + trimmedLine + "'");
133  }
134  } catch (final NumberFormatException ignored) {
135  //noinspection ThrowInsideCatchBlockWhichIgnoresCaughtException
136  throw new InvalidMapFormatException("unexpected map attribute: '" + trimmedLine + "'");
137  }
138  } else {
139  throw new InvalidMapFormatException("unexpected map attribute: '" + trimmedLine + "'");
140  }
141  }
142 
143  mapArchObject.setMapSize(new Size2D(Math.max(1, width), Math.max(1, height)));
144  }
145 
154  protected abstract boolean parseLine(@NotNull String line, @NotNull A mapArchObject, @NotNull BufferedReader reader) throws IOException;
155 
156 }
Utility class for string manipulation.
abstract boolean parseLine(@NotNull String line, @NotNull A mapArchObject, @NotNull BufferedReader reader)
Parse a line for this editor type.
Abstract base class for classes implementing MapArchObjectParsers.
static final Pattern TILE_PATH_PATTERN
Matches the remainder of a "tile_path_xyz" line.
static String removeTrailingWhitespace(@NotNull final CharSequence str)
Removes trailing whitespace from a string.
Utility class for parsing strings into numbers.
Base package of all Gridarta classes.
static int parseInt(@NotNull final String s)
Parses an integer string.
Interface for classes that read or write MapArchObject instances.
void load(@NotNull final BufferedReader reader, @NotNull final A mapArchObject)
Exception that&#39;s thrown when a MapReader read a file and detected that it&#39;s in the wrong format...
The class Size2D represents a 2d rectangular area.
Definition: Size2D.java:30