Package com.sk89q.craftbook.mechanics.crafting

Source Code of com.sk89q.craftbook.mechanics.crafting.CustomCrafting

package com.sk89q.craftbook.mechanics.crafting;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.permissions.PermissionAttachment;

import com.sk89q.craftbook.AbstractCraftBookMechanic;
import com.sk89q.craftbook.LocalPlayer;
import com.sk89q.craftbook.bukkit.CraftBookPlugin;
import com.sk89q.craftbook.bukkit.util.BukkitUtil;
import com.sk89q.craftbook.mechanics.crafting.RecipeManager.RecipeType;
import com.sk89q.craftbook.util.EventUtil;
import com.sk89q.craftbook.util.ItemUtil;
import com.sk89q.craftbook.util.ParsingUtil;
import com.sk89q.util.yaml.YAMLFormat;
import com.sk89q.util.yaml.YAMLProcessor;

/**
* Custom Crafting Recipe Handler
*
* @author Me4502
*/
public class CustomCrafting extends AbstractCraftBookMechanic {

    public static CustomCrafting INSTANCE;

    public static final Map<Recipe, RecipeManager.Recipe> advancedRecipes = new HashMap<Recipe, RecipeManager.Recipe>();

    @Override
    public boolean enable() {

        INSTANCE = this;
        CraftBookPlugin.inst().createDefaultConfiguration(new File(CraftBookPlugin.inst().getDataFolder(), "crafting-recipes.yml"), "crafting-recipes.yml");
        new RecipeManager(new YAMLProcessor(new File(CraftBookPlugin.inst().getDataFolder(), "crafting-recipes.yml"), true, YAMLFormat.EXTENDED));
        Collection<RecipeManager.Recipe> recipeCollection = RecipeManager.INSTANCE.getRecipes();
        int recipes = 0;
        for (RecipeManager.Recipe r : recipeCollection)
            if(addRecipe(r))
                recipes++;
        CraftBookPlugin.inst().getLogger().info("Registered " + recipes + " custom recipes!");

        return true;
    }

    @Override
    public void disable () {

        advancedRecipes.clear();
        RecipeManager.INSTANCE = null;
        INSTANCE = null;
    }

    /**
     * Adds a recipe to the manager.
     */
    public boolean addRecipe(RecipeManager.Recipe r) {
        try {
            Recipe sh = null;

            if (r.getType() == RecipeManager.RecipeType.SHAPELESS) {
                sh = new ShapelessRecipe(r.getResult().getItemStack());
                for (CraftingItemStack is : r.getIngredients())
                    ((ShapelessRecipe) sh).addIngredient(is.getItemStack().getAmount(), is.getItemStack().getData());
            } else if (r.getType() == RecipeManager.RecipeType.SHAPED) {
                sh = new ShapedRecipe(r.getResult().getItemStack());
                ((ShapedRecipe) sh).shape(r.getShape());
                for (Entry<CraftingItemStack, Character> is : r.getShapedIngredients().entrySet())
                    ((ShapedRecipe) sh).setIngredient(is.getValue(), is.getKey().getItemStack().getData());
            } else if (r.getType() == RecipeManager.RecipeType.FURNACE) {
                sh = new FurnaceRecipe(r.getResult().getItemStack(), r.getIngredients().toArray(new CraftingItemStack[r.getIngredients().size()])[0].getItemStack().getType());
                for (CraftingItemStack is : r.getIngredients())
                    ((FurnaceRecipe) sh).setInput(is.getItemStack().getData());
            } else
                return false;

            CraftBookPlugin.inst().getServer().addRecipe(sh);
            if(r.hasAdvancedData()) {
                advancedRecipes.put(sh, r);
                CraftBookPlugin.logDebugMessage("Adding a new recipe with advanced data!", "advanced-data.init");
            }

            return true;
        } catch (IllegalArgumentException e) {
            CraftBookPlugin.inst().getLogger().severe("Corrupt or invalid recipe!");
            CraftBookPlugin.inst().getLogger().severe("Please either delete custom-crafting.yml, or fix the issues with your recipes file!");
            BukkitUtil.printStacktrace(e);
        } catch (Exception e) {
            CraftBookPlugin.inst().getLogger().severe("Failed to load recipe! Is it incorrectly written?");
            BukkitUtil.printStacktrace(e);
        }

        return false;
    }

