Gridarta Editor
AbstractMapManager.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.mapmanager;
21 
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.concurrent.CopyOnWriteArrayList;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
43 
48 public abstract class AbstractMapManager<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements MapManager<G, A, R> {
49 
53  private static final int DELETED_OBJECTS_TO_REPORT = 10;
54 
58  @NotNull
60 
64  @NotNull
66 
70  @NotNull
72 
76  @NotNull
77  private final PathManager pathManager;
78 
82  private final List<MapControl<G, A, R>> mapControls = new CopyOnWriteArrayList<>();
83 
87  private final Collection<MapManagerListener<G, A, R>> listenerList = new CopyOnWriteArrayList<>();
88 
92  @Nullable
94 
102  protected AbstractMapManager(@NotNull final MapReaderFactory<G, A> mapReaderFactory, @NotNull final ProjectSettings projectSettings, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final PathManager pathManager) {
103  this.projectSettings = projectSettings;
104  this.mapReaderFactory = mapReaderFactory;
105  this.pathManager = pathManager;
106 
107  final FaceObjectProvidersListener faceObjectProvidersListener = new FaceObjectProvidersListener() {
108 
109  @Override
110  public void facesReloaded() {
111  for (final MapControl<G, A, R> mapControl : mapControls) {
112  mapControl.getMapModel().facesReloaded();
113  }
114  }
115 
116  };
117  faceObjectProviders.addFaceObjectProvidersListener(faceObjectProvidersListener);
118  }
119 
120  @Deprecated
121  public void setFileControl(@NotNull final FileControl<G, A, R> fileControl) {
122  this.fileControl = fileControl;
123  }
124 
125  @NotNull
126  @Override
127  public MapControl<G, A, R> newMap(@Nullable final List<G> objects, @NotNull final A mapArchObject, @Nullable final MapFile mapFile, final boolean interactive) {
128  final MapControl<G, A, R> mapControl = createMapControl(objects, mapArchObject, mapFile);
129  mapControls.add(mapControl);
130  for (final MapManagerListener<G, A, R> listener : listenerList) {
131  listener.mapCreated(mapControl, interactive);
132  }
133  if (interactive) {
134  setCurrentMap(mapControl);
135  }
136  return mapControl;
137  }
138 
146  @NotNull
147  protected abstract MapControl<G, A, R> createMapControl(@Nullable List<G> objects, @NotNull A mapArchObject, @Nullable MapFile mapFile);
148 
149  @Nullable
150  @Override
152  if (currentMapControl != null) {
153  return currentMapControl;
154  }
155 
156  return mapControls.isEmpty() ? null : mapControls.get(mapControls.size() - 1);
157  }
158 
159  @Override
160  public void closeMap(@NotNull final MapControl<G, A, R> mapControl) {
161  for (final MapManagerListener<G, A, R> listener : listenerList) {
162  listener.mapClosing(mapControl);
163  }
164  assert mapControl.getUseCounter() <= 0;
165  mapControls.remove(mapControl);
166  if (currentMapControl == mapControl) {
167  setCurrentMap(mapControls.isEmpty() ? null : mapControls.get(0));
168  }
169  for (final MapManagerListener<G, A, R> listener : listenerList) {
170  listener.mapClosed(mapControl);
171  }
172  mapControl.getMapModel().mapClosed();
173  }
174 
175  @NotNull
176  @Override
177  public MapControl<G, A, R> openMapFile(@NotNull final MapFile mapFile, final boolean interactive) throws IOException {
178  // First look whether the file isn't already open.
179  // If so, return the previously loaded map.
180  for (final MapControl<G, A, R> mapControl : mapControls) {
181  final MapFile tmpMapFile = mapControl.getMapModel().getMapFile();
182  if (tmpMapFile != null && tmpMapFile.equals(mapFile)) {
183  mapControl.acquire();
184  return mapControl;
185  }
186  }
187 
188  final MapReader<G, A> decoder = decodeMapFile(mapFile.getFile(), interactive);
189  return newMap(decoder.getGameObjects(), decoder.getMapArchObject(), mapFile, interactive);
190  }
191 
192  @NotNull
193  @Override
194  public MapControl<G, A, R> openMapFile(@NotNull final File file, final boolean interactive) throws IOException {
195  return openMapFile(pathManager.getMapFile(file), interactive);
196  }
197 
207  @NotNull
208  private MapReader<G, A> decodeMapFile(@NotNull final File file, final boolean interactive) throws IOException {
209  final MapReader<G, A> decoder;
210  //noinspection ErrorNotRethrown
211  try {
212  decoder = mapReaderFactory.newMapReader(file);
213  } catch (final OutOfMemoryError ex) {
214  throw new IOException("out of memory", ex);
215  }
216 
217  int outOfMapBoundsDeleted = 0;
218  final StringBuilder outOfMapBoundsObjects = new StringBuilder();
219  final int mapWidth = decoder.getMapArchObject().getMapSize().getWidth();
220  final int mapHeight = decoder.getMapArchObject().getMapSize().getHeight();
221  final Iterator<G> it = decoder.getGameObjects().iterator();
222  while (it.hasNext()) {
223  final GameObject<G, A, R> gameObject = it.next();
224  if (!gameObject.isInContainer()) {
225  final int minX = gameObject.getHead().getMapX() + gameObject.getMinX();
226  final int minY = gameObject.getHead().getMapY() + gameObject.getMinY();
227  final int maxX = gameObject.getHead().getMapX() + gameObject.getMaxX();
228  final int maxY = gameObject.getHead().getMapY() + gameObject.getMaxY();
229  if (minX < 0 || minY < 0 || maxX >= mapWidth || maxY >= mapHeight) {
230  it.remove();
231  if (gameObject.isHead()) {
232  outOfMapBoundsDeleted++;
233  if (outOfMapBoundsDeleted <= DELETED_OBJECTS_TO_REPORT) {
234  outOfMapBoundsObjects.append('\n');
235  outOfMapBoundsObjects.append(gameObject.getBestName());
236  outOfMapBoundsObjects.append(" at ");
237  outOfMapBoundsObjects.append(minX).append('/').append(minY);
238  if (minX != maxX || minY != maxY) {
239  outOfMapBoundsObjects.append("..");
240  outOfMapBoundsObjects.append(maxX).append('/').append(maxY);
241  }
242  } else if (outOfMapBoundsDeleted == DELETED_OBJECTS_TO_REPORT + 1) {
243  outOfMapBoundsObjects.append("\n...");
244  }
245  }
246  }
247  }
248  }
249  if (interactive && outOfMapBoundsDeleted > 0) {
250  fileControl.reportOutOfMapBoundsDeleted(file, outOfMapBoundsDeleted, outOfMapBoundsObjects);
251  }
252 
253  return decoder;
254  }
255 
256  @Override
257  public void setCurrentMap(@Nullable final MapControl<G, A, R> mapControl) {
258  if (currentMapControl == mapControl) {
259  return;
260  }
261 
262  currentMapControl = mapControl;
263 
264  for (final MapManagerListener<G, A, R> listener : listenerList) {
265  listener.currentMapChanged(currentMapControl);
266  }
267  }
268 
269  @NotNull
270  @Override
271  public List<MapControl<G, A, R>> getOpenedMaps() {
272  return Collections.unmodifiableList(mapControls);
273  }
274 
280  @Nullable
281  @Override
283  return currentMapControl;
284  }
285 
286  @Override
287  public void addMapManagerListener(@NotNull final MapManagerListener<G, A, R> listener) {
288  listenerList.add(listener);
289  }
290 
291  @Override
292  public void removeMapManagerListener(@NotNull final MapManagerListener<G, A, R> listener) {
293  listenerList.remove(listener);
294  }
295 
296  @Override
297  public void revert(@NotNull final MapControl<G, A, R> mapControl) throws IOException {
298  final MapFile mapFile = mapControl.getMapModel().getMapFile();
299  if (mapFile == null) {
300  return;
301  }
302 
303  final MapReader<G, A> decoder = decodeMapFile(mapFile.getFile(), false);
304  final MapModel<G, A, R> mapModel = mapControl.getMapModel();
305  final A mapArchObject = mapModel.getMapArchObject();
306  mapModel.beginTransaction("revert");
307  try {
308  mapArchObject.setMapSize(decoder.getMapArchObject().getMapSize());
309  mapArchObject.beginTransaction();
310  try {
311  mapArchObject.setState(decoder.getMapArchObject());
312  } finally {
313  mapArchObject.endTransaction();
314  }
315  mapModel.clearMap();
316  mapModel.addObjectListToMap(decoder.getGameObjects());
317  } finally {
318  mapModel.endTransaction();
319  }
320  mapModel.resetModified();
321  }
322 
323  @Override
324  public File getLocalMapDir() {
325  final MapControl<G, A, R> mapControl = currentMapControl;
326  if (mapControl == null) {
328  }
329 
330  final MapFile mapFile = mapControl.getMapModel().getMapFile();
331  if (mapFile == null) {
333  }
334 
335  return mapFile.getFile().getParentFile();
336  }
337 
338  @Override
339  public void release(@NotNull final MapControl<G, A, R> mapControl) {
340  mapControl.release();
341  if (mapControl.getUseCounter() <= 0) {
342  closeMap(mapControl);
343  }
344  }
345 
346 }
net.sf.gridarta.model.mapmodel.MapModel
Definition: MapModel.java:75
net.sf.gridarta.model.io.MapReader
Definition: MapReader.java:31
net.sf.gridarta.model.mapmodel.MapModel.getMapArchObject
A getMapArchObject()
net.sf.gridarta.model.mapmanager.MapManager
Definition: MapManager.java:37
net.sf.gridarta.model.mapmanager.AbstractMapManager.currentMapControl
MapControl< G, A, R > currentMapControl
Definition: AbstractMapManager.java:93
net.sf.gridarta.model.mapmodel.MapModel.resetModified
void resetModified()
net.sf.gridarta.model.mapmanager.FileControl.reportOutOfMapBoundsDeleted
void reportOutOfMapBoundsDeleted(@NotNull File file, int outOfMapBoundsDeleted, @NotNull StringBuilder outOfMapBoundsObjects)
net.sf.gridarta
net.sf.gridarta.model.mapmodel.MapModel.endTransaction
void endTransaction()
net.sf.gridarta.model.mapmanager.AbstractMapManager
Definition: AbstractMapManager.java:48
net.sf.gridarta.model.mapmanager.AbstractMapManager.setFileControl
void setFileControl(@NotNull final FileControl< G, A, R > fileControl)
Definition: AbstractMapManager.java:121
net.sf.gridarta.model.io.MapReaderFactory
Definition: MapReaderFactory.java:32
net.sf.gridarta.model.gameobject.GameObject.isInContainer
boolean isInContainer()
net.sf.gridarta.model.baseobject.BaseObject.getMinY
int getMinY()
net.sf
net.sf.gridarta.model.mapmodel.MapModel.beginTransaction
void beginTransaction(@NotNull String name)
net.sf.gridarta.model.baseobject.BaseObject.getMinX
int getMinX()
net.sf.gridarta.model.mapmanager.FileControl< G, A, R >
net.sf.gridarta.model.mapmanager.MapManagerListener< G, A, R >
net.sf.gridarta.model.io.PathManager
Definition: PathManager.java:39
net.sf.gridarta.model.mapmodel
Definition: AboveFloorInsertionMode.java:20
net.sf.gridarta.model.mapmodel.MapFile.equals
boolean equals(@Nullable final Object obj)
Definition: MapFile.java:122
net.sf.gridarta.model.io.MapReader.getGameObjects
List< G > getGameObjects()
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.face.FaceObjectProviders
Definition: FaceObjectProviders.java:46
net.sf.gridarta.model.gameobject.GameObject
Definition: GameObject.java:36
net.sf.gridarta.model.baseobject.BaseObject.getBestName
String getBestName()
net.sf.gridarta.model.mapcontrol
Definition: DefaultMapControl.java:20
net.sf.gridarta.model.io.MapReaderFactory.newMapReader
MapReader< G, A > newMapReader(@NotNull File file)
net.sf.gridarta.model.mapmanager.AbstractMapManager.listenerList
final Collection< MapManagerListener< G, A, R > > listenerList
Definition: AbstractMapManager.java:87
net.sf.gridarta.model.baseobject.BaseObject.isHead
boolean isHead()
net.sf.gridarta.model.mapmanager.AbstractMapManager.fileControl
FileControl< G, A, R > fileControl
Definition: AbstractMapManager.java:59
net.sf.gridarta.model.mapmanager.AbstractMapManager.addMapManagerListener
void addMapManagerListener(@NotNull final MapManagerListener< G, A, R > listener)
Definition: AbstractMapManager.java:287
net.sf.gridarta.model.mapmanager.AbstractMapManager.getCurrentMap
MapControl< G, A, R > getCurrentMap()
Definition: AbstractMapManager.java:282
net.sf.gridarta.model.gameobject
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.model.mapmanager.AbstractMapManager.openMapFile
MapControl< G, A, R > openMapFile(@NotNull final File file, final boolean interactive)
Definition: AbstractMapManager.java:194
net.sf.gridarta.model.baseobject.BaseObject.getMaxX
int getMaxX()
net.sf.gridarta.model.mapmanager.AbstractMapManager.AbstractMapManager
AbstractMapManager(@NotNull final MapReaderFactory< G, A > mapReaderFactory, @NotNull final ProjectSettings projectSettings, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final PathManager pathManager)
Definition: AbstractMapManager.java:102
net.sf.gridarta.model.maparchobject.MapArchObject
Definition: MapArchObject.java:40
net.sf.gridarta.model.mapmanager.AbstractMapManager.createMapControl
abstract MapControl< G, A, R > createMapControl(@Nullable List< G > objects, @NotNull A mapArchObject, @Nullable MapFile mapFile)
net.sf.gridarta.model.io.PathManager.getMapFile
MapFile getMapFile(@NotNull final AbsoluteMapPath mapPath)
Definition: PathManager.java:72
net.sf.gridarta.model.mapmanager.AbstractMapManager.openMapFile
MapControl< G, A, R > openMapFile(@NotNull final MapFile mapFile, final boolean interactive)
Definition: AbstractMapManager.java:177
net.sf.gridarta.model.mapmodel.MapFile.getFile
File getFile()
Definition: MapFile.java:102
net.sf.gridarta.model.mapmanager.AbstractMapManager.getOpenMap
MapControl< G, A, R > getOpenMap()
Definition: AbstractMapManager.java:151
net.sf.gridarta.model.mapmodel.MapFile
Definition: MapFile.java:31
net.sf.gridarta.model.io
Definition: AbstractArchetypeParser.java:20
net.sf.gridarta.model.settings.ProjectSettings
Definition: ProjectSettings.java:29
net.sf.gridarta.model.mapmanager.AbstractMapManager.newMap
MapControl< G, A, R > newMap(@Nullable final List< G > objects, @NotNull final A mapArchObject, @Nullable final MapFile mapFile, final boolean interactive)
Definition: AbstractMapManager.java:127
net.sf.gridarta.model.mapmanager.AbstractMapManager.mapReaderFactory
final MapReaderFactory< G, A > mapReaderFactory
Definition: AbstractMapManager.java:71
net.sf.gridarta.model.mapmanager.AbstractMapManager.mapControls
final List< MapControl< G, A, R > > mapControls
Definition: AbstractMapManager.java:82
net.sf.gridarta.model.baseobject.BaseObject.getHead
T getHead()
net.sf.gridarta.model.mapmanager.AbstractMapManager.closeMap
void closeMap(@NotNull final MapControl< G, A, R > mapControl)
Definition: AbstractMapManager.java:160
net.sf.gridarta.model.mapmanager.AbstractMapManager.release
void release(@NotNull final MapControl< G, A, R > mapControl)
Definition: AbstractMapManager.java:339
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Definition: Archetype.java:41
net.sf.gridarta.model.face.FaceObjectProvidersListener
Definition: FaceObjectProvidersListener.java:29
net.sf.gridarta.model.face
Definition: AbstractFaceObjects.java:20
net.sf.gridarta.model.baseobject.BaseObject.getMaxY
int getMaxY()
net.sf.gridarta.model.mapmanager.AbstractMapManager.getLocalMapDir
File getLocalMapDir()
Definition: AbstractMapManager.java:324
net.sf.gridarta.model.mapmodel.MapModel.clearMap
void clearMap()
net.sf.gridarta.model.mapcontrol.MapControl
Definition: MapControl.java:35
net.sf.gridarta.model.mapcontrol.MapControl.getMapModel
MapModel< G, A, R > getMapModel()
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.model.io.MapReader.getMapArchObject
A getMapArchObject()
net.sf.gridarta.model.mapmanager.AbstractMapManager.pathManager
final PathManager pathManager
Definition: AbstractMapManager.java:77
net.sf.gridarta.model.mapmanager.AbstractMapManager.removeMapManagerListener
void removeMapManagerListener(@NotNull final MapManagerListener< G, A, R > listener)
Definition: AbstractMapManager.java:292
net.sf.gridarta.model.settings.ProjectSettings.getMapsDirectory
File getMapsDirectory()
net.sf.gridarta.model.mapmanager.AbstractMapManager.decodeMapFile
MapReader< G, A > decodeMapFile(@NotNull final File file, final boolean interactive)
Definition: AbstractMapManager.java:208
net.sf.gridarta.model.mapmodel.MapModel.getMapFile
MapFile getMapFile()
net.sf.gridarta.model.mapmanager.AbstractMapManager.setCurrentMap
void setCurrentMap(@Nullable final MapControl< G, A, R > mapControl)
Definition: AbstractMapManager.java:257
net.sf.gridarta.model.mapmanager.AbstractMapManager.projectSettings
final ProjectSettings projectSettings
Definition: AbstractMapManager.java:65
net.sf.gridarta.model.mapmodel.MapModel.addObjectListToMap
void addObjectListToMap(@NotNull Iterable< G > objects)
net.sf.gridarta.model.face.FaceObjectProvidersListener.facesReloaded
void facesReloaded()
net.sf.gridarta.model.settings
Definition: AbstractDefaultProjectSettings.java:20
net.sf.gridarta.model.mapmanager.AbstractMapManager.revert
void revert(@NotNull final MapControl< G, A, R > mapControl)
Definition: AbstractMapManager.java:297
net.sf.gridarta.model.mapmanager.AbstractMapManager.DELETED_OBJECTS_TO_REPORT
static final int DELETED_OBJECTS_TO_REPORT
Definition: AbstractMapManager.java:53
net.sf.gridarta.model.mapmanager.AbstractMapManager.getOpenedMaps
List< MapControl< G, A, R > > getOpenedMaps()
Definition: AbstractMapManager.java:271