Solved How to access another plugin's data folder?

Discussion in 'Spigot Plugin Development' started by rightfootmessi, Jan 22, 2018.

Thread Status:
Not open for further replies.
  1. I'm making a plugin that takes data on mines from MineResetLite and I need to figure out how to access its folder (I borrowed code from its github so everything else works should work, I just need to replace the getDataFolder() with something else).
     
    #1 rightfootmessi, Jan 22, 2018
    Last edited: Jan 23, 2018
  2. Same method, just from the instance of the other plugin.

    Plugin#getDataFolder()


    You can get the plugin instance of the other plugin via Bukkit.
     
  3. new File("plugins/WorldEdit/schematics"); //EXAMPLE
     
  4. Theoretically the name of the plugins folder can be configured. Also you should be using File.separator / File.separatorChar since it varies depending on the OS.
     
    • Agree Agree x 2
  5. Can't you just do Bukkit.getPlugin("plugin").getDataFolder();
     
    • Agree Agree x 4
  6. Plugin plugin= getServer().getPluginManager().getPlugin("PluginName");

    plugin.getInstance().getDataFolder();

    or the plugin doesn't have the method:

    Write this in yout main class:
    Code (Text):
    private PluginMainClass class;

    public void getPlugin(PluginMainClass class) {

         this.class = class;
    }


    And get the data folder

    getPlugin().getDataFolder();
     
  7. Ignore my post the method of @tatemylove is more efective
     
  8. I can't tell if I'm still not accessing the data correctly or something is just wrong with my code. This is how I'm trying to access the data in my onEnable():
    Code (Java):
        public List<Mine> mines;
        BlockListener BlockListener = new BlockListener(this);

        private static class IsMineFile implements FilenameFilter {
            public boolean accept(File file, String s) {
                return s.contains(".mine.yml");
            }
        }
       
        @Override
        public void onEnable() {
            // Register Listeners
            Bukkit.getPluginManager().registerEvents(BlockListener, this);
            // Load Mines
            if (Bukkit.getServer().getPluginManager().getPlugin("MineResetLite") == null) {
                Bukkit.getConsoleSender().sendMessage("MRL is null...?"); // I never receive this message.
            } else {
            File[] mineFiles = new File(Bukkit.getServer().getPluginManager().getPlugin("MineResetLite").getDataFolder(), "mines").listFiles(new IsMineFile());
            for (File file : mineFiles) {
                FileConfiguration fileConf = YamlConfiguration.loadConfiguration(file);
                try {
                    Object o = fileConf.get("mine");
                    if (!(o instanceof Mine)) {
                        continue;
                    }
                    Mine mine = (Mine) o;
                    mines.add(mine);
                } catch (Throwable t) {
                }
            }
            }
        }
     
    vs. how MRL does it in its onEnable():
    Code (Java):
        private static class IsMineFile implements FilenameFilter {
            public boolean accept(File file, String s) {
                return s.contains(".mine.yml");
            }
        }
        /* other stuff in between */
        public void onEnable() {
            mines = new ArrayList<Mine>();
            /* other stuff in between */
            //Load mines
            File[] mineFiles = new File(getDataFolder(), "mines").listFiles(new IsMineFile());
            for (File file : mineFiles) {
                logger.info("Loading mine from file '" + file.getName() + "'...");
                FileConfiguration fileConf = YamlConfiguration.loadConfiguration(file);
                try {
                    Object o = fileConf.get("mine");
                    if (!(o instanceof Mine)) {
                        logger.severe("Mine wasn't a mine object! Something is off with serialization!");
                        continue;
                    }
                    Mine mine = (Mine) o;
                    mines.add(mine);
                } catch (Throwable t) {
                    logger.severe("Unable to load mine!");
                }
            }
            /* other stuff afterwards */
        }
    Now, I copied the Mine class from MRL's GitHub, but made some edits. Here's my version below:
    Code (Java):
    /**
     * @author jjkoletar
     */

    public class Mine implements ConfigurationSerializable {
        private int minX;
        private int minY;
        private int minZ;
        private int maxX;
        private int maxY;
        private int maxZ;
        private World world;
        private Map<SerializableBlock, Double> composition;
        private int resetDelay;
        private List<Integer> resetWarnings;
        private String name;
        private SerializableBlock surface;
        private boolean fillMode;
        private int resetClock;
        private boolean isSilent;

        public Mine(int minX, int minY, int minZ, int maxX, int maxY, int maxZ, String name, World world) {
            this.minX = minX;
            this.minY = minY;
            this.minZ = minZ;
            this.maxX = maxX;
            this.maxY = maxY;
            this.maxZ = maxZ;
            this.name = name;
            this.world = world;
            composition = new HashMap<SerializableBlock, Double>();
            resetWarnings = new LinkedList<Integer>();
        }

        @SuppressWarnings("unchecked")
        public Mine(Map<String, Object> me) {
            try {
                minX = (Integer) me.get("minX");
                minY = (Integer) me.get("minY");
                minZ = (Integer) me.get("minZ");
                maxX = (Integer) me.get("maxX");
                maxY = (Integer) me.get("maxY");
                maxZ = (Integer) me.get("maxZ");
            } catch (Throwable t) {
                throw new IllegalArgumentException("Error deserializing coordinate pairs");
            }
            try {
                world = Bukkit.getServer().getWorld((String) me.get("world"));
            } catch (Throwable t) {
                throw new IllegalArgumentException("Error finding world");
            }
            if (world == null) {
                throw new IllegalArgumentException("World was null!");
            }
            try {
                Map<String, Double> sComposition = (Map<String, Double>) me.get("composition");
                composition = new HashMap<SerializableBlock, Double>();
                for (Map.Entry<String, Double> entry : sComposition.entrySet()) {
                    composition.put(new SerializableBlock(entry.getKey()), entry.getValue());
                }
            } catch (Throwable t) {
                throw new IllegalArgumentException("Error deserializing composition");
            }
            name = (String) me.get("name");
            resetDelay = (Integer) me.get("resetDelay");
            List<String> warnings = (List<String>) me.get("resetWarnings");
            resetWarnings = new LinkedList<Integer>();
            for (String warning : warnings) {
                try {
                    resetWarnings.add(Integer.valueOf(warning));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Non-numeric reset warnings supplied");
                }
            }
            if (me.containsKey("surface")) {
                if (!me.get("surface").equals("")) {
                    surface = new SerializableBlock((String) me.get("surface"));
                }
            }
            if (me.containsKey("fillMode")) {
                fillMode = (Boolean) me.get("fillMode");
            }
            if (me.containsKey("resetClock")) {
                resetClock = (Integer) me.get("resetClock");
            }
            //Compat for the clock
            if (resetDelay > 0 && resetClock == 0) {
                resetClock = resetDelay;
            }
            if (me.containsKey("isSilent")) {
                isSilent = (Boolean) me.get("isSilent");
            }
        }

        public Map<String, Object> serialize() {
            Map<String, Object> me = new HashMap<String, Object>();
            me.put("minX", minX);
            me.put("minY", minY);
            me.put("minZ", minZ);
            me.put("maxX", maxX);
            me.put("maxY", maxY);
            me.put("maxZ", maxZ);
            me.put("world", world.getName());
            //Make string form of composition
            Map<String, Double> sComposition = new HashMap<String, Double>();
            for (Map.Entry<SerializableBlock, Double> entry : composition.entrySet()) {
                sComposition.put(entry.getKey().toString(), entry.getValue());
            }
            me.put("composition", sComposition);
            me.put("name", name);
            me.put("resetDelay", resetDelay);
            List<String> warnings = new LinkedList<String>();
            for (Integer warning : resetWarnings) {
                warnings.add(warning.toString());
            }
            me.put("resetWarnings", warnings);
            if (surface != null) {
                me.put("surface", surface.toString());
            } else {
                me.put("surface", "");
            }
            me.put("fillMode", fillMode);
            me.put("resetClock", resetClock);
            me.put("isSilent", isSilent);
            return me;
        }

        public World getWorld() {
            return world;
        }

        public String getName() {
            return name;
        }

        public boolean isInside(Location l) {
            return l.getWorld().equals(world)
                && (l.getX() >= minX && l.getX() <= maxX)
                && (l.getY() >= minY && l.getY() <= maxY)
                && (l.getZ() >= minZ && l.getZ() <= maxZ);
        }
    Compared to the original Mine.java, found at this GitHub link.

    Can anyone help? Again, I'm not sure if it's a mistake when I'm accessing MRL's files or there was an error made in the process of "borrowing" code.
     
  9. If you want to access the data from the folder. Then all you need is the location of the folder and then you can access the files from there such as the config.yml and then write to it.

    So File myFile = new File("plugins/MRL/config.yml")
     
  10. Mas

    Mas

    Follow the normal debugging protocol and add debug statements to your code to see which part of it gets triggered, for example inside your loop to see if any mine files are actually detected.

    Also, in your catch statement, print out your exceptions - there are very few cases where you should completely ignore exceptions like that. My guess is that you're getting errors but your blank catch statement is just suppressing them. You should also be catching IOException as opposed to Throwable (catch the type lowest down in the hierarchy that encompasses all the exceptions that may occur).

    Also, FilenameFilter is a FunctionalInterface, so you can pass it as a lambda rather than creating a new instance of a wrapper class each time like you're doing.

    He's trying to access all the files found in another folder inside the data folder which is named "mines", he can't hardcode paths. Also use File.separator rather than hardcoding the char.
     
  11. Keep in mind, most of this code is straight up taken from MRL itself, so it's partially the fault of the original author as well for some of those mistakes (but mine as well for not noticing). I'll try this.
     
  12. I have discovered that the files are not being read properly, as my plugin does not recognize the files as serialized Mine objects, both when I was using a modified Mine.java AND when I straight-up copied MRL's Mine.java (except I commented out 3 lines, 2 of which broadcasted a message in chat and one of which was a logger message, to avoid having to create new classes - is this fine or is it the problem?)
     
  13. Are you trying to loop through all the files in that folder?
     
  14. Mas

    Mas

    Are the files actually being detected and are you able to get parse a YamlConfiguration from them? If not, focus on being able to fetch the files before worrying about serialization. YAML <-> Object serialization is generally a pain anyway.
     
  15. Here is a better Version
    Code (Text):
            File file = new File(".");
            String path="";
            try {
                path = file.getCanonicalPath();
            } catch (IOException e) {
                e.printStackTrace();
            }
            path = path+File.separator+"plugins"+File.separator+"PluginName"+File.separator+"config.yml";
            File configFile = new File(path);
             FileConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
             
    That will give you the config.yml.
     
    #15 KingTux, Jan 23, 2018
    Last edited: Jan 23, 2018
  16. K3ttle

    K3ttle Previously WesternPine

    TIP: If you are still trying to get the plugin's resource folder using bukkit.getPlugin, make sure you have the plugin youre getting information on, listed as a "depend" in your plugin.yml. This way bukkit can map that said plugin needs to enable before yours. That way you can get the plugin stance. ;D

    Although im sure you already knew that, just mentioning it as a tip because I haven't seen it on here yet. xD
     
  17. I've done some more work and found that yes, my plugin is detecting the files, as it's logging every file name to the console. However, I cannot actually read the data inside each mine. I have a YamlConfiguration fc = YamlConfiguration.loadConfiguration(file) that's attempting to get the data but for whatever reason it is failing. Is it because the files hold serialized Mine objects that I can't just read the file normally?
     
  18. Mas

    Mas

    As long as it's valid yaml it shouldn't matter at that point. Do you get any errors? It may be helpful if you post an example of one of the mine files here.
     
  19. Code (YAML):
    mine:
      ==
    : com.koletar.jj.mineresetlite.Mine
      resetDelay
    : 5
      surface
    : ''
      maxZ
    : -358
      maxY
    : 81
      maxX
    : 217
      ignoreLadders
    : false
      fillMode
    : false
      world
    : Prison
      minY
    : 57
      resetWarnings
    : []
      minX
    : 193
      composition
    :
        '57:0'
    : 0.1
        '129:0'
    : 0.2
        '159:2'
    : 0.4
        '133:0'
    : 0.1
        '56:0'
    : 0.2
      name
    : Byte_1
      resetClock
    : 4
      minZ
    : -382
      isSilent
    : true
      tpY
    : -1
      tpX
    : 0
      tpZ
    : 0
     
     
  20. Alright, I have discovered that it's not as much a problem what I'm attempting as it is the files themselves.

    I finally decided to have it print the stack trace rather than a simple "this didn't work" message and I'm getting a deserialization error. I tried everything, including copying the code directly AND having the exact same classpath.

    Is there anywhere I can go from here or do I have to copy all the files to my own folder and work with them there?
     
Thread Status:
Not open for further replies.