NMS Force open custom villager Trade gui!

Discussion in 'Resources' started by mine-care, Feb 11, 2015.

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

    mine-care

    Hi there reader! i have been asked to find a way to force-open villager traed gui for a playerm with custom stuff ect. so i worked on it a litle and came up with a nice class you can simply put in your project that will allow you to do this!

    Why i need this?
    Well people come with any kind of ideas for plugins, the most simple case i can think of is if you make a minigame as shop or if you create a sign trade shop :p

    Example usage:
    Code:
    ForceVillagerTrade f = new ForceVillagerTrade("Name Of Inv displayed");
            //Creating an instance
       
            f.addTrande(new ItemStack(Material.GOLD_INGOT,1), new ItemStack(Material.CARROT,5));
            //Player has to input 1 gold ingot to get 5 carrots
       
            f.addTrande(new ItemStack(Material.DIAMOND,2), new ItemStack(Material.STICK,1), new ItemStack(Material.DIAMOND_SWORD));
            //Player needs to input 2 diamonds and 1 stick to get a diamond sword
       
            f.openTrande(toPlayer);
            //IMPORTANT! When you are done adding stuff to the inv, you HAVE TO invoke this method.
    Class itself:
    Versions 1.7.X (open)

    Code:
    public class ForceVillagerTrade {
        private String invname;
        private MerchantRecipeList l = new MerchantRecipeList();
    
        public ForceVillagerTrade(String invname) {
            this.invname = invname;
        }
    
        public ForceVillagerTrade addTrande(ItemStack itemone, ItemStack out){
            l.a(new MerchantRecipe(CraftItemStack.asNMSCopy(itemone),CraftItemStack.asNMSCopy(out)));
            return this;
        }
        public ForceVillagerTrade addTrande(ItemStack itemone, ItemStack itemtwo, ItemStack out){
            l.a(new MerchantRecipe(CraftItemStack.asNMSCopy(itemone),CraftItemStack.asNMSCopy(itemtwo),CraftItemStack.asNMSCopy(out)));
            return this;
        }
    
        public void openTrande(Player who) {
            final EntityHuman e = ((CraftPlayer) who).getHandle();
            e.openTrade(new IMerchant() {
                @Override
                public MerchantRecipeList getOffers(EntityHuman arg0) {    return l; }
                @Override
                public EntityHuman b() {return e;}
                @Override
                public void a_(net.minecraft.server.v1_7_R4.ItemStack arg0) {}
                @Override
                public void a_(EntityHuman arg0) {}
                @Override
                public void a(MerchantRecipe arg0) {l.a(arg0);}
            }, invname);
        }
    }

    Versions 1.8.X (open)

    Code:
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.ItemStack;
    
    /**
    * This class allows you to open vilager trade inventories that function as normal for players.
    *
    * <h1> ---WARNING--- </h1>
    * <b>This class is version depended! This means that it will <u>only</u>
    * work on servers with the same CraftBukkit version as the one you used to compile your plugin.
    * <br>
    * Some version changes may affect the function of the class (Like they did in the transaction from 1.7.X to 1.8.X)
    * so make sure you check the project page {@link https://bukkit.org/threads/force-open-custom-villager-trade-gui.341546}
    * for updates. You can also leave comments for future changes or bugs.
    * </b>
    *
    * @author mine-care (AKA <b>fillpant</b>)
    *
    */
    public class ForceVillagerTrade {
       
        private String invname;
        private MerchantRecipeList l = new MerchantRecipeList();
    
        /**
         * @param invname Inventory display name, (May contain color)
         *
         */
        public ForceVillagerTrade(String invname) {
            this.invname = invname;
        }
    
        /**
         * @param inOne The itemstack in the first input slot.
         * @param out The itemstack output.
         * @return ForceVillagerTrade object so you can invoke the next method like:
         * addTrade(...).addTrade(...).addTrade(...).openTrade(player);
         */
        public ForceVillagerTrade addTrande(ItemStack in, ItemStack out) {
            l.add(new MerchantRecipe(CraftItemStack.asNMSCopy(in), CraftItemStack
                    .asNMSCopy(out)));
            return this;
        }
    
        /**
         * @param inOne The itemstack in the first input slot.
         * @param inTwo The itemstack on the second input slot.
         * @param out The itemstack output.
         * @return ForceVillagerTrade object so you can invoke the next method like:
         * addTrade(...).addTrade(...).addTrade(...).openTrade(player);
         */
        public ForceVillagerTrade addTrande(ItemStack inOne, ItemStack inTwo,
                ItemStack out) {
            l.add(new MerchantRecipe(CraftItemStack.asNMSCopy(inOne),
                    CraftItemStack.asNMSCopy(inTwo), CraftItemStack.asNMSCopy(out)));
            return this;
        }
    
        /**
         * @param who The player who will see the Trade
         */
        public void openTrande(Player who) {
            final EntityHuman e = ((CraftPlayer) who).getHandle();
            e.openTrade(new IMerchant() {
                @Override
                public MerchantRecipeList getOffers(EntityHuman arg0) {
                    return l;
                }
    
                @Override
                public void a_(net.minecraft.server.v1_8_R3.ItemStack arg0) {
                }
    
                @Override
                public void a_(EntityHuman arg0) {
                }
    
                @Override
                public IChatBaseComponent getScoreboardDisplayName() {
                    return ChatSerializer.a(invname);
                }
    
                @Override
                public EntityHuman v_() {
                    return e;
                }
    
                @Override
                public void a(MerchantRecipe arg0) {
                }
            });
        }
    }

    NOTE: You must use CraftBukkit in your buildpath.
    NOTE #2: All missing Imports have to be from net.minecraft.server.(...) package!

    Todo:
    1. Make Version independed :(
    2. Add selection on how many times someone can trade a specific recipe
    3. Disable auto Recipe regeneration
    4. Add javadog DOC not DOG! darn you autocorrect!
    5. hmm.... Please sugest something :)

    How to support:
    Do you like this resource? i will be glad to know! throw a comment or a like please!
     
    Last edited: Dec 18, 2015
  2. Offline

    ProStriker123

    @mine-care, Wow i so needed it thanks ! you allawys suprise me with it ;)
     
  3. Offline

    mine-care

    ProStriker123 likes this.
  4. Offline

    ChipDev

    I love how you are getting into NMS. Your tutorials are awesome <3
    now i look back at my tuts and shiver.
     
    mine-care likes this.
  5. Offline

    mine-care

    ProStriker123 and ChipDev like this.
  6. Offline

    guitargun

    faved this thread. don't know when I would use it but I will use it in the future...
     
    mine-care likes this.
  7. Offline

    mine-care

  8. Offline

    bwfcwalshy Retired Staff

    *JavaDoc ;)
     
  9. Offline

    mine-care

    @bwfcwalshy Lol just noticed that! i hate autocorrect :mad:
     
  10. Offline

    sgavster

    This looks just amazing. Amazing work.

    I have a question:

    Could this be used to make a custom villager menu? For any villagers, like adding a command to change the villagers trade, and it would stay? That'd be awesome, but I can't figure out how, haha.
     
  11. Offline

    mine-care

    @sgavster hey, thanks for your feedback =] I really appreciate it! So yes you can do that, use inventory click event =] I have published another thread showing how to customize villager inventories in the past, it can be found in recources. You can also listent to entity spawn event and when a villager spawns, set the recipes to the custom ones and so all villagers will have custom recipes =D
     
  12. Offline

    Funergy

    @mine-care Your tutorials are grazy! Just try to fix your spelling. But else its great!
     
    mine-care likes this.
  13. Offline

    Goblom

    @mine-care You will be unable to make this version independent because you make a new instance of an abstract class. And that is not possible with Reflection.
     
  14. Offline

    mine-care

    @Funergy thanks so much!!! I will try to spell check my posts. The resason for my spelling is dislexia D:
    Thanks again =]

    @Goblom yeah that's right, but If I find where this abstract class is called by bukkit, I can reflect to obtain a copy of it for my merchants, that will make it version independed :p
     
    Last edited by a moderator: Mar 18, 2015
  15. Offline

    guitargun

    @mine-care I found a old bukkit 1.7.9 file and use it now.. (spigot 1.8 doesn't work :( ). how can I save the itemtrades of the merchant in a config? I looked into it and only saw that the list returns a Object. do you know if I can cast this object to a itemStack or to something else?
     
  16. Offline

    mine-care

    @guitargun will try to make it spigot compatible asap
    And about saving, mane you can store items before they are added to the merchant.
    I'll look at this issue as well.
    Thanks!
     
  17. Offline

    guitargun

    @mine-care I found out how to get the items of the merchant. to bad I am new to nms. I am trying to convert the nms itemstack to the bukkit itemstack which will be easy to do with the right search. apart from that the merchant is easily to store once you find out how the merchantrecipelist stores it.

    EDIT:


    for those who wonder how to acces it. I made the MerchantRecipelist public so I can acces it from anywhere.
    Code:
            for (int id : plugin.itemfrabric.merchants.keySet()) {
                Merchant m = plugin.itemfrabric.merchants.get(id);
                int total = 0;
                for (int i = 0; i < m.l.size(); i ++) {
                    MerchantRecipe rec = (MerchantRecipe) m.l.get(i);
                    ItemStack bukkitbuy = CraftItemStack.asBukkitCopy(rec
                            .getBuyItem1());
                    ItemStack bukkitsell = CraftItemStack.asBukkitCopy(rec
                            .getBuyItem3());
    }
    }
    buyitem 1 and buyitem 2 are for the to trade slots buyitem 3 is what you get
     
    Last edited: Mar 19, 2015
  18. Offline

    mine-care

    @guitargun great! Now what is left to do for me is to fix spigot compatibility :- )
     
  19. Offline

    lucasdidur

    To me, works fine on Spigot 1.8, but the first item, like of the example, when i put the gold ingot, my minecraft client crash. On second item example works well.
     
  20. Offline

    callum2904

    @mine-care
    How does one go about updating this?
    method "a" is giving an error, I know what it means but I am unsure what to change it too.

    The method a(PacketDataSerializer) in the type MerchantRecipeList is not applicable for the arguments (MerchantRecipe)
     
  21. Offline

    mine-care

    @callum2904 umm what version and build are you using?
     
  22. Offline

    callum2904

    @mine-care spigot/bukkit 1.8.5
     
  23. Offline

    mine-care

    @callum2904 I'll have a look into the source and I'll let u know
     
  24. Offline

    stackbasher

    Really nice work,dude ;D
     
    Last edited: Jul 8, 2015
  25. Offline

    mine-care

  26. Offline

    Look

    have you sir looked into it? I need some help
     
  27. Offline

    mine-care

    @Look Oh hi, unfortunately my time is really limited due to college work! :( i havent looked into it sadly.
     
  28. Offline

    mine-care

    @callum2904 @Look @lucasdidur
    1.8.X compatibility added!!!

    Check the main post, there is a spoiler for versions 1.8.X
    Please report any malfunction or issues you come across because i didnt have the time to test it fully... :(
    Hope it works well and sorry for that tiny delay before updating it!
     
    87pen likes this.
Thread Status:
Not open for further replies.

Share This Page