Registering doors to Players

Discussion in 'Plugin Development' started by x3chaos, Dec 20, 2012.

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

    x3chaos

    I am trying to use signs to register doors to players, and only allow those players to open doors registered either to them, respectively, or to nobody. I've figured out how to get the text from a sign when it's placed and how to find if there is a door immediately around it (and then handle the request, judging by whether there's a door or not).

    What I'm trying to do is figure out how I should store the info. What I really want to be able to store would be the Sign and the door together (should I use Block for either of those?), and then register them as being owned by a player. Obviously, the player would be able to own more than one door, and I would store the player's name instead of the Player object.

    I'm thinking that I should just use a HashMap<Sign, Block> nested inside another HashMap, but that seems really tedious and hard on memory, and for some reason it seems like it would be unreliable to save, be it to a file or using some form of database (if it's better to use the latter, expect another thread on how to use SQL or the like :p).

    Anyway, bottom line: how should I go about saving the registry of doors and their owners?
    If you'd like, I can post any little bits and/or pieces of the code for reference.

    (That's the end of the question, I'm gonna think out loud here for a sec, and if you have the time to read and comment, I'd appreciate it.) :)
    I've read a little bit about player metadata, but I've only played with it a little when I was half-asleep and had no idea what I was doing, so I'm not sure if it could come into play here or not. What would be really cool to me would be to set up an entirely different class for a registered door, which is what I might do. I think I know what I'm doing there, I just don't know what consequences it would have.
     
  2. Offline

    daviga404

    Don't use a HashMap to store this kind of stuff. SQLite or MySQL could be what you are looking for, SQLite seems most appropriate though. MySQL is made for multiple databases and large servers, etc. SQLite is, well, lightweight and reliable. It would not be too hard to store the X, Y and Z of the doors and signs and the owner's name in (a) table(s). You could also use YML to make it even simpler, this would be a less reliable approach but it is integrated into the Bukkit API making it easier to use. Also, don't store the block as they are subject to change, store the co-ords and check if it is still a sign/door.
     
  3. Offline

    x3chaos

    Alright, then my next question is how to set up and use SQLite with a Bukkit plugin. I'll get to Googling, but do you have links to any tutorials or docs offhand? Figured I'd ask before I get too deep into Google. :)

    EDIT: I found one here, gonna keep looking.

    Double posting for this error.

    After reading up a bit, I've added a few methods, and successfully retrieved columns and inserted them. Go me.
    I've run into this error while trying to determine whether a player entry already exists in the database.

    ERROR:
    Show Spoiler

    [​IMG]
    (Pardon the fact that it's an image; I'm too lazy to be bothered to copy it from the console.)


    Here's the code, with line 109 marked.
    Code:
    SQLite sqlite; // This is assigned in onEnable()
    ...
    public boolean exists(String name) throws SQLException {
            Connection connection = null;
            PreparedStatement statement = null;
            ResultSet resultSet = null;
            boolean exists = false;
     
            try {
                connection = sqlite.getConnection();
                statement = connection.prepareStatement("SELECT * FROM table WHERE playername = ?"); // LINE 109
                statement.setString(1, name.toLowerCase());
                resultSet = statement.executeQuery();
                exists = resultSet.next();
            } finally {
                connection.close();
                statement.close();
                resultSet.close();
            }
     
            return exists;
        }
    Could someone better than I am at SQL/SQLite take a look and offer some advice? I'd appreciate it, considering the same method worked for me in another instance (populating a List with the names of all players) and I'm not quite sure what's going wrong, since I don't readily have the source containing the line that throws the NPE. TIA!

    EDIT: Here's a link to the SO thread from which I got the general idea.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 30, 2016
  4. Offline

    reesylou

    Looks like either your connection or the sqlite variable is null. I haven't played with the SQLite library at all, so all I can really suggest is checking that the SQLlite instance is correctly established, and check the call to getConnection is successful.
     
  5. Offline

    x3chaos

    Nah, I threw in a check to make sure that the connection wasn't null, and it threw the same NPE. And the SQLite instance is established correctly, or else it would have thrown the NPE at the line before:
    Code:
    connection = sqlite.getConnection();
    which is why I'm finding this odd. The stack trace says that it's coming from org.sqlite.PrepStmt.<init>.
     
  6. Offline

    fireblast709

    x3chaos what I get from a little bit of research, it that there should be another error somewhere above that
     
  7. Offline

    x3chaos

    I'm not quite sure what you mean by that; the only exception being thrown thus far is the NPE thrown because the connection is still null after sqlite.getConnection(); was unsuccessful (from what I've deduced). Now I'm just trying to figure out how to fix it.
     
  8. Offline

    fireblast709

    if connection is null, the NPE would give another line
     
  9. Offline

    x3chaos

    How do you figure? It shouldn't.
    I initialize Connection connection as null. I assign connection to the return parameter of getConnection() from SQLite sqlite. Then, when I attempt to access the method prepareStatement() from connection, it throws an NPE because connection is still null. From that, I deduce that the assignment (getConnection()) failed.

    If I'm wrong, someone tell me, but I'm 99% sure that I'm right.
     
  10. Offline

    fireblast709

    I figured that like so:
    1. The first line tells me the error is a NullPointerException
    2. The second line tells me where it actually occurs, namely line 42 of PrepStmt.java.
    3. I googled 'PrepStmt java', which gave me this: http://grepcode.com/file/repo1.mave...al/sqlite-jdbc/3.7.2/org/sqlite/PrepStmt.java
    4. On line 42 it tries to invoke 'db.prepare(this)', which means (according to the error) that db is null.
    5. There is no db defined, but it is in his super class (note that 'extends'. If you cannot find in in the current class, try the super class)
    6. I find that it gets db from Connection's method db(), which plainly returns its own DB db. Here again, I look for an initialization of db
    7. The first method in the constructor of Connection cannot set db to null, or it would have thrown an error
    8. Also, the method is called from Conn (sub class of Connection), which means your SQLite is probably suppressing the error
     
  11. Offline

    x3chaos

    OH, okay. I wasn't digging through the source, I was thinking it was something I was doing wrong.
    But then, what can I do to fix this bug in my plugin?
     
  12. Offline

    fireblast709

    Can you post the SQLite class?
     
  13. Offline

    x3chaos

  14. Offline

    fireblast709

    x3chaos ok so lets get to business. Somewhere in your code (probably onEnable()), you use sqlite.open(). What does this return? (Like: null or value)
     
  15. Offline

    x3chaos

    I used it as if it was a void, but it returns a Connection. Should I have a global Connection variable where I store the value of sqlite.open()?

    Here's the method that onEnable() calls to do so:
    Show Spoiler
    Code:
    public void sqlConnection() {
     
        try {
            sqlite.open();
        } catch (Exception ex) {
            log.log(Level.SEVERE, "SQL ERROR! " + ex.getMessage());
            getPluginLoader().disablePlugin(this);
        }
     
    }


    EDIT: This is what I meant, something like this:
    Show Spoiler
    Code:
    Connection globalConnection;
    ...
    @Override
    public void onEnable() {
        ...
        globalConnection = sqlConnection();
        ...
    }
    public Connection sqlConnection() {
        Connection result = null;
     
        try {
            result = sqlite.open();
        } catch (Exception ex) {
            log.log(Level.SEVERE, "SQL Error! " + ex.getMessage());
            getPluginLoader().disablePlugin(this);
        }
     
        return result;
    }
     
  16. Offline

    fireblast709

    looks legit
     
Thread Status:
Not open for further replies.

Share This Page