Gridarta Editor
AbstractResourcesReader.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.resource;
21 
22 import java.io.BufferedReader;
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.Reader;
29 import java.net.URL;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
45 import net.sf.gridarta.utils.IOUtils;
46 import net.sf.japi.swing.action.ActionBuilder;
47 import net.sf.japi.swing.action.ActionBuilderFactory;
48 import org.apache.log4j.Category;
49 import org.apache.log4j.Logger;
50 import org.jetbrains.annotations.NotNull;
51 import org.jetbrains.annotations.Nullable;
52 
60 public abstract class AbstractResourcesReader<G extends GameObject<G, ?, ?>> {
61 
65  @NotNull
66  private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta");
67 
71  @NotNull
72  private static final Category LOG = Logger.getLogger(AbstractResourcesReader.class);
73 
77  @NotNull
78  private final File collectedDirectory;
79 
84  @Nullable
85  private final String imageSet;
86 
90  @NotNull
92 
96  @NotNull
97  private final FaceObjects faceObjects;
98 
106  protected AbstractResourcesReader(@NotNull final File collectedDirectory, @Nullable final String imageSet, @NotNull final AnimationObjects animationObjects, @NotNull final FaceObjects faceObjects) {
107  this.collectedDirectory = collectedDirectory;
108  this.imageSet = imageSet;
109  this.animationObjects = animationObjects;
110  this.faceObjects = faceObjects;
111  }
112 
118  protected void loadAnimationsFromCollect(@NotNull final ErrorView errorView, @NotNull final Map<String, String> animations) {
119  final int animationObjectsSize = animationObjects.size();
120 
121  try {
122  final URL animationsURL = IOUtils.getResource(collectedDirectory, "animations");
123  final ErrorViewCollector errorViewCollector = new ErrorViewCollector(errorView, animationsURL);
124  try {
125  try (InputStream inputStream = animationsURL.openStream()) {
126  try (Reader reader = new InputStreamReader(inputStream, IOUtils.MAP_ENCODING)) {
127  try (Reader bufferedReader = new BufferedReader(reader)) {
128  AnimationObjectsReader.loadAnimations(animationObjects, errorViewCollector, bufferedReader, "anim ", false, null, animations);
129  }
130  }
131  }
132  } catch (final IOException ex) {
133  errorView.addWarning(ErrorViewCategory.ANIMATIONS_FILE_INVALID, animationsURL + ": " + ex.getMessage());
134  } catch (final AnimationParseException ex) {
135  errorView.addWarning(ErrorViewCategory.ANIMATIONS_FILE_INVALID, ex.getLineNumber(), animationsURL + ": " + ex.getMessage());
136  }
137 
138  if (LOG.isInfoEnabled()) {
139  LOG.info("Loaded " + (animationObjects.size() - animationObjectsSize) + " animations from '" + animationsURL + "'.");
140  }
141  } catch (final FileNotFoundException ex) {
142  errorView.addWarning(ErrorViewCategory.ANIMATIONS_FILE_INVALID, new File(collectedDirectory, "animations") + ": " + ex.getMessage());
143  }
144  }
145 
155  protected void addPNGFace(@NotNull final String filename, @NotNull final String path, @NotNull final String name, @NotNull final ErrorView errorView, @NotNull final ArchFaceProvider archFaceProvider) {
156  final String facename = generateFaceName(name);
157  archFaceProvider.addInfo(facename, filename);
158  try {
159  faceObjects.addFaceObject(facename, path + "/" + facename, 0, (int) new File(filename).length());
160  } catch (final DuplicateFaceException e) {
161  errorView.addWarning(ErrorViewCategory.ARCHETYPE_INVALID, ACTION_BUILDER.format("loadDuplicateFace", e.getDuplicate().getFaceName(), e.getDuplicate().getOriginalFilename(), e.getExisting().getOriginalFilename()));
162  } catch (final IllegalFaceException ex) {
163  errorView.addWarning(ErrorViewCategory.ARCHETYPE_INVALID, ACTION_BUILDER.format("loadIllegalFace", ex.getFaceObject().getFaceName(), ex.getFaceObject().getOriginalFilename()));
164  }
165  }
166 
172  @NotNull
173  private String generateFaceName(@NotNull final String name) {
174  //noinspection VariableNotUsedInsideIf
175  if (imageSet != null) {
176  // we have to snip out the image set information here from
177  // the 'name', and the ".png": (e.g. blocked.base.111.png -> blocked.111)
178  int firstDot = 0;
179  int secondDot = 0;
180  for (int t = 0; t < name.length() && secondDot == 0; t++) {
181  if (name.charAt(t) == '.') {
182  if (firstDot == 0) {
183  firstDot = t;
184  } else {
185  secondDot = t;
186  }
187  }
188  }
189 
190  if (firstDot != 0 && secondDot != 0) {
191  return name.substring(0, firstDot) + name.substring(secondDot, name.length() - 4);
192  } else {
193  return name.substring(0, name.length() - 4);
194  }
195  }
196 
197  // no image set: we need only cut off the ".png"
198  return name.substring(0, name.length() - 4);
199  }
200 
207  @NotNull
208  public abstract FaceProvider read(@NotNull ErrorView errorView, @NotNull List<G> invObjects);
209 
218  @NotNull
219  protected static Map<String, String> loadAnimTree(@NotNull final URL url) throws IOException {
220  final Map<String, String> animations;
221  try (InputStream inputStream = url.openStream()) {
222  try (Reader reader = new InputStreamReader(inputStream, IOUtils.MAP_ENCODING)) {
223  try (BufferedReader bufferedReader = new BufferedReader(reader)) {
224  animations = loadAnimTree(bufferedReader);
225  }
226  }
227  }
228  if (LOG.isInfoEnabled()) {
229  LOG.info("Loaded " + animations.size() + " animations from '" + url + "'.");
230  }
231  return animations;
232  }
233 
240  @NotNull
241  private static Map<String, String> loadAnimTree(@NotNull final BufferedReader reader) throws IOException {
242  final Map<String, String> animations = new HashMap<>();
243  while (true) {
244  final String line = reader.readLine();
245  if (line == null) {
246  break;
247  }
248  final int index = line.lastIndexOf('/');
249  final String name = line.substring(index + 1);
250  animations.put(name, line);
251  }
252  return animations;
253  }
254 
255 }
This exception is thrown when parsing an animation definition file (.
Convenience class for adding messages to a ErrorView instance using a fixed category name...
Reading and writing of maps, handling of paths.
Utility class for reading AnimationObjects from files.
static final String MAP_ENCODING
Encoding to use for maps and other data.
Definition: IOUtils.java:51
int size()
Get the number of objects.
FaceObject getExisting()
Returns the other duplicate that caused this exception.
Gridarta can handle frame information of animations and allow the selection of an animation using a t...
This interface represents a lazy loader that provides images on demand.
void loadAnimationsFromCollect(@NotNull final ErrorView errorView, @NotNull final Map< String, String > animations)
Loads all animations from the big collected animations file.
Defines possible error categories for ErrorView instances.
final AnimationObjects animationObjects
The animation objects instance.
String getOriginalFilename()
Get the original filename of this face.
Interface for classes displaying error messages.
Definition: ErrorView.java:28
static void loadAnimations(@NotNull final AnimationObjects animationObjects, @NotNull final ErrorViewCollector errorViewCollector, @NotNull final String path, @NotNull final File animFile, @NotNull final String startKey, final boolean ignoreOtherText)
Loads animations from a file.
String generateFaceName(@NotNull final String name)
Generates the facename for a face.
Base package of all Gridarta classes.
void addFaceObject(String faceName, String originalFilename, int offset, int size)
Adds a new face object.
Reflects a game object (object on a map).
Definition: GameObject.java:36
FaceObject getFaceObject()
Returns the illegal face object.
Exception that&#39;s thrown in case a face name was not unique.
Utility-class for Gridarta&#39;s I/O.
Definition: IOUtils.java:40
final FaceObjects faceObjects
The face objects instance.
Exception thrown to indicate that a face object is not acceptable.
AnimationObjects is a container for AnimationObjects.
GameObjects are the objects based on Archetypes found on maps.
static URL getResource(@Nullable final File dir, @NotNull final String fileName)
Get the URL of a resource.
Definition: IOUtils.java:68
void addPNGFace(@NotNull final String filename, @NotNull final String path, @NotNull final String name, @NotNull final ErrorView errorView, @NotNull final ArchFaceProvider archFaceProvider)
Loads a png from the file, convert it to IconImage and attach it to the face list.
FaceObjects is a container for FaceObjects.
static Map< String, String > loadAnimTree(@NotNull final URL url)
Loads animations from a file.
static final Category LOG
The logger for printing log messages.
The face is the appearance of an object.
int getLineNumber()
Get the number of the erroneous line.
AbstractResourcesReader(@NotNull final File collectedDirectory, @Nullable final String imageSet, @NotNull final AnimationObjects animationObjects, @NotNull final FaceObjects faceObjects)
Creates a new instance.
String getFaceName()
Get the faceName, which is the name of the face as usable by the "face" attribute.
FaceObject getDuplicate()
Returns the duplicate that caused this exception.
Implementation of FaceProvider which reads images from the arch directory.
Abstract base class for archetype set loader classes.
abstract FaceProvider read(@NotNull ErrorView errorView, @NotNull List< G > invObjects)
Reads the resources.
static final ActionBuilder ACTION_BUILDER
Action Builder.
static Map< String, String > loadAnimTree(@NotNull final BufferedReader reader)
Reads Animation Tree from Stream.