Reading Signs - First Plugin

Discussion in 'Plugin Development' started by giodamelio, May 24, 2011.

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

    giodamelio

    I am trying to read the contents of a sign when a player right clicks on it. I'm sure this is super easy. I tried recycling some code I found on the web, but I couldn't get it to work. I would be great if someone could give me a code snippet or point me in the right direction.
     
  2. Offline

    garbagemule

    While this may be very straight-forward to someone who has already written some plugins, it probably isn't to a beginner, so don't feel discouraged!

    Let's take a look at what it is you're looking at. You want to do "something" when a player right clicks on a sign. So how do you capture this "when a player right clicks on a sign"? Probably the easiest way to do it is to make a new class that extends the PlayerListener class, which has a lot of different methods having to do with players (duh ;)). Most interesting to you is the onPlayerInteract method, which takes a PlayerInteractEvent as its only parameter. So start by overriding that method. Assuming your main plugin class is called "ReadingSigns", this basic skeleton follows the general naming convention of listener classes:
    Code:
    ...
    public class ReadingSignsPlayerListener extends PlayerListener
    {
        public void onPlayerInteract(PlayerInteractEvent event)
        {
            ...
        }
    }
    So what do you put in the onPlayerInteract method? Well, you want to check that first of all, the player is clicking a sign, and second of all, that they're right-clicking. Skimming the PlayerInteractEvent documentation, you'll find hasBlock, getClickedBlock and (possibly slightly less obvious) getAction.

    - hasBlock returns a boolean, which you can use to check if there is even a block involved in this PlayerInteractEvent.
    - getClickedBlock will return the Block object that was interacted with, if any. If there was no block, returns null.
    - getAction returns an Action enumerator value, which could be, as you can see in the link, RIGHT_CLICK_BLOCK.

    In your case, the getAction-method actually means you don't have to use hasBlock, since the returned Action value will only be RIGHT_CLICK_BLOCK if there was a block involved. So let's throw that in for starters:
    Code:
    if (event.getAction() == RIGHT_CLICK_BLOCK)
    {
        ...
    }
    So now we have to do something with that Block that is returned from getClickedBlock. If you look in the Block interface, you'll see getState which returns a BlockState. Now, it says in getState that "You may then cast that state into any accepted type, such as Furnace or Sign." so we can use the instanceof operator to check if the BlockState of the clicked Block is an instance of Sign:
    Code:
    if (event.getClickedBlock().getState() instanceof Sign)
    {
        ...
    }
    And that's basically it for your PlayerListener class. Now you simply need to fill out all the essentials, i.e. package name, import the required classes and interfaces, and of course figure out how to send a message (can be called on Player objects) to the player who was involved with this event (look for a way to "get the player of" a PlayerInteractEvent), and how to get the contents of the lines on the sign (I hope the links provide enough hints as to how you can approach this ;)).

    I know this was a bit of a long post, but you asked for code snippets or to be pointed in the right direction. I'm not a big fan of just giving people the code they're looking for, because it doesn't teach them anything, so I hope I've pointed you in the right direction at least :)

    Happy coding!
     
  3. Offline

    giodamelio

    Thanks so much for the quick reply :D. I have this code and it works great. The only problem is, for the sign reading calls I need an object of the type org.bukkit.block.Sign. All I get from the variable event is a block object. How can I get the sign object? Thanks again :)
    Code:
        @Override
        public void onPlayerInteract(PlayerInteractEvent event)
        {
            if (event.getAction() == Action.RIGHT_CLICK_BLOCK)
            {
                if (event.getClickedBlock().getState() instanceof Sign)
                {
    
                }
            }
        }
    
     
  4. Offline

    garbagemule

    Referring back to the getState method of the Block class and the message saying "You may then cast that state into any accepted type, such as Furnace or Sign.", you will have to cast the BlockState to a Sign. Type casting is done (when it is possible) by simply putting the type that you want to cast to in parenthesis in front of the variable that you want to cast from. So at this point, you will be using the event.getClickedBlock().getState() more than once, in which case you should probably assign it to a variable.
    Code:
    BlockState state = event.getClickedBlock().getState();
    if (state instanceof Sign)
    {
        Sign sign = (Sign) state;
        ...
    }
     
  5. Offline

    giodamelio

    Thank you soooo much :). My code works great now.
     
  6. Offline

    garbagemule

    Glad I could help! :)
     
Thread Status:
Not open for further replies.

Share This Page