    @EventHandler(priority = EventPriority.LOW)
    public void prepareCraft(PrepareItemCraftEvent event) {

        if(!EventUtil.passesFilter(event)) return;

        ItemStack bits = null;
        Player p = null;
        LocalPlayer lp = null;
        try {
            p = (Player) event.getViewers().get(0);
            lp = CraftBookPlugin.inst().wrapPlayer(p);
        } catch(Exception e){}
        CraftBookPlugin.logDebugMessage("Pre-Crafting has been initiated!", "advanced-data");
        try {
            boolean hasFailed = false;
            for(Recipe rec : advancedRecipes.keySet()) {

                if(ItemUtil.areRecipesIdentical(rec, event.getRecipe())) {

                    thisrecipe: {
                    RecipeManager.Recipe recipe = advancedRecipes.get(rec);

                    ItemStack[] tests = ((CraftingInventory)event.getView().getTopInventory()).getMatrix();
                    CraftingItemStack[] tests2;
                    if(recipe.getType() == RecipeType.SHAPED) {
                        List<CraftingItemStack> stacks = new ArrayList<CraftingItemStack>();

                        for(String s : recipe.getShape())
                            for(char c : s.toCharArray())
                                for(Entry<CraftingItemStack, Character> entry : recipe.getShapedIngredients().entrySet())
                                    if(entry.getValue() == c)
                                        stacks.add(entry.getKey());
                        tests2 = stacks.toArray(new CraftingItemStack[stacks.size()]);
                    } else
                        tests2 = recipe.getIngredients().toArray(new CraftingItemStack[recipe.getIngredients().size()]);

                    ArrayList<ItemStack> leftovers = new ArrayList<ItemStack>();
                    leftovers.addAll(Arrays.asList(tests));
                    leftovers.removeAll(Collections.singleton(null));

                    for(ItemStack it : tests) {

                        if(!ItemUtil.isStackValid(it))
                            continue;
                        for(CraftingItemStack cit : tests2) {

                            if(ItemUtil.areBaseItemsIdentical(cit.getItemStack(), it)) {
                                CraftBookPlugin.logDebugMessage("Recipe base item is correct!", "advanced-data");
                                if(ItemUtil.areItemsIdentical(cit.getItemStack(), it)) {
                                    leftovers.remove(it);
                                    CraftBookPlugin.logDebugMessage("MetaData is correct!", "advanced-data");
                                } else {
                                    CraftBookPlugin.logDebugMessage("MetaData is incorrect!", "advanced-data");
                                    hasFailed = true;
                                    break thisrecipe;
                                }
                            }
                        }
                    }

                    if(!leftovers.isEmpty())
                        continue;

                    hasFailed = false;

                    if(p != null && recipe.hasAdvancedData("permission-node")) {
                        CraftBookPlugin.logDebugMessage("A recipe with permission nodes detected!", "advanced-data");
                        if(!p.hasPermission((String) recipe.getAdvancedData("permission-node"))) {
                            if(recipe.hasAdvancedData("permission-error"))
                                lp.printError((String) recipe.getAdvancedData("permission-error"));
                            else
                                lp.printError("mech.custom-crafting.recipe-permission");
                            ((CraftingInventory)event.getView().getTopInventory()).setResult(null);
                            return;
                        }
                    }

                    CraftBookPlugin.logDebugMessage("A recipe with custom data is being crafted!", "advanced-data");
                    bits = applyAdvancedEffects(event.getRecipe().getResult(),rec, p);
                    break;
                }
                }
            }
            if(hasFailed)
                throw new InvalidCraftingException("Unmet Item Meta");
        } catch(InvalidCraftingException e){
            ((CraftingInventory)event.getView().getTopInventory()).setResult(null);
            return;
        } catch (Exception e) {
            BukkitUtil.printStacktrace(e);
            ((CraftingInventory)event.getView().getTopInventory()).setResult(null);
            return;
        }
        if(bits != null && !bits.equals(event.getRecipe().getResult())) {
            bits.setAmount(((CraftingInventory)event.getView().getTopInventory()).getResult().getAmount());
            ((CraftingInventory)event.getView().getTopInventory()).setResult(bits);
        }
    }

