Per Player Customer Inventories

Discussion in 'Plugin Development' started by Stroved, Jan 27, 2015.

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

    Stroved

    Hey guys. I'm rather new to Java and Bukkit/Spigot plugins, but I'm trying to code some new features for my server. What I am trying to do is to allow players to choose a title/spell/skill that they have from a customer inventory. All of these are selected from a database, which works well.

    The issue I am having is that when two players have the inventory open, and click the same slot, it gets back both values, even though they are different, and in different inventories. This will then update/give the wrong player a title/skill/spell that they do not have in the database.

    I am using the custom inventory code: http://bukkit.org/threads/icon-menu.108342/

    I have created an inventory which allows you to open another inventory, for titles/skills/spells. Here is the first inventory code:
    Code:
            //Character Menu
            //Shows the Titles, Skills and the Character Stats
           characterMenu = new IconMenu(ChatColor.GREEN + "Character", 27, new IconMenu.OptionClickEventHandler() {
               @Override
               public void onOptionClick(final IconMenu.OptionClickEvent event) {
                  if(event.getName() == "Titles") {
                      Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                          public void run() {
                              event.setWillDestroy(true);
                              try {
                                    makeTitlesMenu(event.getPlayer());
                                } catch (SQLException e) {
                                    e.printStackTrace();
                                }
                              titlesMenu.open(event.getPlayer());
                          }
                      }, 2L);
                  }else
                  if(event.getName() == "Skills") {
                      Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                          public void run() {
                              event.setWillDestroy(true);
                              try {
                                    makeSkillsMenu(event.getPlayer());
                                } catch (SQLException e) {
                                    e.printStackTrace();
                                }
                              skillsMenu.open(event.getPlayer());
                          }
                      }, 2L);
                  }else
                  if(event.getName() == "Spells") {
                      Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                          public void run() {
                              event.setWillDestroy(true);
                              try {
                                    makeSpellsMenu(event.getPlayer());
                                } catch (SQLException e) {
                                    e.printStackTrace();
                                }
                              spellsMenu.open(event.getPlayer());
                          }
                      }, 2L);
                  }else{
                      event.setWillClose(false);
                  }
               }
           }, plugin);
           //End Character Menu
    
    As you can see, when you click the item, it will create the menu, and then open it. Here is the titles menu:

    Code:
       //Create the titles menu, and add each option every time that this is called
        public void makeTitlesMenu(Player event) throws SQLException {
            Player player = event.getPlayer();
           
           //Titles Menu
           //Gets a list of all the titles from the database, and lists them
            titlesMenu = new IconMenu(ChatColor.WHITE + "Titles", 27, new IconMenu.OptionClickEventHandler() {
               @Override
               public void onOptionClick(IconMenu.OptionClickEvent event) {
                  //Check if they have any titles, and if not, don't do anything.
                  if(event.getName() == "No Titles") {
                      //event.setWillClose(true);
                      event.setWillDestroy(true);
                  }else{
                     Statement statement = null;
                      try {
                          statement = c.createStatement();
                      } catch (SQLException e) {
                          e.printStackTrace();
                      }
                     
                      try {
                            statement.executeUpdate("UPDATE players SET `title` = '" + event.getName() + "' WHERE uid = '" + event.getPlayer().getUniqueId() + "';");
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                     
                      //Set their in game name          
                      ResultSet res = null;
                        try {
                            res = statement.executeQuery("SELECT * FROM titles WHERE title = '" + event.getName() + "';");
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                        try {
                            res.next();
                        } catch (SQLException e1) {
                            e1.printStackTrace();
                        }
                        try {
                            if(res.getString("location").equals("before")) {
                                event.getPlayer().sendMessage("Your title is now: " + event.getName() + " " + event.getPlayer().getName());
                                NametagAPI.setNametagHard(event.getPlayer().getName(), event.getName() + " ", "");
                            }else{
                                event.getPlayer().sendMessage("Your title is now: " + event.getPlayer().getName() + " " + event.getName());
                                NametagAPI.setNametagHard(event.getPlayer().getName(), "", " " + event.getName());
                            }
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                       
                        event.setWillDestroy(true);
                  }
               }
           }, plugin);
            //End Titles Menu
           
            //Add the titles to the menu
            ResultSet res4 = c.createStatement().executeQuery("SELECT * FROM player_titles WHERE username = '" + player.getName() + "';");
            int titleLocation = 0;
           
            if(!res4.next()) {
                //getLogger().info("The user has no titles");
                titlesMenu.setOption(0, new ItemStack(Material.PAPER, 1), "No Titles", "You currently do not have any titles. Go out", "and get some!");
            }else{
                //getLogger().info("The user has titles!");
                do {
                    ResultSet res5 = c.createStatement().executeQuery("SELECT * FROM titles WHERE id = '" + res4.getInt("titleid") + "';");
                    res5.next();
                   
                    if(res5.getString("desc").contains("#")) {
                        String[] desc = res5.getString("desc").split("#");
                        titlesMenu.setOption(titleLocation, new ItemStack(Material.PAPER, 1), "" + res5.getString("title") + "", ChatColor.GRAY + "" + desc[0] + "", ChatColor.GRAY + "" + desc[1] + "");
                    }else{
                        titlesMenu.setOption(titleLocation, new ItemStack(Material.PAPER, 1), "" + res5.getString("title") + "", ChatColor.GRAY + "" + res5.getString("desc") + "");
                    }
                    //getLogger().info(player.getName() + " has title: " + res5.getString("title") + " at location: " + titleLocation);
                    titleLocation++;
                } while(res4.next());
            }
            //End menu
           
        }
    
    I create the menu, and then add the items to it from the database. This shows the correct items for the players, but if two players are on the same menu, one will show "No Titles", the other "Archer", but if the no titles player clicks "No Titles", it will give them "Archer", even though they do not have it.

    My question is, is there anyway to create per-player inventories and add items to it for each player? I have fixed most of it, but this is the last hurdle that I cannot seem to fix.

    P.S. I know my code is crap, I'm going to re-write it at some point :p

    Thanks!
     
  2. Offline

    ColonelHedgehog

  3. Offline

    Stroved

    I'd love to test using this, but the documentation isn't fully up yet (I can see you are working on it currently). I'll give it a try when I know how to add items properly.

    Is it per player, or do I need to specify this? Is there any specific way to call these functions, or can they just be called when I click an item and still be per player?

    Thanks!
     
  4. Offline

    ColonelHedgehog

    Each function works very much like a Bukkit event InventoryClickEvent. Anything you could do there, you can do in an ActionHandler. If this doesn't answer your question, could you explain please?
     
  5. Offline

    Stroved

    Well the current API that I'm using, the inventory isn't per player it seems. When I click on an item, it returns the item ID for all items in that slot, across different players.

    E.G: Player 1 has item "Charge" in slot one. Player 2 has item "Fireball" in slot one. If player one clicks Charge, it returns charge and fireball, even though Charge was the item clicked on.

    This is my main problem that I have, as I cannot update the value for the player if it returns items that are not there for the player in question.

    I see that you have updated the Wiki, so I will take a bash at this and see how well it works!
     
  6. Offline

    mythbusterma

    @Stroved

    Out of curiosity, why are you using SQL in a plugin you're making for your own server? Do you just not like performance or something?
     
  7. Offline

    Stroved

    As its only a personal project, I am using it to link to a website which gets all of the information from the database, which is saved through this plugin. As far as I know, you cannot do this via flat file.
     
  8. Offline

    timtower Administrator Administrator Moderator

    @Stroved Is it just me or are you running sql queries on the main thread?
     
  9. @Stroved
    Well, I didn`t understood good, but I think you`re trying to make a GUI, that let u choice some options for your server and store that options.

    Well, you must create a public method for every itemstack or something like that, so when you create the gui, you use that ItemStacks

    Then, on InventoryClickEvent you check if the inventory name equals to the inventory u created. You check if the item isn`t null and then check what itemstack it`s so on every itemstack you could do the stuff you want. (and cancel the event too)
     
  10. Offline

    Stroved

    I probably am. I've just started, and used a small MySQL tutorial on here, which didn't say anything about threads. I will look into it further when I'm re-writing the plugin. I am just trying to get everything work first!

    If you have any tips, that would be awesome.

    I think I am already doing that, but checking the Inventory name would be moot, as it is the same for everyone. I create the inventory for the player in a public method, just for them. I then add the items in that method for them. However, when clicking on the item, if two players have the inventory up, it will return both of the items in that slot. I think this would happen for more then 2 players as well (I don't have that many accounts to test).
     
  11. Offline

    timtower Administrator Administrator Moderator

    @Stroved 1 thread. 1 queue of tasks and objects to return the value to. Then you have that thread take the first item of the queue, handle it, return the value to the object, wait ... time.
     
  12. Offline

    Stroved

    Do you have any links for Java multi-threads? I will of course search, but you may know some good ones that can help me get started.
     
  13. Offline

    timtower Administrator Administrator Moderator

    @Stroved Nope, trial and error is a good thing. It was a long time ago that I learned threads.
     
  14. Offline

    mythbusterma

    @Stroved

    Yea, use the BukkitScheduler rather than your own thread. It's much easier to use and understand if you don't know what you're doing.

    Also, you can't really do what you described with a flat file (not reasonably, anyway), that is correct.

    Just make sure you don't pass any information that has the potential to change between the threads.
     
Thread Status:
Not open for further replies.

Share This Page