Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions oumlib-core/src/main/java/dev/oum/oumlib/inventory/ChestMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,50 @@ public static final class Builder {
return this;
}

@CheckReturnValue
public @NonNull Builder bindBorders(@Nullable ItemStack item, char... ignoredKeys) {
if (layout != null) {
Set<Character> ignored = new HashSet<>();
for (char c : ignoredKeys) {
ignored.add(c);
}
for (char c : layout.characters()) {
if (!ignored.contains(c)) {
layout.bind(c, item);
}
}
}
return this;
}

@CheckReturnValue
public @NonNull Builder bindBorders(@NonNull Supplier<@Nullable ItemStack> supplier, char... ignoredKeys) {
if (layout != null) {
Set<Character> ignored = new HashSet<>();
for (char c : ignoredKeys) {
ignored.add(c);
}
for (char c : layout.characters()) {
if (!ignored.contains(c)) {
layout.bind(c, supplier);
}
}
}
return this;
}

@CheckReturnValue
public @NonNull Builder fill(@Nullable ItemStack item) {
int totalSlots = rows * 9;
for (int i = 0; i < totalSlots; i++) {
final int slot = i;
if (!slotItems.containsKey(slot)) {
slotItems.put(slot, player -> item);
}
}
return this;
}

@CheckReturnValue
public @NonNull Builder item(int slot, @Nullable ItemStack item) {
this.slotItems.put(slot, player -> item);
Expand Down
266 changes: 266 additions & 0 deletions oumlib-core/src/main/java/dev/oum/oumlib/inventory/ConfirmMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
package dev.oum.oumlib.inventory;

import dev.oum.oumlib.scheduler.Scheduler;
import net.kyori.adventure.sound.Sound;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.CheckReturnValue;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public final class ConfirmMenu implements Menu {

private final ChestMenu chestMenu;

private ConfirmMenu(@NonNull Builder builder) {
ChestMenu.Builder cb = ChestMenu.builder()
.title(builder.title)
.rows(builder.rows);

if (builder.pattern != null && builder.pattern.length > 0) {
cb.pattern(builder.pattern);
} else {
cb.pattern(
"#########",
" C D ",
"#########"
);
}

if (builder.openSound != null) cb.openSound(builder.openSound);
if (builder.closeSound != null) cb.closeSound(builder.closeSound);
if (builder.clickSound != null) cb.clickSound(builder.clickSound);

if (builder.borderItem != null) {
cb.bindBorders(builder.borderItem, builder.confirmSlotChar, builder.denySlotChar);
}

cb.bind(builder.confirmSlotChar, builder.confirmItem);
cb.onClick(builder.confirmSlotChar, ctx -> {
Player p = ctx.player();
p.closeInventory();
if (builder.confirmSound != null) p.playSound(builder.confirmSound);
if (builder.onConfirm != null) {
Scheduler.runFor(p, () -> builder.onConfirm.accept(p));
}
});

cb.bind(builder.denySlotChar, builder.denyItem);
cb.onClick(builder.denySlotChar, ctx -> {
Player p = ctx.player();
p.closeInventory();
if (builder.denySound != null) p.playSound(builder.denySound);
if (builder.onDeny != null) {
Scheduler.runFor(p, () -> builder.onDeny.accept(p));
}
});

if (builder.onClose != null) {
cb.onClose(builder.onClose);
}

this.chestMenu = cb.build();
}

@Contract(" -> new")
@CheckReturnValue
public static @NonNull Builder builder() {
return new Builder();
}

@Override
public void open(@NonNull Player player) {
chestMenu.open(player);
}

@Override
public void close(@NonNull Player player) {
chestMenu.close(player);
}

@Override
public void closeAll() {
chestMenu.closeAll();
}

public static final class Builder {
private String title = "<red>Are you sure?";
private int rows = 3;
private String[] pattern;
private char confirmSlotChar = 'C';
private char denySlotChar = 'D';

private Function<Player, ItemStack> confirmItem = p -> ItemBuilder.of(Material.LIME_CONCRETE)
.name("<green><b>Confirm</b>")
.build();
private Function<Player, ItemStack> denyItem = p -> ItemBuilder.of(Material.RED_CONCRETE)
.name("<red><b>Cancel</b>")
.build();
private ItemStack borderItem = ItemBuilder.of(Material.GRAY_STAINED_GLASS_PANE).name(" ").build();

private Consumer<Player> onConfirm;
private Consumer<Player> onDeny;
private Consumer<Player> onClose;

private Sound confirmSound;
private Sound denySound;
private Sound openSound;
private Sound closeSound;
private Sound clickSound;

@CheckReturnValue
public @NonNull Builder title(@NonNull String title) {
this.title = title;
return this;
}

@CheckReturnValue
public @NonNull Builder rows(int rows) {
if (rows < 1 || rows > 6) throw new IllegalArgumentException("Rows must be 1–6.");
this.rows = rows;
return this;
}

@CheckReturnValue
public @NonNull Builder pattern(String @NonNull ... rows) {
this.pattern = rows;
return this;
}

@CheckReturnValue
public @NonNull Builder pattern(@NonNull List<String> rows) {
this.pattern = rows.toArray(new String[0]);
return this;
}

@CheckReturnValue
public @NonNull Builder confirmSlot(char key) {
this.confirmSlotChar = key;
return this;
}

@CheckReturnValue
public @NonNull Builder denySlot(char key) {
this.denySlotChar = key;
return this;
}

@CheckReturnValue
public @NonNull Builder confirmItem(@Nullable ItemStack item) {
this.confirmItem = p -> item;
return this;
}

@CheckReturnValue
public @NonNull Builder confirmItem(@NonNull Supplier<@Nullable ItemStack> supplier) {
this.confirmItem = p -> supplier.get();
return this;
}

@CheckReturnValue
public @NonNull Builder confirmItem(@NonNull Function<@NonNull Player, @Nullable ItemStack> function) {
this.confirmItem = function;
return this;
}

@CheckReturnValue
public @NonNull Builder denyItem(@Nullable ItemStack item) {
this.denyItem = p -> item;
return this;
}

@CheckReturnValue
public @NonNull Builder denyItem(@NonNull Supplier<@Nullable ItemStack> supplier) {
this.denyItem = p -> supplier.get();
return this;
}

@CheckReturnValue
public @NonNull Builder denyItem(@NonNull Function<@NonNull Player, @Nullable ItemStack> function) {
this.denyItem = function;
return this;
}

@CheckReturnValue
public @NonNull Builder border(@Nullable ItemStack item) {
this.borderItem = item;
return this;
}

@CheckReturnValue
public @NonNull Builder onConfirm(@Nullable Consumer<Player> onConfirm) {
this.onConfirm = onConfirm;
return this;
}

@CheckReturnValue
public @NonNull Builder onConfirm(@Nullable Runnable onConfirm) {
this.onConfirm = onConfirm != null ? p -> onConfirm.run() : null;
return this;
}

@CheckReturnValue
public @NonNull Builder onDeny(@Nullable Consumer<Player> onDeny) {
this.onDeny = onDeny;
return this;
}

@CheckReturnValue
public @NonNull Builder onDeny(@Nullable Runnable onDeny) {
this.onDeny = onDeny != null ? p -> onDeny.run() : null;
return this;
}

@CheckReturnValue
public @NonNull Builder onClose(@Nullable Consumer<Player> onClose) {
this.onClose = onClose;
return this;
}

@CheckReturnValue
public @NonNull Builder confirmSound(@Nullable Sound sound) {
this.confirmSound = sound;
return this;
}

@CheckReturnValue
public @NonNull Builder denySound(@Nullable Sound sound) {
this.denySound = sound;
return this;
}

@CheckReturnValue
public @NonNull Builder openSound(@Nullable Sound sound) {
this.openSound = sound;
return this;
}

@CheckReturnValue
public @NonNull Builder closeSound(@Nullable Sound sound) {
this.closeSound = sound;
return this;
}

@CheckReturnValue
public @NonNull Builder clickSound(@Nullable Sound sound) {
this.clickSound = sound;
return this;
}

@Contract(" -> new")
public @NonNull ConfirmMenu build() {
return new ConfirmMenu(this);
}

public void open(@NonNull Player player) {
build().open(player);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,17 @@ private ItemBuilder(@NonNull ItemStack item) {
@Contract("_ -> new")
@CheckReturnValue
public static @NonNull ItemBuilder from(@NonNull String identifier) {
return from(identifier, Material.STONE);
}

@Contract("_, _ -> new")
@CheckReturnValue
public static @NonNull ItemBuilder from(@NonNull String identifier, @NonNull Material fallback) {
return ItemBridge.getItem(identifier)
.map(ItemBuilder::of)
.orElseGet(() -> {
Material mat = Material.matchMaterial(identifier);
return of(mat != null ? mat : Material.STONE);
return of(mat != null ? mat : fallback);
});
}

Expand Down
13 changes: 9 additions & 4 deletions oumlib-core/src/main/java/dev/oum/oumlib/inventory/Layout.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

Expand Down Expand Up @@ -40,6 +37,14 @@ public Layout bind(char key, @NonNull Function<@NonNull Player, @Nullable ItemSt
return this;
}

public @NonNull String[] pattern() {
return pattern;
}

public @NonNull Set<Character> characters() {
return slotMap.keySet();
}

public List<Integer> slotsFor(char key) {
return slotMap.getOrDefault(key, List.of());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import org.bukkit.entity.Player;

public sealed interface Menu permits ChestMenu, PaginatedMenu, AnvilMenu {
public sealed interface Menu permits ChestMenu, PaginatedMenu, AnvilMenu, ConfirmMenu {

void open(Player player);

Expand Down
2 changes: 1 addition & 1 deletion oumlib-core/src/main/java/dev/oum/oumlib/pdc/DataKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ public record DataKey<P, C>(
return new Location(w, x, y, z, yaw, pitch);
}
};
private static final Gson GSON = new Gson();
public static final PersistentDataType<String, List<String>> STRING_LIST_TYPE = new PersistentDataType<>() {
@Override
public @NonNull Class<String> getPrimitiveType() {
Expand All @@ -140,6 +139,7 @@ public record DataKey<P, C>(
return GSON.fromJson(primitive, List.class);
}
};
private static final Gson GSON = new Gson();

public static @NonNull DataKey<String, String> string(@NonNull NamespacedKey key) {
return new DataKey<>(key, PersistentDataType.STRING);
Expand Down
Loading
Loading