    @EventHandler(priority = EventPriority.LOW)
    public void prepareFurnace(InventoryClickEvent event) {

        if(!EventUtil.passesFilter(event)) return;

        if(!(event.getInventory() instanceof FurnaceInventory)) return;
        if(event.getAction() != InventoryAction.PLACE_ALL && event.getAction() != InventoryAction.PLACE_ONE && event.getAction() != InventoryAction.PLACE_SOME) return;
        if(event.getSlot() != 0) return;

        boolean shouldCancel = false;

        for(Recipe rec : advancedRecipes.keySet()) {
            if(!(rec instanceof FurnaceRecipe)) continue;
            FurnaceRecipe frec = (FurnaceRecipe) rec;
            if(ItemUtil.areBaseItemsIdentical(frec.getInput(), event.getCurrentItem())) {

                RecipeManager.Recipe recipe = advancedRecipes.get(rec);
                if(ItemUtil.areItemsIdentical(event.getCurrentItem(), recipe.getIngredients().get(0).getItemStack())) {
                    shouldCancel = false;
                    break;
                } else {
                    shouldCancel = true;
                }
            }
        }

        if(shouldCancel)
            event.setCancelled(true);
    }

    @EventHandler(priority = EventPriority.LOW)
    public void onFurnaceCook(FurnaceSmeltEvent event) {

        if(!EventUtil.passesFilter(event)) return;

        ItemStack bits = null;
        CraftBookPlugin.logDebugMessage("Smelting has been initiated!", "advanced-data");
        for(Recipe rec : advancedRecipes.keySet()) {

            if(!(rec instanceof FurnaceRecipe)) continue;
            try {
                if(checkFurnaceRecipes((FurnaceRecipe) rec, event.getSource(), event.getResult())) {

                    RecipeManager.Recipe recipe = advancedRecipes.get(rec);

                    ArrayList<ItemStack> leftovers = new ArrayList<ItemStack>();
                    leftovers.add(event.getSource());
                    leftovers.removeAll(Collections.singleton(null));

                    if(!ItemUtil.isStackValid(event.getSource()))
                        continue;
                    for(CraftingItemStack cit : recipe.getIngredients()) {

                        if(ItemUtil.areBaseItemsIdentical(cit.getItemStack(), event.getSource())) {
                            CraftBookPlugin.logDebugMessage("Base item is correct!", "advanced-data");
                            if(ItemUtil.areItemsIdentical(cit.getItemStack(), event.getSource())) {
                                leftovers.remove(event.getSource());
                                CraftBookPlugin.logDebugMessage("MetaData correct!", "advanced-data");
                            } else {
                                CraftBookPlugin.logDebugMessage("MetaData incorrect!", "advanced-data");
                                throw new InvalidCraftingException("Unmet Item Meta");
                            }
                        }
                    }

                    if(!leftovers.isEmpty())
                        continue;

                    CraftBookPlugin.logDebugMessage("A recipe with custom data is being smelted!", "advanced-data");
                    bits = applyAdvancedEffects(event.getResult(),rec, null);
                    break;
                }
            } catch(InvalidCraftingException e){
                event.setResult(null);
                event.setCancelled(true);
                return;
            }
        }
        if(bits != null && !bits.equals(event.getResult())) {
            bits.setAmount(event.getResult().getAmount());
            event.setResult(bits);
        }
    }

    @EventHandler(priority = EventPriority.LOWEST)
    public void onCraft(CraftItemEvent event) {

        if(!EventUtil.passesFilter(event)) return;

        CraftBookPlugin.logDebugMessage("Crafting has been initiated!", "advanced-data");
        Player p = (Player) event.getWhoClicked();
        for(Recipe rec : advancedRecipes.keySet()) {

            if(ItemUtil.areRecipesIdentical(rec, event.getRecipe())) {
                CraftBookPlugin.logDebugMessage("A recipe with custom data is being crafted!", "advanced-data");
                RecipeManager.Recipe recipe = advancedRecipes.get(rec);
                applyPostData(recipe, p, event);
                event.setCurrentItem(applyAdvancedEffects(event.getCurrentItem(), event.getRecipe(), (Player) event.getWhoClicked()));
                break;
            }
        }
    }

