/*
 * This file is part of SpongeAPI, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered <https://www.spongepowered.org>
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.spongepowered.api.item.inventory;

import org.spongepowered.api.Sponge;
import org.spongepowered.api.item.ItemType;
import org.spongepowered.api.util.CopyableBuilder;

import java.util.Collection;
import java.util.Random;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * A simple generator that takes a {@link Random} and generates
 * an {@link ItemStack}.
 */
public interface ItemStackGenerator extends Function<Random, ItemStack> {

    /**
     * Creates a new builder to build an {@link ItemStackGenerator}.
     *
     * @return The builder to create an itemstack generator
     */
    static Builder builder() {
        return Sponge.getRegistry().getBuilderRegistry().provideBuilder(Builder.class);
    }

    /**
     * A builder to add various {@link BiConsumer}s that will be applied in order
     * to an {@link ItemStackGenerator}. Normally, most all biconsumers can be
     * created from {@link ItemStackBuilderPopulators}.
     */
    interface Builder extends CopyableBuilder<ItemStackGenerator, Builder> {

        /**
         * Adds a new biconsumer in the current order.
         *
         * @param consumer The consumer that mutates an itemstack builder
         * @return This builder, for chaining
         */
        Builder add(BiConsumer<ItemStack.Builder, Random> consumer);

        /**
         * Adds all the provided biconsumers from the provided collection.
         *
         * @param collection The collection of consumer to add
         * @return This builder, for chaining
         */
        Builder addAll(Collection<BiConsumer<ItemStack.Builder, Random>> collection);

        /**
         * Sets the base {@link ItemType} for the {@link ItemStackGenerator}. A
         * base type must be set to avoid issues.
         *
         * @param itemType The base item type
         * @return This builder, for chaining
         */
        default Builder baseItem(Supplier<? extends ItemType> itemType) {
            return this.baseItem(itemType.get());
        }

        /**
         * Sets the base {@link ItemType} for the {@link ItemStackGenerator}. A
         * base type must be set to avoid issues.
         *
         * @param itemType The base item type
         * @return This builder, for chaining
         */
        Builder baseItem(ItemType itemType);

        /**
         * Creates a new {@link ItemStackGenerator} with all of the added
         * {@link BiConsumer}s.
         *
         * @return The newly created itemstack generator
         */
        ItemStackGenerator build();

    }
}

@@ -1328,16 +1328,102 @@
 Sponge;%0A
+import org.spongepowered.api.data.Key;%0Aimport org.spongepowered.api.data.value.Value;%0A
 import o
@@ -1508,16 +1508,74 @@
 Builder;
+%0Aimport org.spongepowered.api.util.weighted.WeightedTable;
 %0A%0Aimport
@@ -3370,16 +3370,22 @@
 aseItem(
+final 
 Supplier
@@ -3777,24 +3777,1344 @@
 itemType);%0A%0A
+%0A        /**%0A         * Sets the base %7B@link ItemType%7D for the %7B@link ItemStackGenerator%7D. Using%0A         * the defined %7B@link WeightedTable table%7D allows for some dynamic selection%0A         * of the returned type, instead of requiring an %7B@link #add(BiConsumer)%7D%0A         * for each individual variation of a desired type.%0A         *%0A         * @param itemType The base item type%0A         * @return This builder, for chaining%0A         */%0A        Builder baseItem(WeightedTable%3CItemType%3E itemType);%0A%0A        /**%0A         * Adds the given %7B@link Key%7D with the given value.%0A         *%0A         * @param key The key to assign the value with%0A         * @param value The value to assign with the key%0A         * @param %3CV%3E The type of the value%0A         * @return This builder, for chaining%0A         */%0A        %3CV%3E Builder add(Key%3C? extends Value%3CV%3E%3E key, V value);%0A%0A        /**%0A         * Adds the given %7B@link Key%7D with the given value.%0A         *%0A         * @param key The key to assign the value with%0A         * @param value The value to assign with the key%0A         * @param %3CV%3E The type of the value%0A         * @return This builder, for chaining%0A         */%0A        default %3CV%3E Builder add(final Supplier%3C? extends Key%3C? extends Value%3CV%3E%3E%3E key, final V value) %7B%0A            return this.add(key.get(), value);%0A        %7D%0A%0A
         /**%0A

Add supplier based methods to ItemStackGenerator