How to update sign every time something is changed in the config?

Discussion in 'Plugin Development' started by kayc01, Oct 4, 2015.

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

    mcdorli

    First, read trough my laxt comment, because I edited it and it have some tips to use.

    Second.: Okay, tell me what you need, and I give you code examples.
     
  2. Its fine, i know. And the code in that current upload is terrible.
    Last night i just cleaned it all up finally.

    Maybe not amazingly but pretty well.

    So, i am going to be real with you guys.
    You suggested:

    1.: You have a class, which lsitens for every sign placement, if it is a "GymStatus",etc. Sign, store it's x,y and z coordinates in a List.

    I came up with this;

    Code:
    @EventHandler
        public void onSignChange(SignChangeEvent e) {
            Player p = e.getPlayer();
            int x = e.getBlock().getX();
            int y = e.getBlock().getY();
            int z = e.getBlock().getZ();
            String world = e.getBlock().getWorld().getName();
            if (e.getLine(0).equalsIgnoreCase("[GymStatus]") && (p.hasPermission("pixelgym.admin"))) {
                e.setLine(0, "§6" + plugin.getConfig().getString("config."+e.getLine(1)) + " Gym");
                e.setLine(2, "§eLevel Cap: " + plugin.getConfig().getString("config."+e.getLine(1)+"lvlcap"));
                e.setLine(3, "§7to update !");
               
                Sign sign = (Sign) e.getBlock().getState();
               
              if (plugin.getConfig().getString("config."+e.getLine(1)+"stat").equals("Open")) {
                e.setLine(1, "§a" + plugin.getConfig().getString("config."+e.getLine(1)+"stat"));
                sign.update();
              }
              else if (plugin.getConfig().getString("config."+e.getLine(1)+"stat").equals("Closed")) {
                  e.setLine(1, "§c" + plugin.getConfig().getString("config."+e.getLine(1)+"stat"));
                  sign.update();
              }
            }
            else if (e.getLine(0).equalsIgnoreCase("[GymLeaders]") && (p.hasPermission("pixelgym.admin"))) {
                e.setLine(0, "§6" + plugin.getConfig().getString("config."+e.getLine(1))+ " Leaders");
            for (Player staff : Bukkit.getOnlinePlayers()) {
             if (staff.hasPermission("pixelgym"+e.getLine(1)))
                e.setLine(1,staff.getName().toString());
                e.setLine(2,staff.getName().toString());
                e.setLine(3,staff.getName().toString());
               
            }
          }
           
        }

    2.: Create a blockdestroy event, and check, if the block destroyed is a "GymStatus",etc. Sign (by the stored x, y and z coordinates), and remove it from the List, if it got destroyed.

    I could only find blockbreak and i am not sure how i would check it if the sign was those co-ordinates because i have no idea how to store them or where to do so.

    3.: Store the sign x, y and z-s in the config file, and always update it, if the two method above (1. and 2. steps) runs.

    From here on i got lost, my brain has turned to mush...
    So as much help needed as i can here. :/

    4.: Create a method, that goes trough the sign List and updates the signs.

    5.: Link the method described in step 4. to every config update.

    I hope the above reply tells you what i do and don't understand.
    Like i have no idea how to store things, without cluttering up the config.

    And then how i would go through each sign?
    Well, what is a set amount of signs so would it need to loop? I don't know.

    EDIT: I also got confused because i know you mentioned about just updating it every time a change in the config occurs which seems like it would be straight forward as that is when i open/close a gym in game.
    However, it also got suggested you could just do it off in game that when you do /gym open it updates it. I was told i need to make the config reload, However i tried it and it then reset the open gyms to closed every time it reloaded on the command. So it was always set to closed.

    And that's another thing, when you do /gym list it shows the config status as open or closed, live.
    No reloads required. But updating the signs needs a reload and sign.update? Confusing :S

    Thanks

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
  3. Offline

    mcdorli

    Okay lets vegin with some basic java:

    A list is like an array, but infinite.

    List<something, that extends Object> list = new ArrayList<something, that extends Object>();

    You can add objects to this (but only the one that you defined between the <>, like String, Integer, etc..). You can add objects to it by doing list.add(Object). You should really look up more on these, because these are needed in java programming.

    Now lets move on the bukkit stuff. First you create a list, then store it on the config file (I'm not sure, if you can, but I think its possible), then in every sign place or remove event, you get this list back from the config, add or remove the correct element to/from it and set it back to the config.

    Then, by every config update, get the list, loop trough it (like a normal array) and update all the signs with the config.

    The good thing about the lists, is that you can even store the sign object in them, but you can only store one type of object in them (what you specified between the "<>"-s.

    I think that's all, it only uses one place to store the signs, and is reload-proof. The best thing about this solution, that I don't needed to spoon feed you, most of these are only config management, wich you can do.

    Any more questions?
     
  4. I will try give it a go.
    On a side note, whilst we were not getting very far with this. I started doing another part. Do you know how you would convert a Item id from a config to be placed in a itemstack imaginary inventory?


    Code:
    for (Player playerT : Bukkit.getOnlinePlayers()) {
             if ((args[0].equalsIgnoreCase("winner")) && (playerT.getName().equalsIgnoreCase(args[1]) && (p.hasPermission("pixelgym."+args[1])))) {
                 ItemStack badge = new ItemStack(Material.AIR);
                 badge = new ItemStack(Material.getMaterial(getConfig().getInt("config."+args[2])));
                 playerT.openInventory(testInventory);
                 testInventory.addItem(new ItemStack(Material.badge);
    Main lines:



    That sort of thing.
     
  5. Offline

    mcdorli

    There is no such material, as badge, I think you msssed it up, by doing

    ItemStack badge = new ItemStack(Material.AIR) //this creates a new ITEMSTACK (not material) with the material, AIR, so, this is useless

    inventory.addItem(Material.badge) //what? You really didn't understand this, this wants to give the player a new item, that is called badge, but there is no such item you need:

    ItemStack item = new ItemStack("the config stuff")

    inventory.addItem(item)

    You really need to learn this, and not do a bigbproject like this.
     
    dlange likes this.
  6. I had done some research and found it working else where as it needs to get a config string.
    I guess if the first line does not work, neither will the rest.

    Infact adding an item is not long really needed. It can be manually added.
    But, i need it to save the inv against the player in a file.

    And after doing some research it is not so simple..
     
  7. Offline

    mcdorli

    @timtower please lock this thread we got really far from the original question and literally just spoonfeeding.
     
  8. Offline

    timtower Administrator Administrator Moderator

    @mcdorli 1. The questions come from the OP though, so that is fine.
    2. Spoonfeeding is discouraged, not illegal.
     
  9. Thank you. Not very nice @mcdorli when I still had questions.

    As I mentioned before I learn best by seeing an example in code, with everything taken into consideration (code that would work including any extra methods it needs to work) I can then re-apply it in the future.

    It is not what I need to do, it is tieing a lot of it together. Where things should go, what specific code is. I can fine online what the method needs to do, but if I don't know how to write it. It's pointless.

    I rarely see someone on here give working code. Either most are lazy or too busy. Or they think not giving me the code forces me to learn each step separately .. yet you could just comment what each lines does.

    And I would like read it over and over to then understand every element of it.

    Th odd 3-4 times that I have got example code, I have then managed to use simular items in other needs.

    No offense to anyone.
     
  10. ;c
     
  11. Offline

    Zombie_Striker

    You know what, Let Me Google That For You. And Here Is The First Result.

    YES! THAT IS THE REASON (sadly) WHY WE ARE HERE! Sure we can give you a piece of code once, and MAYBE you would learn what is means, but instead of knowing where you should go to learn you will come back asking another question. Even if it is a completely different question, the reason you posted here was because you have not completely learned java (Something you can do by yourself).

    BTW, Those walls of text we posted are there because that's where we channel our frustration caused by people not wanting to learn Java completely.

    So, now onto the new comment.

    No, they want people to learn or they don't want to give broken/bad code.
    DING DING DING. But just commenting alone does not do anything. The reason you are here is not because of some "hard to find/ never been posted about method", it about basic JAVA.
    Even having the comments as to what each line does, you will not know exactly what each line does/means to the rest o f the code. THAT IS WHAT LEARNING JAVA IS FOR. SO YOU KNOW EXACTLY WHAT EVERYTHING MEANS.
    If it's like this post, then it's most likely on a simple thing, so yes, you would use it more than once.

    At this point this is what you should do:
    1. LEARN JAVA (Again, my signature has a link)
    2. Before Making a post Google your problem/what you want. There are already dozens of posts on the same topic that should cover what you want.
    3. When you don't know how/what to do to get something you want and there are no posts about it, then make a post.
    4. If someone says that it is "basic knowledge" (because we would help if it isn't), simply ask were to learn. Everyone here should provide a link as to where to learn. THAT IS WHY WE ARE HEAR.

    EDIT by Timtower: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 7, 2015
  12. Please :p

    I know, i have been coming here a lot lately. However this is because i have been trying to add little features that are obviously totally new to me.

    But yes i will try learn java and bukkit a little more in my own time.
    However, as i am trying to push through these two features, i ask. Please will you give me the code. :p
    For the chance that i will actually then learn something from it also.

    ahah

    I am defiantly going to start going to java learning websites, but. Before i go.

    If you can give me this one code to get this one part finished, great (the signs updating)

    Then, now i just need to make sure this would work.
    As far as i know it should. So my plugin implements PixelmonMod by dispatching some commands in console.

    These are the dispatch commands:

    Code:
    Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "pokegive " + (playerTarget.getWorld().getName()) + " " + (plugin.getConfig().getString("config."+args[2]+"poke1")) + " lvl" + (plugin.getConfig().getString("config."+args[2]+"poke1lvl")));
                                       Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "pokegive " + playerTarget.getWorld().getName() + " " + (plugin.getConfig().getString("config."+args[2]+"poke2")) + " lvl" + (plugin.getConfig().getString("config."+args[2]+"poke2lvl")));
                                       Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "pokegive " + playerTarget.getWorld().getName() + " " + (plugin.getConfig().getString("config."+args[2]+"poke3")) + " lvl" + (plugin.getConfig().getString("config."+args[2]+"poke3lvl")));
                                       Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "pokegive " + playerTarget.getWorld().getName() + " " + (plugin.getConfig().getString("config."+args[2]+"poke4")) + " lvl" + (plugin.getConfig().getString("config."+args[2]+"poke4lvl")));
                                       Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "pokegive " + playerTarget.getWorld().getName() + " " + (plugin.getConfig().getString("config."+args[2]+"poke5")) + " lvl" + (plugin.getConfig().getString("config."+args[2]+"poke5lvl")));
                                       Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "pokegive " + playerTarget.getWorld().getName() + " " + (plugin.getConfig().getString("config."+args[2]+"poke6")) + " lvl" + (plugin.getConfig().getString("config."+args[2]+"poke6lvl")));
    This would use the pixelmon command: /pokegive (username) (pokemonname) (pokemonlevel)

    EDIT:

    I am an idiot, correct me if i am wrong but:

    Code:
    playerTarget.getWorld().getName()
    Is getting the world name, not player name.
    This must of been because i copy'd and pasted from my group manager world implementation command.

    It would need to be:

    Code:
    playerTarget.getName().toString()
    Right? lol

    EDIT by Timtower: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 7, 2015
  13. Offline

    Zombie_Striker

    The first line is trying to get the player's WORLD's name
    The second one is getting the players name.

    Also, the .getname returns a string, so you don't need to turn the string into a string.

    As far as the updater code

    Code:
    MAINPLUGIN plugin;//Class that extends javaplugin
    public (THE CLASS) (MAINPLUGIN plugin){ // constructor
    this.plugin = plugin; // initalize the var
    plugin.getScheduler()scheduleSyncRepeatingTask(plugin,new Runnable(){ // This is creating a task that will repeate itself after ___ ticks (20 ticks = 1 second)
    
    public void run(){//method that gets called after __ ticks
    updateSigns(); // this will update the signs
    //anything else that should happen every second
    }
    
    },2/*delay*/,20L/*repeat after one second THIS YOU CAN CHANGE. IF YOUR SERVER IS LAGGY, SET THE DELAY HIGHER (20 is one second, 40 is 2 seconds, ect.)*/)
    }
    
    public void updateSigns(){
    for(Location l : LocationsLIST){//gets all the locations from the list
    if(l.getBlock.getType == Material.WALL_SIGN||SIGN_POST)//checks to make sure it is a sign
    Sign sign = (Sign)l.getBlock.getState();
    
    sign.setLine(line, "The Text");
    
    }else{//if it is not a sign
    LocationsLIST.remove(l);//remove it
    }
    }
    }
    
    
    
     
    Last edited: Oct 6, 2015
  14. Offline

    mcdorli

    I know, this is a bit offtopic, but i wouldn't recommend websites, they just aren't that good, you should really look into spme books, you're even english, you have everything on your hand. BTW.: I really recommend O'Reilly's Head first java, it's very wide and has everything from basic OOP to the more advanced server stuff

    And really, every better plugin maker here have some years of pure java behind them, I had 3 years, when I began (and that isn't really much), I'm sure, that @Zombie_Striker have at least 5, and not even speak about @timtower
     
    Last edited: Oct 6, 2015
  15. Thank you!

    But it seems like it does not want to play nice.

    plugin.getSchedular The method getScheduler() is undefined for the type PixelGym,
    I do not have any schedular's in my main class, which is fair enough and i thought the schedular was just made in the listener class. Not the main class. I have probably made a noob error there.

    However it does not want to get getBlock() either.

    Add can you elaborate (you know my sort of wanted elaborations) on LocationsLISTS.
    Thanks.
     
  16. Offline

    mcdorli

    Do not use PixelGym plugin, use Plugin plugin, thats all
     
  17. I think i am getting mixed up in some area's.


    Code:
    package me.Ckay.gym;
    
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.event.Listener;
    import org.bukkit.material.Sign;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class SignUpdater extends JavaPlugin {
    
        Plugin plugin;//Class that extends javaplugin
       
        public SignUpdater (Plugin plugin){ // constructor
        this.plugin = plugin; // initalize the var
        plugin.getScheduler()scheduleSyncRepeatingTask(plugin,new Runnable(){ // This is creating a task that will repeate itself after ___ ticks (20 ticks = 1 second)
        
        public void run(){//method that gets called after __ ticks
        updateSigns(); // this will update the signs
        //anything else that should happen every second
        }
        
        },2/*delay*/,20L/*repeat after one second THIS YOU CAN CHANGE. IF YOUR SERVER IS LAGGY, SET THE DELAY HIGHER (20 is one second, 40 is 2 seconds, ect.)*/)
        }
        
        public void updateSigns(){
        for(Location l : LocationsLIST){//gets all the locations from the list
        if(l.getBlock.getType == Material.WALL_SIGN||SIGN_POST)//checks to make sure it is a sign
        Sign sign = (Sign)l.getBlock.getState();
        
        sign.setLine(line, "The Text");
        
        }else{//if it is not a sign
        LocationsLIST.remove(l);//remove it
        }
        }
        }
    
    I have tried PixelGym plugin;
    Whilst:
    Public SignUpdater (Plugin plugin) {
    is that and
    Public SignUpdater (PixelGym plugin) {
    and visa versa. (Plugin plugin;) with changing Public SignUpdater.

    Any idea's?

    Still gives me problems on the same things.
     
  18. Offline

    timtower Administrator Administrator Moderator

    I started 3 to 3.5 years ago.
    @kayc01 I am getting confused, what is the current exact issue?
     
  19. On:
    Code:
    getScheduler
    I am getting:
    The method getScheduler() is undefined for the type PixelGym

    On:
    Code:
    scheduleSyncRepeatingTask
    I am getting:
    The method scheduleSyncRepeatingTask(PixelGym, new Runnable(){}, int, long) is undefined for the type SignUpdater

    On:
    Code:
    LocationsLIST
    I am getting:
    LocationsLIST cannot be resolved to a variable
    (i am guessing i still need to make a list however @mcdorli said changing one thing is all that was needed...)

    On:
    Code:
    getBlock
    I am getting:
    getBlock cannot be resolved or is not a field

    and On:
    Code:
    SIGN_POST)
    I am getting:
    SIGN_POST cannot be resolved to a variable

    There are no imports or reasonable fixes i can see on these errors. (Quick fixes)

    I am sure i am missing something stupid here, or if someone can give me a correct Listener/line for my onEnable in the main class to make sure that is not the issue.

    Thanks
     
  20. Offline

    timtower Administrator Administrator Moderator

    @kayc01 You are calling methods that JavaPlugin has, but your class doesn't.
    Call them through the plugin
    Material.SIGN_POST
    getBlock and LocationsLIST depend on your code.
     
  21. I changed Plugin.getScheduler to Bukkit.getScheculer however it still gets the error on:
    scheduleSyncRepeatingTask But not getScheduler anymore.

    Meterial.SIGN_POST Worked for that.

    But as for .getBlock and LocationsLIST, how do i want to go about doing them?

    A normal list for LocationsLIST? And how do i define getBlock without an event? Or what event would i need?

    The getBlock on Sign sign = (Sign)l.getBlock().getState();
    does not give me an error.

    This is now getting very confusing again.
    Mind giving me the extra bits i need? :S
     
  22. Offline

    timtower Administrator Administrator Moderator

    @kayc01 scheduleTask is probably called on the wrong object.
    Getblock and your list depend on your code, as I haven't seen it: can't help with those.
     
  23. I have nothing in my main class that regards lists or getBlock. However i do have something similar to getBlock in another class (the actual if's to the signs)

    Code:
    package me.Ckay.gym;
    
    import org.bukkit.Bukkit;
    //import org.bukkit.ChatColor;
    import org.bukkit.block.Sign;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.block.SignChangeEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    
    
    public class SignListeners implements Listener {
    
    private PixelGym plugin;   
    
    public SignListeners(PixelGym plugin) {
        this.plugin = plugin;
        //getServer().getPluginManager().registerEvents(this, this);
    }
    //public SignListeners(PixelGym passedPlugin){
    //    this.plugin = passedPlugin;
    //}
    
    
       
        @EventHandler
        public void onSignChange(SignChangeEvent e) {
            Player p = e.getPlayer();
    //        int x = e.getBlock().getX();
    //        int y = e.getBlock().getY();
    //        int z = e.getBlock().getZ();
    //        String world = e.getBlock().getWorld().getName();
            if (e.getLine(0).equalsIgnoreCase("[GymStatus]") && (p.hasPermission("pixelgym.admin"))) {
                e.setLine(0, "§6" + plugin.getConfig().getString("config."+e.getLine(1)) + " Gym");
                e.setLine(2, "§eLevel Cap: " + plugin.getConfig().getString("config."+e.getLine(1)+"lvlcap"));
                e.setLine(3, "§7to update !");
               
                Sign sign = (Sign) e.getBlock().getState();
               
              if (plugin.getConfig().getString("config."+e.getLine(1)+"stat").equals("Open")) {
                e.setLine(1, "§a" + plugin.getConfig().getString("config."+e.getLine(1)+"stat"));
                sign.update();
              }
              else if (plugin.getConfig().getString("config."+e.getLine(1)+"stat").equals("Closed")) {
                  e.setLine(1, "§c" + plugin.getConfig().getString("config."+e.getLine(1)+"stat"));
                  sign.update();
              }
            }
            else if (e.getLine(0).equalsIgnoreCase("[GymLeaders]") && (p.hasPermission("pixelgym.admin"))) {
                e.setLine(0, "§6" + plugin.getConfig().getString("config."+e.getLine(1))+ " Leaders");
            for (Player staff : Bukkit.getOnlinePlayers()) {
             if (staff.hasPermission("pixelgym"+e.getLine(1)))
                e.setLine(1,staff.getName().toString());
                e.setLine(2,staff.getName().toString());
                e.setLine(3,staff.getName().toString());
               
            }
          }
           
        }
       
        @SuppressWarnings("deprecation")
        public void onPlayerInteract(PlayerInteractEvent event) {
            if(event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
            if(event.getClickedBlock().getTypeId() == 63 || event.getClickedBlock().getTypeId() == 68) {
            
            Sign sign = (Sign) event.getClickedBlock().getState();
            if (sign.getLine(0).equals("§6Rock Gym") && (plugin.getConfig().getString("config.gym1").equals("Open"))) {
                sign.setLine(1, "§a" + plugin.getConfig().getString("config.gym1stat"));
                sign.update();
              }
              else if (sign.getLine(0).equals("§6Rock Gym") && (plugin.getConfig().getString("config.gym1").equals("Closed"))) {
                  sign.setLine(1, "§c" + plugin.getConfig().getString("config.gym1stat"));
                  sign.update();
              }
            }
            
            // Do other stuff if you need to
            }
            }
           
       
        @EventHandler
        public void SignClick(PlayerInteractEvent e) {
        //Player p = e.getPlayer();
        if (e.getAction() == Action.RIGHT_CLICK_BLOCK){ //Checks if person is right clicking on a block
            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.
            Sign sign = (Sign) e.getClickedBlock().getState();
            if(sign.getLine(0).equals("§6Rock Gym")) {
              if (plugin.getConfig().getString("config.gym1stat").equals("Open")) {
                sign.setLine(1, "§a" + plugin.getConfig().getString("config.gym1stat"));
            }
              else if (plugin.getConfig().getString("config.gym1stat").equals("Closed")) {
                 sign.setLine(1, "§c" + plugin.getConfig().getString("config.gym1stat"));
              }
        }
           
           
        }
    }
        }
    }
    
    Anywhere we can go with this?
    The on click event was to test it even updating at all. So i plan on removing that.
     
  24. Offline

    mcdorli

    @kayc01 You nees to create the locationLIST variable, and the getBlock method (just basically create a location and do return loc.getType();

    Edit: why the hell do you use getTypeId() == 63 if you could use getType() == Material.The material instead? The first one is deprecated.

    BTW.: This code is a mess, it's really hard to read, you need to format your codes, you can do it in eclipse ba pressing Ctrl+Shift+F, or do it manually. Basically some "rules (recommendations)" to writing java code:

    1. The bracket go in the same line, as the if or the else

    If (...) {
    //stuff
    } else {
    //stuff
    }

    2. Only initialize variables in the same line, if they are null, and frombthe same class

    Wrong:

    int i = 70, j = 42, String s = 10;

    Good:

    int i, j, k;
    String s, t, r;

    3. Use camelCase, except from final variables

    Wrong:

    int MeaningOfLife = 42;
    String SOMESTRINGTTHATWILLCHANGE = "s"

    Good:

    int meaningOfLife = 42;
    final String TITLE = "Hello there!";

    Thats's all I can think of.

    And just a good tip for you: Try to create as less strings as possible, don't store them if you only use them once. Java s*cks at Strings, basically, if you have an object, buf you link the variable in a another object, then the first one goes into a "trash bin", and if java runs out of memory, it will go trough this trash ban and remove everything out of it. The thing with strings, that everytime you change or create a string, it will go into a thing called "string pool", so if you create a for loop like this:

    String a = "";
    for (int i = 0; i < 10; i++) {
    a += i;
    }

    It will create 10 different strings in the memory (0, 01...) and the trash car never goes into the string pool, they stay there, waiting for reuse. When I explained this to one of my friends who uses C# and C++, he asked "why? This is only useful if you create a program that manages big texts.". So basically, try not to store useless strings, it's just doesn't get handled, and it isn't fun, when your memory get clocked up by strings.
     
    Last edited: Oct 7, 2015
Thread Status:
Not open for further replies.

Share This Page