new api events for stations

This commit is contained in:
Indyuce 2021-08-09 19:46:22 +02:00
parent ed1c58aae5
commit fc4f652f5d
7 changed files with 173 additions and 70 deletions

View File

@ -5,7 +5,7 @@ import io.lumine.mythic.lib.api.item.NBTItem;
public class MMOItemPlayerIngredient extends PlayerIngredient {
/*
/**
* No need to save as MMOItemTemplate or Type instances. Just need the string,
* because if they don't exist the recipe ingredients won't load anyways.
* And it's better for performance yes

View File

@ -46,33 +46,53 @@ public class CraftingRecipe extends Recipe {
}
@Override
public void whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
public boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
if (!data.isOnline())
return;
return false;
if (!hasOption(RecipeOption.SILENT_CRAFT))
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
/*
* If the recipe is instant, take the ingredients off and directly add
* the output to the player's inventory
* If the recipe is instant, take the ingredients off
* and directly add the output to the player's inventory
*/
if (isInstant()) {
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe,
PlayerUseCraftingStationEvent.StationAction.INSTANT_RECIPE);
ItemStack result = hasOption(RecipeOption.OUTPUT_ITEM) ? getOutput().generate(data.getRPG()) : null;
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe, result);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return;
return false;
if (hasOption(RecipeOption.OUTPUT_ITEM))
new SmartGive(data.getPlayer()).give(getOutput().generate(data.getRPG()));
if (result != null)
new SmartGive(data.getPlayer()).give(result);
recipe.getRecipe().getTriggers().forEach(trigger -> trigger.whenCrafting(data));
// Play sound
if (!hasOption(RecipeOption.SILENT_CRAFT))
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
// Recipe was successfully used
return true;
/*
* If the recipe is not instant, add the item to the crafting queue
*/
} else
} else {
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(data, station, recipe);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
// Play sound
if (!hasOption(RecipeOption.SILENT_CRAFT))
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
data.getCrafting().getQueue(station).add(this);
// Recipe was successfully used
return true;
}
}
@Override

View File

