Add Merchant API

By: Xor Boole <mcyoung@mit.edu>
This commit is contained in:
Bukkit/Spigot 2016-03-01 08:30:04 +11:00
parent ccc64d57e8
commit ab952a946f
6 changed files with 400 additions and 1 deletions

View File

@ -96,6 +96,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, Permissible, Inv
*/
public void openInventory(InventoryView inventory);
/**
* Starts a trade between the player and the villager.
*
* Note that only one player may trade with a villager at once. You must use
* the force parameter for this.
*
* @param trader The merchant to trade with. Cannot be null.
* @param force whether to force the trade even if another player is trading
* @return The newly opened inventory view, or null if it could not be
* opened.
*/
public InventoryView openMerchant(Villager trader, boolean force);
/**
* Force-closes the currently open inventory view for this player, if any.
*/

View File

@ -1,9 +1,14 @@
package org.bukkit.entity;
import java.util.List;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.MerchantRecipe;
/**
* Represents a villager NPC
*/
public interface Villager extends Ageable, NPC {
public interface Villager extends Ageable, NPC, InventoryHolder {
/**
* Gets the current profession of this villager.
@ -19,6 +24,90 @@ public interface Villager extends Ageable, NPC {
*/
public void setProfession(Profession profession);
/**
* Get a list of trades currently available from this villager.
*
* @return an immutable list of trades
*/
List<MerchantRecipe> getRecipes();
/**
* Set the list of trades currently available from this villager.
* <br>
* This will not change the selected trades of players currently trading
* with this villager.
*
* @param recipes a list of recipes
*/
void setRecipes(List<MerchantRecipe> recipes);
/**
* Get the recipe at a certain index of this villager's trade list.
*
* @param i the index
* @return the recipe
* @throws IndexOutOfBoundsException
*/
MerchantRecipe getRecipe(int i) throws IndexOutOfBoundsException;
/**
* Set the recipe at a certain index of this villager's trade list.
*
* @param i the index
* @param recipe the recipe
* @throws IndexOutOfBoundsException
*/
void setRecipe(int i, MerchantRecipe recipe) throws IndexOutOfBoundsException;
/**
* Get the number of trades this villager currently has available.
*
* @return the recipe count
*/
int getRecipeCount();
/**
* Gets this villager's inventory.
* <br>
* Note that this inventory is not the Merchant inventory, rather, it is the
* items that a villager might have collected (from harvesting crops, etc.)
*
* @inheritDoc
*/
@Override
Inventory getInventory();
/**
* Gets whether this villager is currently trading.
*
* @return whether the villager is trading
*/
boolean isTrading();
/**
* Gets the player this villager is trading with, or null if it is not
* currently trading.
*
* @return the trader, or null
*/
HumanEntity getTrader();
/**
* Gets this villager's riches, the number of emeralds this villager has
* been given.
*
* @return the villager's riches
*/
int getRiches();
/**
* Sets this villager's riches.
*
* @see Villager#getRiches()
*
* @param riches the new riches
*/
void setRiches(int riches);
/**
* Represents the various different Villager professions there may be.

View File

@ -0,0 +1,64 @@
package org.bukkit.event.entity;
import org.bukkit.entity.Villager;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.MerchantRecipe;
/**
* Called whenever a villager acquires a new trade.
*/
public class VillagerAcquireTradeEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
//
private MerchantRecipe recipe;
public VillagerAcquireTradeEvent(Villager what, MerchantRecipe recipe) {
super(what);
this.recipe = recipe;
}
/**
* Get the recipe to be acquired.
*
* @return the new recipe
*/
public MerchantRecipe getRecipe() {
return recipe;
}
/**
* Set the recipe to be acquired.
*
* @param recipe the new recipe
*/
public void setRecipe(MerchantRecipe recipe) {
this.recipe = recipe;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Override
public Villager getEntity() {
return (Villager) super.getEntity();
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,89 @@
package org.bukkit.event.entity;
import org.bukkit.entity.Villager;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.MerchantRecipe;
/**
* Called when a villager's trade's maximum uses is increased, due to a player's
* trade.
*
* @see MerchantRecipe#getMaxUses()
*/
public class VillagerReplenishTradeEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
//
private MerchantRecipe recipe;
private int bonus;
public VillagerReplenishTradeEvent(Villager what, MerchantRecipe recipe, int bonus) {
super(what);
this.recipe = recipe;
this.bonus = bonus;
}
/**
* Get the recipe to replenish.
*
* @return the replenished recipe
*/
public MerchantRecipe getRecipe() {
return recipe;
}
/**
* Set the recipe to replenish.
*
* @param recipe the replenished recipe
*/
public void setRecipe(MerchantRecipe recipe) {
this.recipe = recipe;
}
/**
* Get the bonus uses added. The maximum uses of the recipe will be
* increased by this number.
*
* @return the extra uses added
*/
public int getBonus() {
return bonus;
}
/**
* Set the bonus uses added.
*
* @see VillagerReplenishTradeEvent#getBonus()
* @param bonus the extra uses added
*/
public void setBonus(int bonus) {
this.bonus = bonus;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Override
public Villager getEntity() {
return (Villager) super.getEntity();
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -1,4 +1,23 @@
package org.bukkit.inventory;
/**
* Represents a trading inventory between a player and a villager.
* <br>
* The holder of this Inventory is the owning Villager.
*/
public interface MerchantInventory extends Inventory {
/**
* Get the index of the currently selected recipe.
*
* @return the index of the currently selected recipe
*/
int getSelectedRecipeIndex();
/**
* Get the currently selected recipe.
*
* @return the currently selected recipe
*/
MerchantRecipe getSelectedRecipe();
}

View File

@ -0,0 +1,125 @@
package org.bukkit.inventory;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a Villager's trade.
*
* Trades can take one or two ingredients, and provide one result. The
* ingredients' Itemstack amounts are respected in the trade.
* <br>
* A trade has a limited number of uses, after which the trade can no longer be
* used, unless the player uses a different trade, which will cause its maximum
* uses to increase.
* <br>
* A trade may or may not reward experience for being completed.
*
* @see org.bukkit.event.entity.VillagerReplenishTradeEvent
*/
public class MerchantRecipe implements Recipe {
private ItemStack result;
private List<ItemStack> ingredients = new ArrayList<ItemStack>();
private int uses;
private int maxUses;
private boolean experienceReward;
public MerchantRecipe(ItemStack result, int maxUses) {
this(result, 0, maxUses, false);
}
public MerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward) {
this.result = result;
this.uses = uses;
this.maxUses = maxUses;
this.experienceReward = experienceReward;
}
@Override
public ItemStack getResult() {
return result;
}
public void addIngredient(ItemStack item) {
Preconditions.checkState(ingredients.size() < 2, "Merchant can only have 2 ingredients");
ingredients.add(item.clone());
}
public void removeIngredient(int index) {
ingredients.remove(index);
}
public void setIngredients(List<ItemStack> ingredients) {
this.ingredients = new ArrayList<ItemStack>();
for (ItemStack item : ingredients) {
this.ingredients.add(item.clone());
}
}
public List<ItemStack> getIngredients() {
List<ItemStack> copy = new ArrayList<ItemStack>();
for (ItemStack item : ingredients) {
copy.add(item.clone());
}
return copy;
}
/**
* Get the number of times this trade has been used.
*
* @return the number of uses
*/
public int getUses() {
return uses;
}
/**
* Set the number of times this trade has been used.
*
* @param uses the number of uses
*/
public void setUses(int uses) {
this.uses = uses;
}
/**
* Get the maximum number of uses this trade has.
* <br>
* The maximum uses of this trade may increase when a player trades with the
* owning villager.
*
* @return the maximum number of uses
*/
public int getMaxUses() {
return maxUses;
}
/**
* Set the maximum number of uses this trade has.
*
* @param maxUses the maximum number of time this trade can be used
*/
public void setMaxUses(int maxUses) {
this.maxUses = maxUses;
}
/**
* Whether to reward experience for the trade.
*
* @return whether to reward experience for completing this trade
*/
public boolean hasExperienceReward() {
return experienceReward;
}
/**
* Set whether to reward experience for the trade.
*
* @param flag whether to reward experience for completing this trade
*/
public void setExperienceReward(boolean flag) {
this.experienceReward = flag;
}
}