View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.communication.messages;
2   
3   import java.io.Serializable;
4   import java.util.HashMap;
5   import java.util.Set;
6   
7   import com.thoughtworks.xstream.annotations.XStreamAlias;
8   
9   import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
10  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
11  import cz.cuni.amis.utils.maps.HashMapSet;
12  
13  /**
14   * Type of the item.
15   * 
16   * <p>
17   * Note: Items of the same type might have different names in UT engine.
18   * <b>Always use {@link #equals(Object)} to safely compare two ItemTypes.</b>
19   * 
20   * <p>
21   * Use {@link #getCategory()} to obtain basic categorization of items.
22   * 
23   * <p>
24   * Use {@link #getGroup()} to obtain detailed group info of items.
25   * 
26   * <p>
27   * {@link Comparable} according to {@link ItemType#getName()}.
28   * 
29   * @author Juraj 'Loque' Simlovic
30   * @author Jimmy
31   */
32  public class ItemType implements Serializable, Comparable<ItemType> {
33  
34  	/**
35  	 * Contains item types that belongs to their categories.
36  	 */
37  	public static final HashMapSet<Category, ItemType> CATEGORIES = new HashMapSet<Category, ItemType>();
38  
39  	/**
40  	 * List of all item categories. Categories divide items into several basic
41  	 * categories, based on what the item does and what is it intended to do.
42  	 */
43  	public enum Category {
44  		/** Weapons of all sorts. */
45  		WEAPON("Weapon"),
46  		/** Ammunition for weapons of all sorts. */
47  		AMMO("Ammo"),
48  		/** Projectiles for weapons of all sorts */
49  		PROJECTILE("Projectile"),
50  		/** Health packs and other health restorers. */
51  		HEALTH("Health"),
52  		/** Armor packs and other armor restorers. */
53  		ARMOR("Armor"),
54  		/** Shield packs and other shield restorers. */
55  		SHIELD("Shield"),
56  		/** Adrenaline */
57  		ADRENALINE("Adrenaline"),
58  		/** UDamage, Keys + user defined items */
59  		OTHER("Other"),
60  		/** No category */
61  		NONE("No category");
62  
63  		/* =================================================================== */
64  
65  		/** Human-readable name of the category. */
66  		public final String name;
67  
68  		/* =================================================================== */
69  
70  		/**
71  		 * Constructor.
72  		 * 
73  		 * @param name
74  		 *            Human-readable name of the category.
75  		 */
76  		Category(String name) {
77  			this.name = name;
78  		}
79  
80  		/**
81  		 * Return all item types of a certain category.
82  		 * 
83  		 * @return
84  		 */
85  		public Set<ItemType> getTypes() {
86  			return CATEGORIES.get(this);
87  		}
88  
89  	}
90  
91  	/* ======================================================================== */
92  
93  	/**
94  	 * Contains item types that belongs to their groups.
95  	 */
96  	public static final HashMapSet<Group, ItemType> GROUPS = new HashMapSet<Group, ItemType>();
97  
98  	/**
99  	 * List of all item groups. Groups fine down the categories into specific
100 	 * groups, based on what the item belongs to. Also, groups join items from
101 	 * different categories together, if they belong together (e.g. weapon with
102 	 * its ammo).
103 	 */
104 	public enum Group {
105 		/** Translocating weapon and accessory. */
106 		TRANSLOCATOR("Translocator"),
107 		/** ShieldGun weapon and accessory. */
108 		SHIELD_GUN("ShieldGun"),
109 		/** AssaultRifle weapon and accessory. */
110 		ASSAULT_RIFLE("AssaultRifle"),
111 		/** BioRifle weapon and accessory. */
112 		BIO_RIFLE("BioRifle"),
113 		/** ShockRifle weapon and accessory. */
114 		SHOCK_RIFLE("ShockRifle"),
115 		/** LinkGun weapon and accessory. */
116 		LINK_GUN("LinkGun"),
117 		/** Minigun weapon and accessory. */
118 		MINIGUN("Minigun"),
119 		/** FlakCannon weapon and accessory. */
120 		FLAK_CANNON("FlakCannon"),
121 		/** RocketLauncher weapon and accessory. */
122 		ROCKET_LAUNCHER("RocketLauncher"),
123 		/** LightningGun weapon and accessory. */
124 		LIGHTNING_GUN("LightningGun"),
125 		/** SniperRifle weapon and accessory. */
126 		SNIPER_RIFLE("SniperRifle"),
127 		/** IonPainter weapon and accessory. */
128 		ION_PAINTER("IonPainter"),
129 		/** Redeemer weapon and accessory. */
130 		REDEEMER("Redeemer"),
131 		/** SuperShockRifle weapon and accessory. */
132 		SUPER_SHOCK_RIFLE("SuperShockRifle"),
133 		/** OnsMineLayer weapon and accessory. */
134 		ONS_MINE_LAYER("ONS MineLayer"),
135 		/** OnsGrenadeLauncher weapon and accessory. */
136 		ONS_GRENADE_LAUNCHER("ONS GrenadeLauncher"),
137 		/** OnsAvril weapon and accessory. */
138 		ONS_AVRIL("ONS AVRiL"),
139 		/** TargetPainter weapon and accessory. */
140 		ONS_TARGET_PAINTER("TargetPainter"),
141 
142 		/** Classic health pack. */
143 		HEALTH("HealthKit"),
144 		/** Mini health vial. */
145 		MINI_HEALTH("HealthVial"),
146 		/** Big health recharger. */
147 		SUPER_HEALTH("SuperHealth"),
148 
149 		/** Shield pack. */
150 		SMALL_ARMOR("SmallShield"),
151 		/** Shield pack. */
152 		SUPER_ARMOR("SuperShield"),
153 
154 		/** Adrenaline packs and adrenaline restorers. */
155 		ADRENALINE("Adrenaline"),
156 		/** UDamage bonus items. */
157 		UDAMAGE("UDamage"),
158 		/** Keys. */
159 		KEY("Key"),
160 		/** Other items with user-defined group. */
161 		OTHER("Unknown"),
162 		/** No group, used for the prototype None */
163 		NONE("None");
164 
165 		/* =================================================================== */
166 
167 		/** Human-readable name of the group. */
168 		public String name;
169 
170 		/* =================================================================== */
171 
172 		/**
173 		 * Constructor.
174 		 * 
175 		 * @param name
176 		 *            Human-readable name of the group.
177 		 */
178 		Group(String name) {
179 			this.name = name;
180 		}
181 
182 		public Set<ItemType> getTypes() {
183 			return GROUPS.get(this);
184 		}
185 	}
186 
187 	/* ======================================================================== */
188 
189 	/**
190 	 * Map of all registered ItemType prototypes.
191 	 */
192 	private static HashMap<String, ItemType> protos = new HashMap<String, ItemType>();
193 
194 	/* ======================================================================== */
195 
196 	/** Translocator. */
197 	public static final ItemType TRANSLOCATOR = MakePrototype(Category.WEAPON, Group.TRANSLOCATOR, new String[] {
198 			"XWeapons.TransPickup", "XWeapons.Transpickup", "XWeapons.Translauncher" });
199 
200 	/** Translocator Beacon. */
201 	public static final ItemType TRANSLOCATOR_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.TRANSLOCATOR,
202 			new String[] { "XWeapons.BlueBeacon", "XWeapons.RedBeacon" });
203 
204 	/** ShieldGun weapon. */
205 	public static final ItemType SHIELD_GUN = MakePrototype(Category.WEAPON, Group.SHIELD_GUN, new String[] {
206 			"XWeapons.ShieldGunPickup", "XWeapons.ShieldGun" });
207 
208 	/** ShieldGun ammo - sent when the bot is spawned. */
209 	public static final ItemType SHIELD_GUN_AMMO = MakePrototype(Category.AMMO, Group.SHIELD_GUN, new String[] {
210 			"XWeapons.ShieldAmmoPickup", "XWeapons.ShieldAmmo" });
211 
212 	/** AssaultRifle weapon. */
213 	public static final ItemType ASSAULT_RIFLE = MakePrototype(Category.WEAPON, Group.ASSAULT_RIFLE, new String[] {
214 			"XWeapons.AssaultRiflePickup", "XWeapons.AssaultRifle" });
215 	/** AssaultRifle ammo. */
216 	public static final ItemType ASSAULT_RIFLE_AMMO = MakePrototype(Category.AMMO, Group.ASSAULT_RIFLE, new String[] {
217 			"XWeapons.AssaultAmmoPickup", "XWeapons.AssaultAmmo" });
218 	/** AssaultRifle secondary ammo. */
219 	public static final ItemType ASSAULT_RIFLE_GRENADE = MakePrototype(Category.AMMO, Group.ASSAULT_RIFLE,
220 			new String[] { "XWeapons.GrenadeAmmoPickup", "XWeapons.GrenadeAmmo" });
221 	/** AssaultRifle projectile. */
222 	public static final ItemType ASSAULT_RIFLE_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.ASSAULT_RIFLE,
223 			new String[] { "XWeapons.Grenade" });
224 
225 	/** BioRifle weapon. */
226 	public static final ItemType BIO_RIFLE = MakePrototype(Category.WEAPON, Group.BIO_RIFLE, new String[] {
227 			"XWeapons.BioRiflePickup", "UTClassic.ClassicBioRiflePickup", "XWeapons.BioRifle" });
228 	/** BioRifle ammo. */
229 	public static final ItemType BIO_RIFLE_AMMO = MakePrototype(Category.AMMO, Group.BIO_RIFLE, new String[] {
230 			"XWeapons.BioAmmoPickup", "XWeapons.BioAmmo" });
231 
232 	/** BioRifle projectile. */
233 	public static final ItemType BIO_RIFLE_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.BIO_RIFLE,
234 			new String[] { "XWeapons.BioGlob" });
235 
236 	/** ShockRifle weapon. */
237 	public static final ItemType SHOCK_RIFLE = MakePrototype(Category.WEAPON, Group.SHOCK_RIFLE, new String[] {
238 			"XWeapons.ShockRiflePickup", "UTClassic.ClassicShockRiflePickup", "XWeapons.ShockRifle" });
239 	/** ShockRifle ammo. */
240 	public static final ItemType SHOCK_RIFLE_AMMO = MakePrototype(Category.AMMO, Group.SHOCK_RIFLE, new String[] {
241 			"XWeapons.ShockAmmoPickup", "XWeapons.ShockAmmo" });
242 
243 	/** ShockRifle projectile. */
244 	public static final ItemType SHOCK_RIFLE_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.SHOCK_RIFLE,
245 			new String[] { "XWeapons.ShockProjectile" });
246 
247 	/** LinkGun weapon. */
248 	public static final ItemType LINK_GUN = MakePrototype(Category.WEAPON, Group.LINK_GUN, new String[] {
249 			"XWeapons.LinkGunPickup", "XWeapons.LinkGun" });
250 	/** LinkGun ammo. */
251 	public static final ItemType LINK_GUN_AMMO = MakePrototype(Category.AMMO, Group.LINK_GUN, new String[] {
252 			"XWeapons.LinkAmmoPickup", "XWeapons.LinkAmmo" });
253 
254 	/** LinkGun projectile. */
255 	public static final ItemType LINK_GUN_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.LINK_GUN,
256 			new String[] { "XWeapons.LinkProjectile" });
257 
258 	/** Minigun weapon. */
259 	public static final ItemType MINIGUN = MakePrototype(Category.WEAPON, Group.MINIGUN, new String[] {
260 			"XWeapons.MinigunPickup", "UTClassic.ClassicMinigunPickup", "XWeapons.Minigun" });
261 	/** Minigun ammo. */
262 	public static final ItemType MINIGUN_AMMO = MakePrototype(Category.AMMO, Group.MINIGUN, new String[] {
263 			"XWeapons.MinigunAmmoPickup", "XWeapons.MinigunAmmo" });
264 
265 	/** FlakCannon weapon. */
266 	public static final ItemType FLAK_CANNON = MakePrototype(Category.WEAPON, Group.FLAK_CANNON, new String[] {
267 			"XWeapons.FlakCannonPickup", "UTClassic.ClassicFlakCannonPickup", "XWeapons.FlakCannon" });
268 	/** FlakCannon ammo. */
269 	public static final ItemType FLAK_CANNON_AMMO = MakePrototype(Category.AMMO, Group.FLAK_CANNON, new String[] {
270 			"XWeapons.FlakAmmoPickup", "XWeapons.FlakAmmo" });
271 
272 	/** FlakCannon chunk projectile. */
273 	public static final ItemType FLAK_CANNON_CHUNK = MakePrototype(Category.PROJECTILE, Group.FLAK_CANNON,
274 			new String[] { "XWeapons.FlakChunk" });
275 
276 	/** FlakCannon shell projectile. */
277 	public static final ItemType FLAK_CANNON_SHELL = MakePrototype(Category.PROJECTILE, Group.FLAK_CANNON,
278 			new String[] { "XWeapons.FlakShell" });
279 
280 	/** RocketLauncher weapon. */
281 	public static final ItemType ROCKET_LAUNCHER = MakePrototype(Category.WEAPON, Group.ROCKET_LAUNCHER, new String[] {
282 			"XWeapons.RocketLauncherPickup", "UTClassic.ClassicRocketLauncherPickup", "XWeapons.RocketLauncher" });
283 	/** RocketLauncher ammo. */
284 	public static final ItemType ROCKET_LAUNCHER_AMMO = MakePrototype(Category.AMMO, Group.ROCKET_LAUNCHER,
285 			new String[] { "XWeapons.RocketAmmoPickup", "XWeapons.RocketAmmo" });
286 
287 	/** RocketLauncher projectile. */
288 	public static final ItemType ROCKET_LAUNCHER_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.ROCKET_LAUNCHER,
289 			new String[] { "XWeapons.RocketProj" /* Proj is correct */});
290 
291 	/** LightningGun weapon (modern sniper weapon). */
292 	public static final ItemType LIGHTNING_GUN = MakePrototype(Category.WEAPON, Group.LIGHTNING_GUN, new String[] {
293 			"XWeapons.SniperRiflePickup", "XWeapons.SniperRifle" });
294 
295 	/** LightningGun ammo. */
296 	public static final ItemType LIGHTNING_GUN_AMMO = MakePrototype(Category.AMMO, Group.LIGHTNING_GUN, new String[] {
297 			"XWeapons.SniperAmmoPickup", "XWeapons.SniperAmmo" });
298 
299 	/** SniperRifle weapon (classic sniper weapon). */
300 	public static final ItemType SNIPER_RIFLE = MakePrototype(Category.WEAPON, Group.SNIPER_RIFLE,
301 			new String[] { "UTClassic.ClassicSniperRiflePickup" });
302 	/** SniperRifle ammo. */
303 	public static final ItemType SNIPER_RIFLE_AMMO = MakePrototype(Category.AMMO, Group.SNIPER_RIFLE, new String[] {
304 			"UTClassic.ClassicSniperAmmoPickup", "UTClassic.ClassicSniperAmmo" });
305 
306 	/** Redeemer weapon. */
307 	public static final ItemType REDEEMER = MakePrototype(Category.WEAPON, Group.REDEEMER, new String[] {
308 			"XWeapons.RedeemerPickup", "XWeapons.Redeemer" });
309 	
310 	/** Redeemer ammo. Does not actually exist.*/
311 	public static final ItemType REDEEMER_AMMO = MakePrototype(Category.AMMO, Group.REDEEMER, new String[] {
312 			"XWeapons.RedeemerAmmo" });
313 
314 	/** Redeemer weapon. */
315 	public static final ItemType REDEEMER_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.REDEEMER,
316 			new String[] { "XWeapons.RedeemerProjectile" });
317 
318 	/** SuperShockRifle weapon (instagib weapon). */
319 	public static final ItemType SUPER_SHOCK_RIFLE = MakePrototype(Category.WEAPON, Group.SUPER_SHOCK_RIFLE,
320 			new String[] { "XWeapons.SuperShockRiflePickup", "XWeapons.SuperShockRifle" });
321 
322 	/** IonPainter weapon. */
323 	public static final ItemType ION_PAINTER = MakePrototype(Category.WEAPON, Group.ION_PAINTER, new String[] {
324 			"XWeapons.PainterPickup", "XWeapons.Painter" });
325 	/** IonPainter ammo. Uses BallAmmo odly enough. */
326 	public static final ItemType ION_PAINTER_AMMO = MakePrototype(Category.AMMO, Group.ION_PAINTER, new String[] {"XWeapons.BallAmmo" });
327 	
328 	/** MineLayer Onslaught weapon. */
329 	public static final ItemType ONS_MINE_LAYER = MakePrototype(Category.WEAPON, Group.ONS_MINE_LAYER, new String[] {
330 			"Onslaught.ONSMineLayerPickup", "Onslaught.ONSMineLayer" });
331 	/** MineLayer ammo. */
332 	public static final ItemType ONS_MINE_LAYER_AMMO = MakePrototype(Category.AMMO, Group.ONS_MINE_LAYER, new String[] {
333 			"Onslaught.ONSMineAmmoPickup", "Onslaught.ONSMineAmmo" });
334 
335 	/** MineLayer projectile. */
336 	public static final ItemType ONS_MINE_LAYER_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.ONS_MINE_LAYER,
337 			new String[] { "Onslaught.ONSMineProjectileRED", "Onslaught.ONSMineProjectileBLUE" });
338 
339 	/** GrenadeLauncher Onslaught weapon. */
340 	public static final ItemType ONS_GRENADE_LAUNCHER = MakePrototype(Category.WEAPON, Group.ONS_GRENADE_LAUNCHER,
341 			new String[] { "Onslaught.ONSGrenadePickup", "Onslaught.ONSGrenade" });
342 
343 	/** GrenadeLauncher ammo. */
344 	public static final ItemType ONS_GRENADE_LAUNCHER_AMMO = MakePrototype(Category.AMMO, Group.ONS_GRENADE_LAUNCHER,
345 			new String[] { "Onslaught.ONSGrenadeAmmoPickup" });
346 
347 	/** GrenadeLauncher ammo. */
348 	public static final ItemType ONS_GRENADE_LAUNCHER_PROJECTILE = MakePrototype(Category.PROJECTILE,
349 			Group.ONS_GRENADE_LAUNCHER, new String[] { "Onslaught.ONSGrenadeProjectile" });
350 
351 	/** AVRiL Onslaught weapon. */
352 	public static final ItemType ONS_AVRIL = MakePrototype(Category.WEAPON, Group.ONS_AVRIL, new String[] {
353 			"Onslaught.ONSAVRiLPickup", "Onslaught.ONSAVRiL" });
354 	/** AVRiL ammo. */
355 	public static final ItemType ONS_AVRIL_AMMO = MakePrototype(Category.AMMO, Group.ONS_AVRIL,
356 			new String[] { "Onslaught.ONSAVRiLAmmoPickup" });
357 
358 	/** AVRiL projectile.	*/
359 	public static final ItemType ONS_AVRIL_PROJECTILE = MakePrototype(Category.PROJECTILE, Group.ONS_AVRIL,
360 			new String[] { "Onslaught.ONSAVRiLRocket"});
361 
362 	/** TargetPainter Onslaught weapon. */
363 	public static final ItemType ONS_TARGET_PAINTER = MakePrototype(Category.WEAPON, Group.ONS_TARGET_PAINTER,
364 			new String[] { "OnslaughtFull.ONSPainterPickup", "OnslaughtFull.ONSPainter" });
365 
366 	/** Health kit. */
367 	public static final ItemType HEALTH_PACK = MakePrototype(Category.HEALTH, Group.HEALTH, new String[] {
368 			"XPickups.HealthPack", "XPickups.TournamentHealth" });
369 	/** Health vial. */
370 	public static final ItemType MINI_HEALTH_PACK = MakePrototype(Category.HEALTH, Group.MINI_HEALTH,
371 			new String[] { "XPickups.MiniHealthPack" });
372 	/** SuperHealth charger. */
373 	public static final ItemType SUPER_HEALTH_PACK = MakePrototype(Category.HEALTH, Group.SUPER_HEALTH,
374 			new String[] { "XPickups.SuperHealthPack" });
375 
376 	/** SmallShield. */
377 	public static final ItemType SHIELD_PACK = MakePrototype(Category.ARMOR, Group.SMALL_ARMOR, new String[] {
378 			"XPickups.ShieldPack", "XPickups.ShieldPickup" });
379 	/** SuperShield. */
380 	public static final ItemType SUPER_SHIELD_PACK = MakePrototype(Category.ARMOR, Group.SUPER_ARMOR,
381 			new String[] { "XPickups.SuperShieldPack" });
382 
383 	/** UDamage bonus (damage multiplier). */
384 	public static final ItemType U_DAMAGE_PACK = MakePrototype(Category.OTHER, Group.UDAMAGE, new String[] {
385 			"XPickups.UDamagePack", "XGame.UDamageReward" });
386 
387 	/** Adrenaline capsule. */
388 	public static final ItemType ADRENALINE_PACK = MakePrototype(Category.ADRENALINE, Group.ADRENALINE,
389 			new String[] { "XPickups.AdrenalinePickup" });
390 
391 	/** Key. */
392 	public static final ItemType KEY = MakePrototype(Category.OTHER, Group.KEY, new String[] { "UnrealGame.KeyPickup" });
393 
394 	/** No ItemType */
395 	public static final ItemType NONE = MakePrototype(Category.OTHER, Group.NONE,
396 			new String[] { "None", "NONE", "none" });
397 
398 	/* ======================================================================== */
399 
400 	// //
401 	// STATIC METHODS
402 	// //
403 
404 	/**
405 	 * Attempts to recognize the weapon you are currently holding...
406 	 * <p>
407 	 * <p>
408 	 * See {@link Self#getWeapon()}.
409 	 * <p>
410 	 * <p>
411 	 * May return null == weapon was not recognized. ALWAYS CHECK!
412 	 * 
413 	 * @return
414 	 */
415 	public static ItemType getWeapon(UnrealId id) {
416 		if (id == null)
417 			return null;
418 		String str = id.getStringId();
419 		if (str.contains("."))
420 			str = str.substring(str.lastIndexOf(".") + 1);
421 		str = str.toLowerCase();
422 		if (str.equals("assaultrifle"))
423 			return ItemType.ASSAULT_RIFLE;
424 		if (str.equals("shieldgun"))
425 			return ItemType.SHIELD_GUN;
426 		if (str.equals("flakcannon"))
427 			return ItemType.FLAK_CANNON;
428 		if (str.equals("biorifle"))
429 			return ItemType.BIO_RIFLE;
430 		if (str.equals("shockrifle"))
431 			return ItemType.SHOCK_RIFLE;
432 		if (str.equals("linkgun"))
433 			return ItemType.LINK_GUN;
434 		if (str.equals("sniperrifle"))
435 			return ItemType.SNIPER_RIFLE;
436 		if (str.equals("rocketlauncher"))
437 			return ItemType.ROCKET_LAUNCHER;
438 		if (str.equals("minigun"))
439 			return ItemType.MINIGUN;
440 		if (str.equals("lightinggun"))
441 			return ItemType.LIGHTNING_GUN;
442 		if (str.equals("translocator"))
443 			return ItemType.TRANSLOCATOR;
444 		if (str.equals("translauncher"))
445 			return ItemType.TRANSLOCATOR;
446 		if (str.equals("redeemer"))
447 			return ItemType.REDEEMER;
448 		if (str.equals("painter"))
449 			return ItemType.ION_PAINTER;
450 		return null;
451 	}
452 
453 	/* ======================================================================== */
454 
455 	/**
456 	 * Name of the item in UT engine.
457 	 * 
458 	 * <p>
459 	 * Note: Items of the same type might have different names in UT engine. Use
460 	 * {@link #equals(Object)} to safely compare two ItemTypes. This name is
461 	 * informative only.
462 	 */
463 	private String name;
464 
465 	@Override
466 	public String toString() {
467 		return "ItemType[name = " + name + ", category = " + category + ", group = " + group + "]";
468 	}
469 
470 	/* ======================================================================== */
471 
472 	/**
473 	 * Category of the type.
474 	 */
475 	private Category category;
476 
477 	/**
478 	 * Group of the type.
479 	 */
480 	private Group group;
481 
482 	/**
483 	 * Retreives category of the item type.
484 	 * 
485 	 * @return Category of the item type.
486 	 */
487 	public Category getCategory() {
488 		// do we have a category already?
489 		return (category == null) ? (category = getProto().category) : category;
490 	}
491 
492 	/**
493 	 * Retreives group of the item type.
494 	 * 
495 	 * @return Group of the item type.
496 	 */
497 	public Group getGroup() {
498 		// do we have a group already?
499 		return (group == null) ? (group = getProto().group) : group;
500 	}
501 
502 	/* ======================================================================== */
503 
504 	/**
505 	 * Prototype reference.
506 	 */
507 	private ItemType proto;
508 
509 	/**
510 	 * Retreives (and caches) ItemType prototype.
511 	 * 
512 	 * @return ItemType prototype.
513 	 */
514 	private ItemType getProto() {
515 		// do we have a prototype already?
516 		if (proto != null)
517 			return proto;
518 		synchronized (protos) {
519 			return proto = protos.get(name);
520 		}
521 	}
522 
523 	/* ======================================================================== */
524 
525 	/**
526 	 * Indicates whether some other ItemType is "equal to" this one.
527 	 * 
528 	 * @param obj
529 	 *            Object to be compared with.
530 	 * @return True, if the objects are equal.
531 	 */
532 	@Override
533 	public boolean equals(Object obj) {
534 		// the same object?
535 		if (this == obj)
536 			return true;
537 
538 		// the same type?
539 		if (obj instanceof ItemType) {
540 			// the same prototype?
541 			if (getProto() == ((ItemType) obj).getProto())
542 				return true;
543 		}
544 
545 		return false;
546 	}
547 
548 	/**
549 	 * Returns a hash code value for the object.
550 	 * 
551 	 * @return A hash code value for this object.
552 	 */
553 	@Override
554 	public int hashCode() {
555 		// provide hash of the string name
556 		return getProto().name.hashCode();
557 	}
558 
559 	/* ======================================================================== */
560 
561 	/**
562 	 * Public constructor - creates ItemType of the EXTRA category and Group
563 	 * OTHER.
564 	 * 
565 	 * @param name
566 	 *            Type name from GB engine.
567 	 */
568 	public ItemType(String name) {
569 		this.name = name;
570 		this.category = Category.OTHER;
571 		this.group = Group.OTHER;
572 		this.proto = this;
573 	}
574 
575 	/**
576 	 * Prototypes constructor.
577 	 */
578 	private ItemType(String name, Category category, Group group) {
579 		this.name = name;
580 		this.category = category;
581 		this.group = group;
582 		this.proto = this;
583 	}
584 
585 	/* ======================================================================== */
586 
587 	/**
588 	 * Proto-constructor.
589 	 * 
590 	 * @param category
591 	 *            Category of the item.
592 	 * @param group
593 	 *            Group of the item.
594 	 * @param utNames
595 	 *            Names of the item in UT engine.
596 	 * @return Prototype of known ItemType.
597 	 */
598 	public static ItemType MakePrototype(Category category, Group group, String[] utNames) {
599 		ItemType type;
600 		synchronized (protos) {
601 			// create new itemtype prototype
602 			type = new ItemType(utNames[0], category, group);
603 			// register the itemtype prototype
604 			for (String utName : utNames)
605 				protos.put(utName, type);
606 			// C'est la vie..
607 			if (category != null) {
608 				CATEGORIES.get(category).add(type);
609 			}
610 			if (group != null) {
611 				GROUPS.get(group).add(type);
612 			}
613 		}
614 		return type;
615 	}
616 
617 	/**
618 	 * Retrieves an ItemType for the specified item type name.
619 	 * 
620 	 * @param utName
621 	 *            e.g. Item.getType()
622 	 * @return
623 	 */
624 	public static ItemType getItemType(String utName) {
625 		ItemType type;
626 		synchronized (protos) {
627 			type = protos.get(utName);
628 			if (type != null)
629 				return type;
630 
631 			type = new ItemType(utName);
632 			protos.put(utName, type);
633 		}
634 		return type;
635 	}
636 
637 	public String getName() {
638 		return name;
639 	}
640 
641 	@Override
642 	public int compareTo(ItemType o) {
643 		if (o == null) return 1;
644 		if (getName() == null) {
645 			if (o.getName() == null) return 0;
646 			return 1;
647 		} else {
648 			if (o.getName() == null) return -1;
649 			return getName().compareTo(o.getName());
650 		}
651 	}
652 
653 }