    @SuppressWarnings("unchecked")
    public void applyPostData(RecipeManager.Recipe recipe, Player p, InventoryClickEvent event) {

        if(recipe.hasAdvancedData("permission-node")) {
            CraftBookPlugin.logDebugMessage("A recipe with permission nodes detected!", "advanced-data");
            if(!event.getWhoClicked().hasPermission((String) recipe.getAdvancedData("permission-node"))) {
                p.sendMessage(ChatColor.RED + "You do not have permission to craft this recipe!");
                event.setCancelled(true);
                return;
            }
        }
        if(recipe.hasAdvancedData("extra-results")) {
            CraftBookPlugin.logDebugMessage("A recipe with extra results is detected!", "advanced-data");
            ArrayList<CraftingItemStack> stacks = new ArrayList<CraftingItemStack>((Collection<CraftingItemStack>) recipe.getAdvancedData("extra-results"));
            for(CraftingItemStack stack : stacks) {
                if(stack.hasAdvancedData("chance"))
                    if(CraftBookPlugin.inst().getRandom().nextDouble() < (Double)stack.getAdvancedData("chance"))
                        continue;
                HashMap<Integer, ItemStack> leftovers = event.getWhoClicked().getInventory().addItem(stack.getItemStack());
                if(!leftovers.isEmpty()) {
                    for(ItemStack istack : leftovers.values())
                        event.getWhoClicked().getWorld().dropItemNaturally(event.getWhoClicked().getLocation(), istack);
                }
            }
        }
        if(recipe.hasAdvancedData("commands-player") || recipe.hasAdvancedData("commands-console")) {
            CraftBookPlugin.logDebugMessage("A recipe with commands is detected!", "advanced-data");
            if(recipe.hasAdvancedData("commands-console")) {
                for(String s : (List<String>)recipe.getAdvancedData("commands-console")) {
                    s = ParsingUtil.parseLine(s, p);
                    Bukkit.dispatchCommand(Bukkit.getConsoleSender(), s);
                }
            }
            if(recipe.hasAdvancedData("commands-player")) {
                for(String s : (List<String>)recipe.getAdvancedData("commands-player")) {
                    s = ParsingUtil.parseLine(s, p);
                    PermissionAttachment att = p.addAttachment(CraftBookPlugin.inst());
                    att.setPermission("*", true);
                    boolean wasOp = p.isOp();
                    p.setOp(true);
                    Bukkit.dispatchCommand(p, s);
                    att.remove();
                    p.setOp(wasOp);
                }
            }
        }
    }

    public static ItemStack craftItem(Recipe recipe) {

        for(Recipe rec : advancedRecipes.keySet()) {
            if(ItemUtil.areRecipesIdentical(rec, recipe))
                return applyAdvancedEffects(recipe.getResult(),rec, null);
        }

        return recipe.getResult();
    }

    private static ItemStack applyAdvancedEffects(ItemStack stack, Recipe rep, Player player) {

        RecipeManager.Recipe recipe = advancedRecipes.get(rep);

        if(recipe == null)
            return stack;

        ItemStack res = stack.clone();
        if(recipe.getResult().hasAdvancedData("item-meta"))
            res.setItemMeta(recipe.getResult().getItemStack().getItemMeta());
        return res;
    }

    private static boolean checkFurnaceRecipes(FurnaceRecipe rec1, ItemStack source, ItemStack result) throws InvalidCraftingException {

        if(ItemUtil.areBaseItemsIdentical(rec1.getInput(), source))
            if(ItemUtil.areBaseItemsIdentical(rec1.getResult(), result))
                return true;

        return false;
    }

    @Override
    public void loadConfiguration (YAMLProcessor config, String path) {

    }
}
TOP

Related Classes of com.sk89q.craftbook.mechanics.crafting.CustomCrafting

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.