Gridarta Editor
DefaultMapModel.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2023 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.mapmodel;
21 
22 import java.awt.Point;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Objects;
30 import java.util.Set;
31 import java.util.concurrent.CopyOnWriteArrayList;
47 import net.sf.gridarta.utils.Size2D;
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 
61 public class DefaultMapModel<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements MapModel<G, A, R> {
62 
66  private static final long serialVersionUID = 1L;
67 
71  private static final Category LOG = Logger.getLogger(DefaultMapModel.class);
72 
76  private final transient Object syncLock = new Object();
77 
81  @NotNull
82  private final A mapArchObject;
83 
87  @NotNull
89 
94  @NotNull
96 
100  @NotNull
102 
106  @NotNull
107  private final List<MapModelListener<G, A, R>> mapModelListeners = new CopyOnWriteArrayList<>();
108 
112  @NotNull
113  private final Collection<MapTransactionListener<G, A, R>> mapTransactionListeners = new CopyOnWriteArrayList<>();
114 
121  private int transactionDepth;
122 
127  @Nullable
128  private transient Thread transactionThread;
129 
133  @NotNull
134  private final Set<MapSquare<G, A, R>> changedSquares = new HashSet<>();
135 
140  @NotNull
142 
146  @NotNull
147  private final Set<G> changedGameObjects = new HashSet<>();
148 
152  @NotNull
153  private final Set<G> transientChangedGameObjects = new HashSet<>();
154 
158  @NotNull
160 
165  private int activeEditType;
166 
171  @NotNull
173 
177  @NotNull
179 
183  @NotNull
185 
190  @Nullable
191  private MapFile mapFile;
192 
196  private boolean modified;
197 
201  @NotNull
203 
208  @NotNull
210 
211  @Override
212  public void mapMetaChanged() {
213  setModified();
214  }
215 
216  @Override
217  public void mapSizeChanged(@NotNull final Size2D mapSize) {
218  resizeMapInt(mapSize);
219  }
220 
221  };
222 
234  this.mapArchObject = mapArchObject;
235  this.autojoinLists = autojoinLists;
236  this.archetypeChooserModel = archetypeChooserModel;
237  this.gameObjectFactory = gameObjectFactory;
238  this.gameObjectMatchers = gameObjectMatchers;
239  this.topmostInsertionMode = topmostInsertionMode;
241  mapArchObject.addMapArchObjectListener(mapArchObjectListener);
242  mapGrid = new MapSquareGrid<>(this, mapArchObject.getMapSize());
243  modified = false;
244  }
245 
246  @Override
247  public void mapClosed() {
248  mapArchObject.removeMapArchObjectListener(mapArchObjectListener);
249  }
250 
251  @NotNull
252  @Override
253  public A getMapArchObject() {
254  return mapArchObject;
255  }
256 
257  @Override
258  public Iterator<MapSquare<G, A, R>> iterator() {
259  return new MapSquareIterator<>(this, null, 1, false);
260  }
261 
262  @NotNull
263  @Override
264  public MapSquare<G, A, R> getMapSquare(@NotNull final Point pos) {
265  return mapGrid.getMapSquare(pos.x, pos.y);
266  }
267 
268  @Override
269  public void addObjectListToMap(@NotNull final Iterable<G> objects) {
270  for (final G gameObject : objects) {
271  if (!gameObject.isInContainer()) { // only map arches....
272  addGameObjectToMap(gameObject, new Point(gameObject.getMapX(), gameObject.getMapY()), topmostInsertionMode);
273  }
274  }
275  }
276 
277  @Override
278  public void clearMap() {
279  mapGrid.clearMap();
280  }
281 
282  @Override
283  public boolean isEmpty() {
284  return mapGrid.isEmpty();
285  }
286 
291  private void resizeMapInt(@NotNull final Size2D newSize) {
292  final Size2D mapSize = mapGrid.getMapSize();
293  if (newSize.equals(mapSize)) {
294  return;
295  }
296 
297  // no other thread may access this map model while resizing
298  synchronized (syncLock) {
299  lightMapModelTracker.mapSizeChanging(newSize, mapSize);
300 
301  // first delete all arches in the area that will get cut off
302  // (this is especially important to remove all multi-part objects
303  // reaching into that area)
304  final Collection<GameObject<G, A, R>> objectsToDelete = new HashSet<>();
305  if (mapSize.getWidth() > newSize.getWidth()) {
306  // clear out the right stripe (as far as being cut off)
307  mapGrid.collectHeads(newSize.getWidth(), 0, mapSize.getWidth(), mapSize.getHeight(), objectsToDelete);
308  }
309 
310  if (mapSize.getHeight() > newSize.getHeight()) {
311  // clear out the bottom stripe (as far as being cut off)
312  mapGrid.collectHeads(0, newSize.getHeight(), Math.min(mapSize.getWidth(), newSize.getWidth()), mapSize.getHeight(), objectsToDelete);
313  }
314 
315  for (final GameObject<G, A, R> node : objectsToDelete) {
316  node.remove();
317  }
318 
319  mapGrid.resize(newSize);
323 
324  fireMapSizeChanged(newSize);
325  }
326  }
327 
333  private void discardInvalidMapSquares(@NotNull final Iterable<MapSquare<G, A, R>> mapSquares, @NotNull final Size2D mapSize) {
334  final Iterator<MapSquare<G, A, R>> it = mapSquares.iterator();
335  while (it.hasNext()) {
336  final MapSquare<G, A, R> mapSquare = it.next();
337  if (mapSquare.getMapX() >= mapSize.getWidth() || mapSquare.getMapY() >= mapSize.getHeight()) {
338  it.remove();
339  }
340  }
341  }
342 
348  private void discardInvalidGameObjects(@NotNull final Iterable<G> gameObjects, @NotNull final Size2D mapSize) {
349  final Iterator<G> it2 = gameObjects.iterator();
350  while (it2.hasNext()) {
351  final GameObject<G, A, R> gameObject = it2.next();
352  final G topGameObject = gameObject.getTopContainer();
353  if (topGameObject.getContainer() == null || topGameObject.getMapX() >= mapSize.getWidth() || topGameObject.getMapY() >= mapSize.getHeight()) {
354  it2.remove();
355  }
356  }
357  }
358 
359  @Override
360  public void addMapModelListener(@NotNull final MapModelListener<G, A, R> listener) {
361  mapModelListeners.add(listener);
362  }
363 
364  @Override
365  public void prependMapModelListener(@NotNull final MapModelListener<G, A, R> listener) {
366  mapModelListeners.add(0, listener);
367  }
368 
369  @Override
370  public void removeMapModelListener(@NotNull final MapModelListener<G, A, R> listener) {
371  mapModelListeners.remove(listener);
372  }
373 
374  @Override
375  public void addMapTransactionListener(@NotNull final MapTransactionListener<G, A, R> listener) {
376  mapTransactionListeners.add(listener);
377  }
378 
379  @Override
380  public void removeMapTransactionListener(@NotNull final MapTransactionListener<G, A, R> listener) {
381  mapTransactionListeners.remove(listener);
382  }
383 
384  @Override
385  public void beginSquareChange(@NotNull final MapSquare<G, A, R> mapSquare) {
386  if (transactionDepth == 0) {
387  LOG.error("beginSquareChange: square (" + mapSquare + ") is about to change outside a transaction");
388  return;
389  }
390 
391  savedSquares.recordMapSquare(mapSquare);
392  }
393 
394  @Override
395  public void endSquareChange(@NotNull final MapSquare<G, A, R> mapSquare) {
396  if (transactionDepth == 0) {
397  LOG.error("endSquareChange: square (" + mapSquare + ") was changed outside a transaction");
398  final Set<MapSquare<G, A, R>> mapSquares = new HashSet<>(1);
399  mapSquares.add(mapSquare);
400  lightMapModelTracker.mapSquaresChanged(Collections.unmodifiableCollection(mapSquares));
401  fireMapSquaresChangedEvent(mapSquares);
402  } else {
403  synchronized (changedSquares) {
404  changedSquares.add(mapSquare);
405  }
406  }
407  }
408 
409  @Override
410  public void beginGameObjectChange(@NotNull final G gameObject) {
411  final MapSquare<G, A, R> mapSquare = gameObject.getMapSquare();
412  if (transactionDepth == 0) {
413  LOG.error("beginGameObjectChange: game object (" + gameObject.getBestName() + "@" + mapSquare + ") is about to change outside a transaction");
414  return;
415  }
416 
417  savedSquares.recordMapSquare(mapSquare);
418  }
419 
420  @Override
421  public void endGameObjectChange(@NotNull final G gameObject) {
422  if (transactionDepth == 0) {
423  LOG.error("endGameObjectChange: game object (" + gameObject.getBestName() + "@" + gameObject.getMapSquare() + ") was changed outside a transaction");
424  final Set<G> gameObjects = new HashSet<>(1);
425  gameObjects.add(gameObject);
426  fireGameObjectsChangedEvent(gameObjects, Collections.emptySet());
427  } else {
428  synchronized (changedGameObjects) {
429  changedGameObjects.add(gameObject);
430  }
431  }
432  }
433 
434  @Override
435  public void transientGameObjectChange(@NotNull final G gameObject) {
436  if (transactionDepth == 0) {
437  LOG.error("transientGameObjectChange: game object (" + gameObject.getBestName() + "@" + gameObject.getMapSquare() + ") was changed outside a transaction");
438  final Set<G> gameObjects = new HashSet<>(1);
439  gameObjects.add(gameObject);
440  fireGameObjectsChangedEvent(Collections.emptySet(), gameObjects);
441  } else {
442  synchronized (transientChangedGameObjects) {
443  transientChangedGameObjects.add(gameObject);
444  }
445  }
446  }
447 
448  @Override
449  public void beginTransaction(@NotNull final String name) {
450  if (transactionDepth == 0) {
452  transactionThread = Thread.currentThread();
455  } else {
456  // == is okay for threads.
457  //noinspection ObjectEquality
458  if (transactionThread != Thread.currentThread()) {
459  throw new IllegalStateException("A transaction must only be used by one thread. " + transactionThread + " " + Thread.currentThread());
460  }
462  }
463  }
464 
465  @Override
466  public void endTransaction() {
467  endTransaction(false);
468  }
469 
470  @Override
471  public void endTransaction(final boolean fireEvent) {
472  if (transactionDepth <= 0) {
473  throw new IllegalStateException("Tried to end a transaction but no transaction was open.");
474  }
476  assert transactionDepth >= 0;
477  if (transactionDepth == 0) {
479  } else if (fireEvent && transactionDepth == 1) {
480  fireEvents();
481  }
482  }
483 
487  private void fireEvents() {
488  // Call lightMapModelTracker first as it might change more game objects
489  transactionDepth++; // temporarily increase transaction depth because updating light information causes changes
490  try {
491  // Create copy to avoid ConcurrentModificationExceptions due to newly changed squares
492  final Collection<MapSquare<G, A, R>> mapSquares = new HashSet<>(changedSquares);
493  for (final G gameObject : changedGameObjects) {
494  final MapSquare<G, A, R> mapSquare = gameObject.getMapSquareOptional();
495  if (mapSquare != null) {
496  mapSquares.add(mapSquare);
497  }
498  }
500  } finally {
502  }
503  if (!changedGameObjects.isEmpty() || !transientChangedGameObjects.isEmpty()) {
505  transactionDepth++; // temporarily increase transaction depth because updating edit types causes transient changes
506  try {
507  for (final G gameObject : changedGameObjects) {
508  if (gameObject.isHead()) {
509  for (G env = gameObject; env != null; env = env.getContainerGameObject()) {
511  }
512  }
513  }
514  } finally {
516  }
517  fireGameObjectsChangedEvent(Collections.unmodifiableSet(changedGameObjects), Collections.unmodifiableSet(transientChangedGameObjects));
518  changedGameObjects.clear();
519  }
520  if (!changedSquares.isEmpty()) {
521  fireMapSquaresChangedEvent(Collections.unmodifiableSet(changedSquares));
522  changedSquares.clear();
523  }
524  }
525 
526  @Override
527  public void endAllTransactions() {
528  if (transactionDepth > 0) {
530  }
531  }
532 
537  private void commitTransaction() {
538  transactionDepth = 0;
539  transactionThread = null;
540  fireEvents();
543  }
544 
545  @Override
546  public int getTransactionDepth() {
547  return transactionDepth;
548  }
549 
550  @Override
551  public boolean isAnyTransactionActive() {
552  return transactionDepth > 0;
553  }
554 
559  private void fireMapSquaresChangedEvent(final Set<MapSquare<G, A, R>> mapSquares) {
560  setModified();
561  for (final MapModelListener<G, A, R> listener : mapModelListeners) {
562  listener.mapSquaresChanged(mapSquares);
563  }
564  }
565 
571  private void fireGameObjectsChangedEvent(@NotNull final Set<G> gameObjects, @NotNull final Set<G> transientGameObjects) {
572  if (!gameObjects.isEmpty()) {
573  setModified();
574  }
575  for (final MapModelListener<G, A, R> listener : mapModelListeners) {
576  listener.mapObjectsChanged(gameObjects, transientGameObjects);
577  }
578  }
579 
584  private void fireMapSizeChanged(@NotNull final Size2D newSize) {
585  setModified();
586  for (final MapModelListener<G, A, R> listener : mapModelListeners) {
587  listener.mapSizeChanged(newSize);
588  }
589  }
590 
594  private void firePreBeginTransaction() {
596  listener.preBeginTransaction();
597  }
598  }
599 
604  private void fireBeginTransaction(@NotNull final String name) {
607  listener.beginTransaction(name);
608  }
609  }
610 
614  private void fireEndTransaction() {
616  listener.endTransaction(savedSquares);
617  }
619  }
620 
624  private void firePostEndTransaction() {
626  listener.postEndTransaction();
627  }
628  }
629 
634  private void fireMapFileChanged(@Nullable final MapFile oldMapFile) {
635  for (final MapModelListener<G, A, R> listener : mapModelListeners) {
636  listener.mapFileChanged(oldMapFile);
637  }
638  }
639 
643  private void fireModifiedChanged() {
644  for (final MapModelListener<G, A, R> listener : mapModelListeners) {
645  listener.modifiedChanged();
646  }
647  }
648 
649  @Override
650  public void removeGameObject(@NotNull final G gameObject, final boolean join) {
651  final MapSquare<?, ?, ?> mapSquare = gameObject.getMapSquare();
652  if (gameObject.isInContainer()) {
653  gameObject.remove();
654  } else {
655  gameObject.remove();
656 
657  if (join) {
658  joinDelete(mapSquare.getMapLocation(), gameObject.getArchetype());
659  }
660  }
661  }
662 
663  @Override
664  public boolean isMultiArchFittingToMap(@NotNull final Archetype<G, A, R> archetype, @NotNull final Point pos, final boolean allowDouble) {
665  for (Archetype<G, A, R> part = archetype; part != null; part = part.getMultiNext()) {
666  final Point point = new Point(part.getMultiX(), part.getMultiY());
667  point.translate(pos.x, pos.y);
668  // outside map
669  if (!mapArchObject.isPointValid(point)) {
670  return false;
671  }
672 
673  if (!allowDouble) {
674  final String temp = part.getArchetypeName();
675  for (final BaseObject<G, A, R, ?> node : mapGrid.getMapSquare(point.x, point.y)) {
676  if (node.getArchetype().getArchetypeName().equals(temp)) {
677  return false;
678  }
679  }
680  }
681  }
682 
683  return true;
684  }
685 
686  @Override
687  public void setErrors(@NotNull final ErrorCollector<G, A, R> errors) {
688  this.errors = errors;
689  for (final MapModelListener<G, A, R> listener : mapModelListeners) {
690  listener.errorsChanged(errors);
691  }
692  }
693 
694  @NotNull
695  @Override
697  return errors;
698  }
699 
703  @Nullable
704  @Override
705  public G insertArchToMap(@NotNull final BaseObject<G, A, R, ?> templateBaseObject, @Nullable final G nextGameObject, @NotNull final Point pos, final boolean join) {
706  // map coordinates must be valid
707  if (!mapArchObject.isPointValid(pos)) {
708  return null;
709  }
710 
711  final G newGameObject;
712  final GameObject<G, A, R> nextGameObjectEnv = nextGameObject == null ? null : nextGameObject.getContainerGameObject();
713  if (nextGameObject == null || nextGameObjectEnv == null) {
714  newGameObject = insertBaseObject(templateBaseObject, pos, true, join, topmostInsertionMode);
715  if (newGameObject == null) {
716  return null;
717  }
718 
719  int position = 0;
720  for (final G gameObject : mapGrid.getMapSquare(pos.x, pos.y).reverse()) {
721  // This is okay because nextGameObject is on the desired square.
722  //noinspection ObjectEquality
723  if (gameObject == nextGameObject) {
724  break;
725  }
726  position++;
727  }
728  for (int i = 0; i < position - 1; i++) {
729  newGameObject.moveDown();
730  }
731  } else {
732  newGameObject = templateBaseObject.newInstance(gameObjectFactory);
733  nextGameObjectEnv.addLast(newGameObject);
734  if (templateBaseObject instanceof Archetype) {
735  gameObjectFactory.createInventory(newGameObject, templateBaseObject);
736  }
737  }
738 
739  return newGameObject;
740  }
741 
742  @Nullable
743  @Override
744  public G insertBaseObject(@NotNull final BaseObject<G, A, R, ?> baseObject, @NotNull final Point pos, final boolean allowMany, final boolean join, @NotNull final InsertionMode insertionMode) {
745  if (!mapArchObject.isPointValid(pos)) {
746  return null;
747  }
748 
749  final R realArchetype = baseObject.getArchetype();
750  final R effectiveArchetype;
751  if (join) {
752  final InsertionResult<G, A, R> insertionResult = joinInsert(pos, realArchetype);
753  final G gameObject = insertionResult.getGameObject();
754  if (gameObject != null) {
755  return gameObject;
756  }
757 
758  effectiveArchetype = insertionResult.getArchetype();
759  if (effectiveArchetype == null) {
760  return null; // only one autojoin type per square allowed
761  }
762  } else {
763  effectiveArchetype = realArchetype;
764  }
765 
766  if (!isMultiArchFittingToMap(effectiveArchetype, pos, allowMany)) {
767  return null;
768  }
769 
770  final Integer direction = effectiveArchetype.usesDirection() ? archetypeChooserModel.getDirection() : null;
771 
772  final List<G> parts = new ArrayList<>();
773  for (R archetypePart = effectiveArchetype; archetypePart != null; archetypePart = archetypePart.getMultiNext()) {
774  final G part;
775  if (archetypePart == effectiveArchetype) {
776  part = baseObject.newInstance(gameObjectFactory);
777  part.setArchetype(archetypePart);
778  } else {
779  part = archetypePart.newInstance(gameObjectFactory);
780  }
781  if (direction != null) {
782  part.setAttributeInt(BaseObject.DIRECTION, direction);
783  }
784  if (!parts.isEmpty()) {
785  parts.get(0).addTailPart(part);
786  }
787  parts.add(part);
788  }
789 
790  for (final G part : parts) {
791  final int mapX = pos.x + part.getArchetype().getMultiX();
792  final int mapY = pos.y + part.getArchetype().getMultiY();
793  insertionMode.insert(part, mapGrid.getMapSquare(mapX, mapY));
794  }
795 
796  final G head = parts.get(0);
797  if (baseObject instanceof Archetype) {
798  gameObjectFactory.createInventory(head, effectiveArchetype);
799  }
800 
801  return head;
802  }
803 
804  @Override
805  public void addGameObjectToMap(@NotNull final G gameObject, @NotNull final Point pos, @NotNull final InsertionMode insertionMode) {
806  if (!mapArchObject.isPointValid(pos)) {
807  LOG.error("addGameObjectToMap: trying to insert game object out of map bounds at " + pos.x + "/" + pos.y + ", map bounds is " + mapArchObject.getMapSize());
808  return;
809  }
810 
811  insertionMode.insert(gameObject, mapGrid.getMapSquare(pos.x, pos.y));
812  }
813 
814  @Override
815  public void moveEnv(@NotNull final G gameObject, @NotNull final Point pos, @NotNull final G nextGameObject) {
816  if (!nextGameObject.isHead()) {
817  throw new IllegalArgumentException("can't move tail part of a multi-part object");
818  }
819  assert !gameObject.isMulti(); // no tail parts should be present when inside inventory of another game object
820  final GameObjectContainer<G, A, R> nextGameObjectContainer;
821  if (nextGameObject.isInContainer()) {
822  nextGameObjectContainer = nextGameObject.getContainer();
823  if (nextGameObjectContainer == null) {
824  throw new IllegalArgumentException("can't move into container object");
825  }
826  } else {
827  nextGameObjectContainer = getMapSquare(pos);
828  }
829  final MapSquare<G, A, R> mapSquare = nextGameObjectContainer.getMapSquare();
830  if (mapSquare.getMapModel() != this) {
831  throw new IllegalArgumentException("can't move into a game object in another map");
832  }
833  gameObject.remove();
834  nextGameObjectContainer.insertAfter(nextGameObject, gameObject);
835 
836  // regenerate tail parts when inserted into a map square
837  if (!nextGameObject.isInContainer() && gameObject.getArchetype().isMulti()) {
838  final Point tmp = new Point();
839  for (R archetypeTail = gameObject.getArchetype().getMultiNext(); archetypeTail != null; archetypeTail = archetypeTail.getMultiNext()) {
840  final G gameObjectTail = archetypeTail.newInstance(gameObjectFactory);
841  gameObject.addTailPart(gameObjectTail);
842  tmp.x = pos.x + archetypeTail.getMultiX();
843  tmp.y = pos.y + archetypeTail.getMultiY();
844  addGameObjectToMap(gameObjectTail, tmp, topmostInsertionMode);
845  }
846  }
847  }
848 
849  @Override
850  public void moveInv(@NotNull final G gameObject, @NotNull final GameObject<G, A, R> prevGameObject) {
851  if (!gameObject.isHead() || !prevGameObject.isHead()) {
852  throw new IllegalArgumentException("can't move tail part of a multi-part object");
853  }
854 
855  gameObject.remove();
856  gameObject.removeTailParts();
857  prevGameObject.addFirst(gameObject);
858  }
859 
860  @Override
861  public boolean isAreaEmpty(final int left, final int top, final int width, final int height) {
862  final Point point = new Point();
863  for (int x = left; x < left + width; x++) {
864  point.x = x;
865  for (int y = top; y < top + height; y++) {
866  point.y = y;
867  if (!getMapSquare(point).isEmpty()) {
868  return false;
869  }
870  }
871  }
872  return true;
873  }
874 
875  @Override
876  public void addActiveEditType(final int editType) {
877  // calculate only if needed
878  if ((activeEditType & editType) != editType) {
879  beginTransaction("update edit types");
880  try {
881  for (final Iterable<G> mapSquare : this) {
882  for (final GameObject<G, A, R> gameObject : mapSquare) {
883  updateEditType(gameObject.getHead(), editType);
884  }
885  }
886  } finally {
887  endTransaction();
888  }
889  // from now on we have this type, so we don't have to calculate it again
890  activeEditType |= editType;
891  }
892  }
893 
894  @Override
895  public void setMapFile(@Nullable final MapFile mapFile) {
896  if (Objects.equals(this.mapFile, mapFile)) {
897  return;
898  }
899 
900  final MapFile oldMapFile = this.mapFile;
901  this.mapFile = mapFile;
902  fireMapFileChanged(oldMapFile);
903  }
904 
905  @Nullable
906  @Override
907  public MapFile getMapFile() {
908  return mapFile;
909  }
910 
911  @NotNull
912  @Override
913  public MapFile getMapFile(@NotNull final MapPath mapPath) throws SameMapException, UnsavedMapException {
914  final MapFile thisMapFile = mapFile;
915  if (thisMapFile == null) {
916  throw new UnsavedMapException();
917  }
918  final MapFile newMapFile = new MapFile(thisMapFile, mapPath);
919  if (newMapFile.equals(thisMapFile)) {
920  throw new SameMapException();
921  }
922  return newMapFile;
923  }
924 
925  @NotNull
926  @Override
927  public List<G> getAllGameObjects() {
928  final List<G> gameObjects = new ArrayList<>();
929  for (final Iterable<G> mapSquare : this) {
930  for (final G gameObject : mapSquare) {
931  if (gameObject.isHead()) {
932  gameObjects.add(gameObject);
933  }
934  }
935  }
936  return gameObjects;
937  }
938 
939  @Override
940  public boolean isModified() {
941  return modified;
942  }
943 
944  @Override
945  public void resetModified() {
946  if (!modified) {
947  return;
948  }
949 
950  modified = false;
952  }
953 
954  @Override
955  public void facesReloaded() {
956  beginTransaction("reload faces");
957  try {
958  for (final Iterable<G> mapSquare : this) {
959  for (final G gameObject : mapSquare) {
960  gameObject.facesReloaded();
961  }
962  }
963  } finally {
964  endTransaction();
965  }
966  }
967 
968  @Override
969  public void nextPoint(final Point point, final int direction) {
970  final Size2D mapSize = mapArchObject.getMapSize();
971  if (direction > 0) {
972  point.x++;
973  if (point.x >= mapSize.getWidth()) {
974  point.x = 0;
975  point.y++;
976  if (point.y >= mapSize.getHeight()) {
977  point.y = 0;
978  }
979  }
980  } else {
981  point.x--;
982  if (point.x < 0) {
983  point.x = mapSize.getWidth() - 1;
984  point.y--;
985  if (point.y < 0) {
986  point.y = mapSize.getHeight() - 1;
987  }
988  }
989  }
990  }
991 
995  private void setModified() {
996  if (modified) {
997  return;
998  }
999 
1000  modified = true;
1002  }
1003 
1010  private void updateEditType(@NotNull final GameObject<G, A, R> gameObject, final int checkType) {
1011  assert gameObject.isHead();
1012  if (checkType == 0) {
1013  return;
1014  }
1015 
1016  // all flags from 'checkType' must be unset in this game object because
1017  // they get recalculated now
1018  final int editType = gameObject.getEditType();
1019  final int retainedEditType = editType == BaseObject.EDIT_TYPE_NONE ? 0 : editType & ~checkType;
1020  final int newEditType = retainedEditType | calculateEditType(gameObject, checkType);
1021  gameObject.setEditType(newEditType);
1022  }
1023 
1030  private int calculateEditType(@NotNull final GameObject<?, ?, ?> gameObject, final int checkType) {
1031  int editType = 0;
1032  for (final NamedGameObjectMatcher matcher : gameObjectMatchers) {
1033  final int matcherEditType = matcher.getEditType();
1034  if ((matcherEditType & checkType) != 0 && matcher.isMatching(gameObject)) {
1035  editType |= matcherEditType;
1036  }
1037  }
1038  return editType;
1039  }
1040 
1051  @NotNull
1052  private InsertionResult<G, A, R> joinInsert(@NotNull final Point point, @NotNull final R archetype) {
1053  if (archetype.isMulti()) {
1054  return new InsertionResult<>(archetype);
1055  }
1056 
1057  final AutojoinList<G, A, R> autojoinList = autojoinLists.getAutojoinList(archetype);
1058  if (autojoinList == null) {
1059  return new InsertionResult<>(archetype);
1060  }
1061 
1062  // if there already is an archetype of this list at point -> abort
1063  final boolean isMainIndex = autojoinList.isMainIndex(archetype);
1064  final G gameObject = findGameObjectOfAutojoinList(point, autojoinList);
1065  if (gameObject != null) {
1066  final R gameObjectArchetype = gameObject.getArchetype();
1067  final boolean isExistingMainIndex = autojoinList.isMainIndex(gameObjectArchetype);
1068  if (isMainIndex) {
1069  // alt/main -> main
1070  if (isExistingMainIndex) {
1071  // ignore main -> main
1072  return new InsertionResult<>(); // we don't want same archetypes over each other
1073  }
1074  // alt -> main -> update
1075  } else {
1076  // alt/main -> alt
1077  if (isExistingMainIndex) {
1078  // main -> alt -> update
1079  } else {
1080  // alt -> alt -> update if different archetype
1081  if (gameObjectArchetype == archetype) {
1082  return new InsertionResult<>(); // we don't want same archetypes over each other
1083  }
1084  }
1085  }
1086  }
1087 
1088  // now do the joining in all four directions:
1089  final int altIndex = isMainIndex ? -1 : autojoinList.getAlternativeIndex(archetype);
1090  int newIndex = 0; // return value, see above
1091  newIndex |= joinInsert(point, autojoinList, 0, -1, AutojoinList.NORTH, AutojoinList.SOUTH, altIndex);
1092  newIndex |= joinInsert(point, autojoinList, +1, 0, AutojoinList.EAST, AutojoinList.WEST, altIndex);
1093  newIndex |= joinInsert(point, autojoinList, 0, +1, AutojoinList.SOUTH, AutojoinList.NORTH, altIndex);
1094  newIndex |= joinInsert(point, autojoinList, -1, 0, AutojoinList.WEST, AutojoinList.EAST, altIndex);
1095  final R newArchetype = isMainIndex ? autojoinList.getArchetype(newIndex) : archetype;
1096  if (gameObject != null) {
1097  gameObject.setArchetype(newArchetype);
1098  return new InsertionResult<>(gameObject);
1099  }
1100  return new InsertionResult<>(newArchetype);
1101  }
1102 
1103  private int joinInsert(@NotNull final Point point, @NotNull final AutojoinList<G, A, R> autojoinList, final int dx, final int dy, final int dir, final int reverseDir, final int altIndex) {
1104  final Point tmp = new Point(point.x + dx, point.y + dy);
1105  if (!mapArchObject.isPointValid(tmp)) {
1106  return 0;
1107  }
1108 
1109  final GameObject<G, A, R> gameObject = findGameObjectOfAutojoinList(tmp, autojoinList);
1110  if (gameObject == null) {
1111  return 0;
1112  }
1113 
1114  final R archetype = gameObject.getArchetype();
1115  final int index = autojoinList.getAlternativeIndex(archetype);
1116  if (index != -1) {
1117  return (index & reverseDir) == 0 ? 0 : dir;
1118  }
1119 
1120  final int archetypeIndex = autojoinList.getIndex(archetype);
1121  final int newIndex;
1122  if ((altIndex & dir) == 0) {
1123  newIndex = archetypeIndex & ~reverseDir;
1124  } else {
1125  newIndex = archetypeIndex | reverseDir;
1126  }
1127  gameObject.setArchetype(autojoinList.getArchetype(newIndex));
1128  return dir;
1129  }
1130 
1139  private void joinDelete(@NotNull final Point point, @NotNull final R archetype) {
1140  if (archetype.isMulti()) {
1141  return;
1142  }
1143 
1144  final AutojoinList<G, A, R> autojoinList = autojoinLists.getAutojoinList(archetype);
1145  if (autojoinList == null) {
1146  return;
1147  }
1148 
1149  final boolean isMainIndex = autojoinList.isMainIndex(archetype);
1150  final int altIndex = isMainIndex ? -1 : autojoinList.getAlternativeIndex(archetype);
1151 
1152  joinDelete(point, autojoinList, 0, -1, AutojoinList.NORTH, AutojoinList.SOUTH, altIndex);
1153  joinDelete(point, autojoinList, +1, 0, AutojoinList.EAST, AutojoinList.WEST, altIndex);
1154  joinDelete(point, autojoinList, 0, +1, AutojoinList.SOUTH, AutojoinList.NORTH, altIndex);
1155  joinDelete(point, autojoinList, -1, 0, AutojoinList.WEST, AutojoinList.EAST, altIndex);
1156  }
1157 
1158  private void joinDelete(@NotNull final Point point, @NotNull final AutojoinList<G, A, R> autojoinList, final int dx, final int dy, final int reverseDir, final int dir, final int altIndex) {
1159  if ((altIndex & reverseDir) == 0) {
1160  return;
1161  }
1162 
1163  final Point tmp = new Point(point.x + dx, point.y + dy);
1164  if (!mapArchObject.isPointValid(tmp)) {
1165  return;
1166  }
1167 
1168  final GameObject<G, A, R> gameObject = findMainGameObjectOfAutojoinList(tmp, autojoinList);
1169  if (gameObject == null) {
1170  return;
1171  }
1172 
1173  gameObject.setArchetype(autojoinList.getArchetype(autojoinList.getIndex(gameObject.getArchetype()) & ~dir));
1174  }
1175 
1184  @Nullable
1185  private G findGameObjectOfAutojoinList(@NotNull final Point point, @NotNull final AutojoinList<G, A, R> autojoinList) {
1186  for (final G gameObject : getMapSquare(point).reverse()) {
1187  if (autojoinLists.getAutojoinList(gameObject.getArchetype()) == autojoinList) {
1188  return gameObject;
1189  }
1190  }
1191 
1192  return null;
1193  }
1194 
1203  @Nullable
1204  private GameObject<G, A, R> findMainGameObjectOfAutojoinList(@NotNull final Point point, @NotNull final AutojoinList<G, A, R> autojoinList) {
1205  for (final GameObject<G, A, R> gameObject : getMapSquare(point).reverse()) {
1206  final R archetype = gameObject.getArchetype();
1207  if (autojoinLists.getAutojoinList(archetype) == autojoinList && autojoinList.isMainIndex(archetype)) {
1208  return gameObject;
1209  }
1210  }
1211 
1212  return null;
1213  }
1214 
1215 }
net.sf.gridarta.model.mapmodel.MapSquare.getMapY
int getMapY()
Returns the y coordinate on the map.
Definition: MapSquare.java:115
net.sf.gridarta.utils.Size2D.getWidth
int getWidth()
Returns the width of the area.
Definition: Size2D.java:96
name
name
Definition: ArchetypeTypeSetParserTest-ignoreDefaultAttribute1-result.txt:2
net.sf.gridarta.model.mapmodel.MapSquareGrid.getMapSize
Size2D getMapSize()
Returns the size of this map grid in map squares.
Definition: MapSquareGrid.java:195
net.sf.gridarta.model.mapmodel.MapModel
A MapModel reflects the data of a map.
Definition: MapModel.java:75
net.sf.gridarta.model.mapmodel.DefaultMapModel.getAllGameObjects
List< G > getAllGameObjects()
Definition: DefaultMapModel.java:927
net.sf.gridarta.model.mapmodel.SameMapException
Exception thrown if the destination path points to the source map.
Definition: SameMapException.java:26
net.sf.gridarta.model.gameobject.GameObjectFactory
Abstract factory for creating GameObject instances.
Definition: GameObjectFactory.java:31
net.sf.gridarta.model.mapmodel.DefaultMapModel
Implementation of MapModel that covers the similarities between crossfire and daimonin.
Definition: DefaultMapModel.java:61
net.sf.gridarta.model.mapmodel.DefaultMapModel.DefaultMapModel
DefaultMapModel(@NotNull final AutojoinLists< G, A, R > autojoinLists, @NotNull final A mapArchObject, @NotNull final ArchetypeChooserModel< G, A, R > archetypeChooserModel, @NotNull final GameObjectFactory< G, A, R > gameObjectFactory, @NotNull final GameObjectMatchers gameObjectMatchers, @NotNull final InsertionMode topmostInsertionMode)
Creates a new instance.
Definition: DefaultMapModel.java:233
net.sf.gridarta.model.mapmodel.DefaultMapModel.resetModified
void resetModified()
Definition: DefaultMapModel.java:945
net.sf.gridarta.model.mapmodel.DefaultMapModel.isMultiArchFittingToMap
boolean isMultiArchFittingToMap(@NotNull final Archetype< G, A, R > archetype, @NotNull final Point pos, final boolean allowDouble)
Definition: DefaultMapModel.java:664
net.sf.gridarta.model.mapmodel.DefaultMapModel.syncLock
final transient Object syncLock
Sync Lock Object.
Definition: DefaultMapModel.java:76
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireMapSizeChanged
void fireMapSizeChanged(@NotNull final Size2D newSize)
Fires a map size changed event.
Definition: DefaultMapModel.java:584
net.sf.gridarta.model.mapmodel.MapSquare.getMapSquareOptional
MapSquare< G, A, R > getMapSquareOptional()
Returns the MapSquare this game object is part of.
Definition: MapSquare.java:156
net.sf.gridarta.model.mapmodel.MapSquareGrid.resize
void resize(@NotNull final Size2D newSize)
Resizes the map grid to a new size.
Definition: MapSquareGrid.java:157
net.sf.gridarta.model.mapmodel.DefaultMapModel.transientChangedGameObjects
final Set< G > transientChangedGameObjects
The ArrayList with transient changed gameObjects.
Definition: DefaultMapModel.java:153
net.sf.gridarta.model.mapmodel.MapSquare.getMapLocation
Point getMapLocation()
Returns the coordinate on the map.
Definition: MapSquare.java:124
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapArchObjectListener
final transient MapArchObjectListener mapArchObjectListener
The MapArchObjectListener used to detect changes in {} and set the #modified} flag accordingly.
Definition: DefaultMapModel.java:209
net.sf.gridarta.model.mapmodel.LightMapModelTracker.mapSquaresChanged
void mapSquaresChanged(@NotNull final Iterable< MapSquare< G, A, R >> mapSquares)
Called whenever some game objects have changed.
Definition: LightMapModelTracker.java:97
net.sf.gridarta.model.mapmodel.DefaultMapModel.autojoinLists
final AutojoinLists< G, A, R > autojoinLists
The AutojoinLists for performing autojoining.
Definition: DefaultMapModel.java:88
net.sf.gridarta.model.mapmodel.MapSquare.getMapX
int getMapX()
Returns the x coordinate on the map.
Definition: MapSquare.java:107
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireEndTransaction
void fireEndTransaction()
Fires an end transaction event.
Definition: DefaultMapModel.java:614
net.sf.gridarta.model.archetypechooser.ArchetypeChooserModel
The view of the archetype chooser.
Definition: ArchetypeChooserModel.java:38
net.sf.gridarta.model.autojoin.InsertionResult
The result of an insertion operation involving autojoining.
Definition: InsertionResult.java:38
net.sf.gridarta.model.autojoin.AutojoinList.getAlternativeIndex
int getAlternativeIndex(@NotNull final R archetype)
Returns the index of an Archetype if it is an alternative archetype for any direction.
Definition: AutojoinList.java:177
net.sf.gridarta.model.mapmodel.DefaultMapModel.lightMapModelTracker
final LightMapModelTracker< G, A, R > lightMapModelTracker
The LightMapModelTracker tracking this instance.
Definition: DefaultMapModel.java:202
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.model.mapmodel.DefaultMapModel.updateEditType
void updateEditType(@NotNull final GameObject< G, A, R > gameObject, final int checkType)
Updates the edit type of a GameObject.
Definition: DefaultMapModel.java:1010
net.sf.gridarta.model.mapmodel.DefaultMapModel.errors
ErrorCollector< G, A, R > errors
The errors of this map model.
Definition: DefaultMapModel.java:159
net.sf.gridarta.model.mapmodel.DefaultMapModel.discardInvalidMapSquares
void discardInvalidMapSquares(@NotNull final Iterable< MapSquare< G, A, R >> mapSquares, @NotNull final Size2D mapSize)
Discards map squares that are out of map bounds.
Definition: DefaultMapModel.java:333
net.sf.gridarta.model.autojoin.AutojoinList.isMainIndex
boolean isMainIndex(@NotNull final R archetype)
Returns the index of an Archetype if it is a main archetype for any direction.
Definition: AutojoinList.java:161
net.sf.gridarta.model.autojoin.AutojoinList.WEST
static final int WEST
Definition: AutojoinList.java:65
net.sf.gridarta.model.mapmodel.DefaultMapModel.setModified
void setModified()
Marks the map as being modified.
Definition: DefaultMapModel.java:995
net.sf.gridarta.model.mapmodel.MapSquare< G, A, R >
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireEvents
void fireEvents()
Delivers all pending events.
Definition: DefaultMapModel.java:487
net.sf.gridarta.model.mapmodel.DefaultMapModel.addMapModelListener
void addMapModelListener(@NotNull final MapModelListener< G, A, R > listener)
Definition: DefaultMapModel.java:360
net.sf.gridarta.model.archetypechooser
Definition: ArchetypeChooserFolder.java:20
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireBeginTransaction
void fireBeginTransaction(@NotNull final String name)
Fires a begin transaction event.
Definition: DefaultMapModel.java:604
net.sf.gridarta.model.mapmodel.MapTransactionListener< G, A, R >
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapModelListeners
final List< MapModelListener< G, A, R > > mapModelListeners
The registered MapModelListeners.
Definition: DefaultMapModel.java:107
net.sf.gridarta.model.mapmodel.DefaultMapModel.clearMap
void clearMap()
Definition: DefaultMapModel.java:278
net.sf
net.sf.gridarta.model.maparchobject.MapArchObjectListener
Interface for listeners listening on map arch object changes.
Definition: MapArchObjectListener.java:30
net.sf.gridarta.model.mapmodel.DefaultMapModel.firePreBeginTransaction
void firePreBeginTransaction()
Fire a pre-begin transaction event.
Definition: DefaultMapModel.java:594
net.sf.gridarta.model.mapmodel.LightMapModelTracker.mapSizeChanging
void mapSizeChanging(@NotNull final Size2D newSize, @NotNull final Size2D oldSize)
Called whenever the tracked map is about to change size.
Definition: LightMapModelTracker.java:74
net.sf.gridarta.model.mapmodel.DefaultMapModel.insertBaseObject
G insertBaseObject(@NotNull final BaseObject< G, A, R, ?> baseObject, @NotNull final Point pos, final boolean allowMany, final boolean join, @NotNull final InsertionMode insertionMode)
Definition: DefaultMapModel.java:744
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapTransactionListeners
final Collection< MapTransactionListener< G, A, R > > mapTransactionListeners
The registered MapTransactionListeners.
Definition: DefaultMapModel.java:113
net.sf.gridarta.model.mapmodel.MapSquareGrid.clearMap
void clearMap()
This implementation is very safe by recreating every single MapSquare as new empty square with the tr...
Definition: MapSquareGrid.java:119
net.sf.gridarta.model.mapmodel.DefaultMapModel.archetypeChooserModel
final ArchetypeChooserModel< G, A, R > archetypeChooserModel
The ArchetypeChooserModel to use when inserting directional game objects.
Definition: DefaultMapModel.java:95
net.sf.gridarta.model.mapmodel.DefaultMapModel.endSquareChange
void endSquareChange(@NotNull final MapSquare< G, A, R > mapSquare)
Definition: DefaultMapModel.java:395
net.sf.gridarta.model.mapmodel.DefaultMapModel.getMapFile
MapFile getMapFile(@NotNull final MapPath mapPath)
Definition: DefaultMapModel.java:913
net.sf.gridarta.model.mapmodel.MapFile.equals
boolean equals(@Nullable final Object obj)
Definition: MapFile.java:122
net.sf.gridarta.model.mapmodel.DefaultMapModel.joinInsert
InsertionResult< G, A, R > joinInsert(@NotNull final Point point, @NotNull final R archetype)
Does autojoining on insertion of a game object on the map.
Definition: DefaultMapModel.java:1052
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.mapmodel.DefaultMapModel.calculateEditType
int calculateEditType(@NotNull final GameObject<?, ?, ?> gameObject, final int checkType)
Returns the edit type for a GameObject.
Definition: DefaultMapModel.java:1030
net.sf.gridarta.model.mapmodel.DefaultMapModel.iterator
Iterator< MapSquare< G, A, R > > iterator()
Definition: DefaultMapModel.java:258
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapClosed
void mapClosed()
Definition: DefaultMapModel.java:247
net.sf.gridarta.model.gameobject.GameObject
Reflects a game object (object on a map).
Definition: GameObject.java:36
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireMapSquaresChangedEvent
void fireMapSquaresChangedEvent(final Set< MapSquare< G, A, R >> mapSquares)
Fires a map squares changed event.
Definition: DefaultMapModel.java:559
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireGameObjectsChangedEvent
void fireGameObjectsChangedEvent(@NotNull final Set< G > gameObjects, @NotNull final Set< G > transientGameObjects)
Fires a game objects changed event.
Definition: DefaultMapModel.java:571
net.sf.gridarta.model.mapmodel.DefaultMapModel.isAreaEmpty
boolean isAreaEmpty(final int left, final int top, final int width, final int height)
Definition: DefaultMapModel.java:861
net.sf.gridarta.model.mapmodel.DefaultMapModel.endTransaction
void endTransaction()
Definition: DefaultMapModel.java:466
net.sf.gridarta.model.mapmodel.MapSquareGrid.getMapSquare
MapSquare< G, A, R > getMapSquare(final int x, final int y)
Returns the MapSquare at a given location.
Definition: MapSquareGrid.java:108
net.sf.gridarta.model.autojoin.AutojoinLists.getAutojoinList
AutojoinList< G, A, R > getAutojoinList(@NotNull final Archetype< G, A, R > archetype)
Returns an AutojoinList for a given archetype.
Definition: AutojoinLists.java:75
net.sf.gridarta.model.autojoin.AutojoinList.NORTH
static final int NORTH
Definition: AutojoinList.java:59
net.sf.gridarta.model.mapmodel.DefaultMapModel.joinDelete
void joinDelete(@NotNull final Point point, @NotNull final AutojoinList< G, A, R > autojoinList, final int dx, final int dy, final int reverseDir, final int dir, final int altIndex)
Definition: DefaultMapModel.java:1158
net.sf.gridarta.model.mapmodel.DefaultMapModel.savedSquares
final SavedSquares< G, A, R > savedSquares
Records unchanged square contents for all squares in {}.
Definition: DefaultMapModel.java:141
net.sf.gridarta.model.mapmodel.DefaultMapModel.facesReloaded
void facesReloaded()
Definition: DefaultMapModel.java:955
net.sf.gridarta.model.mapmodel.DefaultMapModel.endAllTransactions
void endAllTransactions()
Definition: DefaultMapModel.java:527
net.sf.gridarta.model.mapmodel.DefaultMapModel.findMainGameObjectOfAutojoinList
GameObject< G, A, R > findMainGameObjectOfAutojoinList(@NotNull final Point point, @NotNull final AutojoinList< G, A, R > autojoinList)
Looks for an archetype at map-position point which is the main archetypes part of an autojoin list.
Definition: DefaultMapModel.java:1204
net.sf.gridarta.model.mapmodel.DefaultMapModel.moveInv
void moveInv(@NotNull final G gameObject, @NotNull final GameObject< G, A, R > prevGameObject)
Definition: DefaultMapModel.java:850
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapGrid
final MapSquareGrid< G, A, R > mapGrid
The map, containing all arches grid-wise.
Definition: DefaultMapModel.java:101
net.sf.gridarta.model.mapmodel.DefaultMapModel.beginSquareChange
void beginSquareChange(@NotNull final MapSquare< G, A, R > mapSquare)
Definition: DefaultMapModel.java:385
net.sf.gridarta.model.archetypechooser.ArchetypeChooserModel.getDirection
Integer getDirection()
Returns the default direction for game objects created from archetypes.
Definition: ArchetypeChooserModel.java:198
net.sf.gridarta.model.mapmodel.SavedSquares< G, A, R >
net.sf.gridarta.model.baseobject.BaseObject.getArchetype
R getArchetype()
Returns the Archetype this GameObject is based on.
net.sf.gridarta.model.mapmodel.DefaultMapModel.getMapFile
MapFile getMapFile()
Definition: DefaultMapModel.java:907
net.sf.gridarta.model.autojoin.AutojoinList.SOUTH
static final int SOUTH
Definition: AutojoinList.java:63
net.sf.gridarta.model.match.NamedGameObjectMatcher
Decorates an arbitrary GameObjectMatcher with a localized name that is suitable for the user interfac...
Definition: NamedGameObjectMatcher.java:33
net.sf.gridarta.model.baseobject.BaseObject.EDIT_TYPE_NONE
int EDIT_TYPE_NONE
Definition: BaseObject.java:36
net.sf.gridarta.model.gameobject
GameObjects are the objects based on Archetypes found on maps.
Definition: AbstractGameObject.java:20
net.sf.gridarta.model.mapmodel.DefaultMapModel.LOG
static final Category LOG
The Logger for printing log messages.
Definition: DefaultMapModel.java:71
net.sf.gridarta.model.mapmodel.MapSquareGrid.isEmpty
boolean isEmpty()
Returns whether the map is empty.
Definition: MapSquareGrid.java:142
net
net.sf.gridarta.utils.Size2D.getHeight
int getHeight()
Returns the height of the area.
Definition: Size2D.java:104
net.sf.gridarta.model.mapmodel.SavedSquares.clear
void clear()
Forgets all saved squares.
Definition: SavedSquares.java:155
net.sf.gridarta.model.mapmodel.DefaultMapModel.endGameObjectChange
void endGameObjectChange(@NotNull final G gameObject)
Definition: DefaultMapModel.java:421
net.sf.gridarta.model.mapmodel.DefaultMapModel.resizeMapInt
void resizeMapInt(@NotNull final Size2D newSize)
Resizes the map grid after the map size has changed.
Definition: DefaultMapModel.java:291
net.sf.gridarta.model.mapmodel.DefaultMapModel.isEmpty
boolean isEmpty()
Definition: DefaultMapModel.java:283
net.sf.gridarta.model.mapmodel.DefaultMapModel.addGameObjectToMap
void addGameObjectToMap(@NotNull final G gameObject, @NotNull final Point pos, @NotNull final InsertionMode insertionMode)
Definition: DefaultMapModel.java:805
net.sf.gridarta.model.mapmodel.DefaultMapModel.findGameObjectOfAutojoinList
G findGameObjectOfAutojoinList(@NotNull final Point point, @NotNull final AutojoinList< G, A, R > autojoinList)
Looks for an archetype at map-position point which is part of an autojoin list.
Definition: DefaultMapModel.java:1185
net.sf.gridarta.model.mapmodel.LightMapModelTracker< G, A, R >
net.sf.gridarta.model.mapmodel.SavedSquares.recordMapSquare
void recordMapSquare(@NotNull final MapSquare< G, A, R > mapSquare)
Records a map square as changed.
Definition: SavedSquares.java:82
net.sf.gridarta.model.mapmodel.DefaultMapModel.removeMapTransactionListener
void removeMapTransactionListener(@NotNull final MapTransactionListener< G, A, R > listener)
Definition: DefaultMapModel.java:380
net.sf.gridarta.model.match
Classes related to matching {GameObjects}, so called { net.sf.gridarta.model.match....
Definition: AndGameObjectMatcher.java:20
net.sf.gridarta.model.autojoin
Definition: AutojoinList.java:20
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireModifiedChanged
void fireModifiedChanged()
Fires a map size changed event.
Definition: DefaultMapModel.java:643
net.sf.gridarta.model.mapmodel.MapSquareGrid.collectHeads
void collectHeads(final int minX, final int minY, final int maxX, final int maxY, @NotNull final Collection< GameObject< G, A, R >> objectsToDelete)
Adds all head parts for game object within an area to a collection.
Definition: MapSquareGrid.java:180
net.sf.gridarta.model.maparchobject.MapArchObject
Interface for MapArchObjects.
Definition: MapArchObject.java:40
net.sf.gridarta.model.mapmodel.DefaultMapModel.discardInvalidGameObjects
void discardInvalidGameObjects(@NotNull final Iterable< G > gameObjects, @NotNull final Size2D mapSize)
Discards game objects that are out of map bounds.
Definition: DefaultMapModel.java:348
net.sf.gridarta.model.match.GameObjectMatchers
Maintains GameObjectMatcher instances.
Definition: GameObjectMatchers.java:40
net.sf.gridarta.model.mapmodel.DefaultMapModel.removeGameObject
void removeGameObject(@NotNull final G gameObject, final boolean join)
Definition: DefaultMapModel.java:650
net.sf.gridarta.model.mapmodel.DefaultMapModel.isModified
boolean isModified()
Definition: DefaultMapModel.java:940
net.sf.gridarta.model.mapmodel.DefaultMapModel.transactionThread
transient Thread transactionThread
The thread that performs the current transaction.
Definition: DefaultMapModel.java:128
net.sf.gridarta.model.mapmodel.DefaultMapModel.getMapSquare
MapSquare< G, A, R > getMapSquare(@NotNull final Point pos)
Definition: DefaultMapModel.java:264
net.sf.gridarta.model.mapmodel.DefaultMapModel.isAnyTransactionActive
boolean isAnyTransactionActive()
Definition: DefaultMapModel.java:551
net.sf.gridarta.model.validation.ErrorCollector
An interface for classes that collect errors.
Definition: ErrorCollector.java:33
net.sf.gridarta.model.mapmodel.MapPath
Represents a maps directory local map path.
Definition: MapPath.java:31
net.sf.gridarta.model.mapmodel.DefaultMapModel.transactionDepth
int transactionDepth
The transaction depth.
Definition: DefaultMapModel.java:121
net.sf.gridarta.model.mapmodel.UnsavedMapException
Exception thrown if an operation is attempted on an unsaved map.
Definition: UnsavedMapException.java:26
net.sf.gridarta.model.validation
This package contains the framework for validating maps.
Definition: AbstractValidator.java:20
net.sf.gridarta.model.autojoin.AutojoinList
Contains a list of (typically wall-)arches which do autojoining.
Definition: AutojoinList.java:39
net.sf.gridarta.model.mapmodel.DefaultMapModel.getTransactionDepth
int getTransactionDepth()
Definition: DefaultMapModel.java:546
net.sf.gridarta.model.mapmodel.InsertionMode
Insertion modes.
Definition: InsertionMode.java:33
net.sf.gridarta.model.mapmodel.DefaultMapModel.gameObjectMatchers
final GameObjectMatchers gameObjectMatchers
The GameObjectMatchers to use.
Definition: DefaultMapModel.java:178
net.sf.gridarta.model.baseobject.BaseObject
Definition: BaseObject.java:34
net.sf.gridarta.model.mapmodel.DefaultMapModel.endTransaction
void endTransaction(final boolean fireEvent)
Definition: DefaultMapModel.java:471
net.sf.gridarta.model.mapmodel.MapFile
The location of a map file with a map directory.
Definition: MapFile.java:31
net.sf.gridarta.model.autojoin.AutojoinLists
Manages a mapping between archetypes to AutojoinLists.
Definition: AutojoinLists.java:35
net.sf.gridarta.model.mapmodel.DefaultMapModel.commitTransaction
void commitTransaction()
Performs ending a transaction.
Definition: DefaultMapModel.java:537
net.sf.gridarta.model.mapmodel.MapSquare.getMapModel
MapModel< G, A, R > getMapModel()
Returns the MapModel this map square is part of.
Definition: MapSquare.java:99
net.sf.gridarta.model.mapmodel.DefaultMapModel.firePostEndTransaction
void firePostEndTransaction()
Fires a post-end transaction event.
Definition: DefaultMapModel.java:624
net.sf.gridarta.model.mapmodel.MapModelListener< G, A, R >
net.sf.gridarta.model.mapmodel.DefaultMapModel.activeEditType
int activeEditType
Contains the edit types that have already been (requested and) calculated (edit types get calculated ...
Definition: DefaultMapModel.java:165
net.sf.gridarta.model.baseobject.GameObjectContainer.insertAfter
void insertAfter(@Nullable final G previousGameObject, @NotNull final G gameObject)
Adds a game object after another.
Definition: GameObjectContainer.java:461
net.sf.gridarta.model.mapmodel.DefaultMapModel.prependMapModelListener
void prependMapModelListener(@NotNull final MapModelListener< G, A, R > listener)
Definition: DefaultMapModel.java:365
net.sf.gridarta.model.mapmodel.DefaultMapModel.getErrors
ErrorCollector< G, A, R > getErrors()
Definition: DefaultMapModel.java:696
net.sf.gridarta.model.mapmodel.DefaultMapModel.nextPoint
void nextPoint(final Point point, final int direction)
Definition: DefaultMapModel.java:969
net.sf.gridarta.model.mapmodel.DefaultMapModel.joinInsert
int joinInsert(@NotNull final Point point, @NotNull final AutojoinList< G, A, R > autojoinList, final int dx, final int dy, final int dir, final int reverseDir, final int altIndex)
Definition: DefaultMapModel.java:1103
net.sf.gridarta.model.mapmodel.DefaultMapModel.gameObjectFactory
final GameObjectFactory< G, A, R > gameObjectFactory
The GameObjectFactory for creating GameObjects.
Definition: DefaultMapModel.java:172
net.sf.gridarta.model.mapmodel.DefaultMapModel.modified
boolean modified
Set if the map has changed since last save.
Definition: DefaultMapModel.java:196
net.sf.gridarta.model.mapmodel.DefaultMapModel.beginGameObjectChange
void beginGameObjectChange(@NotNull final G gameObject)
Definition: DefaultMapModel.java:410
net.sf.gridarta.model.gameobject.GameObject.addLast
void addLast(@NotNull G gameObject)
Add the given GameObject at the end of this Container.
net.sf.gridarta.model.mapmodel.DefaultMapModel.getMapArchObject
A getMapArchObject()
Definition: DefaultMapModel.java:253
net.sf.gridarta.model.gameobject.GameObject.getTopContainer
G getTopContainer()
Get the topmost container of this GameObject (in Game sense, which means being in a MapSquare isn't,...
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Reflects an Archetype.
Definition: Archetype.java:41
net.sf.gridarta.model.mapmodel.DefaultMapModel.addActiveEditType
void addActiveEditType(final int editType)
Definition: DefaultMapModel.java:876
net.sf.gridarta.model.baseobject
Definition: AbstractBaseObject.java:20
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapArchObject
final A mapArchObject
The MapArchObject associated with this model.
Definition: DefaultMapModel.java:82
net.sf.gridarta.model.mapmodel.DefaultMapModel.beginTransaction
void beginTransaction(@NotNull final String name)
Definition: DefaultMapModel.java:449
net.sf.gridarta.model.mapmodel.DefaultMapModel.changedSquares
final Set< MapSquare< G, A, R > > changedSquares
The ArrayList with changed squares.
Definition: DefaultMapModel.java:134
net.sf.gridarta.model.mapmodel.DefaultMapModel.addObjectListToMap
void addObjectListToMap(@NotNull final Iterable< G > objects)
Definition: DefaultMapModel.java:269
net.sf.gridarta.model.mapmodel.DefaultMapModel.mapFile
MapFile mapFile
The backing map file.
Definition: DefaultMapModel.java:191
net.sf.gridarta.var.crossfire.model.gameobject.GameObject<?, ?, ?>
net.sf.gridarta.model.mapmodel.DefaultMapModel.changedGameObjects
final Set< G > changedGameObjects
The ArrayList with changed gameObjects.
Definition: DefaultMapModel.java:147
net.sf.gridarta.model.autojoin.AutojoinList.getArchetype
R getArchetype(final int index)
Definition: AutojoinList.java:189
net.sf.gridarta.model.validation.DefaultErrorCollector
Simple error collector that just collects the error in a collection for later retrieval through itera...
Definition: DefaultErrorCollector.java:37
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.model.mapmodel.DefaultMapModel.joinDelete
void joinDelete(@NotNull final Point point, @NotNull final R archetype)
Does autojoining on deletion of a GameObject on the map.
Definition: DefaultMapModel.java:1139
net.sf.gridarta.model.baseobject.BaseObject.getMultiNext
T getMultiNext()
Returns the next of this multi-part object.
net.sf.gridarta.model.mapmodel.DefaultMapModel.moveEnv
void moveEnv(@NotNull final G gameObject, @NotNull final Point pos, @NotNull final G nextGameObject)
Definition: DefaultMapModel.java:815
net.sf.gridarta.model.mapmodel.DefaultMapModel.fireMapFileChanged
void fireMapFileChanged(@Nullable final MapFile oldMapFile)
Firess a map file changed event.
Definition: DefaultMapModel.java:634
net.sf.gridarta.model.mapmodel.DefaultMapModel.serialVersionUID
static final long serialVersionUID
The serial version UID.
Definition: DefaultMapModel.java:66
net.sf.gridarta.model.mapmodel.DefaultMapModel.insertArchToMap
G insertArchToMap(@NotNull final BaseObject< G, A, R, ?> templateBaseObject, @Nullable final G nextGameObject, @NotNull final Point pos, final boolean join)
@xxx I'm too complex
Definition: DefaultMapModel.java:705
net.sf.gridarta.model.mapmodel.DefaultMapModel.setMapFile
void setMapFile(@Nullable final MapFile mapFile)
Definition: DefaultMapModel.java:895
net.sf.gridarta.model.baseobject.GameObjectContainer
Base class for classes that contain GameObjects as children in the sense of containment.
Definition: GameObjectContainer.java:50
net.sf.gridarta.model.mapmodel.DefaultMapModel.transientGameObjectChange
void transientGameObjectChange(@NotNull final G gameObject)
Definition: DefaultMapModel.java:435
net.sf.gridarta.model.mapmodel.DefaultMapModel.addMapTransactionListener
void addMapTransactionListener(@NotNull final MapTransactionListener< G, A, R > listener)
Definition: DefaultMapModel.java:375
net.sf.gridarta.utils.Size2D
The class Size2D represents a 2d rectangular area.
Definition: Size2D.java:30
net.sf.gridarta.model.mapmodel.DefaultMapModel.removeMapModelListener
void removeMapModelListener(@NotNull final MapModelListener< G, A, R > listener)
Definition: DefaultMapModel.java:370
net.sf.gridarta.model.autojoin.InsertionResult.getGameObject
G getGameObject()
Returns the GameObject that has been modified.
Definition: InsertionResult.java:87
net.sf.gridarta.model.mapmodel.DefaultMapModel.setErrors
void setErrors(@NotNull final ErrorCollector< G, A, R > errors)
Definition: DefaultMapModel.java:687
net.sf.gridarta.model.baseobject.GameObjectContainer.getMapSquare
abstract MapSquare< G, A, R > getMapSquare()
Returns the MapSquare this game object is part of.
net.sf.gridarta.model.mapmodel.MapSquare.getMapSquare
MapSquare< G, A, R > getMapSquare()
Returns the MapSquare this game object is part of.
Definition: MapSquare.java:150
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.model.autojoin.InsertionResult.getArchetype
R getArchetype()
Returns the Archetype that should be inserted.
Definition: InsertionResult.java:97
net.sf.gridarta.model.gameobject.GameObject.setArchetype
void setArchetype(@NotNull R archetype)
Set the Archetype of this GameObject.
net.sf.gridarta.model.mapmodel.MapSquareIterator
Iterator for iterating over all squares of a model.
Definition: MapSquareIterator.java:37
net.sf.gridarta.model.mapmodel.DefaultMapModel.topmostInsertionMode
final InsertionMode topmostInsertionMode
The "topmost" InsertionMode.
Definition: DefaultMapModel.java:184
net.sf.gridarta.model.gameobject.GameObjectFactory.createInventory
void createInventory(@NotNull GameObject< G, A, R > gameObject, @NotNull Iterable< G > archetype)
Copies inventory objects from an archetype into a game object.
it
This document describes some hints and requirements for general development on the CrossfireEditor If you plan to make changes to the editor code or setup please read the following and keep it in derived from a basic editor application called Gridder by Pasi Ker�nen so please communicate with best through the cf devel mailing before considering any fundamental changes About code DO NOT USE TABS No matter what Java development platform you are please configure insert indent Tabs are displayed totally different in every editor and there are millions of different editors out there The insertion of tabs in the source code is messing up the syntax formatting in a way that is UNREPAIRABLE Apart from please keep code indentation accurate This is not just good it helps to keep code readable and in that way dramatically decreases the chance for overlooked bugs Everyone is welcomed to correct indentation errors wherever they are spotted Before you start to do this please double check that your editor is really configured to insert spaces Line feeds may be checked in either in windows or in unix linux style All reasonable text and java editors can deal with both linefeed formats Converting line feeds is but in this case please make sure that only linefeed characters are changed and nothing else is affected Due to the platform independent nature of the editor has the potential to run on almost any given operating system the build process differs greatly between systems as well as java environments In the several people have attempted to add build scripts along with structural changes to optimize the setup on one particular system environment which has led to conflict Please do *not *attempt to change the structure or any directories for the mere purpose of improving a build process or performance in a java environment Build scripts may be placed in the root it would be especially fine if it is just one or two files but the latter is not required Please excuse me for placing such restriction I and many users of the editor greatly appreciate build scripts We just had some real troubles over this issue in the past and I don t want to have them repeated the editor has relatively high performance requirements I ve spent a lot of extra work to keep everything as fast and memory efficient as possible when you add new data fields or calculations in the archetype please make sure they are as efficient as possible and worth both the time and space they consume Now don t be afraid too much No development would be possible without adding calculations and data at all Just bear in mind unlike for many other open source performance does make a difference for the CrossfireEditor The for as many systems as possible In case you are unexperienced with java and note that the graphics look different on every and with every font They also have different sizes proportions and behave different A seemingly trivial and effectless change can wreck havoc for the same GUI run on another system please don t be totally afraid of it
Definition: Developer_README.txt:76
net.sf.gridarta.model.baseobject.BaseObject.DIRECTION
String DIRECTION
The attribute name of the object's direction.
Definition: BaseObject.java:48
net.sf.gridarta.model.autojoin.AutojoinList.EAST
static final int EAST
Definition: AutojoinList.java:61
net.sf.gridarta.model.gameobject.GameObject.getContainerGameObject
G getContainerGameObject()
Returns the environment game object if this game object is in the inventory or.
net.sf.gridarta.model.mapmodel.MapSquareGrid< G, A, R >