method from other class

Discussion in 'Plugin Development' started by Copyright2017, Jul 22, 2017.

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

    Copyright2017

    I am sorry, This is probably the simplest thing ever. just want to access a method from another class:

    main class:

    Code:
    package me.Copyright2017.plugins.skywarsPlugin;
    import java.util.List;
    import org.bukkit.plugin.java.JavaPlugin;
    public class skywarsPlugin extends JavaPlugin {
        @Override
        public void onEnable() {
            this.getServer().getPluginManager().registerEvents(new blockBreakListener(), this);
        }
        public List<String> getLBDL() {
            getConfig().options().copyDefaults(true);
            saveConfig();
            List<String> luckyBlockDropList = getConfig().getStringList("luckyBlockDropList");
            return luckyBlockDropList;
        }
    }
    
    
    and the subclass:

    Code:
    package me.Copyright2017.plugins.skywarsPlugin;
    import java.util.Random;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.inventory.ItemStack;
    public class blockBreakListener implements Listener {
        @EventHandler
        public void onBlockBreakEvent(BlockBreakEvent e) {
            if(e.getBlock().getType() == Material.IRON_ORE) {
                // Remove the real break, remove the block and drop iron
                e.setCancelled(true);
                e.getBlock().setType(Material.AIR);
                e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new ItemStack(Material.IRON_INGOT));
            } else if(e.getBlock().getType() == Material.SMOOTH_BRICK) {
                Player player = e.getPlayer();
                e.setCancelled(true);
                e.getBlock().setType(Material.AIR);
                skywarsPlugin object = new skywarsPlugin();
                Random rand = new Random();
                if(object.getLBDL() == null) {
                    player.sendMessage("its null brah");
                }
                player.sendMessage(object.getLBDL().toString());
                int n = rand.nextInt(object.getLBDL().size()) +1;
                e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new ItemStack(Material.getMaterial(object.getLBDL().get(n))));
            }
        }
    
    }
    
    just trying to access the "getLBDL()" method from the main class

    EDIT: changed code to:




    got error when I break the stonebrick:
    Code:
    [13:32:56 ERROR]: Could not pass event BlockBreakEvent to skywarsPlugin v0.1
    org.bukkit.event.EventException: null
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:298) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:498) [craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:483) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerInteractManager.breakBlock(PlayerInteractManager.java:289) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerInteractManager.a(PlayerInteractManager.java:216) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerConnection.a(PlayerConnection.java:869) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PacketPlayInBlockDig.a(SourceFile:40) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PacketPlayInBlockDig.a(SourceFile:10) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerConnectionUtils$1.run(SourceFile:13) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_131]
            at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_131]
            at net.minecraft.server.v1_12_R1.SystemUtils.a(SourceFile:46) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:695) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:366) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:650) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:554) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    Caused by: java.lang.IllegalArgumentException: Plugin already initialized!
            at org.bukkit.plugin.java.PluginClassLoader.initialize(PluginClassLoader.java:98) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.java.JavaPlugin.<init>(JavaPlugin.java:60) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at me.Copyright2017.plugins.skywarsPlugin.skywarsPlugin.<init>(skywarsPlugin.java:4) ~[?:?]
            at me.Copyright2017.plugins.skywarsPlugin.blockBreakListener.onBlockBreakEvent(blockBreakListener.java:21) ~[?:?]
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_131]
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
            at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_131]
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:296) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            ... 17 more
    Caused by: java.lang.IllegalStateException: Initial initialization
            at org.bukkit.plugin.java.PluginClassLoader.initialize(PluginClassLoader.java:101) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.java.JavaPlugin.<init>(JavaPlugin.java:60) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at me.Copyright2017.plugins.skywarsPlugin.skywarsPlugin.<init>(skywarsPlugin.java:4) ~[?:?]
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_131]
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_131]
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_131]
            at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:1.8.0_131]
            at java.lang.Class.newInstance(Unknown Source) ~[?:1.8.0_131]
            at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:52) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:127) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.java:325) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager.java:248) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.craftbukkit.v1_12_R1.CraftServer.loadPlugins(CraftServer.java:298) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.craftbukkit.v1_12_R1.CraftServer.<init>(CraftServer.java:260) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerList.<init>(PlayerList.java:76) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.DedicatedPlayerList.<init>(SourceFile:14) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.DedicatedServer.init(DedicatedServer.java:186) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:521) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            ... 1 more
    >
    I realize this is probably something that I should be able to find on my own. can someone point me in the right direction as to what to look for?
     
    Last edited: Jul 22, 2017
  2. Offline

    Zombie_Striker

    Package names should be all lower case.

    Class names should start with an Uppercase letter.

    To get the other class's instance, you will need to set up a constructor for the subclass. In it, require the main class's instance, and store that instance in a field. Then, when you need to access the main class, reference that field.

    Also, don't create a new instance of random every time a block is broken. Instead, use ThreadLocalRandom.current to get the current random instance.
     
  3. Offline

    morpheus99

    First, create a method like this in your SecondClass :
    Code:
            static SecondClass instance = new SecondClass();
        
            public static SecondClass getInstance() {
                    return instance;
            }
           
    Then, link it to your MainClass:
    // In your MainClass:
    Code:
        SecondClass sec = SecondClass.getInstance();
    
    --> to call a method from SecondClass :
    Code:
     sec.YourMethod(); 
    I hope it helps
     
    Last edited: Jul 24, 2017
  4. Offline

    Caderape2

    There's no need to static. Just use constructor.
     
    teej107 and Zombie_Striker like this.
  5. Offline

    Copyright2017

    Ok I've done some more coding and now I have run into the same problem. I have two sub-classes that both need an instance of the main class passed to them. and one of the sub classes needs an instance of the other.

    Main class:
    Code:
    package me.Copyright2017.plugins.skywarsPlugin;
    import java.util.List;
    import java.util.logging.Logger;
    
    import org.bukkit.Bukkit;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.plugin.java.JavaPlugin;
    public class skywarsPlugin extends JavaPlugin {
    
        public Logger log = Bukkit.getLogger();
    
        @Override
        public void onEnable() {
            this.getServer().getPluginManager().registerEvents(new blockBreakListener(this), this);
            this.getCommand("pickPlayers").setExecutor(new commands(this));
            getConfig().options().copyDefaults(true);
            saveConfig();
        }
       
        String luckyBlock = getConfig().getString("luckyBlock");
        List<String> luckyBlockDropList = getConfig().getStringList("luckyBlockDropList");
        List<String> customDropList = getConfig().getStringList("customDrops");
    
        public List<String> getLBDL() {
            return luckyBlockDropList;
        }
        public String getLB() {
            return luckyBlock;
        }
        public List<String> getCD() {
            return customDropList;
        }
        public ItemStack setName(ItemStack is, String name){
            ItemMeta m = is.getItemMeta();
            m.setDisplayName(name);
            is.setItemMeta(m);
            return is;
        }
    
    
    }
    
    Class that I somehow got to work:
    Code:
    package me.Copyright2017.plugins.skywarsPlugin;
    import java.util.Random;
    
    import org.bukkit.GameMode;
    import org.bukkit.Material;
    import org.bukkit.enchantments.Enchantment;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.inventory.ItemStack;
    public class blockBreakListener implements Listener {
        public skywarsPlugin plugin;
        public blockBreakListener(skywarsPlugin instance) {
            plugin = instance;
        }
    
    
        @EventHandler
        public void onBlockBreakEvent(BlockBreakEvent e) {
            if(!(e.getPlayer().getGameMode() == GameMode.CREATIVE)) {
                if(e.getBlock().getType() == Material.getMaterial((plugin.getLB()).replaceAll("\\[", "").replaceAll("\\]",""))) { //lucky block
                    e.setCancelled(true);
                    e.getBlock().setType(Material.AIR);
                    Random rand = new Random();
                    int n = rand.nextInt(plugin.getLBDL().size());
                    String str = plugin.getLBDL().get(n);
                    String[] split = str.split(" ");
                    if(split.length == 2) { //just item and count
                        e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1])));
                    } else if (split.length == 3) { //item, count, and name
                        ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                        plugin.setName(item, split[2]);
                        e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                    } else if(split.length == 4) { //item, count, name, and ench (lvl1)   
                        if(!(split[2].equals("*"))) { //set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            plugin.setName(item, split[2]);
                            item.addEnchantment(Enchantment.getByName(split[3]), 1);
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        } else { //dont set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            item.addEnchantment(Enchantment.getByName(split[3]), 1);
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        }
                    } else if(split.length >= 5) { //item, count, name, ench and level
                        if(!(split[2].equals("*"))) { //set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            plugin.setName(item, split[2]);
                            item.addEnchantment(Enchantment.getByName(split[3]), Integer.parseInt(split[4]));
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        } else {//dont set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            item.addEnchantment(Enchantment.getByName(split[3]), Integer.parseInt(split[4]));
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        }
                    } else {
                        plugin.log.info("Bad item in lucky block list at #" + n + 1);
                    }
                } else { //check for any custom drops
                    for (int i = 0; i < plugin.getCD().size(); i++) {
                        String str = plugin.getCD().get(i);
                        String[] split = str.split(" ");
                        if(e.getBlock().getType() == Material.getMaterial(split[0])) {
                            e.setCancelled(true);
                            e.getBlock().setType(Material.AIR);
                            if(split.length == 3) { //just item and count
                                e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2])));
                            } else if (split.length == 4) { //item, count, and name
                                ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                plugin.setName(item, split[3]);
                                e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                            } else if(split.length == 5) { //item, count, name, and ench (lvl1)   
                                if(!(split[3].equals("*"))) { //set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    plugin.setName(item, split[3]);
                                    item.addEnchantment(Enchantment.getByName(split[4]), 1);
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                } else { //dont set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    item.addEnchantment(Enchantment.getByName(split[4]), 1);
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                }
                            } else if(split.length >= 6) { //item, count, name, ench and level
                                if(!(split[3].equals("*"))) { //set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    plugin.setName(item, split[3]);
                                    item.addEnchantment(Enchantment.getByName(split[4]), Integer.parseInt(split[5]));
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                } else {//dont set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    item.addEnchantment(Enchantment.getByName(split[4]), Integer.parseInt(split[5]));
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    Class that just needs access to the main class (I want to be able to call the scheduler inside the genTerrain method so that when I call genTerrain from the next class it does everything, afaik this isn't a problem. correct me if im wrong)
    Code:
    package me.Copyright2017.plugins.skywarsPlugin;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.craftbukkit.Main;
    import org.bukkit.entity.Item;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.scheduler.BukkitRunnable;
    
    public class generator extends BukkitRunnable {
    
        Main plugin;
        public generator(Main plugin) {
            this.plugin = plugin;
        }
    
        int counter = 0;
        int ticks;
        Item droppedItem;
        Material material;
    
    
        public void genTerrain(Material material, Location location, int ticks) {
            ItemStack t = new ItemStack(material, 64);
            Item droppedItem = location.getWorld().dropItem(location, t);
            droppedItem.setGravity(false);
            droppedItem.setInvulnerable(true);
            droppedItem.setPickupDelay(32767);
    
        }
        @Override
        public void run() {
            if(counter < ticks) {
                Block block = droppedItem.getLocation().getBlock();
                if(block.getType() == Material.AIR) {
                    block.setType(material);
                    counter++;
                }
    
            } else {
                cancel();
            }
        }
    }
    
    and my last class that needs access to the previous class and the main class. and I do know that my onCommand method is missing a ton of things, just havent got that far yet.

    Code:
    package me.Copyright2017.plugins.skywarsPlugin;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    
    
    public class commands implements CommandExecutor {
    
        public static generator gen;
        public commands(generator instance) {
            gen = instance;
        }
       
        @Override
        public boolean onCommand(CommandSender arg0, Command arg1, String arg2, String[] arg3) {
            
            gen.genTerrain(Material.WOOD, ((Player) arg0).getLocation(), 500); 
            gen.runTaskTimer(plugin, 0, 1); //i want to somehow make this part of the genTerrain method in the other class
    
            return false;
        }
    
    }
    

    summary: I have no clue how to link the classes correctly, I have seen dozens of methods describing how to link it but none of them seem to work


    oh and I forgot, the error I always get is "plugin already initialized".
     
  6. Offline

    Zombie_Striker

    @Copyright2017
    The 'plugin already initialized' message only appears if you have duplicate plugins on the server or if you have multiple instances of JavaPlugin in the same class.

    Can you post the full error log here?
     
  7. Offline

    Copyright2017

    Wait wut now im getting this:
    Code:
    [14:41:36 ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'pickplayers' in plugin skywarsPlugin v0.8
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:140) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.craftbukkit.v1_12_R1.CraftServer.dispatchCommand(CraftServer.java:623) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerConnection.handleCommand(PlayerConnection.java:1326) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerConnection.a(PlayerConnection.java:1186) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PacketPlayInChat.a(SourceFile:37) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PacketPlayInChat.a(SourceFile:9) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.PlayerConnectionUtils$1.run(SourceFile:13) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_131]
            at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_131]
            at net.minecraft.server.v1_12_R1.SystemUtils.a(SourceFile:46) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:695) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:366) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:650) [craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:554) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    Caused by: java.lang.NullPointerException
            at me.Copyright2017.plugins.skywarsPlugin.commands.onCommand(commands.java:71) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            ... 15 more


    For the record I would still like to know the correct way to link MULTIPLE classes.
     
    Last edited: Jul 23, 2017
  8. Offline

    Zombie_Striker

    @Copyright2017
    The way you currently have it is the right way. Using constructors is the correct way to pass instances around.

    The issue is that the commands class requires a generator, but you are providing a skywarsPlugin instance. Also, the constructor for generator requires some class called Main instead of skywarsPlugin. Change this:
    To this
    And this:
    To this:
     
  9. Offline

    Copyright2017

    Thanks everyone for your help, I think ive got everything working so far except one small bit:
    Code:
    @Override
        public void run() {
            for (Entry<UUID, Integer> entry : ite.entrySet()) {
                int blockNum = entry.getValue();
                if(blockNum >= 1) {
                    Block block = Bukkit.getServer().getEntity(entry.getKey()).getLocation().getBlock();
                    if(block.getType() == Material.AIR) {
                        block.setType(((Item) Bukkit.getServer().getEntity(entry.getKey())).getItemStack().getType());
                        entry.setValue(blockNum -1);   
                    }
                } else {
                    Bukkit.getServer().getEntity(entry.getKey()).remove();
                    ite.remove(entry.getKey());
                }
            }
        }
    
    it throws this exception:
    Code:
    [21:50:53 WARN]: [SkywarsPlugin] Plugin SkywarsPlugin v0.8 generated an exception while executing task 2
    java.util.ConcurrentModificationException: null
            at java.util.HashMap$HashIterator.nextNode(Unknown Source) ~[?:1.8.0_131]
            at java.util.HashMap$EntryIterator.next(Unknown Source) ~[?:1.8.0_131]
            at java.util.HashMap$EntryIterator.next(Unknown Source) ~[?:1.8.0_131]
            at me.Copyright2017.plugins.SkywarsPlugin.Generator.run(Generator.java:33) ~[?:?]
            at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:53) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:52) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_131]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_131]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    how would I change that for statement to avoid that?
     
  10. Offline

    Zombie_Striker

    @Copyright2017
    You can't modify an array while looping through it. Create an iterator for the entry set and use that for the for loop.
     
  11. Offline

    Copyright2017

    Never worked with an iterator before. how would I code that exactly? :p
     
  12. Offline

    Zombie_Striker

    To create a new Iterator, use:
    Then, to loop through the array, use:
    Code:
    for (; iterator.hasNext(); ){
        Entry<UUID,Integer> entry = iterator.next();
     
  13. Offline

    Copyright2017

    @Zombie_Striker Did that. got rid of most of the errors. New bugs new bugs.

    To give you an idea. I have this really cool command block creation that when I repeat an execute a setblock on an item it will force the item out of the block and create a repeating spire of terrain. I have hit the end of what I can do with the command blocks in terms of creating a full minigame. so I mustered my wits and came here. I really appreciate all of the help I've got so far!

    Main Class:
    Code:
    package me.Copyright2017.plugins.SkywarsPlugin;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.logging.Logger;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.GameMode;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.command.ConsoleCommandSender;
    import org.bukkit.enchantments.Enchantment;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class SkywarsPlugin extends JavaPlugin implements Listener{
        public Logger log = Bukkit.getLogger();
    
        @Override
        public void onEnable() {
            getConfig().options().copyDefaults(true);
            saveConfig();
            Generator gen = Generator.getInstance();
            Bukkit.getServer().getPluginManager().registerEvents(this, this);
    
            String genSetting = getConfig().getString("terrainGenCoverage");
            if(genSetting.contains("LOW")) {
                gen.runTaskTimerAsynchronously(this, 0, 4);
                log.info("Generator loaded. Setting: LOW");
            } else if(genSetting.contains("MEDIUM")) {
                gen.runTaskTimerAsynchronously(this, 0, 3);
                log.info("Generator loaded. Setting: MEDIUM");
            } else if(genSetting.contains("HIGH")) {
                gen.runTaskTimerAsynchronously(this, 0, 2);
                log.info("Generator loaded. Setting: HIGH");
            } else {
                log.warning("Generator not loaded!!! bad terrainGenCoverage setting in config!!!");
            }
    
        }
    
        String luckyBlock = getConfig().getString("luckyBlock");
        List<String> luckyBlockDropList = getConfig().getStringList("luckyBlockDropList");
        List<String> customDropList = getConfig().getStringList("customDrops");
        List<String> terrainGenList = getConfig().getStringList("terrainGenList");
    
        public ItemStack setName(ItemStack is, String name){
            ItemMeta m = is.getItemMeta();
            m.setDisplayName(name);
            is.setItemMeta(m);
            return is;
        }
    
        public void genRandFromList(int strands, Location location) {
            for(int i = 0; i < strands; i++) {
                Generator gen = Generator.getInstance();
                //int n = ThreadLocalRandom.current().nextInt(0, terrainGenList.size() + 1);
                Random rand = new Random();
                int n = rand.nextInt(terrainGenList.size());
                String str = terrainGenList.get(n);
                String[] split = str.split(" ");
                gen.genTerrain(Material.getMaterial(split[0]), location, Integer.parseInt(split[1]));
            }
        }
    
        public void genRandFromListAuto(Location location, boolean flat) {
            Generator gen = Generator.getInstance();
            //int n = ThreadLocalRandom.current().nextInt(0, terrainGenList.size() + 1);
            Random rand = new Random();
            int n = rand.nextInt(terrainGenList.size());
            String str = terrainGenList.get(n);
            String[] split = str.split(" ");
            gen.genTerrainAuto(Material.getMaterial(split[0]), location, Integer.parseInt(split[1]), flat);
        }
    
    
        @EventHandler
        public void onBlockBreakEvent(BlockBreakEvent e) {
            if(!(e.getPlayer().getGameMode() == GameMode.CREATIVE)) {
                if(e.getBlock().getType() == Material.getMaterial((luckyBlock).replaceAll("\\[", "").replaceAll("\\]",""))) { //lucky block
                    e.setCancelled(true);
                    e.getBlock().setType(Material.AIR);
                    Random rand = new Random();
                    int n = rand.nextInt(luckyBlockDropList.size());
                    String str = luckyBlockDropList.get(n);
                    String[] split = str.split(" ");
                    if(split.length == 2) { //just item and count
                        e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1])));
                    } else if (split.length == 3) { //item, count, and name
                        ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                        setName(item, split[2]);
                        e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                    } else if(split.length == 4) { //item, count, name, and ench (lvl1)   
                        if(!(split[2].equals("*"))) { //set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            setName(item, split[2]);
                            item.addEnchantment(Enchantment.getByName(split[3]), 1);
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        } else { //dont set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            item.addEnchantment(Enchantment.getByName(split[3]), 1);
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        }
                    } else if(split.length >= 5) { //item, count, name, ench and level
                        if(!(split[2].equals("*"))) { //set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            setName(item, split[2]);
                            item.addEnchantment(Enchantment.getByName(split[3]), Integer.parseInt(split[4]));
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        } else {//dont set name
                            ItemStack item = new ItemStack(Material.getMaterial(split[0]), Integer.parseInt(split[1]));
                            item.addEnchantment(Enchantment.getByName(split[3]), Integer.parseInt(split[4]));
                            e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                        }
                    } else {
                        log.info("Bad item in lucky block list at #" + n + 1);
                    }
                } else { //check for any custom drops
                    for (int i = 0; i < customDropList.size(); i++) {
                        String str = customDropList.get(i);
                        String[] split = str.split(" ");
                        if(e.getBlock().getType() == Material.getMaterial(split[0])) {
                            e.setCancelled(true);
                            e.getBlock().setType(Material.AIR);
                            if(split.length == 3) { //just item and count
                                e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2])));
                            } else if (split.length == 4) { //item, count, and name
                                ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                setName(item, split[3]);
                                e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                            } else if(split.length == 5) { //item, count, name, and ench (lvl1)   
                                if(!(split[3].equals("*"))) { //set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    setName(item, split[3]);
                                    item.addEnchantment(Enchantment.getByName(split[4]), 1);
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                } else { //dont set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    item.addEnchantment(Enchantment.getByName(split[4]), 1);
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                }
                            } else if(split.length >= 6) { //item, count, name, ench and level
                                if(!(split[3].equals("*"))) { //set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    setName(item, split[3]);
                                    item.addEnchantment(Enchantment.getByName(split[4]), Integer.parseInt(split[5]));
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                } else {//dont set name
                                    ItemStack item = new ItemStack(Material.getMaterial(split[1]), Integer.parseInt(split[2]));
                                    item.addEnchantment(Enchantment.getByName(split[4]), Integer.parseInt(split[5]));
                                    e.getBlock().getWorld().dropItem(e.getBlock().getLocation(), item);
                                }
                            }
                        }
                    }
                }
            }
        }
    
    
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, String[] args) {
            Generator gen = Generator.getInstance();
            if(cmdLabel.equalsIgnoreCase("genTerrain")) {
                if(sender instanceof Player) {
                    Player player = (Player) sender;
                    if(!(args.length == 0)) {
                        try{
                            Integer.parseInt(args[0]);
                        }catch(NumberFormatException e){
                            player.sendMessage(ChatColor.RED + "Invalid Arguments! Please specify a value for the number of strands to generate!");
                        }
                        player.sendMessage(ChatColor.GREEN + "Generating " + args[0] + " strands from " + terrainGenList.size() + " possibilities.");
                        this.genRandFromList(Integer.parseInt(args[0]), player.getLocation());
                    } else {
                        player.sendMessage(ChatColor.RED + "Invalid Arguments! Please specify a value for the number of strands to generate!");
                    }
                } else if(sender instanceof ConsoleCommandSender) {
                    //The command was executed from console.
                } else {
                    //OMG, it's herobrine (no, there can be other senders, too, but it's unlikely).
                }
            } else if(cmdLabel.equalsIgnoreCase("genTerrainAuto")) {
                if(sender instanceof Player) {
                    Player player = (Player) sender;
                    if(!(args.length == 0)) {
                        if(args[0].equals("true")) { this.genRandFromListAuto(player.getLocation(), true);
                        } else if(args[0].equalsIgnoreCase("false")) { this.genRandFromListAuto(player.getLocation(), false);
                        } else {player.sendMessage(ChatColor.RED + "Invalid Arguments! Please specify true or false");}
                    } else {
                        player.sendMessage(ChatColor.RED + "Invalid Arguments! Please specify true or false");
                    }
                } else if(sender instanceof ConsoleCommandSender) {
                    //The command was executed from console.
                } else {
                    //OMG, it's herobrine (no, there can be other senders, too, but it's unlikely).
                }
            } else if(cmdLabel.equalsIgnoreCase("registerPoint")) {
                if(sender instanceof Player) {
                    Player player = (Player) sender;
                    //if(!(args.length == 0)) {
                    gen.registerPoint(player.getLocation().getBlockX(), player.getLocation().getBlockZ());
                    //}
                } else if(sender instanceof ConsoleCommandSender) {
                    //The command was executed from console.
                } else {
                    //OMG, it's herobrine (no, there can be other senders, too, but it's unlikely).
                }
            } else if(cmdLabel.equalsIgnoreCase("pickPlayers")) {
                if(sender instanceof Player) {
                    Random r = new Random();
                    List<Player> players = new ArrayList<>();
    
                    for (Player player : Bukkit.getOnlinePlayers()) {
                        if(player.getScoreboardTags().contains("skyCue")) {
                            players.add(player);
                        }
                    }
                    log.info("players in cue are:" + Integer.toString(players.size()));
                    Player p1;
                    Player p2;
                    Player p3;
                    Player p4;
                    List<Player> warriors = new ArrayList<>();
    
                    if(players.size() <= 1) {
                        log.info("not enough players!!!");
                    }
                    if(players.size() > 1) {
                        p1 = players.get(r.nextInt(players.size()));
                        players.remove(p1);
                        warriors.add(p1);
                        p2 = players.get(r.nextInt(players.size()));
                        players.remove(p2);
                        warriors.add(p2);
                    }
                    if(players.size() > 2) {
                        p3 = players.get(r.nextInt(players.size()));
                        players.remove(p3);
                        warriors.add(p3);
                    }
                    if(players.size() > 3) {
                        p4 = players.get(r.nextInt(players.size()));
                        players.remove(p4);
                        warriors.add(p4);
                    }
                    for(int i = 0; i < warriors.size(); i++) {
                        Player p = warriors.get(i);
                        p.removeScoreboardTag("skyCue");
                        p.addScoreboardTag("skywars");
                    }
                }
            }
            return false;
        }
    }
    
    Generator Class:
    Code:
    package me.Copyright2017.plugins.SkywarsPlugin;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Random;
    import java.util.Map.Entry;
    import java.util.UUID;
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.entity.Item;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.scheduler.BukkitRunnable;
    import org.bukkit.util.Vector;
    public class Generator extends BukkitRunnable {
        static SkywarsPlugin plugin;
        public Generator(SkywarsPlugin instance) {
            this.plugin = instance;
        }
        static Generator instance = new Generator(plugin);
        public static Generator getInstance() {
                return instance;
        }
       
        HashMap<UUID, Integer> auto = new HashMap<UUID, Integer>();
        HashMap<UUID, Integer> ite = new HashMap<UUID, Integer>();
        ArrayList<Point> placeLoc = new ArrayList<>();
    
        public void registerPoint(int x, int z){
            Point point = new Point(x, z);
            if(!(placeLoc.contains(point))) {
                placeLoc.add(point);
                Block block = Bukkit.getServer().getWorlds().get(0).getHighestBlockAt(x, z);
                System.out.println(block.getType() + "is the block we found");
                if(block.getType() == Material.AIR) {
                    block.setType(Material.STONE);
                }
            }
        }
       
        public void genTerrain(Material material, Location location, int blocks) {
            ItemStack t = new ItemStack(material, 64);
            Item droppedItem = location.getWorld().dropItem(location, t);
            droppedItem.setGravity(false);
            droppedItem.setInvulnerable(true);
            droppedItem.setPickupDelay(32767);
            droppedItem.setVelocity(new Vector(0,0,0));
            ite.put(droppedItem.getUniqueId(), blocks);
        }
       
       
        public void genTerrainAuto(Material material, Location location, int blocks, boolean flat) {
            ItemStack t = new ItemStack(material, 64);
            Item droppedItem;
            if(placeLoc.size() == 0) {
                droppedItem = location.getWorld().dropItem(location, t);
            } else {
                System.out.println("found data");
                Random rand = new Random();
                int n = rand.nextInt(placeLoc.size());
                Point place = placeLoc.get(n);
                int y = location.getWorld().getHighestBlockYAt(place.x, place.z);
                location = new Location(location.getWorld(), place.x, y, place.z);
                droppedItem = location.getWorld().dropItem(location, t);
            }
            droppedItem.setGravity(false);
            droppedItem.setInvulnerable(true);
            droppedItem.setPickupDelay(32767);
            if(flat) {
                droppedItem.setVelocity(new Vector(0,0,0));
            } else {
                droppedItem.setVelocity(new Vector(0,1,0).multiply(0.1));
            }
            auto.put(droppedItem.getUniqueId(), blocks);
        }
       
       
        @Override
        public void run() {
            Iterator<Entry<UUID, Integer>> it = ite.entrySet().iterator();
            while (it.hasNext()) {
                Entry<UUID, Integer> entry = it.next();
                int blockNum = entry.getValue();
                if(blockNum >= 1) {
                    Block block = Bukkit.getServer().getEntity(entry.getKey()).getLocation().getBlock();
                    if(block.getType() == Material.AIR) {
                        block.setType(((Item) Bukkit.getServer().getEntity(entry.getKey())).getItemStack().getType());
                        entry.setValue(blockNum -1); //set ticks   
                    }
                } else {
                    Bukkit.getServer().getEntity(entry.getKey()).remove();
                    it.remove();
                }
            }
            Iterator<Entry<UUID, Integer>> ita = auto.entrySet().iterator();
            while (ita.hasNext()) {
                Entry<UUID, Integer> entry = ita.next();
                int blockNum = entry.getValue();
                if(blockNum >= 1) {
                    Block block = Bukkit.getServer().getEntity(entry.getKey()).getLocation().getBlock();
                    if(block.getType() == Material.AIR) {
                        block.setType(((Item) Bukkit.getServer().getEntity(entry.getKey())).getItemStack().getType());
                        int x = block.getLocation().getBlockX();
                        int z = block.getLocation().getBlockZ();
                        Point point = new Point(x, z);
                        if(!(placeLoc.contains(point))) {
                            placeLoc.add(point);
                        }
                        entry.setValue(blockNum -1); //set ticks   
                    }
                } else {
                    Bukkit.getServer().getEntity(entry.getKey()).remove();
                    ita.remove();
                }
            }
        }
    }
    
    Point Class:
    Code:
    package me.Copyright2017.plugins.SkywarsPlugin;
    
    public class Point {
        public int x = 0;
        public int z = 0;
        //constructor
        public Point(int a, int b) {
            x = a;
            z = b;
        }
    }
    
    Here is a screencap of whats going on:


    The errors are as follows:

    This error pops up occasionally.
    Code:
    java.util.ConcurrentModificationException: null
            at java.util.HashMap$HashIterator.nextNode(Unknown Source) ~[?:1.8.0_131]
            at java.util.HashMap$EntryIterator.next(Unknown Source) ~[?:1.8.0_131]
            at java.util.HashMap$EntryIterator.next(Unknown Source) ~[?:1.8.0_131]
            at me.Copyright2017.plugins.SkywarsPlugin.Generator.run(Generator.java:98) ~[?:?]
            at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:53) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:52) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_131]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_131]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    and after a bunch of those I get this:
    Code:
    [13:58:27 ERROR]: Encountered an unexpected exception
    net.minecraft.server.v1_12_R1.ReportedException: Exception ticking world
            at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:743) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:366) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:650) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:554) [craftbukkit.jar:git-Bukkit-3819f8d]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    Caused by: java.util.ConcurrentModificationException
            at java.util.HashMap$HashIterator.nextNode(Unknown Source) ~[?:1.8.0_131]
            at java.util.HashMap$KeyIterator.next(Unknown Source) ~[?:1.8.0_131]
            at net.minecraft.server.v1_12_R1.PlayerChunkMap.flush(PlayerChunkMap.java:122) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.WorldServer.doTick(WorldServer.java:307) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:739) ~[craftbukkit.jar:git-Bukkit-3819f8d]
            ... 4 more
    
    and then the server proceeds to crash.

    Also in my generator class I have a warning:
    https://photos.app.goo.gl/VD8SAFklHh55F6or2
    I do not know what that means so I have no idea how to fix it. (I was probably following someones directions somewhere on the internet :p)


    a few questions:
    Is it ok to have my own methods in a bukkit runnable class (like I do in the generator class) for the sake of simplicity?

    If I need to access these variables in multiple methods in the class, putting them in onEnable() won't work.
    https://photos.app.goo.gl/ORNV6DOMxqZChwfF3
    what is the correct way to do this? also what should be in onEnable() and what shouldn't?

    Sorry for being so nooby, the only reason I've got this far is because I know Powershell and some things hit home.
     
  14. Offline

    Caderape2

    @Copyright2017
    - The warning it's because you cant use the keyword 'this' for static field. this is a keyword for refer to a field in the class. static field are global
    - You can create a field outside of your onEnable, and declare it in your onEnable. Then you can access it with constructors.
    - What is the line 98 of the method run in your generator class ?
     
  15. Offline

    Copyright2017

    Last edited: Jul 24, 2017
  16. Offline

    Caderape2

    @Copyright2017 You didn't modified your code ? That line should not throw an error.
    The issue might come if you try to modify data of the hasmap while iterate it.
     
    Last edited: Jul 24, 2017
  17. Offline

    Copyright2017

    @Caderape2 nevermind I did some reading. instead of running runTaskTimerAsynchronously (for applications that take more than a tick to complete) I needed runTaskTimer instead because the data wasn't being synced correctly. I just switched to runTaskTimer and boom no errors.

    Now what do I need to change about that warning?
     
Thread Status:
Not open for further replies.

Share This Page