1 package cz.cuni.amis.pogamut.udk.agent.module.sensor; 2 3 import java.util.Collection; 4 import java.util.Collections; 5 import java.util.HashMap; 6 import java.util.Map; 7 import java.util.logging.Logger; 8 9 import cz.cuni.amis.pogamut.base.agent.module.SensorModule; 10 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView; 11 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener; 12 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent; 13 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener; 14 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectListener; 15 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent; 16 import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils; 17 import cz.cuni.amis.pogamut.udk.bot.IUDKBotController; 18 import cz.cuni.amis.pogamut.udk.bot.impl.UDKBot; 19 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId; 20 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Player; 21 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.PlayerLeft; 22 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Self; 23 import cz.cuni.amis.utils.collections.MyCollections; 24 25 /** 26 * Memory module specialized on whereabouts of other players. 27 * 28 * <h2>Auto updating</h2> 29 * 30 * <p>All Player objects returned by this memory module are always self-updating 31 * throughout the time, until the associated player leaves the game. This means 32 * that once a valid Player object is obtained, it is not necessary to call any 33 * methods of this memory module to get the object's info updated (e.g. player's 34 * location, visibility, reachability, etc.). The object will autoupdate itself. 35 * 36 * <p>The same principle is applied to all Maps returned by this memory module. 37 * Each returned Map is self-updating throughout the time. Once a specific Map 38 * is obtained (e.g. a map of visible enemies) from this memory module, the Map 39 * will get updated based on actions of the players (e.g. joining or leaving 40 * the game, changing their team, moving around the map, etc.) automatically. 41 * 42 * <p>Note: All Maps returned by this memory module are locked and can not be 43 * modified outside this memory module. If you need to modify a Map returned by 44 * this module (for your own specific purpose), create a duplicate first. Such 45 * duplicates, however and of course, will not get updated. 46 * 47 * <p>If you need to get info about players' deaths use {@link Senses} module. 48 * 49 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 50 * 51 * <p><p> 52 * It is designed to be initialized inside {@link IUDKBotController#prepareBot(UDKBot)} method call 53 * and may be used since {@link IUDKBotController#botInitialized(cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.GameInfo, cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.ConfigChange, cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.InitedMessage)} 54 * is called. 55 * 56 * 57 * @author Juraj 'Loque' Simlovic 58 * @author Jimmy 59 */ 60 public class Players extends SensorModule<UDKBot> 61 { 62 /** 63 * Retreives last known info about given player. 64 * 65 * <p>Note: The returned Player object is self updating throughout time. 66 * Once you have a valid Player object, you do not have to call this 67 * method to get updated info about that player. 68 * 69 * @param UnrealId Player UnrealId to be retreived. 70 * @return Last known player info; or null upon none. 71 * 72 * @see getVisiblePlayer(UnrealId) 73 * @see getReachablePlayer(UnrealId) 74 */ 75 public Player getPlayer(UnrealId UnrealId) 76 { 77 // retreive from map of all players 78 return players.all.get(UnrealId); 79 } 80 81 /** 82 * Retreives info about given player, but only it the player is visible. 83 * 84 * <p>Note: The returned Player object is self updating throughout time. 85 * Once you have a valid Player object, you do not have to call this 86 * method to get updated info about visibility of that player. 87 * 88 * @param UnrealId Player UnrealId to be retrieved. 89 * @return Player info; or null upon none or not visible. 90 * 91 * @see getPlayer(UnrealId) 92 * @see getReachablePlayer(UnrealId) 93 */ 94 public Player getVisiblePlayer(UnrealId UnrealId) 95 { 96 // retreive from map of all visible players 97 return players.visible.get(UnrealId); 98 } 99 100 /** 101 * Retreives info about given player, but only it the player is reachable. 102 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 103 * 104 * <p>Note: The returned Player object is self updating throughout time. 105 * Once you have a valid Player object, you do not have to call this 106 * method to get updated info about reachability of that player. 107 * 108 * @param UnrealId Player UnrealId to be retreived. 109 * @return Player info; or null upon none or not reachable. 110 * 111 * @see getPlayer(UnrealId) 112 * @see getVisiblePlayer(UnrealId) 113 */ 114 public Player getReachablePlayer(UnrealId UnrealId) 115 { 116 // retreive from map of all reachable players 117 return players.reachable.get(UnrealId); 118 } 119 120 /*========================================================================*/ 121 122 /** 123 * Retreives a Map of all players. 124 * 125 * <p>Note: The returned Map is unmodifiable and self updating throughout 126 * time. Once you obtain a specific Map of players from this memory module, 127 * the Map will get updated based on actions of the players (e.g. joining 128 * or leaving the game, changing their status, etc.). 129 * 130 * @return Map of all players, using their UnrealIds as keys. 131 * 132 * @see getEnemies() 133 * @see getFriends() 134 * @see getVisiblePlayers() 135 * @see getReachablePlayers() 136 */ 137 public Map<UnrealId, Player> getPlayers() 138 { 139 // publish map of all players 140 return Collections.unmodifiableMap(players.all); 141 } 142 143 /** 144 * Retreives a Map of all enemies. 145 * 146 * <p>Note: The returned Map is unmodifiable and self updating throughout 147 * time. Once you obtain a specific Map of enemies from this memory module, 148 * the Map will get updated based on actions of the players (e.g. joining 149 * or leaving the game, changing their team or status, etc.). 150 * 151 * @return Map of all enemies, using their UnrealIds as keys. 152 * 153 * @see getPlayers() 154 * @see getFriends() 155 * @see getVisibleEnemies() 156 * @see getReachableEnemies() 157 */ 158 public Map<UnrealId, Player> getEnemies() 159 { 160 // publish map of all enemies 161 return Collections.unmodifiableMap(enemies.all); 162 } 163 164 /** 165 * Retreives a Map of all friends. 166 * 167 * <p>Note: The returned Map is unmodifiable and self updating throughout 168 * time. Once you obtain a specific Map of friends from this memory module, 169 * the Map will get updated based on actions of the players (e.g. joining 170 * or leaving the game, changing their team or status, etc.). 171 * 172 * @return Map of all friends, using their UnrealIds as keys. 173 * 174 * @see getPlayers() 175 * @see getEnemies() 176 * @see getVisibleFriends() 177 * @see getReachableFriends() 178 */ 179 public Map<UnrealId, Player> getFriends() 180 { 181 // publish map of all friends 182 return Collections.unmodifiableMap(friends.all); 183 } 184 185 /*========================================================================*/ 186 187 /** 188 * Retreives a Map of all visible players. 189 * 190 * <p>Note: The returned Map is unmodifiable and self updating throughout 191 * time. Once you obtain a specific Map of players from this memory module, 192 * the Map will get updated based on actions of the players (e.g. joining 193 * or leaving the game, or changing their visibility, etc.). 194 * 195 * @return Map of all visible players, using their UnrealIds as keys. 196 * 197 * @see getPlayers() 198 * @see getVisibleEnemies() 199 * @see getVisibleFriends() 200 * @see canSeePlayers() 201 */ 202 public Map<UnrealId, Player> getVisiblePlayers() 203 { 204 // publish map of all visible players 205 return Collections.unmodifiableMap(players.visible); 206 } 207 208 /** 209 * Retreives a Map of all visible enemies. 210 * 211 * <p>Note: The returned Map is unmodifiable and self updating throughout 212 * time. Once you obtain a specific Map of enemies from this memory module, 213 * the Map will get updated based on actions of the players (e.g. joining 214 * or leaving the game, changing their team, status or visibility, etc.). 215 * 216 * @return Map of all visible enemies, using their UnrealIds as keys. 217 * 218 * @see getEnemies() 219 * @see getVisiblePlayers() 220 * @see getVisibleFriends() 221 * @see canSeeEnemies() 222 */ 223 public Map<UnrealId, Player> getVisibleEnemies() 224 { 225 // publish map of all visible enemies 226 return Collections.unmodifiableMap(enemies.visible); 227 } 228 229 /** 230 * Retreives a Map of all visible friends. 231 * 232 * <p>Note: The returned Map is unmodifiable and self updating throughout 233 * time. Once you obtain a specific Map of friends from this memory module, 234 * the Map will get updated based on actions of the players (e.g. joining 235 * or leaving the game, changing their team, status or visibility, etc.). 236 * 237 * @return Map of all visible friends, using their UnrealIds as keys. 238 * 239 * @see getFriends() 240 * @see getVisiblePlayers() 241 * @see getVisibleEnemies() 242 * @see canSeeFriends() 243 */ 244 public Map<UnrealId, Player> getVisibleFriends() 245 { 246 // publish map of all visible friends 247 return Collections.unmodifiableMap(friends.visible); 248 } 249 250 /*========================================================================*/ 251 252 /** 253 * Retreives a Map of all reachable players. 254 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 255 * 256 * <p>Note: The returned Map is unmodifiable and self updating throughout 257 * time. Once you obtain a specific Map of players from this memory module, 258 * the Map will get updated based on actions of the players (e.g. joining 259 * or leaving the game, or changing their visibility, etc.). 260 * 261 * @return Map of all reachable players, using their UnrealIds as keys. 262 * 263 * @see getPlayers() 264 * @see getReachableEnemies() 265 * @see getReachableFriends() 266 * @see canReachPlayers() 267 */ 268 public Map<UnrealId, Player> getReachablePlayers() 269 { 270 // publish map of all reachable players 271 return Collections.unmodifiableMap(players.reachable); 272 } 273 274 /** 275 * Retreives a Map of all reachable enemies. 276 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 277 * 278 * <p>Note: The returned Map is unmodifiable and self updating throughout 279 * time. Once you obtain a specific Map of enemies from this memory module, 280 * the Map will get updated based on actions of the players (e.g. joining 281 * or leaving the game, changing their team, status or visibility, etc.). 282 * 283 * @return Map of all reachable enemies, using their UnrealIds as keys. 284 * 285 * @see getEnemies() 286 * @see getReachablePlayers() 287 * @see getReachableFriends() 288 * @see canReachEnemies() 289 */ 290 public Map<UnrealId, Player> getReachableEnemies() 291 { 292 // publish map of all reachable enemies 293 return Collections.unmodifiableMap(enemies.reachable); 294 } 295 296 /** 297 * Retreives a Map of all reachable friends. 298 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 299 * 300 * <p>Note: The returned Map is unmodifiable and self updating throughout 301 * time. Once you obtain a specific Map of friends from this memory module, 302 * the Map will get updated based on actions of the players (e.g. joining 303 * or leaving the game, changing their team, status or visibility, etc.). 304 * 305 * @return Map of all reachable friends, using their UnrealIds as keys. 306 * 307 * @see getFriends() 308 * @see getReachablePlayers() 309 * @see getReachableEnemies() 310 * @see canReachFriends() 311 */ 312 public Map<UnrealId, Player> getReachableFriends() 313 { 314 // publish map of all reachable friends 315 return Collections.unmodifiableMap(friends.reachable); 316 } 317 318 /*========================================================================*/ 319 320 /** 321 * Returns nearest player that is visible or that was 'recently' visible. If no such player exists, returns null. 322 * 323 * @param recentlyVisibleTime how long the player may be non-visible 324 * @return nearest visible or 'recentlyVisibleTime' visible player 325 */ 326 public Player getNearestPlayer(double recently) { 327 Player nearest = null; 328 double distance = Double.MAX_VALUE; 329 for (Player plr : players.all.values()) { 330 if (plr.isVisible() || lastSelf.getLastSeenTime() - plr.getLastSeenTime() <= recently) { 331 double d = lastSelf.getLocation().getDistance(plr.getLocation()); 332 if (d < distance) { 333 distance = d; 334 nearest = plr; 335 } 336 } 337 } 338 return nearest; 339 } 340 341 /** 342 * Returns nearest enemy that is visible or that was 'recently' visible. If no such enemy exists, returns null. 343 * 344 * @param recentlyVisibleTime how long the player may be non-visible 345 * @return nearest visible or 'recently' visible enemy 346 */ 347 public Player getNearestEnemy(double recentlyVisibleTime) { 348 Player nearest = null; 349 double distance = Double.MAX_VALUE; 350 for (Player plr : enemies.all.values()) { 351 if (plr.isVisible() || lastSelf.getLastSeenTime() - plr.getLastSeenTime() <= recentlyVisibleTime) { 352 double d = lastSelf.getLocation().getDistance(plr.getLocation()); 353 if (d < distance) { 354 distance = d; 355 nearest = plr; 356 } 357 } 358 } 359 return nearest; 360 } 361 362 /** 363 * Returns nearest friend that is visible or that was 'recently' visible. If no such friend exists, returns null. 364 * 365 * @param recentlyVisibleTime how long the player may be non-visible 366 * @return nearest visible or 'recently' visible friend 367 */ 368 public Player getNearestFriend(double recentlyVisibleTime) { 369 Player nearest = null; 370 double distance = Double.MAX_VALUE; 371 for (Player plr : friends.all.values()) { 372 if (plr.isVisible() || lastSelf.getLastSeenTime() - plr.getLastSeenTime() <= recentlyVisibleTime) { 373 double d = lastSelf.getLocation().getDistance(plr.getLocation()); 374 if (d < distance) { 375 distance = d; 376 nearest = plr; 377 } 378 } 379 } 380 return nearest; 381 } 382 383 /** 384 * Returns nearest-visible player - if no if no player is visible returns null. 385 * 386 * @return nearest visible player 387 */ 388 public Player getNearestVisiblePlayer() { 389 return DistanceUtils.getNearest(players.visible.values(), lastSelf.getLocation()); 390 } 391 392 /** 393 * Returns nearest-visible enemy - if no enemy is visible returns null. 394 * 395 * @return nearest visible enemy 396 */ 397 public Player getNearestVisibleEnemy() { 398 return DistanceUtils.getNearest(enemies.visible.values(), lastSelf.getLocation()); 399 } 400 401 /** 402 * Returns nearest-visible friend - if no friend is visible returns null. 403 * 404 * @return nearest visible friend 405 */ 406 public Player getNearestVisibleFriend() { 407 return DistanceUtils.getNearest(friends.visible.values(), lastSelf.getLocation()); 408 } 409 410 /** 411 * Returns nearest-visible player to the bot from the collection of 'players' - if no player 412 * is visible returns null. 413 * 414 * @param players collection to go through 415 * @return nearest visible player from the collection 416 */ 417 public Player getNearestVisiblePlayer(Collection<Player> players) { 418 return DistanceUtils.getNearestVisible(players, lastSelf.getLocation()); 419 } 420 421 /** 422 * Returns random visible player - if no if no player is visible returns null. 423 * 424 * @return random visible player 425 */ 426 public Player getRandomVisiblePlayer() { 427 return MyCollections.getRandom(players.visible.values()); 428 } 429 430 /** 431 * Returns random visible enemy - if no enemy is visible returns null. 432 * 433 * @return random visible enemy 434 */ 435 public Player getRandomVisibleEnemy() { 436 return MyCollections.getRandom(enemies.visible.values()); 437 } 438 439 /** 440 * Returns random friend - if no friend is visible returns null. 441 * 442 * @return random visible friend 443 */ 444 public Player getRandomVisibleFriend() { 445 return MyCollections.getRandom(friends.visible.values()); 446 } 447 448 /*========================================================================*/ 449 450 /** 451 * Tells, whether the agent sees any other players. 452 * 453 * @return True, if at least one other player is visible; false otherwise. 454 * 455 * @see getVisiblePlayers() 456 */ 457 public boolean canSeePlayers() 458 { 459 // search map of all visible players 460 return (players.visible.size() > 0); 461 } 462 463 /** 464 * Tells, whether the agent sees any other enemies. 465 * 466 * @return True, if at least one other enemy is visible; false otherwise. 467 * 468 * @see getVisibleEnemies() 469 */ 470 public boolean canSeeEnemies() 471 { 472 // search map of all visible enemies 473 return (enemies.visible.size() > 0); 474 } 475 476 /** 477 * Tells, whether the agent sees any other friends. 478 * 479 * @return True, if at least one other friend is visible; false otherwise. 480 * 481 * @see getVisibleFriends() 482 */ 483 public boolean canSeeFriends() 484 { 485 // search map of all visible friends 486 return (friends.visible.size() > 0); 487 } 488 489 /*========================================================================*/ 490 491 /** 492 * Tells, whether the agent can reach any other players. 493 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 494 * 495 * @return True, if at least one other player is reachable; false otherwise. 496 * 497 * @see getReachablePlayers() 498 */ 499 public boolean canReachPlayers() 500 { 501 // search map of all reachable players 502 return (players.reachable.size() > 0); 503 } 504 505 /** 506 * Tells, whether the agent can reach any other enemies. 507 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 508 * 509 * @return True, if at least one other enemy is reachable; false otherwise. 510 * 511 * @see getReachableEnemies() 512 */ 513 public boolean canReachEnemies() 514 { 515 // search map of all reachable enemies 516 return (enemies.reachable.size() > 0); 517 } 518 519 /** 520 * Tells, whether the agent can reach any other friends. 521 * <p><b>WARNING:</b>It is totally unclear what UT2004 means by reachable!!! 522 * 523 * @return True, if at least one other friend is reachable; false otherwise. 524 * 525 * @see getReachableFriends() 526 */ 527 public boolean canReachFriends() 528 { 529 // search map of all reachable friends 530 return (friends.reachable.size() > 0); 531 } 532 533 /** 534 * Tells, whether a given team is an enemy team to the agent. 535 * 536 * @param team Team number to be tested. 537 * @return True, if the given team is an enemy team. 538 * 539 * @see getTeam() 540 * @see isFriend(int) 541 */ 542 public boolean isEnemy(int team) 543 { 544 // freelancers' team or different team 545 return (team == AgentInfo.TEAM_NONE) || (team != lastSelf.getTeam()); 546 } 547 548 /** 549 * Tells, whether a given player is an enemy to the agent. 550 * 551 * @param player Player to be tested. 552 * @return True, if the given player is an enemy. 553 * 554 * @see getTeam() 555 * @see isFriend(Player) 556 */ 557 public boolean isEnemy(Player player) 558 { 559 // test the enemy team number 560 return isEnemy(player.getTeam()); 561 } 562 563 /** 564 * Tells, whether a given team is a friend team to the agent. 565 * 566 * @param team Team number to be tested. 567 * @return True, if the given team is a friend team. 568 * 569 * @see getTeam() 570 * @see isEnemy(int) 571 */ 572 public boolean isFriend(int team) 573 { 574 // same team only 575 return team != AgentInfo.TEAM_NONE && (team == lastSelf.getTeam()); 576 } 577 578 /** 579 * Tells, whether a given player is a friend to the agent. 580 * 581 * @param player Player to be tested. 582 * @return True, if the given player is a friend. 583 * 584 * @see getTeam() 585 * @see isEnemy(Player) 586 */ 587 public boolean isFriend(Player player) 588 { 589 // test the friend team number 590 return isFriend(player.getTeam()); 591 } 592 593 /*========================================================================*/ 594 595 /** 596 * Maps of players of specific type. 597 */ 598 private class PlayerMaps 599 { 600 /** Map of all players of the specific type. */ 601 private HashMap<UnrealId, Player> all = new HashMap<UnrealId, Player> (); 602 /** Map of visible players of the specific type. */ 603 private HashMap<UnrealId, Player> visible = new HashMap<UnrealId, Player> (); 604 /** Map of reachable players of the specific type. */ 605 private HashMap<UnrealId, Player> reachable = new HashMap<UnrealId, Player> (); 606 607 /** 608 * Processes events. 609 * @param player Player to process. 610 */ 611 private void notify(Player player) 612 { 613 UnrealId uid = player.getId(); 614 615 // be sure to be within all 616 if (!all.containsKey(uid)) 617 all.put(uid, player); 618 619 // previous visibility 620 boolean wasVisible = visible.containsKey(uid); 621 boolean isVisible = player.isVisible(); 622 623 // refresh visible 624 if (isVisible && !wasVisible) 625 { 626 // add to visibles 627 visible.put(uid, player); 628 } 629 else if (!isVisible && wasVisible) 630 { 631 // remove from visibles 632 visible.remove(uid); 633 } 634 635 // previous reachability 636 boolean wasReachable = reachable.containsKey(uid); 637 boolean isReachable = player.isReachable(); 638 639 // refresh reachable 640 if (isReachable && !wasReachable) 641 { 642 // add to reachables 643 reachable.put(uid, player); 644 } 645 else if (!isReachable && wasReachable) 646 { 647 // remove from reachables 648 reachable.remove(uid); 649 } 650 } 651 652 /** 653 * Removes player from all maps. 654 * @param uid UnrealId of player to be removed. 655 */ 656 private void remove(UnrealId uid) 657 { 658 // remove from all maps 659 all.remove(uid); 660 visible.remove(uid); 661 reachable.remove(uid); 662 } 663 664 private void clear() { 665 all.clear(); 666 visible.clear(); 667 reachable.clear(); 668 } 669 } 670 671 /** Maps of all players. */ 672 private PlayerMaps players = new PlayerMaps (); 673 /** Maps of all enemies. */ 674 private PlayerMaps enemies = new PlayerMaps (); 675 /** Maps of all friends. */ 676 private PlayerMaps friends = new PlayerMaps (); 677 678 /*========================================================================*/ 679 680 /** 681 * Player listener. 682 */ 683 private class PlayerListener implements IWorldObjectEventListener<Player, WorldObjectUpdatedEvent<Player>> 684 { 685 @Override 686 public void notify(WorldObjectUpdatedEvent<Player> event) 687 { 688 Player player = event.getObject(); 689 // do the job in map of players 690 players.notify(player); 691 if (lastSelf == null) return; // we do not have self yet ... we do not know which team are we in 692 // do the job in map of enemies 693 if (isEnemy(player)) 694 enemies.notify(player); 695 // do the job in map of friends 696 if (isFriend(player)) 697 friends.notify(player); 698 } 699 700 /** 701 * Constructor. Registers itself on the given WorldView object. 702 * @param worldView WorldView object to listent to. 703 */ 704 public PlayerListener(IWorldView worldView) 705 { 706 worldView.addObjectListener(Player.class, WorldObjectUpdatedEvent.class, this); 707 } 708 } 709 710 /** Player listener */ 711 PlayerListener playerListener; 712 713 /*========================================================================*/ 714 715 /** 716 * PlayerLeft listener. 717 */ 718 private class PlayerLeftListener implements IWorldEventListener<PlayerLeft> 719 { 720 @Override 721 public void notify(PlayerLeft event) 722 { 723 UnrealId uid = event.getId(); 724 725 // remove from all maps 726 players.remove(uid); 727 enemies.remove(uid); 728 friends.remove(uid); 729 } 730 731 /** 732 * Constructor. Registers itself on the given WorldView object. 733 * @param worldView WorldView object to listent to. 734 */ 735 public PlayerLeftListener(IWorldView worldView) 736 { 737 worldView.addEventListener(PlayerLeft.class, this); 738 } 739 } 740 741 /** PlayerLeft listener */ 742 PlayerLeftListener playerLeftListener; 743 744 /*========================================================================*/ 745 746 /** 747 * Self listener. 748 */ 749 private class SelfListener implements IWorldObjectListener<Self> 750 { 751 @Override 752 public void notify(IWorldObjectEvent<Self> event) 753 { 754 if (lastSelf == null) { 755 lastSelf = event.getObject(); 756 for (Player plr : players.all.values()) { 757 if (isFriend(plr)) friends.notify(plr); 758 if (isEnemy(plr)) enemies.notify(plr); 759 } 760 } else { 761 lastSelf = event.getObject(); 762 } 763 } 764 765 /** 766 * Constructor. Registers itself on the given WorldView object. 767 * @param worldView WorldView object to listent to. 768 */ 769 public SelfListener(IWorldView worldView) 770 { 771 worldView.addObjectListener(Self.class, this); 772 } 773 } 774 775 /** Self listener */ 776 SelfListener selfListener; 777 778 Self lastSelf = null; 779 780 /** 781 * Constructor. Setups the memory module based on bot's world view. 782 * @param bot owner of the module that is using it 783 */ 784 public Players(UDKBot bot) 785 { 786 this(bot, null); 787 } 788 789 /** 790 * Constructor. Setups the memory module based on bot's world view. 791 * @param bot owner of the module that is using it 792 * @param log Logger to be used for logging runtime/debug info. If <i>null</i>, module creates its own logger. 793 */ 794 public Players(UDKBot bot, Logger log) 795 { 796 super(bot, log); 797 798 799 // create listeners 800 playerListener = new PlayerListener(worldView); 801 playerLeftListener = new PlayerLeftListener(worldView); 802 selfListener = new SelfListener(worldView); 803 } 804 805 /** 806 * Provides initialization of the module (clearing internal data structures). Called automatically 807 * during the agent starting sequence. 808 */ 809 @Override 810 protected void start(boolean startPaused) { 811 super.start(startPaused); 812 lastSelf = null; 813 players.clear(); 814 friends.clear(); 815 enemies.clear(); 816 } 817 }