001/* 002 * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games. 003 * Copyright (C) 2000-2010 The Gridarta Developers. 004 * 005 * This program is free software; you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation; either version 2 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License along 016 * with this program; if not, write to the Free Software Foundation, Inc., 017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 018 */ 019 020package net.sf.gridarta.var.crossfire.model.gameobject; 021 022import java.util.Iterator; 023import net.sf.gridarta.model.baseobject.GameObjectContainer; 024import net.sf.gridarta.var.crossfire.model.archetype.Archetype; 025import net.sf.gridarta.var.crossfire.model.maparchobject.MapArchObject; 026import org.jetbrains.annotations.NotNull; 027import org.junit.Assert; 028import org.junit.Test; 029 030/** 031 * Checks that {@link GameObjectContainer GameObjectContainers} correctly 032 * propagate elevation information when being modified. 033 * @author Andreas Kirschbaum 034 */ 035public class PropagateElevationTest { 036 037 /** 038 * Checks that {@link GameObjectContainer#addFirst(net.sf.gridarta.model.gameobject.GameObject)} 039 * does work correctly. 040 */ 041 @Test 042 public void testAddFirst() { 043 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 044 final GameObjectContainer<GameObject, MapArchObject, Archetype> gameObjectContainer = gameObjectCreator.newGameObject(0); 045 046 // first game object => keep 047 gameObjectContainer.addFirst(gameObjectCreator.newGameObject(123)); 048 check(gameObjectContainer, 123); 049 050 // without elevation => propagate 051 gameObjectContainer.addFirst(gameObjectCreator.newGameObject(0)); 052 check(gameObjectContainer, 123); 053 054 // with elevation => ignore but propagate 055 gameObjectContainer.addFirst(gameObjectCreator.newGameObject(321)); 056 check(gameObjectContainer, 123); 057 } 058 059 /** 060 * Checks that {@link GameObjectContainer#addLast(net.sf.gridarta.model.gameobject.GameObject)} 061 * does work correctly. 062 */ 063 @Test 064 public void testAddLast() { 065 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 066 final GameObjectContainer<GameObject, MapArchObject, Archetype> gameObjectContainer = gameObjectCreator.newGameObject(0); 067 068 // first game object => keep 069 gameObjectContainer.addLast(gameObjectCreator.newGameObject(123)); 070 check(gameObjectContainer, 123); 071 072 // without elevation => keep 073 gameObjectContainer.addLast(gameObjectCreator.newGameObject(0)); 074 check(gameObjectContainer, 123, 0); 075 076 // with elevation => keep 077 gameObjectContainer.addLast(gameObjectCreator.newGameObject(321)); 078 check(gameObjectContainer, 123, 0, 321); 079 } 080 081 /** 082 * Checks that {@link GameObjectContainer#insertBefore(net.sf.gridarta.model.gameobject.GameObject, 083 * net.sf.gridarta.model.gameobject.GameObject)} does work correctly. 084 */ 085 @Test 086 public void testInsertBefore() { 087 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 088 final GameObjectContainer<GameObject, MapArchObject, Archetype> gameObjectContainer = gameObjectCreator.newGameObject(0); 089 090 // first game object => keep 091 gameObjectContainer.insertBefore(gameObjectCreator.newGameObject(1), null); 092 check(gameObjectContainer, 1); 093 094 // without elevation => propagate 095 gameObjectContainer.insertBefore(gameObjectCreator.newGameObject(0), null); 096 check(gameObjectContainer, 1, 0); 097 098 // with elevation => ignore but propagate 099 final GameObject ob1 = gameObjectCreator.newGameObject(2); 100 gameObjectContainer.insertBefore(ob1, null); 101 check(gameObjectContainer, 1, 0, 0); 102 103 // with elevation => keep 104 gameObjectContainer.insertBefore(gameObjectCreator.newGameObject(3), ob1); 105 check(gameObjectContainer, 1, 3, 0, 0); 106 107 // with elevation => ignore but propagate 108 gameObjectContainer.insertBefore(gameObjectCreator.newGameObject(4), null); 109 check(gameObjectContainer, 1, 0, 3, 0, 0); 110 } 111 112 /** 113 * Checks that {@link GameObjectContainer#insertAfter(net.sf.gridarta.model.gameobject.GameObject, 114 * net.sf.gridarta.model.gameobject.GameObject)} does work correctly. 115 */ 116 @Test 117 public void testInsertAfter() { 118 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 119 final GameObjectContainer<GameObject, MapArchObject, Archetype> gameObjectContainer = gameObjectCreator.newGameObject(0); 120 121 // first game object => keep 122 gameObjectContainer.insertAfter(null, gameObjectCreator.newGameObject(1)); 123 check(gameObjectContainer, 1); 124 125 // at end => keep 126 final GameObject ob1 = gameObjectCreator.newGameObject(2); 127 gameObjectContainer.insertAfter(null, ob1); 128 check(gameObjectContainer, 1, 2); 129 130 // at front, without elevation => propagate 131 gameObjectContainer.insertAfter(ob1, gameObjectCreator.newGameObject(0)); 132 check(gameObjectContainer, 1, 0, 2); 133 134 // middle => keep 135 gameObjectContainer.insertAfter(ob1, gameObjectCreator.newGameObject(3)); 136 check(gameObjectContainer, 1, 0, 3, 2); 137 138 // at front, with elevation => ignore but propagate 139 gameObjectContainer.insertAfter(gameObjectContainer.getFirst(), gameObjectCreator.newGameObject(4)); 140 check(gameObjectContainer, 1, 0, 0, 3, 2); 141 } 142 143 /** 144 * Checks that {@link GameObjectContainer#moveBottom(net.sf.gridarta.model.gameobject.GameObject)} 145 * does work correctly. 146 */ 147 @Test 148 public void testMoveBottom() { 149 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 150 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0); 151 container1.moveBottom(get(container1, 0)); 152 check(container1, 1, 0, 0, 0); 153 container1.moveBottom(get(container1, 1)); 154 check(container1, 1, 0, 0, 0); 155 container1.moveBottom(get(container1, 3)); 156 check(container1, 1, 0, 0, 0); 157 } 158 159 /** 160 * Checks that {@link GameObjectContainer#moveDown(net.sf.gridarta.model.gameobject.GameObject)} 161 * does work correctly. 162 */ 163 @Test 164 public void testMoveDown() { 165 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 166 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0); 167 container1.moveDown(get(container1, 0)); 168 check(container1, 1, 0, 0, 0); 169 container1.moveDown(get(container1, 1)); 170 check(container1, 1, 0, 0, 0); 171 container1.moveDown(get(container1, 3)); 172 check(container1, 1, 0, 0, 0); 173 } 174 175 /** 176 * Checks that {@link GameObjectContainer#moveUp(net.sf.gridarta.model.gameobject.GameObject)} 177 * does work correctly. 178 */ 179 @Test 180 public void testMoveUp() { 181 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 182 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0); 183 container1.moveUp(get(container1, 0)); 184 check(container1, 1, 0, 0, 0); 185 container1.moveUp(get(container1, 1)); 186 check(container1, 1, 0, 0, 0); 187 container1.moveUp(get(container1, 3)); 188 check(container1, 1, 0, 0, 0); 189 } 190 191 /** 192 * Checks that {@link GameObjectContainer#moveTop(net.sf.gridarta.model.gameobject.GameObject)} 193 * does work correctly. 194 */ 195 @Test 196 public void testMoveTop() { 197 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 198 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0); 199 container1.moveTop(get(container1, 0)); 200 check(container1, 1, 0, 0, 0); 201 container1.moveTop(get(container1, 1)); 202 check(container1, 1, 0, 0, 0); 203 container1.moveTop(get(container1, 3)); 204 check(container1, 1, 0, 0, 0); 205 } 206 207 /** 208 * Checks that {@link GameObjectContainer#remove(net.sf.gridarta.model.gameobject.GameObject)} 209 * does work correctly. 210 */ 211 @Test 212 public void testRemove() { 213 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 214 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0); 215 container1.remove(get(container1, 0)); 216 check(container1, 1, 0, 0); 217 container1.remove(get(container1, 2)); 218 check(container1, 1, 0); 219 container1.remove(get(container1, 0)); 220 check(container1, 1); 221 container1.remove(get(container1, 0)); 222 check(container1); 223 } 224 225 /** 226 * Checks that {@link GameObjectContainer#replace(net.sf.gridarta.model.gameobject.GameObject, 227 * net.sf.gridarta.model.gameobject.GameObject)} does work correctly. 228 */ 229 @Test 230 public void testReplace() { 231 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 232 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0); 233 container1.replace(get(container1, 0), gameObjectCreator.newGameObject(2)); 234 check(container1, 1, 0, 0, 0); 235 container1.replace(get(container1, 1), gameObjectCreator.newGameObject(3)); 236 check(container1, 1, 3, 0, 0); 237 container1.replace(get(container1, 0), gameObjectCreator.newGameObject(4)); 238 check(container1, 1, 3, 0, 0); 239 } 240 241 /** 242 * Checks that {@link GameObjectContainer#iterator()}'s {@link 243 * Iterator#remove()} does work correctly. 244 */ 245 @Test 246 public void testIterator() { 247 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 248 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0, 0, 0); 249 final Iterator<GameObject> it = container1.iterator(); 250 it.next(); 251 it.remove(); 252 check(container1, 1, 0, 0, 0, 0); 253 it.next(); 254 it.remove(); 255 check(container1, 1, 0, 0, 0); 256 it.next(); 257 it.next(); 258 it.remove(); 259 check(container1, 1, 0, 0); 260 } 261 262 /** 263 * Checks that {@link GameObjectContainer#reverse()}'s {@link 264 * Iterator#remove()} does work correctly. 265 */ 266 @Test 267 public void testReverse() { 268 final GameObjectCreator gameObjectCreator = new GameObjectCreator(); 269 final GameObjectContainer<GameObject, MapArchObject, Archetype> container1 = newContainer(gameObjectCreator, 1, 0, 0, 0, 0, 0); 270 final Iterator<GameObject> it = container1.reverse().iterator(); 271 it.next(); 272 it.remove(); 273 check(container1, 1, 0, 0, 0, 0); 274 it.next(); 275 it.remove(); 276 check(container1, 1, 0, 0, 0); 277 it.next(); 278 it.next(); 279 it.remove(); 280 check(container1, 1, 0, 0); 281 it.next(); 282 it.remove(); 283 check(container1, 1, 0); 284 it.next(); 285 it.remove(); 286 check(container1, 1); 287 Assert.assertFalse(it.hasNext()); 288 } 289 290 /** 291 * Creates a new {@link GameObjectContainer} that contains game objects with 292 * the given elevation values. 293 * @param gameObjectCreator the game object creator to use 294 * @param elevations the elevations 295 * @return the game object container 296 */ 297 @NotNull 298 private static GameObjectContainer<GameObject, MapArchObject, Archetype> newContainer(@NotNull final GameObjectCreator gameObjectCreator, final int... elevations) { 299 final GameObjectContainer<GameObject, MapArchObject, Archetype> gameObject = gameObjectCreator.newGameObject(0); 300 for (final int elevation : elevations) { 301 gameObject.addLast(gameObjectCreator.newGameObject(elevation)); 302 } 303 return gameObject; 304 } 305 306 /** 307 * Returns the game object at a given index. 308 * @param gameObjects the game objects to search 309 * @param index the index 310 * @return the game object at <code>index</code> 311 */ 312 @NotNull 313 private static GameObject get(@NotNull final Iterable<GameObject> gameObjects, final int index) { 314 int left = index; 315 for (final GameObject gameObject : gameObjects) { 316 if (left == 0) { 317 return gameObject; 318 } 319 left--; 320 } 321 322 Assert.fail("index " + index + " not found"); 323 throw new AssertionError(); 324 } 325 326 /** 327 * Checks some game objects for expected elevation values. 328 * @param gameObjects the game objects 329 * @param elevation the expected elevation value for the first game object 330 */ 331 private static void check(@NotNull final Iterable<GameObject> gameObjects, final int... elevation) { 332 int i = 0; 333 for (final GameObject gameObject : gameObjects) { 334 final int thisElevation = gameObject.getAttributeInt(GameObject.ELEVATION); 335 final int expectedElevation = i < elevation.length ? elevation[i] : 0; 336 Assert.assertEquals(gameObject.getBestName(), expectedElevation, thisElevation); 337 i++; 338 } 339 } 340 341}