1 /* $Id$ */ 2 /*************************************************************************** 3 * (C) Copyright 2003 - Marauroa * 4 *************************************************************************** 5 *************************************************************************** 6 * * 7 * This program is free software; you can redistribute it and/or modify * 8 * it under the terms of the GNU General Public License as published by * 9 * the Free Software Foundation; either version 2 of the License, or * 10 * (at your option) any later version. * 11 * * 12 ***************************************************************************/ 13 package games.stendhal.server.core.rule.defaultruleset; 14 15 import java.net.URI; 16 import java.util.Collection; 17 import java.util.HashMap; 18 import java.util.List; 19 import java.util.Map; 20 21 import org.apache.log4j.Logger; 22 23 import games.stendhal.common.parser.ExpressionType; 24 import games.stendhal.common.parser.WordList; 25 import games.stendhal.server.core.config.CreatureGroupsXMLLoader; 26 import games.stendhal.server.core.config.ItemGroupsXMLLoader; 27 import games.stendhal.server.core.config.ShopsXMLLoader; 28 import games.stendhal.server.core.config.SpellGroupsXMLLoader; 29 import games.stendhal.server.core.rule.EntityManager; 30 import games.stendhal.server.entity.Entity; 31 import games.stendhal.server.entity.creature.Creature; 32 import games.stendhal.server.entity.item.Item; 33 import games.stendhal.server.entity.spell.Spell; 34 35 /** 36 * entity manager for the default ruleset. 37 * 38 * @author Matthias Totz 39 */ 40 public class DefaultEntityManager implements EntityManager { 41 42 /** the logger instance. */ 43 private static final Logger LOGGER = Logger.getLogger(DefaultEntityManager.class); 44 45 /** maps the tile ids to the classes. */ 46 private final Map<String, String> idToClass; 47 48 /** maps the item names to the actual item enums. */ 49 private final Map<String, DefaultItem> classToItem; 50 51 /** lists all creatures that are being used at least once. */ 52 private final Map<String, Creature> createdCreature; 53 54 /** lists all items that are being used at least once . */ 55 private final Map<String, Item> createdItem; 56 57 /** lists all spell that are being used at least once . */ 58 private final Map<String, Spell> createdSpell; 59 60 /** 61 * lists all loaded default spells that are usable 62 */ 63 private final Map<String, DefaultSpell> nameToSpell; 64 65 private LowerCaseMap<DefaultCreature> classToCreature; 66 67 /** no public constructor. */ DefaultEntityManager()68 public DefaultEntityManager() { 69 idToClass = new HashMap<String, String>(); 70 createdCreature = new HashMap<String, Creature>(); 71 createdItem = new HashMap<String, Item>(); 72 createdSpell = new HashMap<String, Spell>(); 73 classToItem = new HashMap<String, DefaultItem>(); 74 nameToSpell = new HashMap<String, DefaultSpell>(); 75 buildItemTables(); 76 buildCreatureTables(); 77 buildSpellTables(); 78 79 ShopsXMLLoader.get().init(); 80 } 81 82 /** 83 * builds the spell tables 84 */ buildSpellTables()85 private void buildSpellTables() { 86 try { 87 final SpellGroupsXMLLoader loader = new SpellGroupsXMLLoader(new URI("/data/conf/spells.xml")); 88 List<DefaultSpell> loadedDefaultSpells = loader.load(); 89 for (DefaultSpell defaultSpell : loadedDefaultSpells) { 90 addSpell(defaultSpell); 91 } 92 } catch (Exception e) { 93 LOGGER.error("spells.xml could not be loaded", e); 94 } 95 } 96 97 /** 98 * Build the items tables 99 */ buildItemTables()100 private void buildItemTables() { 101 try { 102 final ItemGroupsXMLLoader loader = new ItemGroupsXMLLoader(new URI("/data/conf/items.xml")); 103 final List<DefaultItem> items = loader.load(); 104 105 for (final DefaultItem item : items) { 106 final String clazz = item.getItemName(); 107 108 if (classToItem.containsKey(clazz)) { 109 LOGGER.warn("Repeated item name: " + clazz); 110 } 111 112 classToItem.put(clazz, item); 113 114 String typeString = ExpressionType.OBJECT; 115 116 if (item.getItemClass().equals("food")) { 117 typeString += ExpressionType.SUFFIX_FOOD; 118 } else if (item.getItemClass().equals("drink")) { 119 typeString += ExpressionType.SUFFIX_FOOD; 120 typeString += ExpressionType.SUFFIX_FLUID; 121 } 122 123 WordList.getInstance().registerName(item.getItemName(), typeString); 124 } 125 } catch (final Exception e) { 126 LOGGER.error("items.xml could not be loaded", e); 127 } 128 } 129 130 /** 131 * Build the creatures tables 132 */ buildCreatureTables()133 private void buildCreatureTables() { 134 classToCreature = new LowerCaseMap<DefaultCreature>(); 135 136 final CreatureGroupsXMLLoader loader = new CreatureGroupsXMLLoader("/data/conf/creatures.xml"); 137 final List<DefaultCreature> creatures = loader.load(); 138 139 for (final DefaultCreature creature : creatures) { 140 final String id = creature.getTileId(); 141 final String clazz = creature.getCreatureName(); 142 143 if (classToCreature.containsKey(clazz)) { 144 LOGGER.warn("Repeated creature name: " + clazz); 145 } 146 147 if (!creature.verifyItems(this)) { 148 LOGGER.warn("Items dropped by creature name: " + clazz + " doesn't exists"); 149 } 150 151 classToCreature.put(clazz, creature); 152 idToClass.put(id, clazz); 153 154 WordList.getInstance().registerName(creature.getCreatureName(), ExpressionType.SUBJECT); 155 } 156 } 157 158 @Override addItem(final DefaultItem item)159 public boolean addItem(final DefaultItem item) { 160 final String clazz = item.getItemName(); 161 162 if (classToItem.containsKey(clazz)) { 163 LOGGER.warn("Repeated item name: " + clazz); 164 return false; 165 } 166 167 classToItem.put(clazz, item); 168 169 return true; 170 } 171 172 @Override addCreature(final DefaultCreature creature)173 public boolean addCreature(final DefaultCreature creature) { 174 final String id = creature.getTileId(); 175 final String clazz = creature.getCreatureName(); 176 177 if (classToCreature.containsKey(clazz)) { 178 LOGGER.warn("Repeated creature name: " + clazz); 179 } 180 181 if (!creature.verifyItems(this)) { 182 LOGGER.warn("Items dropped by creature name: " + clazz + " doesn't exists"); 183 } 184 classToCreature.put(clazz, creature); 185 idToClass.put(id, clazz); 186 187 return true; 188 } 189 190 /** 191 * For manually populating the creature list. 192 * 193 * Useful for tests. 194 */ 195 @Override populateCreatureList()196 public void populateCreatureList() { 197 for (final DefaultCreature cr: getDefaultCreatures()) { 198 createdCreature.put(cr.getCreatureName(), cr.getCreature()); 199 } 200 } 201 202 @Override addSpell(DefaultSpell spell)203 public boolean addSpell(DefaultSpell spell) { 204 if(nameToSpell.containsKey(spell.getName())) { 205 LOGGER.warn("Repeated spell name: "+ spell.getName()); 206 } 207 nameToSpell.put(spell.getName(), spell); 208 return true; 209 } 210 211 /** 212 * @return a list of all Creatures that are instantiated. 213 */ 214 @Override getCreatures()215 public Collection<Creature> getCreatures() { 216 return createdCreature.values(); 217 } 218 219 /** 220 * @return a list of all Items that are instantiated. 221 */ 222 @Override getItems()223 public Collection<Item> getItems() { 224 return createdItem.values(); 225 } 226 227 /** 228 * returns the entity or <code>null</code> if the id is unknown. 229 * 230 * @param clazz 231 * RPClass 232 * @return the new created entity or null if class not found 233 * 234 * @throws NullPointerException 235 * if clazz is <code>null</code> 236 */ 237 @Override getEntity(final String clazz)238 public Entity getEntity(final String clazz) { 239 if (clazz == null) { 240 throw new IllegalArgumentException("entity class is null"); 241 } 242 243 Entity entity; 244 // Lookup the id in the creature table 245 entity = getCreature(clazz); 246 if (entity != null) { 247 return entity; 248 } 249 250 // Lookup the id in the item table 251 entity = getItem(clazz); 252 if (entity != null) { 253 return entity; 254 } 255 256 return null; 257 } 258 259 /** 260 * @param tileset 261 * @param id 262 * @return the creature or <code>null</code> if the id is unknown. 263 */ 264 @Override getCreature(final String tileset, final int id)265 public Creature getCreature(final String tileset, final int id) { 266 final String clazz = idToClass.get(tileset + ":" + id); 267 if (clazz == null) { 268 return null; 269 } 270 271 return getCreature(clazz); 272 } 273 274 /** 275 * @param clazz 276 * @return the creature or <code>null</code> if the clazz is unknown. 277 * 278 * @throws NullPointerException 279 * if clazz is <code>null</code> 280 */ 281 @Override getCreature(final String clazz)282 public Creature getCreature(final String clazz) { 283 if (clazz == null) { 284 throw new IllegalArgumentException("entity class is null"); 285 } 286 287 // Lookup the clazz in the creature table 288 final DefaultCreature creature = classToCreature.get(clazz); 289 if (creature != null) { 290 if (createdCreature.get(clazz) == null) { 291 createdCreature.put(clazz, creature.getCreature()); 292 } 293 return creature.getCreature(); 294 } 295 296 return null; 297 } 298 299 /** 300 * @param clazz 301 * @return the DefaultCreature or <code>null</code> if the clazz is 302 * unknown. 303 * 304 * @throws NullPointerException 305 * if clazz is <code>null</code> 306 */ 307 @Override getDefaultCreature(final String clazz)308 public DefaultCreature getDefaultCreature(final String clazz) { 309 if (clazz == null) { 310 throw new IllegalArgumentException("entity class is null"); 311 } 312 313 // Lookup the clazz in the creature table 314 return classToCreature.get(clazz); 315 } 316 317 /** @param tileset 318 * @param id 319 * @return true if the Entity is a creature. */ 320 @Override isCreature(final String tileset, final int id)321 public boolean isCreature(final String tileset, final int id) { 322 final String clazz = idToClass.get(tileset + ":" + id); 323 if (clazz == null) { 324 return false; 325 } 326 327 return isCreature(clazz); 328 } 329 330 /** @param clazz 331 * @return true if the Entity is a creature . */ 332 @Override isCreature(final String clazz)333 public boolean isCreature(final String clazz) { 334 if (clazz == null) { 335 throw new IllegalArgumentException("entity class is null"); 336 } 337 338 return classToCreature.containsKey(clazz); 339 } 340 341 /** @param clazz 342 * @return true if the Entity is a creature. */ 343 @Override isItem(final String clazz)344 public boolean isItem(final String clazz) { 345 if (clazz == null) { 346 throw new IllegalArgumentException("entity class is null"); 347 } 348 349 return classToItem.containsKey(clazz); 350 } 351 352 /** 353 * @param clazz 354 * @return the item or <code>null</code> if the clazz is unknown. 355 * 356 * @throws NullPointerException 357 * if clazz is <code>null</code> 358 */ 359 @Override getItem(final String clazz)360 public Item getItem(final String clazz) { 361 if (clazz == null) { 362 throw new IllegalArgumentException("entity class is null"); 363 } 364 365 // Lookup the clazz in the item table 366 final DefaultItem item = classToItem.get(clazz); 367 if (item != null) { 368 if (createdItem.get(clazz) == null) { 369 createdItem.put(clazz, item.getItem()); 370 } 371 return item.getItem(); 372 } 373 374 return null; 375 } 376 377 @Override getSpell(String spell)378 public Spell getSpell(String spell) { 379 if(spell == null) { 380 throw new IllegalArgumentException("spell name is null"); 381 } 382 DefaultSpell defaultSpell = nameToSpell.get(spell); 383 if (defaultSpell != null) { 384 Spell spellEntity = defaultSpell.getSpell(); 385 if(!createdSpell.containsKey(spell)) { 386 createdSpell.put(spell, spellEntity); 387 } 388 return spellEntity; 389 } 390 return null; 391 } 392 393 @Override isSpell(String spellName)394 public boolean isSpell(String spellName) { 395 return nameToSpell.containsKey(spellName); 396 } 397 398 @Override getSpells()399 public Collection<Spell> getSpells() { 400 return createdSpell.values(); 401 } 402 403 @Override getDefaultCreatures()404 public Collection<DefaultCreature> getDefaultCreatures() { 405 return classToCreature.values(); 406 } 407 408 @Override getDefaultItems()409 public Collection<DefaultItem> getDefaultItems() { 410 return classToItem.values(); 411 } 412 getConfiguredItems()413 public Collection<String> getConfiguredItems() { 414 return classToItem.keySet(); 415 } 416 417 @Override getConfiguredSpells()418 public Collection<String> getConfiguredSpells() { 419 return nameToSpell.keySet(); 420 } 421 } 422