ItemBuilder abstraction

This commit is contained in:
NichtStudioCode 2021-08-08 15:27:23 +02:00
parent ba8c523514
commit f17287d508
19 changed files with 150 additions and 75 deletions

@ -5,7 +5,7 @@ import de.studiocode.invui.gui.builder.GUIBuilder;
import de.studiocode.invui.gui.impl.*;
import de.studiocode.invui.gui.structure.Structure;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.virtualinventory.VirtualInventory;
import de.studiocode.invui.virtualinventory.event.UpdateReason;
import de.studiocode.invui.window.Window;
@ -167,20 +167,20 @@ public interface GUI extends GUIParent {
void addItems(@NotNull Item... items);
/**
* Sets the {@link ItemBuilder} that will be used if nothing else
* Sets the {@link ItemProvider} that will be used if nothing else
* is placed on a slot.
*
* @param itemBuilder The {@link ItemBuilder}
* @param itemBuilder The {@link ItemProvider}
*/
void setBackground(@Nullable ItemBuilder itemBuilder);
void setBackground(@Nullable ItemProvider itemBuilder);
/**
* Gets the {@link ItemBuilder} that will used if nothing else
* Gets the {@link ItemProvider} that will used if nothing else
* is placed on a slot.
*
* @return The {@link ItemBuilder}
* @return The {@link ItemProvider}
*/
ItemBuilder getBackground();
ItemProvider getBackground();
/**
* Removes an {@link Item} by its coordinates.
@ -376,9 +376,9 @@ public interface GUI extends GUIParent {
* @param y The y coordinate where the rectangle should start
* @param width The line length of the rectangle. (VirtualInventory does not define a width)
* @param virtualInventory The {@link VirtualInventory} to be put into this {@link GUI}.
* @param background The {@link ItemBuilder} for empty slots of the {@link VirtualInventory}
* @param background The {@link ItemProvider} for empty slots of the {@link VirtualInventory}
* @param replaceExisting If existing {@link SlotElement}s should be replaced.
*/
void fillRectangle(int x, int y, int width, @NotNull VirtualInventory virtualInventory, @Nullable ItemBuilder background, boolean replaceExisting);
void fillRectangle(int x, int y, int width, @NotNull VirtualInventory virtualInventory, @Nullable ItemProvider background, boolean replaceExisting);
}

