[Tutorial] Sign Changing and Interacting

Discussion in 'Resources' started by iiHeroo, Dec 8, 2013.

?

Was this helpful

Poll closed Dec 8, 2014.
  1. Yes

    6 vote(s)
    60.0%
  2. No

    4 vote(s)
    40.0%
Thread Status:
Not open for further replies.
  1. Offline

    iiHeroo

    This is my first tutorial, so just ignore my 'noobness'. And I've been seeing people getting issues with sign changing and interacting with a sign. Remember this is all an example, don't use what I'm doing exactly. Also, really pay attention to the notes to know how to stop people from exploiting bugs/glitches Sign Changing and Interacting is probably one of my favorite things within Bukkit to be honest since it's so broad, you can do the following with Interacting:

    *READ THIS* IGNORE ALL NOTES SAYING CAPITALIZATION MATTERS, I MADE AN ERROR WHILE TESTING AND I THOUGHT IT WAS RELATED TO CAPITALIZATION*

    • Having the player perform a command
    • Creating a player inventory and opening it
    • Even killing the player
    • etc.
    You obviously know what Sign Changing does just by the name of it, the name of the events are:
    PlayerInteractEvent & SignChangeEvent. I'm first going to show you how to do the SignChangeEvent, I have a GitHub for all of this at the bottom, and it has somewhat decent documentation, feel free to do a PR. If you'd rather read the GitHub than this, I understand, because it'll be harder for me to go line by line :p

    SignChangeEvent:

    Remember to put the @EventHandler annotation.

    Code:java
    1. @EventHandler
    2. public void onSignChange(SignChangeEvent e) {
    3. Player p = e.getPlayer();


    That'll register the event and it will register the annotation, make sure to import the right EventHandler :p I believe there is one for Google.

    Next you will want to get the first line, defined as line 0, this will check the line text, so if you want to check if it is equal to [KitMe] you'd do this:

    Code:java
    1. if(e.getLine(0).equalsIgnoreCase("[KitMe]")) { //Capitalization matters for this.


    That's an If statement, obviously, so now I would recommend checking if the player has permission to prevent exploiting bugs/glitches, so next, put something like this to prevent that, and if the player doesn't have permission, it won't do anything:

    Code:java
    1. if(p.hasPermission("kitme.admin.signmake")) { //If the player has that permission, it'll set the line, else, it won't, that will be good so people can't exploit a glitch, although,
    2. //a colored signs plugin ex: Essentials can conflict if you use it, and give the permission to reg players, I suggest not to.


    Now, if the player that placed the sign has permission, the sign will change, if he doesn't, then that sucks for the player, setting the line is a bit different from getting the line, now this is how you'd stop people from exploiting bugs:

    Code:java
    1. e.setLine(0, ChatColor.BLACK + "[" + ChatColor.DARK_RED + "KitMe" + ChatColor.BLACK + "]"); //Capitalization matters for this too.


    Okay, that's it for Sign Changing, and if you're wondering how people could exploit bugs, if you didn't add a permission to changing the sign, they could exploit it and get a bunch of items or what ever you want the sign to do. It can also be an issue when it comes to Player Interacting if the player has essentials sign color they could just add the color to the sign manually and exploit it, although, they'd need permission to what ever the sign is suppose to do. Here's the full Event for SignChangeEvent

    Code:java
    1. @EventHandler
    2. public void onSignChange(SignChangeEvent e) {
    3. Player p = e.getPlayer();
    4. if(e.getLine(0).equalsIgnoreCase("[KitMe]")) { //Capitalization matters for this.
    5. if(p.hasPermission("kitme.admin.signmake")) { //If the player has that permission, it'll set the line, else, it won't, that will be good so people can't exploit a glitch, although,
    6. //a colored signs plugin ex: Essentials can conflict if you use it, and give the permission to reg players, I suggest not to.
    7. e.setLine(0, ChatColor.BLACK + "[" + ChatColor.DARK_RED + "KitMe" + ChatColor.BLACK + "]"); //Capitalization matters for this too.
    8. }
    9. }
    10. }


    PlayerInteractEvent:

    Remember to put the EventHandler annotation again :p

    Code:java
    1. @EventHandler
    2. public void SignClick(PlayerInteractEvent e) {
    3. Player p = e.getPlayer();


    Next you want to check how the player is interacting, it can be:

    • LEFT_CLICK_BLOCK
    • LEFT_CLICK_AIR
    • PHYSICAL
    • RIGHT_CLICK_BLOCK
    • RIGHT_CLICK_AIR
    If we're interacting with a sign it can be LEFT_CLICK_BLOCK or RIGHT_CLICK_BLOCK since you can do both on a sign, and a sign is a block. I'll use RIGHT_CLICK_BLOCK as an example though, it's not hard to change, it won't be anything different except the Action type.

    So now to get the Action:

    Code:java
    1. if (e.getAction() == Action.RIGHT_CLICK_BLOCK){ //Checks if person is right clicking on a block


    Now that you checked how the player is making the action, now you need to check what he's interacting with exactly, what block he's interacting with and getting it's state:

    Code:java
    1. if (e.getClickedBlock().getState() instanceof Sign) { //This checks if the player is right clicking on the sign and it'll do all the code below if it is a sign.
    2. Sign sign = (Sign) e.getClickedBlock().getState();



    Now you got to check the first line of the sign, line 0, now, you'd use getLine(), but whatever you used for setLine on the SignChangeEvent, you use for this getLine, so I'd do this:

    Code:java
    1. if(sign.getLine(0).equalsIgnoreCase(ChatColor.BLACK + "[" + ChatColor.DARK_RED + "KitMe" + ChatColor.BLACK + "]") && p.getGameMode() == GameMode.SURVIVAL) { //Capitalization matters for this too.


    You don't need to check if the player is in GMS but I do, because why would someone need a kit in GMC.

    Now, I'm going to check the signs 2nd line, getLine(1), since this is a kit plugin sign example,

    Code:java
    1. if(sign.getLine(1).equalsIgnoreCase("Diamond")) { //Capitalization matters for this too.


    So if it does contain both it'll look like

    [KitMe]
    Diamond

    If it does contain 'Diamond', it will run this command:

    Code:java
    1. p.performCommand("kitme diamond"); //This will run all the code under the command 'kitme diamond' besides the updating of the inventory, so you should add that.
    2. p.updateInventory();


    Now you're done :D

    This is the event for the Player Interact Event
    Code:java
    1. @EventHandler
    2. public void SignClick(PlayerInteractEvent e) {
    3. Player p = e.getPlayer();
    4. if (e.getAction() == Action.RIGHT_CLICK_BLOCK){ //Checks if person is right clicking on a block
    5. if (e.getClickedBlock().getState() instanceof Sign) { //This checks if the player is right clicking on the sign and it'll do all the code below if it is a sign.
    6. Sign sign = (Sign) e.getClickedBlock().getState();
    7. if(sign.getLine(0).equalsIgnoreCase(ChatColor.BLACK + "[" + ChatColor.DARK_RED + "KitMe" + ChatColor.BLACK + "]") && p.getGameMode() == GameMode.SURVIVAL) { //Capitalization matters for this too.
    8. if(sign.getLine(1).equalsIgnoreCase("Diamond")) { //Capitalization matters for this too.
    9. p.performCommand("kitme diamond"); //This will run all the code under the command 'kitme diamond' besides the updating of the inventory, so you should add that.
    10. p.updateInventory();
    11. }
    12. }
    13. }
    14. }
    15. }


    Here's the main class too:

    Code:java
    1. package org.me.horrgs.signs;
    2.  
    3. import org.bukkit.plugin.java.JavaPlugin;
    4.  
    5. import java.util.logging.Logger;
    6.  
    7. /**
    8. * Created with IntelliJ IDEA.
    9. * User: Matt
    10. * Date: 12/7/13
    11. * Time: 3:14 PM
    12. * To change this template use File | Settings | File Templates.
    13. */
    14. public final class Main extends JavaPlugin {
    15.  
    16. public final Logger logger = Logger.getLogger("Minecraft");
    17. public static Main plugin;
    18.  
    19. @Override
    20. public void onEnable() {
    21. //Enable listener
    22. getServer().getPluginManager().registerEvents(new SignsEvent(), this);
    23. getCommand("kitme").setExecutor(new Commands());
    24. }
    25.  
    26. @Override
    27. public void onDisable() {
    28. }
    29.  
    30.  
    31. }


    The full Event class can be found here
    The command being ran can be found here
    The main class can be found here
    The full GitHub can be found here


    Thanks for reading, I hope to do more advanced tutorials in the future :)

    Reserved.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  2. Offline

    Garris0n

    Well that actually checks if it is equal to "[KitMe]" it, not contains it. Also, it says it's case sensitive in the comment but it's not... I'm guessing you meant to put .contains(...) there instead?
     
  3. Offline

    iiHeroo



    Ahhh thanks, I didn't notice that, and I shall change that now, and I thought it was case-sensitive? Must've not put in my plugin.... and no, I didn't mean to put contains actually :p
     
  4. Offline

    macguy8

    You should probably store the BlockState in a variable when you're checking for it.

    Code:
    BlockState state = block.getState();
    
    if (state instanceof Sign) { 
      Sign sign = (Sign) state
    
    }
     
    yewtree8 likes this.
  5. Offline

    iiHeroo


    Fixed, thanks for that :)
     
  6. Offline

    Garris0n

  7. Offline

    iiHeroo

  8. Offline

    macguy8

    I was commenting on the fact .getState() generates a new object each time, therefor it'd be better to store it. As well as yes, it might, the fact that on other materials with a block state, it'd be easier to see how to check that state from my example. Also, what if minecraft were to add a different type of sign or such besides wall sign and sign post? Then your method would break, and mine would still continue to operate correctly.
     
  9. Offline

    iiHeroo


    Not sure exactly what you're saying, but this works on all types of Signs, and you can easily change if so.
     
  10. Offline

    macguy8

    I know, but the other way is future proof, even though it may only be 1 additional line of code.
     
  11. Offline

    iiHeroo


    In the event of more signs, I will update this, but it doesn't seem they'll add new signs or more, since what else can you add for signs.
     
  12. Offline

    cockatoo2

    you forgot to register the event in the onEnable section of your code like this:
    Code:java
    1. Bukkit.getServer().getPluginManager().registerEvents(this, this);
     
    CoolGamerXD likes this.
  13. Offline

    iiHeroo


    It's in the onEnable method of the GitHub here
     
  14. Offline

    cockatoo2

    ok i would just put in here on the fourm for the people who dint read the GitHub
     
  15. Offline

    iiHeroo


    k, will add now ;o
     
Thread Status:
Not open for further replies.

Share This Page