Armor stand shenanigans not working

Discussion in 'Plugin Development' started by dieabetes, Nov 2, 2020.

  1. Offline

    dieabetes

    error (open)

    [15:27:42 ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'iron' in plugin stuff v1.0
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[patched_1.16.3.jar:git-Paper-251]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:159) ~[patched_1.16.3.jar:git-Paper-251]
    at org.bukkit.craftbukkit.v1_16_R2.CraftServer.dispatchCommand(CraftServer.java:802) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.PlayerConnection.handleCommand(PlayerConnection.java:1918) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.PlayerConnection.a(PlayerConnection.java:1729) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.PacketPlayInChat.a(PacketPlayInChat.java:47) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.PacketPlayInChat.a(PacketPlayInChat.java:5) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.PlayerConnectionUtils.lambda$ensureMainThread$1(PlayerConnectionUtils.java:23) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.TickTask.run(SourceFile:18) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.IAsyncTaskHandler.executeTask(IAsyncTaskHandler.java:136) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.IAsyncTaskHandlerReentrant.executeTask(SourceFile:23) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.IAsyncTaskHandler.executeNext(IAsyncTaskHandler.java:109) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.MinecraftServer.ba(MinecraftServer.java:1135) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.MinecraftServer.executeNext(MinecraftServer.java:1128) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.IAsyncTaskHandler.awaitTasks(IAsyncTaskHandler.java:119) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.MinecraftServer.sleepForTick(MinecraftServer.java:1089) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.MinecraftServer.w(MinecraftServer.java:1003) ~[patched_1.16.3.jar:git-Paper-251]
    at net.minecraft.server.v1_16_R2.MinecraftServer.lambda$a$0(MinecraftServer.java:177) ~[patched_1.16.3.jar:git-Paper-251]
    at java.lang.Thread.run(Thread.java:832) [?:?]
    Caused by: java.lang.ClassCastException: class com.dieabetes.stuff.commands.commands cannot be cast to class org.bukkit.plugin.Plugin (com.dieabetes.stuff.commands.commands is in unnamed module of loader org.bukkit.plugin.java.PluginClassLoader @41c18be9; org.bukkit.plugin.Plugin is in unnamed module of loader 'app')
    at com.dieabetes.stuff.commands.commands.onCommand(commands.java:48) ~[?:?]
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[patched_1.16.3.jar:git-Paper-251]
    ... 18 more

    [CODE]@Override public boolean onCommand(CommandSender sender
    Code:
    @Override
        public boolean onCommand(CommandSender sender, Command cmd, String s, String[] strings)
        {
    
    
            if (sender instanceof Player) {
    
                Player player = (Player) sender;
    
                // /iron
                if (cmd.getName().equalsIgnoreCase("iron")) {
    
                    World world = player.getWorld();
    
                    Location loc = player.getLocation();
    
                    ItemStack item =new ItemStack(Material.IRON_INGOT, 10);
    
                    ArmorStand john = (ArmorStand) player.getLocation().getWorld().spawn(player.getLocation(),ArmorStand.class);
    
                    john.setCustomName("metalas");
    
                    john.isCustomNameVisible();
    
                    john.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY,1000000000,1,false,false));
    
                    int id = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask((Plugin) this, new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            world.dropItem(loc, item);
                        }
                    }, 0,200);
    
                }
    
    
            }
    
    
            return true;
        }
    }

    So basically this code is meant to deploy an armor stand ( which it does), give it a name and effects(doesn't do that) and spawn 10 iron on it every 200 ticks(that part makes it shit errors), I assume I need to move the loop part outside of the actual command, but that doesn't seem to work either, also I don't even know what's wrong with the name and pot effect deployment code
     
  2. Offline

    CraftCreeper6

    @dieabetes
    Is this code inside your main class?

    If so, remove
    Code:
    (Plugin)
    infront of
    Code:
    this
    in your scheduler.

    Although, my assumption is that this code is not in your main class. For that reason I suggest you make a constructor for your class that will take in the main instance, then when you register the command in your main class, pass the instance of the main class with it and use that inside the schedulers parameter.
     
    dieabetes likes this.
  3. Offline

    dieabetes

    1. Do you mean transfer the loop into my main class and then use a constructor?
    2. I can't find the bug with my setting the name and effect code
     
  4. Offline

    CraftCreeper6

    @dieabetes
    1. Nope, just simply pass the instance of the main class into your Commands class.

    2. I've never worked with armor stands but as far as I can see, just use stand#setVisible(bool) to make the armor stand invisible.
     
  5. Offline

    dieabetes

    What about the name tho, that doesn't show up, I can't find any errors in the code myself
     
  6. Offline

    CraftCreeper6

  7. Offline

    dieabetes

    Changing the armor stand name and making it transparent worked, but what do I do with the constructors, do I put that entire code into a constructor and then put it in my main class?
     
  8. Offline

    CraftCreeper6

    @dieabetes
    Nope, you need to make the constructor in your 'commands.java' class, all it needs to do is initialize a variable that holds the instance of your main class. Once you've done that you just need to pass that instance into the scheduler.

    This is an example. Except for the static, you don't need that in this case.
     
  9. Offline

    dieabetes

    What is the variable that holds my main class, why would I do it in the commands class if I need to create a constructor with my main class, I just watched 3 tutorials on this, none explained anything, the example just shows the exact same thing as I watched, I'm really confused, I understand there shouldn't be any spoon feeding, but can you at least put me on the right track?
     
  10. Offline

    CraftCreeper6

    @dieabetes
    [​IMG]
    Quick class diagram to get the basic idea across. Not my finest work :)

    In your commands class you need a variable of type Main (Main is your main class, so if your main class is called Cheese, then the 'datatype' of instance needs to be Cheese)

    Also inside of the commands class you will have a constructor. It's just like your onCommand method except its return type will be set as the class itself, and it doesn't need a name either.

    Something like
    Code:
    public commands(Main ins)
    will do fine.

    Inside of the constructor, just like in a method, you need to set the value of instance to be the parameter that you passed to the constructor, aptly named 'ins' above.

    Once you have this set up, all you need to do is change
    Code:
    (Plugin) this
    to
    Code:
    instance
    Why does this work?
    Well if you think about it, you're just telling the other class what your main class is. Once it knows what it is, it can access anything (except private and protected etc...) inside of that class, including methods. In your case, the scheduler requires an instance of your main class to make the scheduler work.
     
  11. Offline

    dieabetes

    Code:
     public commands stuff(Main ins)
           {
               return this;
    
           }
    I put this in my commands, and what parameter am I passing into the constructor?
     
  12. Offline

    CraftCreeper6

    @dieabetes
    You don't need to give it a name (stuff doesn't need to be there) and you don't need to return anything.

    Instead of
    Code:
    return this;
    you need to set the
    Code:
    Main instance
    variable in your commands class equal to the ins parameter.

    Remember to click the 'Tahg User' button beneath my messages so that I get a notification when you reply.
     
    Last edited: Nov 3, 2020
  13. Offline

    dieabetes

    @CraftCreeper6
    you mean like this?
    Code:
    public commands (Main ins)
           {
               Main instance = Main;
    
           }
    cause if so it fucks over the line of code for registering my commands class in my main class
    Code:
    getCommand("iron").setExecutor(new commands());
    parameter can't be applied to this
     
  14. Offline

    CraftCreeper6

    @dieabetes
    Close, take the Main instance out of the constructor and just use instance = ins inside of the constructor.

    In your setExecutor, add 'this' inside the brackets of commands.
     
  15. Offline

    dieabetes

    @CraftCreeper6

    it cannot resolve the symbol instance, do I need to create a variable for that or what?
     
  16. Offline

    CraftCreeper6

  17. Offline

    dieabetes

    Code:
    static class instance
        {
           
        };
    @CraftCreeper6
    what do I need to put inside, or am I doing it wrong again, is there any easier way to make a timer, cause I couldn't find one on the internet
     
  18. Offline

    jonthe445

    Due to "scope" you want the commandExecutor to have a "copy" of your main class. So in order to do this you can create an object of type Main (Your main class) and assign it equal to the Main Class you pass to it during its constructor call.

    Code:
    //Start of Class
    public commandClass implements CommandExecutor {
        private static Main main;   //(A)
    
       //Constructor Defintion
      public commandClass(Main main) //(B) {
    
           this.main = main;  //(A) = (B)
    
      }
    
    }
    
     
    Last edited: Nov 18, 2020
  19. Offline

    dieabetes

    Code:
    public class commands implements CommandExecutor
    {
    
           private static Main main;
    
        public commandClass(Main main)
        {
            this.main = main;
    
        }
    
         
    
    @jonthe445
    the b part:
    Invalid method declaration; return type required
     
  20. Offline

    CraftCreeper6

    @dieabetes
    commandClass should be commands

    And why are you making the instance static? No need for that.
     
  21. Offline

    jonthe445

    @CraftCreeper6
    Yeah not sure why i declared static, no need lol.

    @dieabetes
    Do you understand WHY you have to use 'commandClass' as oppose to 'commands' BUT only in this example?

    Remember when you create a class you can name it just about anything you want. For example if we needed our code to have a 'Person" class we would create
    Code:
    public class Person { //Start of Class
    
       //Varaible that 'each' person has... a name and age. 
       private string name;
       private int age;
    
    
       public Person(string name, int age) {   //this is a constructor notice that the constructor SHARES the class name.
                                                           //   if you name it anything OTHER than the class name you arent creating a constructor. 
                   this.name = name;
                   this.age=age;                   
       }
    }
    
    So when ever you want to 'create' a 'person' you will call the constructor for the "person" class and use somthing like this.
    Person p = new Person("Robert", 25);

    Just prog basics honestly. Hope it helps!
     
  22. Offline

    dieabetes

    @jonthe445

    okay I have it accessing my main class somewhat succesfully from what I understand, but now where do I use the access

    if I do this:
    Code:
    int id = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(main, new Runnable() {
                            @Override
                            public void run() {
                                world.dropItem(loc, item);
                            }
                        }, 0, 200);
    this error: Cannot resolve method 'scheduleSyncRepeatingTask(com.sun.tools.javac.Main, anonymous java.lang.Runnable, int, int)'
    also it shows an error in my main class, where I register the command:
    Code:
    getCommand("iron").setExecutor(new commands(this));
    'commands(com.sun.tools.javac.Main)' in 'com.dieabetes.stuff.commands.commands' cannot be applied to '(com.dieabetes.stuff.stuff)'
     
  23. Offline

    CraftCreeper6

    @dieabetes
    What's the name of your main class? The one that extends JavaPlugin.

    You've imported the incorrect Main class.
     
  24. Offline

    dieabetes

  25. Offline

    CraftCreeper6

    @dieabetes
    I hope not.

    I assume you mean your class is called stuff?
     
  26. Offline

    jonthe445

    @dieabetes
    I think what you want to do is in your main class ->

    Also if your Main Class is called stuff, then you need to use this in your commands class/constructor.
    //PSUEDOCODE
    stuff instance;
    and commands(stuff i) {
    instance = i;
    }

    Code:
    OnEnable() {
    getCommand("iron").setExecutor(new commands(this));
    }
    
    Then in the commands class you would want to checked the LABEL to be "iron", then if it is you can go ahead and start your runnable.

    //Delayed
    Code:
    scheduler.scheduleSyncDelayedTask(this, new Runnable() {
    @Override
    public void run() {
    // Do something
    }
    }, 20L);
    
    //Repeating
    Code:
    BukkitScheduler scheduler = getServer().getScheduler();
    scheduler.scheduleSyncRepeatingTask(this, new Runnable() {
    @Override
    public void run() {
    // Do something
    }
    }, 0L, 20L);
    
     
    Last edited: Nov 19, 2020
  27. Offline

    dieabetes

  28. Offline

    CraftCreeper6

    @dieabetes
    Then instead of Main you need stuff
     

Share This Page