Gridarta Editor
SavedSquares.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.mapmodel;
21 
22 import java.awt.Point;
23 import java.io.Serializable;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
33 import net.sf.gridarta.utils.Size2D;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36 
41 public class SavedSquares<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements Serializable {
42 
46  private static final long serialVersionUID = 1L;
47 
52  @NotNull
53  private final List<ArrayList<ArrayList<G>>> savedSquares = new ArrayList<>();
54 
58  @NotNull
60 
64  @NotNull
66 
72  public SavedSquares(@NotNull final GameObjectFactory<G, A, R> gameObjectFactory, @NotNull final GameObjectMatchers gameObjectMatchers) {
73  this.gameObjectFactory = gameObjectFactory;
74  this.gameObjectMatchers = gameObjectMatchers;
75  }
76 
82  public void recordMapSquare(@NotNull final MapSquare<G, A, R> mapSquare) {
83  final int x = mapSquare.getMapX();
84  final int y = mapSquare.getMapY();
85  final ArrayList<G> list = allocateMapSquare(x, y);
86  if (list == null) {
87  return;
88  }
89 
90  for (final G content : mapSquare) {
91  if (content.isHead()) {
92  list.add(gameObjectFactory.cloneMultiGameObject(content));
93  }
94  }
95  list.trimToSize();
96  }
97 
105  @Nullable
106  private ArrayList<G> allocateMapSquare(final int x, final int y) {
107  final ArrayList<ArrayList<G>> col;
108  if (x >= savedSquares.size()) {
109  while (savedSquares.size() < x) {
110  savedSquares.add(null);
111  }
112  col = new ArrayList<>();
113  savedSquares.add(col);
114  } else {
115  final ArrayList<ArrayList<G>> tmp = savedSquares.get(x);
116  if (tmp != null) {
117  col = tmp;
118  } else {
119  col = new ArrayList<>();
120  savedSquares.set(x, col);
121  }
122  }
123 
124  final ArrayList<G> result;
125  if (y >= col.size()) {
126  while (col.size() < y) {
127  col.add(null);
128  }
129  result = new ArrayList<>();
130  col.add(result);
131  } else {
132  final Collection<G> tmp = col.get(y);
133  if (tmp != null) {
134  return null;
135  }
136 
137  result = new ArrayList<>();
138  col.set(y, result);
139  }
140 
141  return result;
142  }
143 
148  public boolean isEmpty() {
149  return savedSquares.isEmpty();
150  }
151 
155  public void clear() {
156  savedSquares.clear();
157  }
158 
164  @NotNull
167  clone.savedSquares.addAll(savedSquares);
168  savedSquares.clear();
169  return clone;
170  }
171 
176  public void applyChanges(@NotNull final MapModel<G, A, R> mapModel) {
177  final Collection<G> objectsToDelete = new ArrayList<>();
178 
179  final Point point = new Point();
180  point.x = 0;
181  for (final Iterable<ArrayList<G>> col : savedSquares) {
182  if (col != null) {
183  point.y = 0;
184  for (final Iterable<G> square : col) {
185  if (square != null) {
186  final GameObjectContainer<G, A, R> mapSquare = mapModel.getMapSquare(point);
187  for (final G gameObject : mapSquare) {
188  if (gameObject.isHead()) {
189  objectsToDelete.add(gameObject);
190  }
191  }
192  for (final G gameObject : objectsToDelete) {
193  mapModel.removeGameObject(gameObject, false);
194  }
195  objectsToDelete.clear();
196  for (final G gameObject : square) {
197  mapSquare.addLast(gameObject);
198  }
199  }
200  point.y++;
201  }
202  }
203  point.x++;
204  }
205 
206  final Point point2 = new Point();
207  point.x = 0;
208  for (final Iterable<ArrayList<G>> col : savedSquares) {
209  if (col != null) {
210  point.y = 0;
211  for (final Iterable<G> square : col) {
212  if (square != null) {
213  for (final GameObject<G, A, R> gameObject : square) {
214  final Point map = gameObject.getMapLocation();
215  for (G tailGameObject = gameObject.getMultiNext(); tailGameObject != null; tailGameObject = tailGameObject.getMultiNext()) {
216  point2.x = map.x + tailGameObject.getArchetype().getMultiX();
217  point2.y = map.y + tailGameObject.getArchetype().getMultiY();
218  final GameObjectContainer<G, A, R> mapSquare = mapModel.getMapSquare(point2);
219  mapSquare.addLast(tailGameObject);
220  }
221  }
222  }
223  point.y++;
224  }
225  }
226  point.x++;
227  }
228  }
229 
234  public void removeEmptySquares(@NotNull final Size2D size) {
235  final int width = size.getWidth();
236  final int height = size.getHeight();
237 
238  if (!isOutsideEmpty(width, height)) {
239  throw new IllegalArgumentException();
240  }
241 
242  for (int x = 0; x < width && x < savedSquares.size(); x++) {
243  final List<ArrayList<G>> col = savedSquares.get(x);
244  if (col != null) {
245  for (int y = col.size() - 1; y >= height; y--) {
246  col.remove(y);
247  }
248  }
249  }
250  for (int x = savedSquares.size() - 1; x >= width; x--) {
251  savedSquares.remove(x);
252  }
253  }
254 
261  private boolean isOutsideEmpty(final int width, final int height) {
262  for (int x = 0; x < width && x < savedSquares.size(); x++) {
263  final List<ArrayList<G>> col = savedSquares.get(x);
264  if (col != null) {
265  for (int y = height; y < col.size(); y++) {
266  final Collection<G> square = col.get(y);
267  if (!square.isEmpty()) {
268  return false;
269  }
270  }
271  }
272  }
273 
274  for (int x = width; x < savedSquares.size(); x++) {
275  final Iterable<ArrayList<G>> col = savedSquares.get(x);
276  if (col != null) {
277  for (final Collection<G> square : col) {
278  if (square != null && !square.isEmpty()) {
279  return false;
280  }
281  }
282  }
283  }
284 
285  return true;
286  }
287 
288 }
void applyChanges(@NotNull final MapModel< G, A, R > mapModel)
Applies the saved squares to the given map model.
boolean isEmpty()
Returns whether no saved squares exist.
SavedSquares(@NotNull final GameObjectFactory< G, A, R > gameObjectFactory, @NotNull final GameObjectMatchers gameObjectMatchers)
Creates a new instance.
void addLast(@NotNull final G gameObject)
Add the given GameObject at the end of this Container.
void recordMapSquare(@NotNull final MapSquare< G, A, R > mapSquare)
Records a map square as changed.
This package contains classes related to matching GameObjects, so called GameObjectMatchers.
abstract MapSquare< G, A, R > getMapSquare()
Returns the MapSquare of this container.
boolean isOutsideEmpty(final int width, final int height)
Returns whether all squares outside a given area are empty or unchanged.
G cloneMultiGameObject(@NotNull G gameObject)
Creates a copy of a game object, including tail parts.
Base class for classes that contain GameObjects as children in the sense of containment.
SavedSquares< G, A, R > cloneAndClear()
Creates a new instance having the same contents as this instance, then forgets all saves squares in t...
Base package of all Gridarta classes.
final List< ArrayList< ArrayList< G > > > savedSquares
The saved squares.
Reflects a game object (object on a map).
Definition: GameObject.java:36
Abstract factory for creating GameObject instances.
final GameObjectFactory< G, A, R > gameObjectFactory
The GameObjectFactory to use.
GameObjects are the objects based on Archetypes found on maps.
ArrayList< G > allocateMapSquare(final int x, final int y)
Allocates a saved map square.
Maintains GameObjectMatcher instances.
static final long serialVersionUID
The serial version UID.
final GameObjectMatchers gameObjectMatchers
The GameObjectMatchers to use.
void clear()
Forgets all saved squares.
void removeEmptySquares(@NotNull final Size2D size)
Removes empty squares outside a given area.
Records a set of changed map squares.
The class Size2D represents a 2d rectangular area.
Definition: Size2D.java:30