Villager trade gui

Discussion in 'Plugin Development' started by Funergy, Sep 16, 2014.

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

    Funergy

    I'm trying to create a Village trade GUI.
    I've seen done this but it doesn't work.

    Inventory i = Bukkit.getServer().createInventory(null, InventoryType.MERCHANT);

    So how can I do this?
     
  2. Offline

    indyetoile

    Funergy
    There's no API for Villager trading yet, so you would indeed have to create a custom inventory.
    The InventoryType.MERCHANT will open a GUI with 2 TRADE-IN slots and 1 RESULT slot.

    What doesn't work for you? Post your code maybe?
     
  3. Offline

    adam753

    Looks alright. Stupid question, did you remember to open the inventory on the player's screen?
    Code:
    player.openInventory(i);
     
  4. Offline

    Funergy

    yes of course

    Code:
    @EventHandler
        public void onMerchantOpen(PlayerInteractEntityEvent e) {
            if(!e.getRightClicked().getType().equals(EntityType.VILLAGER))
                return;
                 
            Inventory i = Bukkit.getServer().createInventory(null, InventoryType.MERCHANT);
                 
            e.getPlayer().openInventory(i);
         
            e.setCancelled(true);
        }
    indyetoile
    How do I edit the slots like
    You need 2 iron ingots to get a gold ingot or something

    i.addItem doesn't work

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 14, 2016
  5. Offline

    indyetoile

    Funergy
    Use setItem, not addItem.
     
  6. Offline

    Funergy

    indyetoile
    What I have now
    but it doesn't work
    Code:
    @EventHandler
        public void onMerchantOpen(PlayerInteractEntityEvent e) {
            if(!e.getRightClicked().getType().equals(EntityType.VILLAGER))
                return;
                 
            Inventory i = Bukkit.getServer().createInventory(null, InventoryType.MERCHANT);
            i.setItem(0, new ItemStack(Material.IRON_INGOT,1));
            i.setItem(2, new ItemStack(Material.IRON_INGOT,1));
            i.setItem(1, new ItemStack(Material.IRON_INGOT,1));
     
            e.getPlayer().openInventory(i);
         
            e.setCancelled(true);
        }
     
  7. Offline

    fireblast709

    Funergy you probably need to create your own extended CraftInventory
     
  8. Offline

    ChipDev

    Debug messages?
    (Seriously, they are super helpful <3)
     
  9. Offline

    Funergy

    how? I know a little bit nms :$
     
  10. Offline

    bennie3211

    did you register the event?
     
  11. Offline

    Funergy

    bennie3211 likes this.
  12. Offline

    fireblast709

    Funergy If you set slot 0 or 1, it will update slot 2 with the trades the villager has. Try updating slot 2 as last.
     
  13. Offline

    Funergy

    fireblast709 still doesn't work. the inventory doesn't even show.
     
  14. Offline

    fireblast709

    As in, it doesn't open at all :confused:? That would be a completely different issue then I had in mind xD.

    After looking in the source it seems that they just haven't added support for it yet. So if you like to work with it, you either have to use some wizardry or use NMS.
     
  15. Offline

    Funergy

  16. Offline

    fireblast709

    Funergy EntityPlayer has a method named openTrade(IMerchant, String). Normally, this would be called with an EntityVillager and it's custom name, but it should be doable to just create a class that implements IMerchant instead of creating an EntityVillager. As a quick list of methods to implement, I'll attach the interface with some commentary
    Code:java
    1. public abstract interface IMerchant
    2. {
    3. /**
    4.   * Sets the EntityHuman the 'villager' is trading with
    5.   * I guess a simple EntityHuman field which you set with
    6.   * this would suffice
    7.   */
    8. public abstract void a_(EntityHuman paramEntityHuman);
    9.  
    10. /**
    11.   * Returns the EntityHuman the 'villager' is trading with.
    12.   * Should just be the player that was set with the previous
    13.   * method.
    14.   */
    15. public abstract EntityHuman b();
    16.  
    17. /**
    18.   * This is where the fun starts.
    19.   * 1. Start off by creating a MerchantRecipeList
    20.   * 2. Create MerchantRecipes and add them to the MerchantRecipeList
    21.   * (note: it extends ArrayList, so just invoke add(recipe))
    22.   * 2a. The constructor for MerchantRecipe is slot 0, slot 1, slot 2
    23.   * (where slot 2 is the result. Also, they are all NMS ItemStacks (duh))
    24.   * 2b. There is a max amount of uses. Override public void f() to prevent
    25.   * that from happening
    26.   * 3b. Simply return the MerchantRecipeList. Or, if you want progress per player
    27.   * add some crazy mechanics by extending the class :3.
    28.   */
    29. public abstract MerchantRecipeList getOffers(EntityHuman paramEntityHuman);
    30.  
    31. /**
    32.   * These last two seem to be entity specific and wouldn't really
    33.   * be useful for your cause
    34.   */
    35. public abstract void a(MerchantRecipe paramMerchantRecipe);
    36.  
    37. public abstract void a_(ItemStack paramItemStack);
    38. }
    [pre-edit addition] While writing all of this, I noticed something pretty interesting. When you have an EntityVillager, you can call 'getOffers()' to get their MerchantRecipesList. This List is actually mutable, thus
    Code:java
    1. MerchantRecipesList offers = someVillager.getOffers();
    2. offers.clear();
    3. // Note, we do not invoke add(MercheantRecipe), but this method
    4. // This actually takes care of duplicate offers.
    5. // Also: first, second and result are NMS ItemStacks
    6. offers.a(new MerchantRecipe(first, second, result));
    should reset their offers and add your own.
     
  17. Offline

    Funergy

    But I wanna open the gui withoud a Villager how should I do that then
     
  18. Offline

    fireblast709

    Funergy Simply create a class, implement IMerchant, invoke openTrade(instance of that class, 'name of the villager').
     
  19. Offline

    Funergy

    fireblast709 When I cast a player to an entity human it doesn't work
    this is what I have.
    if I do villager.getOffers() it says I need to add a EntityHuman. is that a player. or a Villager.
    because I don't wanna use a villager. just the trade screen
    Code:
      MerchantRecipeList offers = villager.getOffers((EntityHuman)e.getPlayer());
            offers.clear();
            offers.a(new MerchantRecipe(
                    new net.minecraft.server.v1_7_R3.ItemStack(net.minecraft.server.v1_7_R3.Item.d(Material.COBBLESTONE.getId()), 10),
                    new net.minecraft.server.v1_7_R3.ItemStack(net.minecraft.server.v1_7_R3.Item.d(Material.COBBLESTONE.getId()), 10),
                    new net.minecraft.server.v1_7_R3.ItemStack(net.minecraft.server.v1_7_R3.Item.d(Material.EMERALD.getId()), 10)
                    ));        ((CraftPlayer)e.getPlayer()).getHandle().openTrade(villager, "test");
          
    Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer cannot be cast to net.minecraft.server.v1_7_R3.EntityHuman

    at com.funergy.bedwars.Events.onMerchantOpen(Events.java:27) ~[?:?]
     
  20. Offline

    fireblast709

    Funergy EntityHuman is the superclass of EntityPlayer (which obviously means that EntityPlayer is a valid type to pass to the method ;3)
     
  21. Offline

    Funergy

    fireblast709 Yeah but why do I need to add a EntityHuman /EntityPlayer
    Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer cannot be cast to net.minecraft.server.v1_7_R3.EntityPlayer

    at com.funergy.bedwars.Events.onMerchantOpen(Events.java:28) ~[?:?]

    error is on this line

    MerchantRecipeList offers = villager.getOffers((EntityPlayer)e.getPlayer());
     
  22. Offline

    fireblast709

    Funergy you have to cast to CraftPlayer and use getHandle() to get the underlying EntityPlayer
     
  23. Offline

    Funergy

  24. Offline

    fireblast709

    Funergy stacktrace and updated code?
     
  25. Offline

    MineStein

  26. Offline

    Funergy

    fireblast709 My Villager IMerchant class
    Code:
    package com.funergy.bedwars;
     
    import net.minecraft.server.v1_7_R3.EntityHuman;
    import net.minecraft.server.v1_7_R3.IMerchant;
    import net.minecraft.server.v1_7_R3.ItemStack;
    import net.minecraft.server.v1_7_R3.MerchantRecipe;
    import net.minecraft.server.v1_7_R3.MerchantRecipeList;
     
    public class Villager implements IMerchant{
     
        @Override
        public void a(MerchantRecipe arg0) {
            // TODO Auto-generated method stub
       
        }
     
        @Override
        public void a_(EntityHuman arg0) {
            // TODO Auto-generated method stub
       
        }
     
        @Override
        public void a_(ItemStack arg0) {
            // TODO Auto-generated method stub
       
        }
     
        @Override
        public EntityHuman b() {
            // TODO Auto-generated method stub
            return null;
        }
     
        @Override
        public MerchantRecipeList getOffers(EntityHuman arg0) {
            // TODO Auto-generated method stub
            return null;
        }
     
    }
    
    And my Events class
    Code:
    package com.funergy.bedwars;
     
    import net.minecraft.server.v1_7_R3.MerchantRecipe;
    import net.minecraft.server.v1_7_R3.MerchantRecipeList;
     
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer;
    import org.bukkit.entity.EntityType;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.event.inventory.InventoryType;
    import org.bukkit.event.player.PlayerInteractEntityEvent;
    import org.bukkit.inventory.Inventory;
     
    public class Events implements Listener {
        public Villager villager;
     
        @EventHandler
        public void onMerchantOpen(PlayerInteractEntityEvent e) {
            if(!e.getRightClicked().getType().equals(EntityType.VILLAGER))
                return;
            villager = new Villager();
            MerchantRecipeList offers = villager.getOffers(((CraftPlayer)e.getPlayer()).getHandle());
     
     
            offers.clear();//error on this line line
     
     
            offers.a(new MerchantRecipe(
                    new net.minecraft.server.v1_7_R3.ItemStack(net.minecraft.server.v1_7_R3.Item.d(Material.COBBLESTONE.getId()), 10),
             
                    new net.minecraft.server.v1_7_R3.ItemStack(net.minecraft.server.v1_7_R3.Item.d(Material.EMERALD.getId()), 10)));   
            ((CraftPlayer)e.getPlayer()).getHandle().openTrade(villager, "test");
     
            e.setCancelled(true);
        }
        @EventHandler
        public void onclickevent(InventoryClickEvent e){
            if(e.getInventory().getTitle().equalsIgnoreCase("VillageShop")){
     
                Inventory i = Bukkit.getServer().createInventory(null, InventoryType.MERCHANT);
         
                // TODO: Customize the inventory!
         
         
         
            }
        }
     
    }
    
    The important part of the error.
    Caused by: java.lang.NullPointerException

    at com.funergy.bedwars.Events.onMerchantOpen(Events.java:26) ~[?:?]
     
  27. Offline

    fireblast709

    Funergy either implement IMerchant or use getOffers() on an actual Villager, not both :p. Note, for the IMerchant method to work you need to implement the methods properly, of course
     
  28. Offline

    Funergy

    fireblast709 "Note, for the IMerchant method to work you need to implement the methods properly, of course"
    What did I do wrong ?
     
  29. Offline

    fireblast709

    Funergy you have your class, Villager, and you also use
    Code:
    offers.clear();
    offers.a(new MerchantRecipe(...));
    The latter should only be there if you intend to modify an actual NMS EntityVillager.
     
  30. Offline

    Funergy

    fireblast709 Did you ever create a Merchant GUI without a villager? if yes please say how you did it.
     
Thread Status:
Not open for further replies.

Share This Page