Add memoization support and implement equals/hashCode methods
All checks were successful
SteamWarCI Build successful
All checks were successful
SteamWarCI Build successful
This commit is contained in:
@@ -26,6 +26,7 @@ import de.steamwar.inventory.ui.util.RenderItem;
|
||||
import de.steamwar.inventory.ui.util.Size;
|
||||
import de.steamwar.message.Message;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -38,6 +39,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class UIInventory {
|
||||
@@ -49,6 +51,9 @@ public abstract class UIInventory {
|
||||
private Player currentRender;
|
||||
private final int playerSlots;
|
||||
|
||||
private List<MemoHookMeta<?>> memoHooks = new ArrayList<>();
|
||||
private int buildHookCount = 0;
|
||||
|
||||
protected UIInventory() {
|
||||
this(0);
|
||||
}
|
||||
@@ -63,6 +68,31 @@ public abstract class UIInventory {
|
||||
|
||||
void onClose() { }
|
||||
|
||||
public <T> T useMemo(Supplier<T> supplier, List<Object> dependencies) {
|
||||
int currentHook = buildHookCount++;
|
||||
|
||||
if (currentHook >= memoHooks.size()) {
|
||||
T value = supplier.get();
|
||||
memoHooks.add(new MemoHookMeta<>(dependencies, value));
|
||||
return value;
|
||||
}
|
||||
|
||||
MemoHookMeta<T> hook = (MemoHookMeta<T>) memoHooks.get(currentHook);
|
||||
|
||||
if (!hook.getDependencies().equals(dependencies)) {
|
||||
hook.setDependencies(dependencies);
|
||||
T value = supplier.get();
|
||||
hook.setValue(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
return hook.getValue();
|
||||
}
|
||||
|
||||
public <T> T useMemo(Supplier<T> supplier) {
|
||||
return useMemo(supplier, Collections.emptyList());
|
||||
}
|
||||
|
||||
public void addViewer(Player... players) {
|
||||
viewers.addAll(Arrays.asList(players));
|
||||
|
||||
@@ -92,7 +122,9 @@ public abstract class UIInventory {
|
||||
int invSize = inventoryHeight * width;
|
||||
|
||||
currentRender = player;
|
||||
buildHookCount = 0;
|
||||
ComponentRender render = render().render(new RenderContext(new Size(width, height), new Size(width, height), this));
|
||||
buildHookCount = -1;
|
||||
currentRender = null;
|
||||
|
||||
if (render.getSize().getWidth() > width || render.getSize().getHeight() > height) {
|
||||
@@ -199,4 +231,12 @@ public abstract class UIInventory {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
private class MemoHookMeta<T> {
|
||||
private List<Object> dependencies;
|
||||
private T value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +52,14 @@ public class ActionBar extends UIFragment {
|
||||
|
||||
@Override
|
||||
public UIComponent build(RenderContext context) {
|
||||
UIComponent[] components = new UIComponent[context.getContainerSize().getWidth()];
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
components[i] = actionBar.getOrDefault(i, filler);
|
||||
}
|
||||
UIComponent[] components = context.useMemo(() -> {
|
||||
UIComponent[] cmp = new UIComponent[context.getContainerSize().getWidth()];
|
||||
for (int i = 0; i < cmp.length; i++) {
|
||||
cmp[i] = actionBar.getOrDefault(i, filler);
|
||||
}
|
||||
|
||||
return cmp;
|
||||
}, Arrays.asList(actionBar));
|
||||
|
||||
return new Row(Arrays.asList(components)).size(new Size(context.getContainerSize().getWidth(), 1));
|
||||
}
|
||||
|
||||
@@ -64,24 +64,28 @@ public class HorizontalScrollLayout extends UIFragment {
|
||||
boolean hasPrev = scroll > 0;
|
||||
boolean hasNext = data.size() - scroll > 9;
|
||||
|
||||
Map<Integer, UIComponent> actionBar = new HashMap<>(this.actionBar);
|
||||
Map<Integer, UIComponent> actionBar = context.useMemo(() -> {
|
||||
Map<Integer, UIComponent> content = new HashMap<>(this.actionBar);
|
||||
|
||||
actionBar.put(0, new UIItem(ItemBuilder.color(hasPrev ? DyeColor.LIME : DyeColor.GRAY).message(Core.MESSAGE).translateName(hasPrev ? "SWLISINV_PREVIOUS_PAGE_ACTIVE" : "SWLISINV_PREVIOUS_PAGE_INACTIVE")).onClickWithUpdate(inventoryClickEvent -> {
|
||||
if (scroll > 0) {
|
||||
scroll = Math.max(0, scroll - 9);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
actionBar.put(8, new UIItem(ItemBuilder.color(hasNext ? DyeColor.LIME : DyeColor.GRAY).message(Core.MESSAGE).translateName(hasNext ? "SWLISINV_NEXT_PAGE_ACTIVE" : "SWLISINV_NEXT_PAGE_INACTIVE")).onClickWithUpdate(inventoryClickEvent -> {
|
||||
if (hasNext) {
|
||||
scroll = Math.min(scroll + 9, data.size() - 9);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
content.put(0, new UIItem(ItemBuilder.color(hasPrev ? DyeColor.LIME : DyeColor.GRAY).message(Core.MESSAGE).translateName(hasPrev ? "SWLISINV_PREVIOUS_PAGE_ACTIVE" : "SWLISINV_PREVIOUS_PAGE_INACTIVE")).onClickWithUpdate(inventoryClickEvent -> {
|
||||
if (scroll > 0) {
|
||||
scroll = Math.max(0, scroll - 9);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
content.put(8, new UIItem(ItemBuilder.color(hasNext ? DyeColor.LIME : DyeColor.GRAY).message(Core.MESSAGE).translateName(hasNext ? "SWLISINV_NEXT_PAGE_ACTIVE" : "SWLISINV_NEXT_PAGE_INACTIVE")).onClickWithUpdate(inventoryClickEvent -> {
|
||||
if (hasNext) {
|
||||
scroll = Math.min(scroll + 9, data.size() - 9);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
|
||||
return content;
|
||||
}, Arrays.asList(hasPrev, hasNext));
|
||||
|
||||
return new Column(
|
||||
new FixedSizeContainer(context.getContainerSize().shrink(0, 1),
|
||||
|
||||
@@ -55,35 +55,44 @@ public class PageLayout<T> extends UIFragment {
|
||||
|
||||
@Override
|
||||
public UIComponent build(RenderContext context) {
|
||||
List<UIComponent> uiItems = new ArrayList<>();
|
||||
|
||||
int itemsOnPage = context.getContainerSize().getWidth() * (context.getContainerSize().getHeight() - 1);
|
||||
|
||||
int ipageLimit = items.size() - page * itemsOnPage;
|
||||
if (ipageLimit > itemsOnPage) {
|
||||
ipageLimit = itemsOnPage;
|
||||
}
|
||||
List<UIComponent> uiItems = context.useMemo(() -> {
|
||||
int i = page * itemsOnPage;
|
||||
|
||||
int i = page * itemsOnPage;
|
||||
for (int ipage = 0; ipage < ipageLimit; ipage++) {
|
||||
UIListEntry<T> e = items.get(i);
|
||||
int ipageLimit = items.size() - page * itemsOnPage;
|
||||
if (ipageLimit > itemsOnPage) {
|
||||
ipageLimit = itemsOnPage;
|
||||
}
|
||||
|
||||
uiItems.add(new UIItem(e.item).onClickNoUpdate(inventoryClickEvent -> callback.clicked(inventoryClickEvent.getClick(), e.object)));
|
||||
i++;
|
||||
}
|
||||
List<UIComponent> pageItems = new ArrayList<>();
|
||||
for (int ipage = 0; ipage < ipageLimit; ipage++) {
|
||||
UIListEntry<T> e = items.get(i);
|
||||
|
||||
Map<Integer, UIComponent> uiBar = new HashMap<>(itemsOnBar);
|
||||
pageItems.add(new UIItem(e.item).onClickNoUpdate(inventoryClickEvent -> callback.clicked(inventoryClickEvent.getClick(), e.object)));
|
||||
i++;
|
||||
}
|
||||
|
||||
if (page != 0) {
|
||||
uiBar.put(0, new UIItem(ItemBuilder.color(DyeColor.LIME).message(Core.MESSAGE).translateName("SWLISINV_PREVIOUS_PAGE_ACTIVE")).onClick(inventoryClickEvent -> page--));
|
||||
} else {
|
||||
uiBar.put(0, new UIItem(ItemBuilder.color(DyeColor.GRAY).message(Core.MESSAGE).translateName("SWLISINV_PREVIOUS_PAGE_INACTIVE")).cancelOnClick());
|
||||
}
|
||||
if (page < items.size() / itemsOnPage - (items.size() % itemsOnPage == 0 ? 1 : 0)) {
|
||||
uiBar.put(8, new UIItem(ItemBuilder.color(DyeColor.LIME).message(Core.MESSAGE).translateName("SWLISINV_NEXT_PAGE_ACTIVE")).onClick(inventoryClickEvent -> page++));
|
||||
} else {
|
||||
uiBar.put(8, new UIItem(ItemBuilder.color(DyeColor.GRAY).message(Core.MESSAGE).translateName("SWLISINV_NEXT_PAGE_INACTIVE")).cancelOnClick());
|
||||
}
|
||||
return pageItems;
|
||||
}, Arrays.asList(page, items.size(), itemsOnPage));
|
||||
|
||||
Map<Integer, UIComponent> uiBar = context.useMemo(() -> {
|
||||
Map<Integer, UIComponent> content = new HashMap<>(itemsOnBar);
|
||||
|
||||
if (page != 0) {
|
||||
content.put(0, new UIItem(ItemBuilder.color(DyeColor.LIME).message(Core.MESSAGE).translateName("SWLISINV_PREVIOUS_PAGE_ACTIVE")).onClick(inventoryClickEvent -> page--));
|
||||
} else {
|
||||
content.put(0, new UIItem(ItemBuilder.color(DyeColor.GRAY).message(Core.MESSAGE).translateName("SWLISINV_PREVIOUS_PAGE_INACTIVE")).cancelOnClick());
|
||||
}
|
||||
if (page < items.size() / itemsOnPage - (items.size() % itemsOnPage == 0 ? 1 : 0)) {
|
||||
content.put(8, new UIItem(ItemBuilder.color(DyeColor.LIME).message(Core.MESSAGE).translateName("SWLISINV_NEXT_PAGE_ACTIVE")).onClick(inventoryClickEvent -> page++));
|
||||
} else {
|
||||
content.put(8, new UIItem(ItemBuilder.color(DyeColor.GRAY).message(Core.MESSAGE).translateName("SWLISINV_NEXT_PAGE_INACTIVE")).cancelOnClick());
|
||||
}
|
||||
|
||||
return content;
|
||||
}, Arrays.asList(page, items.size(), itemsOnPage));
|
||||
|
||||
return new Column(
|
||||
new FixedSizeContainer(context.getContainerSize().shrink(0, 1),
|
||||
|
||||
@@ -183,4 +183,23 @@ public class ItemBuilder {
|
||||
itemMeta.setCustomModelData(modelData);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ItemBuilder that = (ItemBuilder) o;
|
||||
return Objects.equals(itemStack, that.itemStack) && Objects.equals(itemMeta, that.itemMeta) && Objects.equals(message, that.message) && Objects.equals(translateName, that.translateName) && Objects.equals(translateLore, that.translateLore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemBuilder{" +
|
||||
"itemStack=" + itemStack +
|
||||
", itemMeta=" + itemMeta +
|
||||
", message=" + message +
|
||||
", translateName=" + translateName +
|
||||
", translateLore=" + translateLore +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import de.steamwar.inventory.ui.util.RenderItem;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class OnClick implements UIComponent {
|
||||
@@ -56,4 +55,20 @@ public class OnClick implements UIComponent {
|
||||
|
||||
return render;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OnClick{" +
|
||||
"children=" + children +
|
||||
", allowDoubleClick=" + allowDoubleClick +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
OnClick onClick = (OnClick) o;
|
||||
return allowDoubleClick == onClick.allowDoubleClick && children.equals(onClick.children);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,9 @@ public class Space implements UIComponent {
|
||||
new Size(1, 1)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Space;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@ package de.steamwar.inventory.ui.item;
|
||||
|
||||
import de.steamwar.inventory.ui.UIComponent;
|
||||
import de.steamwar.inventory.ui.util.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public class UIItem implements UIComponent {
|
||||
|
||||
@@ -44,4 +46,19 @@ public class UIItem implements UIComponent {
|
||||
new Size(1, 1)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UIItem{" +
|
||||
"itemStack=" + itemStack +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
UIItem uiItem = (UIItem) o;
|
||||
return Objects.equals(itemStack, uiItem.itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,21 @@ import de.steamwar.inventory.ui.UIInventory;
|
||||
import lombok.Data;
|
||||
import lombok.With;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Data
|
||||
@With
|
||||
public class RenderContext {
|
||||
private final Size inventorySize;
|
||||
private final Size containerSize;
|
||||
private final UIInventory inventory;
|
||||
|
||||
public <T> T useMemo(Supplier<T> supplier, List<Object> dependencies) {
|
||||
return inventory.useMemo(supplier, dependencies);
|
||||
}
|
||||
|
||||
public <T> T useMemo(Supplier<T> supplier) {
|
||||
return inventory.useMemo(supplier);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user