@ -1,7 +1,7 @@
package de.studiocode.invui.gui;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.virtualinventory.VirtualInventory;
import org.bukkit.inventory.ItemStack;
@ -30,7 +30,7 @@ public interface SlotElement {
@Override
public ItemStack getItemStack(UUID viewerUUID) {
return item.getItemBuilder().buildFor(viewerUUID);
return item.getItemBuilder().getFor(viewerUUID);
}
@Override
@ -47,7 +47,7 @@ public interface SlotElement {
private final VirtualInventory virtualInventory;
private final int slot;
private final ItemBuilder background;
private final ItemProvider background;
public VISlotElement(VirtualInventory virtualInventory, int slot) {
this.virtualInventory = virtualInventory;
@ -55,7 +55,7 @@ public interface SlotElement {
this.background = null;
}
public VISlotElement(VirtualInventory virtualInventory, int slot, ItemBuilder background) {
public VISlotElement(VirtualInventory virtualInventory, int slot, ItemProvider background) {
this.virtualInventory = virtualInventory;
this.slot = slot;
this.background = background;
@ -69,14 +69,14 @@ public interface SlotElement {
return slot;
}
public ItemBuilder getBackground() {
public ItemProvider getBackground() {
return background;
}
@Override
public ItemStack getItemStack(UUID viewerUUID) {
ItemStack itemStack = virtualInventory.getUnsafeItemStack(slot);
if (itemStack == null && background != null) itemStack = background.buildFor(viewerUUID);
if (itemStack == null && background != null) itemStack = background.getFor(viewerUUID);
return itemStack;
}

@ -6,7 +6,7 @@ import de.studiocode.invui.gui.impl.*;
import de.studiocode.invui.gui.structure.Marker;
import de.studiocode.invui.gui.structure.Structure;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.inventory.ShapedRecipe;
import org.jetbrains.annotations.NotNull;
@ -48,7 +48,7 @@ public class GUIBuilder {
return this;
}
public GUIBuilder addIngredient(char key, @NotNull ItemBuilder itemBuilder) {
public GUIBuilder addIngredient(char key, @NotNull ItemProvider itemBuilder) {
structure.addIngredient(key, itemBuilder);
return this;
}

@ -9,7 +9,7 @@ import de.studiocode.invui.gui.SlotElement.LinkedSlotElement;
import de.studiocode.invui.gui.SlotElement.VISlotElement;
import de.studiocode.invui.gui.structure.Structure;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.util.ArrayUtils;
import de.studiocode.invui.util.InventoryUtils;
import de.studiocode.invui.util.SlotUtils;
@ -47,7 +47,7 @@ public abstract class BaseGUI implements GUI {
private SlotElement[] animationElements;
private Animation animation;
private ItemBuilder background;
private ItemProvider background;
public BaseGUI(int width, int height) {
this.width = width;
@ -137,8 +137,8 @@ public abstract class BaseGUI implements GUI {
&& (isBuilderSimilar(background, uuid, clicked) || isBuilderSimilar(element.getBackground(), uuid, clicked));
}
private boolean isBuilderSimilar(ItemBuilder builder, UUID uuid, ItemStack expected) {
return builder != null && builder.buildFor(uuid).isSimilar(expected);
private boolean isBuilderSimilar(ItemProvider builder, UUID uuid, ItemStack expected) {
return builder != null && builder.getFor(uuid).isSimilar(expected);
}
@SuppressWarnings("deprecation")
@ -527,12 +527,12 @@ public abstract class BaseGUI implements GUI {
}
@Override
public void setBackground(ItemBuilder itemBuilder) {
public void setBackground(ItemProvider itemBuilder) {
this.background = itemBuilder;
}
@Override
public ItemBuilder getBackground() {
public ItemProvider getBackground() {
return background;
}
@ -656,7 +656,7 @@ public abstract class BaseGUI implements GUI {
}
@Override
public void fillRectangle(int x, int y, int width, @NotNull VirtualInventory virtualInventory, @Nullable ItemBuilder background, boolean replaceExisting) {
public void fillRectangle(int x, int y, int width, @NotNull VirtualInventory virtualInventory, @Nullable ItemProvider background, boolean replaceExisting) {
int height = (int) Math.ceil((double) virtualInventory.getSize() / (double) width);
int slotIndex = 0;

@ -5,7 +5,7 @@ import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.gui.SlotElement.ItemSlotElement;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.impl.SimpleItem;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.inventory.ShapedRecipe;
import org.jetbrains.annotations.NotNull;
@ -30,7 +30,7 @@ public class Structure {
.replace("\n", "");
}
public static void addGlobalIngredient(char key, @NotNull ItemBuilder itemBuilder) {
public static void addGlobalIngredient(char key, @NotNull ItemProvider itemBuilder) {
addGlobalIngredient(key, new SimpleItem(itemBuilder));
}
@ -50,7 +50,7 @@ public class Structure {
globalIngredientMap.put(key, new Ingredient(itemSupplier));
}
public Structure addIngredient(char key, @NotNull ItemBuilder itemBuilder) {
public Structure addIngredient(char key, @NotNull ItemProvider itemBuilder) {
return addIngredient(key, new SimpleItem(itemBuilder));
}

@ -12,12 +12,12 @@ import java.util.Set;
public interface Item {
/**
* Gets the {@link ItemBuilder}.
* Gets the {@link ItemProvider}.
* This method gets called every time a {@link Window} is notified ({@link #notifyWindows()}).
*
* @return The {@link ItemBuilder}
* @return The {@link ItemProvider}
*/
ItemBuilder getItemBuilder();
ItemProvider getItemBuilder();
/**
* Adds a {@link Window} to the window set, telling the {@link Item} that it is
@ -46,7 +46,7 @@ public interface Item {
/**
* Calls the {@link Window#handleItemBuilderUpdate(Item)} method on every {@link Window}
* in the set, notifying them that the {@link ItemBuilder} has been updated
* in the set, notifying them that the {@link ItemProvider} has been updated
* and the {@link ItemStack} inside the {@link Window}'s {@link Inventory} should
* be replaced.
*/

@ -26,7 +26,7 @@ import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class ItemBuilder implements Cloneable {
public class ItemBuilder implements ItemProvider {
protected ItemStack base;
protected Material material;
@ -87,7 +87,7 @@ public class ItemBuilder implements Cloneable {
*
* @return The {@link ItemStack}
*/
public ItemStack build() {
public ItemStack get() {
ItemStack itemStack;
if (base != null) {
itemStack = base;
@ -128,11 +128,11 @@ public class ItemBuilder implements Cloneable {
* translates the item's name into the player's language.
*
* @param playerUUID The {@link UUID} of the {@link Player}
* for who this {@link ItemStack} should be built.
* for whom this {@link ItemStack} should be built.
* @return The {@link ItemStack}
*/
public ItemStack buildFor(@NotNull UUID playerUUID) {
return build();
public ItemStack getFor(@NotNull UUID playerUUID) {
return get();
}
public ItemBuilder setMaterial(@NotNull Material material) {

@ -0,0 +1,33 @@
package de.studiocode.invui.item;
import de.studiocode.invui.window.impl.BaseWindow;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.function.Supplier;
public interface ItemProvider extends Supplier<ItemStack>, Cloneable {
/**
* Builds the {@link ItemStack}
*
* @return The {@link ItemStack}
*/
ItemStack get();
/**
* Gets the {@link ItemStack} for a specific player.
* This is the method called by {@link BaseWindow} which gives you
* the option to (for example) create a subclass of {@link ItemProvider} that automatically
* translates the item's name into the player's language.
*
* @param playerUUID The {@link UUID} of the {@link Player}
* for whom this {@link ItemStack} should be made.
* @return The {@link ItemStack}
*/
ItemStack getFor(@NotNull UUID playerUUID);
}

@ -0,0 +1,41 @@
package de.studiocode.invui.item;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
/**
* An {@link ItemProvider} that just returns the {@link ItemStack}
* passed to it in the constructor regardless of the {@link UUID players uuid}.
*/
public class ItemWrapper implements ItemProvider {
private ItemStack itemStack;
public ItemWrapper(ItemStack itemStack) {
this.itemStack = itemStack;
}
@Override
public ItemStack get() {
return itemStack;
}
@Override
public ItemStack getFor(@NotNull UUID playerUUID) {
return itemStack;
}
@Override
public ItemWrapper clone() {
try {
ItemWrapper clone = (ItemWrapper) super.clone();
clone.itemStack = itemStack.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new Error(e);
}
}
}

@ -1,6 +1,7 @@
package de.studiocode.invui.item.impl;
import de.studiocode.invui.InvUI;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import org.bukkit.Bukkit;
@ -14,14 +15,14 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Supplier;
/**
* An {@link Item} that creates it's {@link ItemBuilder} asynchronously and displays
* a placeholder {@link ItemBuilder} until the actual {@link ItemBuilder} has been created.
* An {@link Item} that creates it's {@link ItemProvider} asynchronously and displays
* a placeholder {@link ItemProvider} until the actual {@link ItemProvider} has been created.
*/
public class AsyncItem extends BaseItem {
private volatile ItemBuilder itemBuilder;
private volatile ItemProvider itemBuilder;
public AsyncItem(@Nullable ItemBuilder itemBuilder, @NotNull Supplier<ItemBuilder> builderSupplier) {
public AsyncItem(@Nullable ItemProvider itemBuilder, @NotNull Supplier<? extends ItemProvider> builderSupplier) {
this.itemBuilder = itemBuilder == null ? new ItemBuilder(Material.AIR) : itemBuilder;
Bukkit.getScheduler().runTaskAsynchronously(InvUI.getInstance().getPlugin(), () -> {
@ -30,12 +31,12 @@ public class AsyncItem extends BaseItem {
});
}
public AsyncItem(@NotNull Supplier<ItemBuilder> builderSupplier) {
public AsyncItem(@NotNull Supplier<? extends ItemProvider> builderSupplier) {
this(null, builderSupplier);
}
@Override
public ItemBuilder getItemBuilder() {
public ItemProvider getItemBuilder() {
return itemBuilder;
}

@ -2,7 +2,7 @@ package de.studiocode.invui.item.impl;
import de.studiocode.invui.InvUI;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.window.Window;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -12,17 +12,17 @@ import org.bukkit.scheduler.BukkitTask;
/**
* An {@link Item} that automatically cycles through a predefined array of
* {@link ItemBuilder} at a predefined speed.
* {@link ItemProvider} at a predefined speed.
*/
public class AutoCycleItem extends BaseItem {
private final ItemBuilder[] itemBuilders;
private final ItemProvider[] itemBuilders;
private final int period;
private BukkitTask task;
private int state;
public AutoCycleItem(int period, ItemBuilder... itemBuilders) {
public AutoCycleItem(int period, ItemProvider... itemBuilders) {
this.itemBuilders = itemBuilders;
this.period = period;
}
@ -44,7 +44,7 @@ public class AutoCycleItem extends BaseItem {
}
@Override
public ItemBuilder getItemBuilder() {
public ItemProvider getItemBuilder() {
return itemBuilders[state];
}

@ -2,21 +2,21 @@ package de.studiocode.invui.item.impl;
import de.studiocode.invui.InvUI;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
import java.util.function.Supplier;
/**
* An {@link Item} that updates it's {@link ItemBuilder} every specified amount
* An {@link Item} that updates it's {@link ItemProvider} every specified amount
* of ticks.
*/
public class AutoUpdateItem extends SuppliedItem {
private final BukkitTask task;
public AutoUpdateItem(int period, Supplier<ItemBuilder> builderSupplier) {
public AutoUpdateItem(int period, Supplier<? extends ItemProvider> builderSupplier) {
super(builderSupplier, null);
task = Bukkit.getScheduler().runTaskTimer(InvUI.getInstance().getPlugin(), this::notifyWindows, 0, period);
}

@ -1,7 +1,7 @@
package de.studiocode.invui.item.impl;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -14,7 +14,7 @@ public class CommandItem extends SimpleItem {
private final String command;
public CommandItem(@NotNull ItemBuilder itemBuilder, @NotNull String command) {
public CommandItem(@NotNull ItemProvider itemBuilder, @NotNull String command) {
super(itemBuilder);
this.command = command;
}

@ -1,7 +1,7 @@
package de.studiocode.invui.item.impl;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -11,22 +11,22 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
/**
* An {@link Item} that cycles trough a predefined array of {@link ItemBuilder}s when clicked.
* An {@link Item} that cycles trough a predefined array of {@link ItemProvider}s when clicked.
*/
public class CycleItem extends BaseItem {
private final Consumer<Integer> stateChangeHandler;
private final ItemBuilder[] states;
private final ItemProvider[] states;
private int state;
public CycleItem(@Nullable Consumer<Integer> stateChangeHandler, @NotNull ItemBuilder... states) {
public CycleItem(@Nullable Consumer<Integer> stateChangeHandler, @NotNull ItemProvider... states) {
this.stateChangeHandler = stateChangeHandler;
this.states = states;
}
@Override
public ItemBuilder getItemBuilder() {
public ItemProvider getItemBuilder() {
return states[state];
}

@ -2,7 +2,7 @@ package de.studiocode.invui.item.impl;
import de.studiocode.invui.item.Click;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -16,20 +16,20 @@ import java.util.function.Consumer;
*/
public class SimpleItem extends BaseItem {
private final ItemBuilder itemBuilder;
private final ItemProvider itemBuilder;
private final Consumer<Click> clickHandler;
public SimpleItem(@NotNull ItemBuilder itemBuilder) {
public SimpleItem(@NotNull ItemProvider itemBuilder) {
this.itemBuilder = itemBuilder;
this.clickHandler = null;
}
public SimpleItem(@NotNull ItemBuilder itemBuilder, @Nullable Consumer<Click> clickHandler) {
public SimpleItem(@NotNull ItemProvider itemBuilder, @Nullable Consumer<Click> clickHandler) {
this.itemBuilder = itemBuilder;
this.clickHandler = clickHandler;
}
public ItemBuilder getItemBuilder() {
public ItemProvider getItemBuilder() {
return itemBuilder;
}

@ -1,7 +1,7 @@
package de.studiocode.invui.item.impl;
import de.studiocode.invui.item.Click;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -13,16 +13,16 @@ import java.util.function.Supplier;
public class SuppliedItem extends BaseItem {
private final Supplier<ItemBuilder> builderSupplier;
private final Supplier<? extends ItemProvider> builderSupplier;
private final Function<Click, Boolean> clickHandler;
public SuppliedItem(@NotNull Supplier<ItemBuilder> builderSupplier, @Nullable Function<Click, Boolean> clickHandler) {
public SuppliedItem(@NotNull Supplier<? extends ItemProvider> builderSupplier, @Nullable Function<Click, Boolean> clickHandler) {
this.builderSupplier = builderSupplier;
this.clickHandler = clickHandler;
}
@Override
public ItemBuilder getItemBuilder() {
public ItemProvider getItemBuilder() {
return builderSupplier.get();
}

@ -1,17 +1,17 @@
package de.studiocode.invui.item.impl.controlitem;
import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.item.impl.BaseItem;
public abstract class ControlItem<G extends GUI> extends BaseItem {
private G gui;
public abstract ItemBuilder getItemBuilder(G gui);
public abstract ItemProvider getItemBuilder(G gui);
@Override
public final ItemBuilder getItemBuilder() {
public final ItemProvider getItemBuilder() {
return getItemBuilder(gui);
}

@ -3,7 +3,7 @@ package de.studiocode.invui.window;
import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.GUIParent;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.virtualinventory.VirtualInventory;
import de.studiocode.invui.window.impl.merged.MergedWindow;
import de.studiocode.invui.window.impl.merged.combined.SimpleCombinedWindow;
@ -107,10 +107,10 @@ public interface Window extends GUIParent {
/**
* A method called by the {@link Item} itself to notify the {@link Window}
* that its {@link ItemBuilder} has been updated and the {@link ItemStack}
* that its {@link ItemProvider} has been updated and the {@link ItemStack}
* in the {@link Inventory} should be replaced.
*
* @param item The {@link Item} whose {@link ItemBuilder} has been updated.
* @param item The {@link Item} whose {@link ItemProvider} has been updated.
*/
void handleItemBuilderUpdate(Item item);

@ -7,7 +7,7 @@ import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.gui.SlotElement.ItemSlotElement;
import de.studiocode.invui.gui.SlotElement.VISlotElement;
import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.util.ArrayUtils;
import de.studiocode.invui.util.Pair;
import de.studiocode.invui.virtualinventory.VirtualInventory;
@ -57,8 +57,8 @@ public abstract class BaseWindow implements Window {
// put ItemStack in inventory
ItemStack itemStack;
if (element == null || (element instanceof VISlotElement && element.getItemStack(viewerUUID) == null)) {
ItemBuilder background = getGuiAt(index).getFirst().getBackground();
itemStack = background == null ? null : background.buildFor(viewerUUID);
ItemProvider background = getGuiAt(index).getFirst().getBackground();
itemStack = background == null ? null : background.getFor(viewerUUID);
} else itemStack = element.getItemStack(viewerUUID);
setInvItem(index, itemStack);