Solved Registering an Abstract Listener Class

Discussion in 'Plugin Development' started by MrFigg, Aug 20, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    MrFigg

    Hey everyone, so I ran into an interesting problem that I think is just a limitation of bukkit or java, but I wanted to make sure.

    I was making a class to handle selecting locations by punching blocks, and I figured I might as well make it abstract with an overridable method for handling the returned result. When I tried to use it, nothing happened, though it did send the expiration message so I new it was created successfully. After a bit of investigating I found that the 'this' on line 27 of the code below didn't return the BlockSelector class when I called .getClass() on it as I expected. Instead it returned some sort of subclass thing or something (MyCommandExecutor$1) of the CommandExecutor class that the BlockSelector object was created in.

    That's where this problem started to go beyond my understanding of java and I decided to make a post here. Am I missing something or is this just a limitation of bukkit or java as I thought? And if possible would anyone mind giving me a better explanation of what's going on with the '$1' thing? I think I have an ok idea but being self-taught my terminology is a mess.

    Here's the class if you're interested:
    Code:JAVA
    1. import org.bukkit.Location;
    2. import org.bukkit.World;
    3. import org.bukkit.entity.Player;
    4. import org.bukkit.event.EventHandler;
    5. import org.bukkit.event.Listener;
    6. import org.bukkit.event.block.Action;
    7. import org.bukkit.event.player.PlayerInteractEvent;
    8. import org.bukkit.event.player.PlayerQuitEvent;
    9. import org.bukkit.event.player.PlayerTeleportEvent;
    10.  
    11. public abstract class BlockSelector implements Runnable, Listener {
    12. private MyPlugin plugin;
    13. protected Player player;
    14. private boolean lockWorld;
    15. private World world;
    16. private int schedulerTaskID = 0;
    17.  
    18. public BlockSelector(MyPlugin plugin, Player player, boolean lockWorld) {
    19. this.plugin = plugin;
    20. this.player = player;
    21. this.lockWorld = lockWorld;
    22. this.world = player.getWorld();
    23. }
    24.  
    25. public void start() {
    26. schedulerTaskID = plugin.scheduler.scheduleSyncDelayedTask(plugin, this, 1200L);
    27. plugin.getServer().getPluginManager().registerEvents(this, plugin);
    28. }
    29.  
    30. @EventHandler
    31. public void onPlayerLeaveWorld(PlayerTeleportEvent event) {
    32. if(!lockWorld) return;
    33. if(event.isCancelled()) return;
    34. if(!event.getPlayer().equals(player)) return;
    35. if(event.getTo().getWorld().equals(world)) return;
    36. cancel();
    37. }
    38.  
    39. @EventHandler
    40. public void onPlayerInteract(PlayerInteractEvent event) {
    41. if(event.isCancelled()) return;
    42. if(!event.getPlayer().equals(player)) return;
    43. if(!event.hasBlock()) return;
    44. if(!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)&&!event.getAction().equals(Action.LEFT_CLICK_BLOCK)) return;
    45. destroy();
    46. onBlockSelected(event.getClickedBlock().getLocation());
    47. }
    48.  
    49. @EventHandler
    50. public void onPlayerQuit(PlayerQuitEvent event) {
    51. if(!event.getPlayer().equals(player)) return;
    52. cancel();
    53. }
    54.  
    55. public void cancel() {
    56. destroy();
    57. onCancel();
    58. }
    59.  
    60. public void run() {
    61. if(player.isOnline()) player.sendMessage(plugin.configs.getLangConfig().getString("blockselector.expired"));
    62. destroy();
    63. onExpire();
    64. }
    65.  
    66. private void destroy() {
    67. if(schedulerTaskID!=0 && plugin.scheduler.isQueued(schedulerTaskID)) plugin.scheduler.cancelTask(schedulerTaskID);
    68. schedulerTaskID = 0;
    69. HandlerList.unregisterAll(this);
    70. }
    71.  
    72. public void boolean onBlockSelected(Location block);
    73.  
    74. public void boolean onCancel();
    75.  
    76. public void boolean onExpire();
    77. }

    Thanks for your time.
     
  2. I noticed this too, one time.

    You can create a new class that implements Listener.
    And create that class in the constructor of your BlockSelector.

    Here's an example:
    This class is like your BlockSelector, it wants to listen for events:
    https://github.com/Mtihc/TreasureCh...reasurechest/v8/core/TreasureManager.java#L98
    (I do this because I don't like it that EventHandlers must be public)

    And this class is the listener:
    https://github.com/Mtihc/TreasureCh...asurechest/v8/core/TreasureChestListener.java
    Look at onPlayerInteract(). It just calls a method at the main class.
    That method is not public. It's just default. So it's accessible by classes inside the same package.
    The listener class is also not public. Because only my manager needs to use it.

    Edit: Conclusion - Create a seperate listener class, that is not abstract.
    You can remove some "public" keywords to keep it "encapsulated" (is that the word? hihi)
     
  3. Offline

    MrFigg

    I was wondering if I would have to end up taking that approach. Thanks for the quick reply.

    Here's what I ended up with and it seems to work fine:
    Code:JAVA
    1. import org.bukkit.Location;
    2. import org.bukkit.World;
    3. import org.bukkit.entity.Player;
    4. import org.bukkit.event.EventHandler;
    5. import org.bukkit.event.Listener;
    6. import org.bukkit.event.block.Action;
    7. import org.bukkit.event.player.PlayerInteractEvent;
    8. import org.bukkit.event.player.PlayerQuitEvent;
    9. import org.bukkit.event.player.PlayerTeleportEvent;
    10.  
    11. public abstract class BlockSelector implements Runnable {
    12. private MyPlugin plugin;
    13. private BlockSelectorListener listener;
    14. protected Player player;
    15. private boolean lockWorld;
    16. private World world;
    17. private int schedulerTaskID = 0;
    18.  
    19. public BlockSelector(MyPlugin plugin, Player player, boolean lockWorld) {
    20. this.plugin = plugin;
    21. this.player = player;
    22. this.lockWorld = lockWorld;
    23. this.world = player.getWorld();
    24. listener = new BlockSelectorListener(this);
    25. }
    26.  
    27. public void start() {
    28. schedulerTaskID = plugin.scheduler.scheduleSyncDelayedTask(plugin, this, 1200L);
    29. plugin.getServer().getPluginManager().registerEvents(listener, plugin);
    30. }
    31.  
    32. public void onPlayerLeaveWorld(PlayerTeleportEvent event) {
    33. if(!lockWorld) return;
    34. if(event.isCancelled()) return;
    35. if(!event.getPlayer().equals(player)) return;
    36. if(event.getTo().getWorld().equals(world)) return;
    37. cancel();
    38. }
    39.  
    40. public void onPlayerInteract(PlayerInteractEvent event) {
    41. if(event.isCancelled()) return;
    42. if(!event.getPlayer().equals(player)) return;
    43. if(!event.hasBlock()) return;
    44. if(!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)&&!event.getAction().equals(Action.LEFT_CLICK_BLOCK)) return;
    45. destroy();
    46. onBlockSelected(event.getClickedBlock().getLocation());
    47. }
    48.  
    49. public void onPlayerQuit(PlayerQuitEvent event) {
    50. if(!event.getPlayer().equals(player)) return;
    51. cancel();
    52. }
    53.  
    54. public void cancel() {
    55. destroy();
    56. onCancel();
    57. }
    58.  
    59. public void run() {
    60. if(player.isOnline()) player.sendMessage(plugin.configs.getLangConfig().getString("blockselector.expired"));
    61. destroy();
    62. onExpire();
    63. }
    64.  
    65. private void destroy() {
    66. if(schedulerTaskID!=0 && plugin.scheduler.isQueued(schedulerTaskID)) plugin.scheduler.cancelTask(schedulerTaskID);
    67. schedulerTaskID = 0;
    68. HandlerList.unregisterAll(listener);
    69. }
    70.  
    71. public abstract void onBlockSelected(Location block);
    72.  
    73. public abstract void onCancel();
    74.  
    75. public abstract void onExpire();
    76.  
    77. public class BlockSelectorListener implements Listener {
    78. private BlockSelector selector;
    79.  
    80. public BlockSelectorListener(BlockSelector selector) {
    81. this.selector = selector;
    82. }
    83.  
    84. @EventHandler
    85. public void onPlayerLeaveWorld(PlayerTeleportEvent event) {
    86. selector.onPlayerLeaveWorld(event);
    87. }
    88.  
    89. @EventHandler
    90. public void onPlayerInteract(PlayerInteractEvent event) {
    91. selector.onPlayerInteract(event);
    92. }
    93.  
    94. @EventHandler
    95. public void onPlayerQuit(PlayerQuitEvent event) {
    96. selector.onPlayerQuit(event);
    97. }
    98. }
    99. }
     
  4. Hmmm that's some nice and clean code :D
     
  5. Offline

    MrFigg

    Thanks :)
     
Thread Status:
Not open for further replies.

Share This Page