001package net.tnemc.item.providers;
002
003/*
004 * The New Item Library Minecraft Server Plugin
005 *
006 * Copyright (C) 2022 - 2025 Daniel "creatorfromhell" Vidmar
007 *
008 * This program is free software; you can redistribute it and/or
009 * modify it under the terms of the GNU Lesser General Public
010 * License as published by the Free Software Foundation; either
011 * version 3 of the License, or (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016 * Lesser General Public License for more details.
017 *
018 * You should have received a copy of the GNU Lesser General Public License
019 * along with this program; if not, write to the Free Software Foundation,
020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
021 */
022
023import net.tnemc.item.AbstractItemStack;
024import net.tnemc.item.InventoryType;
025
026import java.util.Collection;
027import java.util.Optional;
028import java.util.UUID;
029
030/**
031 * Represents a provider that is utilized for item-based calculations and comparisons.
032 *
033 * @param <I> The implementation's instance of {@link AbstractItemStack}
034 * @param <S> The implementation's instance of item stacks.
035 * @param <U> The implementation's instace of inventories.
036 *
037 * @author creatorfromhell
038 * @since 0.1.5.0
039 */
040public interface CalculationsProvider<I extends AbstractItemStack<S>, S, U> {
041
042  /**
043   * Removes items from a collection based on certain criteria.
044   *
045   * @param left      The collection of items from which to remove items.
046   * @param player    The UUID of the player associated with the removal operation.
047   * @param setOwner  Indicates whether to set the owner of the removed items.(supports spigot/paper 1.16.5+)
048   *
049   * @return True if the removal operation was successful, false otherwise.
050   */
051  boolean drop(Collection<I> left, UUID player, final boolean setOwner);
052
053  /**
054   * Removes all items that are equal to the stack from an inventory.
055   *
056   * @param stack     The stack to compare to for removal from the inventory.
057   * @param inventory The inventory to remove the items from.
058   *
059   * @return The amount of items removed.
060   */
061  int removeAll(I stack, U inventory);
062
063  /**
064   * Removes all items that are equal to the stack from an inventory.
065   *
066   * @param stack      The stack to compare to for removal from the inventory.
067   * @param identifier The identifier of the player to remove the items from.
068   *
069   * @return The amount of items removed.
070   */
071  default int removeAll(final I stack, final UUID identifier) {
072
073    final Optional<U> inventory = inventory(identifier, InventoryType.PLAYER);
074    return inventory.map(u->removeAll(stack, u)).orElse(0);
075  }
076
077  /**
078   * Returns a count of items equal to the specific stack in an inventory.
079   *
080   * @param stack     The stack to get a count of.
081   * @param inventory The inventory to check.
082   *
083   * @return The total count of items in the inventory.
084   */
085  int count(I stack, U inventory);
086
087  /**
088   * Returns a count of items equal to the specific stack in an inventory.
089   *
090   * @param stack      The stack to get a count of.
091   * @param identifier The identifier of the player to check.
092   *
093   * @return The total count of items in the inventory.
094   */
095  default int count(final I stack, final UUID identifier) {
096
097    final Optional<U> inventory = inventory(identifier, InventoryType.PLAYER);
098    return inventory.map(u->count(stack, u)).orElse(0);
099  }
100
101  /**
102   * Takes a collection of items from an inventory.
103   *
104   * @param items     The collection of items to remove.
105   * @param inventory The inventory to remove the items from.
106   */
107  void takeItems(Collection<I> items, U inventory);
108
109  /**
110   * Takes a collection of items from an inventory.
111   *
112   * @param items      The collection of items to remove.
113   * @param identifier The identifier of the player to remove the items from.
114   */
115  default void takeItems(final Collection<I> items, final UUID identifier) {
116
117    final Optional<U> inventory = inventory(identifier, InventoryType.PLAYER);
118    inventory.ifPresent(u->takeItems(items, u));
119  }
120
121  /**
122   * Adds a collection of item stacks to an inventory, returns the leftover items that won't fit in
123   * the inventory.
124   *
125   * @param items     The collection of items to add to the inventory.
126   * @param inventory The inventory to add the collection of items to.
127   *
128   * @return The collection of items that won't fit in the inventory.
129   */
130  Collection<I> giveItems(Collection<I> items, U inventory);
131
132  /**
133   * Adds a collection of item stacks to an inventory, returns the leftover items that won't fit in
134   * the inventory.
135   *
136   * @param items      The collection of items to add to the inventory.
137   * @param identifier The identifier of the player to add the collection of items to.
138   *
139   * @return The collection of items that won't fit in the inventory.
140   */
141  default Collection<I> giveItems(final Collection<I> items, final UUID identifier) {
142
143    final Optional<U> inventory = inventory(identifier, InventoryType.PLAYER);
144    return inventory.map(u->giveItems(items, u)).orElse(items);
145  }
146
147  /**
148   * Removes an net.tnemc.item stack with a specific amount from an inventory.
149   *
150   * @param stack     The stack, with the correct amount, to remove.
151   * @param inventory The inventory to remove the net.tnemc.item stack from.
152   *
153   * @return The remaining amount of items to remove.
154   */
155  int removeItem(I stack, U inventory);
156
157  /**
158   * Removes an net.tnemc.item stack with a specific amount from an inventory.
159   *
160   * @param stack      The stack, with the correct amount, to remove.
161   * @param identifier The identifier of the player to remove the net.tnemc.item stack from.
162   *
163   * @return The remaining amount of items to remove.
164   */
165  default int removeItem(final I stack, final UUID identifier) {
166
167    final Optional<U> inventory = inventory(identifier, InventoryType.PLAYER);
168    return inventory.map(u->removeItem(stack, u)).orElseGet(stack::amount);
169  }
170
171  /**
172   * Used to locate an invetory for a UUID identifier.
173   *
174   * @param identifier The identifier to use for the search.
175   * @param type       The inventory type to return.
176   *
177   * @return An optional containing the inventory if it works, otherwise false.
178   */
179  Optional<U> inventory(UUID identifier, InventoryType type);
180
181  /**
182   * Checks to see if two net.tnemc.item stacks are equal.
183   *
184   * @param original The original net.tnemc.item stack.
185   * @param compare  The net.tnemc.item stack you're comparing to the original.
186   *
187   * @return True if the net.tnemc.item stacks are equal, otherwise false.
188   */
189  default boolean itemsEqual(final I original, final S compare) {
190
191    if(!original.provider().similar(original, compare)) {
192      return false;
193    }
194
195    return original.provider().componentsEqual(original, compare);
196  }
197
198  /**
199   * Checks to see if two net.tnemc.item stacks are equal.
200   *
201   * @param original The original net.tnemc.item stack.
202   * @param compare  The net.tnemc.item stack you're comparing to the original.
203   *
204   * @return True if the net.tnemc.item stacks are equal, otherwise false.
205   */
206  default boolean itemsEqual(final I original, final I compare) {
207
208    if(!original.provider().similar(original, compare)) {
209      return false;
210    }
211
212    return original.provider().componentsEqual(original, compare);
213  }
214}