Instance Retriever

Discussion in 'Spigot Plugin Development' started by Hallowizer, May 1, 2017.

  1. Hi! I have a class as follows:

    Code (Text):
    package com.hallowizer.questionmarkheads;

    import org.bukkit.entity.Player;
    import org.bukkit.event.block.BlockPlaceEvent;

    public class PlayerData {
        public static PlayerData[] instances = new PlayerData[20000000];
        public static int nextSlot = 0;
     
        public static PlayerData getPlayerData(Player player) {
            PlayerData result = null;
            for (PlayerData playerData : instances) {
                if (playerData.getPlayer() == player) {
                    result = playerData;
                }
            }
            return result;
        }
     
        public Player player;
        public boolean chatListening = false;
        public BlockPlaceEvent placeEvent = null;
     
        public PlayerData(Player player) {
            this.player = player;
            PlayerData.instances[nextSlot] = this;
            nextSlot++;
        }
     
        public Player getPlayer() {
            return player;
        }
     
        public boolean isListeningForChat() {
            return chatListening;
        }
     
        public void enableChatListening(BlockPlaceEvent evt) {
            this.chatListening = true;
            this.placeEvent = evt;
        }
     
        public void disableChatListening() {
            this.chatListening = false;
            this.placeEvent = null;
        }
     
        public BlockPlaceEvent getPlaceEvent() {
            return placeEvent;
        }
    }
     


    And here is the error I'm getting from spigot:

    Code (Text):
    Could not pass event AsyncPlayerChatEvent to QuestionMarkHeads v1.0
    org.bukkit.event.EventException
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:484) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.PlayerConnection.chat(PlayerConnection.java:1266) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:1204) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.PacketPlayInChat$1.run(PacketPlayInChat.java:39) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_45]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_45]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_45]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_45]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45]
    Caused by: java.lang.NullPointerException
        at com.hallowizer.questionmarkheads.PlayerData.getPlayerData(PlayerData.java:13) ~[?:?]
        at com.hallowizer.questionmarkheads.Events.onPlayerChat(Events.java:88) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:302) ~[spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        ... 11 more


    I am aware that what I need to fix is line 13 in that class, but what exactly is wrong? To save you some work, line 13 is the line that says
    Code (Text):
    if (playerData.getPlayer() == player)
     
  2. GetPlayer only appears to return the player of an instance. You would need to find the instance of the class before this will ever not be null.


    I would suggest making a loop that goes through the array of instances and then returns the playerData object once player matches.





    Sent from my iPhone using Tapatalk
     
  3. Also please use an ArrayList instead of an array as creating an array of 20000000 PlayerData will actually allocate enough memory for all of those instances.
     
  4. Yeah an arraylist or set is much better as it will only grow as big as required


    Sent from my iPhone using Tapatalk
     
  5. When you instantiate the PlayerData class it must be sending a null player somehow.
    I would also use an arraylist as said above, and I would store the instances in my main class.

    I also assume you're instantiating the PlayerData class in onEnable() and PlayerLoginEvent?
     
  6. Same error, except with a PlayerQuitEvent. Here is the error:

    Code (Text):
    Could not pass event PlayerQuitEvent to QuestionMarkHeads v1.0
    org.bukkit.event.EventException
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.PlayerList.disconnect(PlayerList.java:379) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:1054) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.NetworkManager.handleDisconnection(NetworkManager.java:318) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.ServerConnection.c(ServerConnection.java:174) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.MinecraftServer.D(MinecraftServer.java:842) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:399) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:678) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:576) [spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45]
    Caused by: java.lang.NullPointerException
        at com.hallowizer.questionmarkheads.PlayerData.getPlayerData(PlayerData.java:14) ~[?:?]
        at com.hallowizer.questionmarkheads.Events.onPlayerQuit(Events.java:34) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:302) ~[spigot.jar:git-Spigot-d4f98a3-cb61ac0]
        ... 12 more
    My PlayerData class:

    Code (Text):
    package com.hallowizer.questionmarkheads;

    import org.bukkit.entity.Player;
    import org.bukkit.event.block.BlockPlaceEvent;

    public class PlayerData {
        public static QuestionMarkHeads staticPlugin = QuestionMarkHeads.getInstance();
        public static PlayerData[] instances = new PlayerData[20000000];
        public static int nextSlot = 0;
       
        public static PlayerData getPlayerData(Player player) {
            PlayerData result = null;
            for (PlayerData playerData : instances) {
                if (playerData.getPlayer() == player) {
                    if (result == null) {
                        result = playerData;
                    } else {
                        staticPlugin.getLogger().info("Two duplicates of a player were found.");
                    }
                }
            }
            return result;
        }
       
        public QuestionMarkHeads plugin = QuestionMarkHeads.getInstance();
        public Player player;
        public boolean chatListening = false;
        public BlockPlaceEvent placeEvent = null;
        public int arraySlot;
       
        public PlayerData(Player player) {
            this.player = player;
            PlayerData.instances[PlayerData.nextSlot] = this;
            this.arraySlot = PlayerData.nextSlot;
            PlayerData.nextSlot++;
        }
       
        public void quitPlayer() {
            PlayerData.instances[arraySlot] = null;
        }
       
        public Player getPlayer() {
            return player;
        }
       
        public boolean isListeningForChat() {
            return chatListening;
        }
       
        public void enableChatListening(BlockPlaceEvent evt) {
            this.chatListening = true;
            this.placeEvent = evt;
        }
       
        public void disableChatListening() {
            this.chatListening = false;
            this.placeEvent = null;
        }
       
        public BlockPlaceEvent getPlaceEvent() {
            return placeEvent;
        }
    }
     
    And here is my event listener:

    Code (Text):
    package com.hallowizer.questionmarkheads;

    import org.bukkit.ChatColor;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.block.BlockState;
    import org.bukkit.block.Skull;
    import org.bukkit.configuration.ConfigurationSection;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockPlaceEvent;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerQuitEvent;

    public class Events implements Listener {
        QuestionMarkHeads plugin = QuestionMarkHeads.getInstance();
       
        @EventHandler
        public void onPlayerJoin(PlayerJoinEvent evt) {
            Player player = evt.getPlayer();
            @SuppressWarnings("unused")
            PlayerData data = new PlayerData(player);
        }
       
        @EventHandler
        public void onPlayerQuit(PlayerQuitEvent evt) {
            Player player = evt.getPlayer();
            PlayerData playerData = PlayerData.getPlayerData(player);
            playerData.quitPlayer();
        }
       
        @EventHandler
        public void onPlayerInteract(PlayerInteractEvent evt) {
            Player player = evt.getPlayer();
            Location looking = player.getEyeLocation();
            Block block = looking.getBlock();
            if (block.getType() == Material.SKULL) {
                if (player.hasPermission("questionmarkheads.click")) {
                    Skull skull = (Skull)block;
                    if (skull.getOwner() == "MHF_Question") {
                        Location targetLocation = block.getLocation();
                        Location location;
                        String worldName;
                        World world;
                        int x;
                        int y;
                        int z;
                        String message;
                        FileConfiguration config = plugin.config;
                        ConfigurationSection section;
                        for (String sectionName : config.getKeys(false)) {
                            section = config.getConfigurationSection(sectionName);
                            worldName = section.getString("world");
                            world = plugin.getServer().getWorld(worldName);
                            x = section.getInt("x");
                            y = section.getInt("y");
                            z = section.getInt("z");
                            location = new Location(world, x, y, z);
                            if (location == targetLocation) {
                                message = section.getString("message");
                                player.sendMessage(ChatColor.GREEN + message);
                            }
                        }
                    }
                }
            }
        }
       
        @EventHandler
        public void onBlockPlace(BlockPlaceEvent evt) {
            Player player = evt.getPlayer();
            Block block = evt.getBlockPlaced();
            Material material = block.getType();
            if (material == Material.SKULL) {
                BlockState state = block.getState();
                Skull skull = (Skull)state;
                if (skull.getOwner() == "MHF_Question") {
                    if (player.hasPermission("questionmarkheads.place")) {
                        player.sendMessage(ChatColor.GREEN + "Now, type in chat what you want the player to see when they right click the skull! Type " + ChatColor.YELLOW + "cancel" + ChatColor.GREEN + " to cancel this head!");
                        PlayerData playerData = PlayerData.getPlayerData(player);
                        playerData.enableChatListening(evt);
                    }
                }
            }
        }
       
        @EventHandler
        public void onPlayerChat(AsyncPlayerChatEvent evt) {
            Player player = evt.getPlayer();
            PlayerData playerData = PlayerData.getPlayerData(player);
            if (playerData.isListeningForChat()) {
                evt.setCancelled(true);
                BlockPlaceEvent placeEvent = playerData.getPlaceEvent();
                playerData.disableChatListening();
                if (evt.getMessage().equalsIgnoreCase("cancel")) {
                    player.sendMessage(ChatColor.GREEN + "Question Mark Head message prompt has been cancelled!");
                } else {
                    String message = evt.getMessage();
                    FileConfiguration config = plugin.config;
                    double random = Math.random();
                    int intName = (int)random;
                    String name = Integer.toString(intName);
                    config.createSection(name);
                    Block skull = placeEvent.getBlockPlaced();
                    World world = skull.getWorld();
                    String worldName = world.getName();
                    int x = skull.getX();
                    int y = skull.getY();
                    int z = skull.getZ();
                    ConfigurationSection section = config.getConfigurationSection(name);
                    section.set("world", worldName);
                    section.set("x", x);
                    section.set("y", y);
                    section.set("z", z);
                    section.set("message", message);
                    player.sendMessage(ChatColor.GREEN + "Message successfully set!");
                }
            }
        }
    }
     
     
  7. fix your memory leak first.
    rather use a collection of some sort which will auto increment its bounds when needed.
    a map would actually be a perfect use for this, because right now the speed is O(n), but a map would reduce it to O(1), and fix your NPE
     
  8. I fixed the NullPointerException, but now the events aren't even getting handled as far as I know. I am not receiving chat messages:

    Events.java:

    Code (Text):
    package com.hallowizer.questionmarkheads;

    import org.bukkit.ChatColor;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.block.BlockState;
    import org.bukkit.block.Skull;
    import org.bukkit.configuration.ConfigurationSection;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockPlaceEvent;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerQuitEvent;

    public class Events implements Listener {
        QuestionMarkHeads plugin = QuestionMarkHeads.getInstance();
       
        @EventHandler
        public void onPlayerJoin(PlayerJoinEvent evt) {
            if (evt.getPlayer() instanceof Player) {
                Player player = evt.getPlayer();
                @SuppressWarnings("unused")
                PlayerData data = new PlayerData(player);
            }
        }
       
        @EventHandler
        public void onPlayerQuit(PlayerQuitEvent evt) {
            if (evt.getPlayer() instanceof Player) {
                Player player = evt.getPlayer();
                PlayerData playerData = PlayerData.getPlayerData(player);
                if (playerData != null) {
                    playerData.quitPlayer();
                }
            }
        }
       
        @EventHandler
        public void onPlayerInteract(PlayerInteractEvent evt) {
            Player player = evt.getPlayer();
            Location looking = player.getEyeLocation();
            Block block = looking.getBlock();
            if (block.getType() == Material.SKULL) {
                if (player.hasPermission("questionmarkheads.click")) {
                    Skull skull = (Skull)block;
                    if (skull.getOwner() == "MHF_Question") {
                        Location targetLocation = block.getLocation();
                        Location location;
                        String worldName;
                        World world;
                        int x;
                        int y;
                        int z;
                        String message;
                        FileConfiguration config = plugin.config;
                        ConfigurationSection section;
                        for (String sectionName : config.getKeys(false)) {
                            section = config.getConfigurationSection(sectionName);
                            worldName = section.getString("world");
                            world = plugin.getServer().getWorld(worldName);
                            x = section.getInt("x");
                            y = section.getInt("y");
                            z = section.getInt("z");
                            location = new Location(world, x, y, z);
                            if (location == targetLocation) {
                                message = section.getString("message");
                                player.sendMessage(ChatColor.GREEN + message);
                            }
                        }
                    }
                }
            }
        }
       
        @SuppressWarnings("deprecation")
        @EventHandler
        public void onBlockPlace(BlockPlaceEvent evt) {
            Player player = evt.getPlayer();
            Block block = evt.getBlockPlaced();
            Material material = block.getType();
            if (material == Material.SKULL) {
                BlockState state = block.getState();
                Skull skull = (Skull)state;
                if (skull.getOwner() == "MHF_Question") {
                    if (player.hasPermission("questionmarkheads.place")) {
                        player.sendMessage(ChatColor.GREEN + "Now, type in chat what you want the player to see when they right click the skull! Type " + ChatColor.YELLOW + "cancel" + ChatColor.GREEN + " to cancel this head!");
                        PlayerData playerData = PlayerData.getPlayerData(player);
                        playerData.enableChatListening(evt);
                    }
                }
            }
        }
       
        @EventHandler
        public void onPlayerChat(AsyncPlayerChatEvent evt) {
            Player player = evt.getPlayer();
            PlayerData playerData = PlayerData.getPlayerData(player);
            if (playerData.isListeningForChat()) {
                evt.setCancelled(true);
                BlockPlaceEvent placeEvent = playerData.getPlaceEvent();
                playerData.disableChatListening();
                if (evt.getMessage().equalsIgnoreCase("cancel")) {
                    player.sendMessage(ChatColor.GREEN + "Question Mark Head message prompt has been cancelled!");
                } else {
                    String message = evt.getMessage();
                    FileConfiguration config = plugin.config;
                    double random = Math.random();
                    int intName = (int)random;
                    String name = Integer.toString(intName);
                    config.createSection(name);
                    Block skull = placeEvent.getBlockPlaced();
                    World world = skull.getWorld();
                    String worldName = world.getName();
                    int x = skull.getX();
                    int y = skull.getY();
                    int z = skull.getZ();
                    ConfigurationSection section = config.getConfigurationSection(name);
                    section.set("world", worldName);
                    section.set("x", x);
                    section.set("y", y);
                    section.set("z", z);
                    section.set("message", message);
                    player.sendMessage(ChatColor.GREEN + "Message successfully set!");
                }
            }
        }
    }
     
    QuestionMarkHeads.java (main class):

    Code (Text):
    package com.hallowizer.questionmarkheads;

    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.java.JavaPlugin;

    public final class QuestionMarkHeads extends JavaPlugin {
        public static QuestionMarkHeads instance;
       
        public static QuestionMarkHeads getInstance() {
            return instance;
        }
       
        public FileConfiguration config;
       
        @Override
        public void onEnable() {
            Events events = new Events();
            this.getServer().getPluginManager().registerEvents(events, this);
            QuestionMarkHeads.instance = this;
            registerPlayers();
            this.saveDefaultConfig();
            config = this.getConfig();
            this.getCommand("questionmark").setExecutor(new CommandQuestionMark());
            this.getCommand("qmreload").setExecutor(new CommandQuestionMarkReload());
            getLogger().info("QuestionMarkHeads have been enabled!");
        }

        @Override
        public void onDisable() {
            getLogger().info("QuestionMarkHeads have been disabled!");
        }
       
        public void registerPlayers() {
            for (Player player : this.getServer().getOnlinePlayers()) {
                @SuppressWarnings("unused")
                PlayerData playerData = new PlayerData(player);
            }
        }
    }
     
     
  9. Static is a memory tool, not an access modifier. Don't abuse it as such.

    Also, don't make fields public.
     
    • Agree Agree x 1
  10. To expand on this, use encapsulation. Make fields private and create public getters/setters as needed.


    Sent from my iPhone using Tapatalk