@ -144,13 +144,17 @@ public abstract class Recipe {
* Called when all the recipe conditions are to true and when the player
* eventually starts crafting OR when the player claims the item in the
* crafting queue once the delay is over.
* <p>
* This however checks for the bukkit event which can be cancelled; if
* this method returns false the ingredients shall not be consumed.
*
* @param data Player crafting the item
* @param inv The player's ingredients
* @param recipe The recipe used to craft the item
* @param station The station used to craft the item
* @return If the crafting recipe was successfully used
*/
public abstract void whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station);
public abstract boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station);
/**
* Applies extra conditions when a player has just clicked on a recipe item

View File

@ -9,11 +9,13 @@ import net.Indyuce.mmoitems.api.crafting.ingredient.CheckedIngredient;
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
import net.Indyuce.mmoitems.api.crafting.ingredient.MMOItemIngredient;
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
import net.Indyuce.mmoitems.api.event.PlayerUseCraftingStationEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.util.ConfigItems;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.util.message.Message;
import net.Indyuce.mmoitems.stat.data.UpgradeData;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
@ -40,17 +42,29 @@ public class UpgradingRecipe extends Recipe {
}
@Override
public void whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe castRecipe, CraftingStation station) {
public boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe castRecipe, CraftingStation station) {
if (!data.isOnline())
return false;
CheckedUpgradingRecipe recipe = (CheckedUpgradingRecipe) castRecipe;
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return false;
// Update item
recipe.getUpgradeData().upgrade(recipe.getMMOItem());
recipe.getUpgraded().setItemMeta(recipe.getMMOItem().newBuilder().build().getItemMeta());
castRecipe.getRecipe().getTriggers().forEach(trigger -> trigger.whenCrafting(data));
if (!data.isOnline())
return;
Message.UPGRADE_SUCCESS.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(recipe.getUpgraded())).send(data.getPlayer());
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
// Play sound
if (!hasOption(RecipeOption.SILENT_CRAFT))
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
// Recipe used successfully
return true;
}
@Override

View File

@ -1,52 +1,94 @@
package net.Indyuce.mmoitems.api.event;
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
import net.Indyuce.mmoitems.api.crafting.recipe.Recipe;
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
import net.Indyuce.mmoitems.api.crafting.recipe.UpgradingRecipe;
import net.Indyuce.mmoitems.api.player.PlayerData;
import org.apache.commons.lang.Validate;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
public class PlayerUseCraftingStationEvent extends PlayerDataEvent {
private final Recipe recipe;
private final CheckedRecipe recipeInfo;
private final CraftingStation station;
private final Recipe recipe;
private final StationAction action;
@Nullable
private final CheckedRecipe recipeInfo;
@Nullable
private final ItemStack result;
private static final HandlerList handlers = new HandlerList();
/**
* Called when a player directly interacts with a recipe in the crafting
* station GUI. The recipe is either instant and the item is given
* instaneously, or the item is sent in the crafting queue
*
* Called when interacting with a non instant recipe. The item
* is therefore sent to the crafting queue.
*
* @param playerData The player interacting with the crafting station
* @param station The crafting station being used
* @param recipeInfo The recipe being used to craft the item
*/
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, CheckedRecipe recipeInfo, StationAction action) {
this(playerData, station, recipeInfo, recipeInfo.getRecipe(), action);
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, CheckedRecipe recipeInfo) {
this(playerData, station, recipeInfo, recipeInfo.getRecipe(), null, StationAction.INTERACT_WITH_RECIPE);
}
/**
* Called when a player claims an item from the crafting queue.
*
* Called when interacting with an upgrading recipe
*
* @param playerData The player interacting with the crafting station
* @param station The crafting station being used
* @param recipeInfo The recipe being used to craft the item
*/
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, UpgradingRecipe.CheckedUpgradingRecipe recipeInfo) {
this(playerData, station, recipeInfo, recipeInfo.getRecipe(), null, StationAction.UPGRADE_RECIPE);
}
/**
* Called when interacting with an instant recipe
*
* @param playerData The player interacting with the crafting station
* @param station The crafting station being used
* @param recipeInfo The recipe being used to craft the item
* @param result The item given to the player
*/
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, CheckedRecipe recipeInfo, ItemStack result) {
this(playerData, station, recipeInfo, recipeInfo.getRecipe(), result, StationAction.INSTANT_RECIPE);
}
/**
* Called when a player claims an item from the crafting queue
*
* @param playerData The player interacting with the crafting station
* @param station The crafting station being used
* @param recipe The recipe being used to craft the item
* @param result The item given to the player
*/
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, Recipe recipe, ItemStack result) {
this(playerData, station, null, recipe, result, StationAction.CRAFTING_QUEUE);
}
/**
* Called when a player removes an item from the queue
*
* @param playerData The player interacting with the crafting station
* @param station The crafting station being used
* @param recipe The recipe being used to craft the item
*/
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, Recipe recipe, StationAction action) {
this(playerData, station, null, recipe, action);
public PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, Recipe recipe) {
this(playerData, station, null, recipe, null, StationAction.CANCEL_QUEUE);
}
private PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, CheckedRecipe recipeInfo, Recipe recipe,
StationAction action) {
private PlayerUseCraftingStationEvent(PlayerData playerData, CraftingStation station, CheckedRecipe recipeInfo, Recipe recipe, ItemStack result, StationAction action) {
super(playerData);
this.recipeInfo = recipeInfo;
this.recipe = recipe;
this.station = station;
this.recipe = recipe;
this.recipeInfo = recipeInfo;
this.result = result;
this.action = action;
}
@ -54,20 +96,33 @@ public class PlayerUseCraftingStationEvent extends PlayerDataEvent {
return station;
}
/**
* @return The corresponding recipe info IF AND ONLY IF the player is
* interacting with a recipe. This method cannot be used when a
* player claims an item from the crafting queue.
*/
public CheckedRecipe getRecipeInfo() {
Validate.notNull(recipeInfo, "No recipe info is provided when a player claims an item in the crafting queue");
return recipeInfo;
}
public boolean hasRecipeInfo() {
return recipeInfo != null;
}
/**
* @return The corresponding recipe info if the current
* interaction is either INTERACT_WITH_RECIPE or INSTANT_RECIPE
*/
public CheckedRecipe getRecipeInfo() {
Validate.notNull(action == StationAction.INSTANT_RECIPE || action == StationAction.INTERACT_WITH_RECIPE, "No recipe info is provided with " + action.name());
return recipeInfo;
}
public boolean hasResult() {
return result != null;
}
/**
* @return The result item if the current interaction
* is either INSTANT_RECIPE or CRAFTING_QUEUE
*/
public ItemStack getResult() {
Validate.notNull(action == StationAction.INSTANT_RECIPE || action == StationAction.CRAFTING_QUEUE, "No result item is provided with " + action.name());
return result;
}
public Recipe getRecipe() {
return recipe;
}
@ -76,6 +131,10 @@ public class PlayerUseCraftingStationEvent extends PlayerDataEvent {
return action;
}
/**
* @return If the recipe used is an instantaneous recipe
* @deprecated Check if the interaction type is INSTANT_RECIPE instead
*/
@Deprecated
public boolean isInstant() {
return recipe instanceof CraftingRecipe && ((CraftingRecipe) recipe).isInstant();
@ -91,6 +150,11 @@ public class PlayerUseCraftingStationEvent extends PlayerDataEvent {
public enum StationAction {
/**
* Called when a player uses an upgrading recipe. Upgrading recipes are always instantaneous
*/
UPGRADE_RECIPE,
/**
* Called when a player places an item in the crafting queue when the
* recipe is not instantaneous

View File

@ -181,39 +181,45 @@ public class CraftingStationView extends PluginInventory {
* to the player and remove the recipe from the queue
*/
if (recipeInfo.isReady()) {
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe,
PlayerUseCraftingStationEvent.StationAction.CRAFTING_QUEUE);
ItemStack result = recipe.hasOption(Recipe.RecipeOption.OUTPUT_ITEM) ? recipe.getOutput().generate(playerData.getRPG()) : null;
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe, result);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return;
// Remove from crafting queue
playerData.getCrafting().getQueue(station).remove(recipeInfo);
// Apply triggers
recipe.getTriggers().forEach(trigger -> trigger.whenCrafting(playerData));
ItemStack craftedItem = recipe.getOutput().generate(playerData.getRPG());
CustomSoundListener.stationCrafting(craftedItem, player);
// Play sounds
CustomSoundListener.stationCrafting(result, player);
if (!recipe.hasOption(Recipe.RecipeOption.SILENT_CRAFT))
player.playSound(player.getLocation(), station.getSound(), 1, 1);
if (recipe.hasOption(Recipe.RecipeOption.OUTPUT_ITEM))
new SmartGive(player).give(craftedItem);
if (result != null)
new SmartGive(player).give(result);
/*
* If the recipe is not ready, cancel the recipe and give the
* ingredients back to the player
*/
} else {
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe,
PlayerUseCraftingStationEvent.StationAction.CANCEL_QUEUE);
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return;
// Remove from crafting queue
playerData.getCrafting().getQueue(station).remove(recipeInfo);
player.playSound(player.getLocation(), station.getSound(), 1, 1);
// Play sounds
if (!recipe.hasOption(Recipe.RecipeOption.SILENT_CRAFT))
player.playSound(player.getLocation(), station.getSound(), 1, 1);
// Give ingredients back
for (Ingredient ingredient : recipeInfo.getRecipe().getIngredients())
new SmartGive(player).give(ingredient.generateItemStack(playerData.getRPG()));
}
@ -241,17 +247,12 @@ public class CraftingStationView extends PluginInventory {
return;
}
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe,
PlayerUseCraftingStationEvent.StationAction.INTERACT_WITH_RECIPE);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return;
if (recipe.getRecipe().whenUsed(playerData, ingredients, recipe, station)) {
recipe.getIngredients().forEach(ingredient -> ingredient.takeAway());
recipe.getConditions().forEach(condition -> condition.getCondition().whenCrafting(playerData));
recipe.getRecipe().whenUsed(playerData, ingredients, recipe, station);
recipe.getIngredients().forEach(ingredient -> ingredient.takeAway());
recipe.getConditions().forEach(condition -> condition.getCondition().whenCrafting(playerData));
updateData();
updateData();
}
}
private CheckedRecipe getRecipe(String id) {

View File

@ -78,9 +78,9 @@ public class PlayerListener implements Listener {
}
/*
* prevent players from dropping items which are bound to them with a
* soulbound. items are cached inside a map waiting for the player to
* respawn. if he does not respawn the items are dropped on the ground, this
* Prevent players from dropping items which are bound to them with a
* soulbound. Items are cached inside a map waiting for the player to
* respawn. If he does not respawn the items are dropped on the ground, this
* way there don't get lost
*/
@EventHandler(priority = EventPriority.HIGH)