Skip to content

Villager Trades

LLytho edited this page May 26, 2023 · 6 revisions

Disabling offers when start trading

/**
 * Disables the offers when the player starts trading.
 * In the example we will use a stage to disable the offers.
 */
// for 1.18 pls use: onEvent("morejs.player.start_trading", (event) => { ... })
MoreJSEvents.playerStartTrading((event) => {
    // We don't have the stage, so no trades for us :(
    if (!event.player.stages.has("allow_trading")) {
        event.forEachOffers((o, i) => {
            o.disabled = true;
        });
    }
});

/**
 * Another simple example to disable offers from the goblin trader mod.
 * `event.merchant` returns the trader entity.
 */
// for 1.18 pls use: onEvent("morejs.player.start_trading", (event) => { ... })
MoreJSEvents.playerStartTrading((event) => {
    let hasStage = event.player.stages.has("allow_trading_with_goblin");
    let isGoblin = event.merchant.getClass().getName().includes("GoblinTraderEntity");
    if (isGoblin && !hasStage) {
        event.forEachOffers((o, i) => {
            o.disabled = true;
        });
    }
});

Villager Trade event

Clear existing trades:

// for 1.18 pls use: onEvent("morejs.villager.trades", (event) => { ... })
MoreJSEvents.villagerTrades((event) => {
    /*
     * Will remove all vanilla trades. You can also just remove them for specific professions.
     */
    event.removeVanillaTrades();
    event.removeVanillaTrades([...professions], level);

    /*
     * Will remove all mod trades. You can also just remove them for specific professions.
     */
    event.removeModdedTrades();
    event.removeModdedTrades([...professions], level);
});

Adding a simple trade:

// for 1.18 pls use: onEvent("morejs.villager.trades", (event) => { ... })
MoreJSEvents.villagerTrades((event) => {
    /**
     * Adds a trade to the given profession.
     * - `profession`: The profession to add the trade to.
     * - `level`: The level, the villager needs to offer the trade.
     * - `input`: The input items for the trade. You can use a single item or an array with two items.
     * - `output`: The output items for the trade.
     */
    const trade = event.addTrade(profession, level, [...input], output);

    // For 1.19+ only:
    // If you want to use random selected price ranges, you can use `TradeItem.of(item, min, max)` for input and outputs
    // event.addTrade("farmer", 1, ["minecraft:diamond", TradeItem.of("minecraft:apple", 10, 19)], "minecraft:acacia_sapling");


    // `addTrade` return the trade to set optional data.
    // trade.maxUses(number); // Sets the maximum amount of uses for the trade.
    // trade.villagerExperience(number); // Sets the amount of villager experience the trade gives.
    // trade.priceMultiplier(number); // Sets the price multiplier for the trade.
    // trade.transform((offer, entity, random) => { ... }); // Transforms the offer when it's generated.
});

Adding a complex trade:

MoreJS provides you with additional functions to create complex trades. To create such a trade see VillagerUtils

// for 1.18 pls use: onEvent("morejs.villager.trades", (event) => { ... })
MoreJSEvents.villagerTrades((event) => {
    /**
     * - `trade`: The trade to add. Read the wiki for more information.
     *
     * `addTrade` returns the trade to set optional data.
     */
    event.addTrade(profession, level, trade);
});

Adding a custom trade with a callback

// for 1.18 pls use: onEvent("morejs.villager.trades", (event) => { ... })
MoreJSEvents.villagerTrades((event) => {
    /**
     * - `offer`: The trade offer
     * - `entity`: The villager entity
     * - `random`: The random number generator
     */
    event.addCustomTrade(profession, level, (offer, entity, random) => {
        offer.setFirstInput(item);
        offer.setSecondInput(item);
        offer.setOutput(item);
        offer.setMaxUses(number);
        offer.setVillagerExperience(number);
        offer.setPriceMultiplier(number);
    });
});

Wanderer Trades

You can also modify wanderer trades. Just use morejs.wanderer.trades (1.18) or MoreJSEvents.wandererTrades (1.19) event instead. The difference is, that you don't use a profession. The wanderer also has 2 levels internally. The first level are for standard trades. The second level are for special trades. You can read more about it on https://minecraft.fandom.com/wiki/Trading#Wandering_trader

Update villager offers

This Event is for 1.19+ only!

The event gets called when the villager offers are updated. This can happen when the villager levels up or updates the profession.

MoreJSEvents.updateVillagerOffers((event) => {
    /**
     * event.getEntity() // Returns the villager entity.
     * event.getVillagerData() // Returns the villager data.
     * event.isProfession(profession) // Returns true if the villager has the given profession.
     * event.getVillagerLevel() // Returns the villager level.
     * event.getProfession() // Returns the villager profession.
     * event.getOffers() // Returns the current offers the villager has.
     * event.getAddedOffers() // Returns the offers that were added to the villager.
     * event.getUsedTrades() // Returns the trades that were used to generate the new offers.
     * event.deleteAddedOffers() // Deletes all added offers.
     * event.addRandomOffer() // Adds a random offer to the villager. Can return null if no offer was added.
     * event.addRandomOffer(trades) // Adds a random offer to the villager by given trades. Can return null if no offer was added.
     * event.getVillagerTrades(profession) // Returns all trades for the given profession.
     * event.getVillagerTrades(profession, level) // Returns all trades for the given profession and level.
     * event.getWandererTrades() // Returns all trades for the wanderer.
     * event.getWandererTrades(level) // Returns all trades for the wanderer and level (1 or 2).
     */

    // Example: Add a random trade to the villager from another profession.
    if (event.isProfession("minecraft:farmer")) {
        let trades = event.getVillagerTrades("minecraft:armorer");
        event.addRandomOffer(trades);
    }

    // Example: Update added offers
    event.getAddedOffers().forEach((offer) => {
        offer.getFirstInput().setCount(1); // Set the first input to just 1.
    });
});

The update event also exists for the wanderer, just use MoreJSEvents.updateWandererOffers instead and for other abstract villagers from other mods use MoreJSEvents.updateAbstractVillagerOffers.