mirror of
https://github.com/Xiao-MoMi/Custom-Fishing.git
synced 2026-01-04 15:41:35 +00:00
gui framework
This commit is contained in:
@@ -129,5 +129,5 @@ public interface AdventureManager {
|
|||||||
* @param component shaded component
|
* @param component shaded component
|
||||||
* @return paper component
|
* @return paper component
|
||||||
*/
|
*/
|
||||||
Object shadedComponentToPaperComponent(Component component);
|
Object shadedComponentToOriginalComponent(Component component);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class InventoryUtils {
|
|||||||
null,
|
null,
|
||||||
inventoryHolder,
|
inventoryHolder,
|
||||||
size,
|
size,
|
||||||
isSpigot ? CustomFishingPlugin.get().getAdventure().componentToLegacy(component) : CustomFishingPlugin.get().getAdventure().shadedComponentToPaperComponent(component)
|
isSpigot ? CustomFishingPlugin.get().getAdventure().componentToLegacy(component) : CustomFishingPlugin.get().getAdventure().shadedComponentToOriginalComponent(component)
|
||||||
);
|
);
|
||||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) {
|
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) {
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
@@ -94,7 +94,7 @@ public class InventoryUtils {
|
|||||||
null,
|
null,
|
||||||
inventoryHolder,
|
inventoryHolder,
|
||||||
type,
|
type,
|
||||||
isSpigot ? CustomFishingPlugin.get().getAdventure().componentToLegacy(component) : CustomFishingPlugin.get().getAdventure().shadedComponentToPaperComponent(component)
|
isSpigot ? CustomFishingPlugin.get().getAdventure().componentToLegacy(component) : CustomFishingPlugin.get().getAdventure().shadedComponentToOriginalComponent(component)
|
||||||
);
|
);
|
||||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) {
|
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) {
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import com.comphenix.protocol.ProtocolLibrary;
|
|||||||
import com.comphenix.protocol.ProtocolManager;
|
import com.comphenix.protocol.ProtocolManager;
|
||||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||||
import de.tr7zw.changeme.nbtapi.utils.VersionChecker;
|
import de.tr7zw.changeme.nbtapi.utils.VersionChecker;
|
||||||
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
|
|
||||||
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
|
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
|
||||||
import net.momirealms.customfishing.api.CustomFishingPlugin;
|
import net.momirealms.customfishing.api.CustomFishingPlugin;
|
||||||
import net.momirealms.customfishing.api.util.LogUtils;
|
import net.momirealms.customfishing.api.util.LogUtils;
|
||||||
@@ -211,8 +210,12 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin {
|
|||||||
"org.xerial:sqlite-jdbc:3.43.0.0", mavenRepo,
|
"org.xerial:sqlite-jdbc:3.43.0.0", mavenRepo,
|
||||||
"dev.jorel:commandapi-bukkit-shade:9.2.0", mavenRepo,
|
"dev.jorel:commandapi-bukkit-shade:9.2.0", mavenRepo,
|
||||||
"xyz.xenondevs.invui:invui-core:1.19", "https://repo.xenondevs.xyz/releases/",
|
"xyz.xenondevs.invui:invui-core:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
|
"xyz.xenondevs.invui:inventory-access:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
"xyz.xenondevs.invui:inventory-access-r8:1.19", "https://repo.xenondevs.xyz/releases/",
|
"xyz.xenondevs.invui:inventory-access-r8:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
"xyz.xenondevs.invui:inventory-access-r9:1.19", "https://repo.xenondevs.xyz/releases/",
|
"xyz.xenondevs.invui:inventory-access-r9:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
|
"xyz.xenondevs.invui:inventory-access-r10:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
|
"xyz.xenondevs.invui:inventory-access-r11:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
|
"xyz.xenondevs.invui:inventory-access-r12:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
"xyz.xenondevs.invui:inventory-access-r13:1.19", "https://repo.xenondevs.xyz/releases/",
|
"xyz.xenondevs.invui:inventory-access-r13:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
"xyz.xenondevs.invui:inventory-access-r14:1.19", "https://repo.xenondevs.xyz/releases/",
|
"xyz.xenondevs.invui:inventory-access-r14:1.19", "https://repo.xenondevs.xyz/releases/",
|
||||||
"xyz.xenondevs.invui:inventory-access-r15:1.19", "https://repo.xenondevs.xyz/releases/"
|
"xyz.xenondevs.invui:inventory-access-r15:1.19", "https://repo.xenondevs.xyz/releases/"
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public class AdventureManagerImpl implements AdventureManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object shadedComponentToPaperComponent(Component component) {
|
public Object shadedComponentToOriginalComponent(Component component) {
|
||||||
Object cp;
|
Object cp;
|
||||||
try {
|
try {
|
||||||
cp = ReflectionUtils.gsonDeserializeMethod.invoke(ReflectionUtils.gsonInstance, GsonComponentSerializer.gson().serialize(component));
|
cp = ReflectionUtils.gsonDeserializeMethod.invoke(ReflectionUtils.gsonInstance, GsonComponentSerializer.gson().serialize(component));
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package net.momirealms.customfishing.adventure.component;
|
||||||
|
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class Languages {
|
||||||
|
|
||||||
|
private static final Languages INSTANCE = new Languages();
|
||||||
|
private final Map<String, Map<String, String>> translations = new HashMap<>();
|
||||||
|
private Function<Player, Locale> languageProvider = Player::locale;
|
||||||
|
private boolean serverSideTranslations = true;
|
||||||
|
|
||||||
|
private Languages() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Languages getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLanguage(@NotNull String lang, @NotNull Map<String, String> translations) {
|
||||||
|
this.translations.put(lang, translations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadLanguage(@NotNull String lang, @NotNull Reader reader) throws IOException {
|
||||||
|
var translations = new HashMap<String, String>();
|
||||||
|
try (var jsonReader = new JsonReader(reader)) {
|
||||||
|
jsonReader.beginObject();
|
||||||
|
while (jsonReader.hasNext()) {
|
||||||
|
var key = jsonReader.nextName();
|
||||||
|
var value = jsonReader.nextString();
|
||||||
|
translations.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
addLanguage(lang, translations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadLanguage(@NotNull String lang, @NotNull File file, @NotNull Charset charset) throws IOException {
|
||||||
|
try (var reader = new FileReader(file, charset)) {
|
||||||
|
loadLanguage(lang, reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getFormatString(@NotNull String lang, @NotNull String key) {
|
||||||
|
var map = translations.get(lang);
|
||||||
|
if (map == null)
|
||||||
|
return null;
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLanguageProvider(@NotNull Function<Player, Locale> languageProvider) {
|
||||||
|
this.languageProvider = languageProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull Locale getLanguage(@NotNull Player player) {
|
||||||
|
return languageProvider.apply(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enableServerSideTranslations(boolean enable) {
|
||||||
|
serverSideTranslations = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean doesServerSideTranslations() {
|
||||||
|
return serverSideTranslations;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package net.momirealms.customfishing.adventure.component;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.Style;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
|
||||||
|
public class ShadedAdventureComponentUtils {
|
||||||
|
|
||||||
|
private static final Style FORMATTING_TEMPLATE = Style.style()
|
||||||
|
.color(NamedTextColor.WHITE)
|
||||||
|
.decoration(TextDecoration.ITALIC, false)
|
||||||
|
.decoration(TextDecoration.BOLD, false)
|
||||||
|
.decoration(TextDecoration.STRIKETHROUGH, false)
|
||||||
|
.decoration(TextDecoration.UNDERLINED, false)
|
||||||
|
.decoration(TextDecoration.OBFUSCATED, false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static Component withoutPreFormatting(Component component) {
|
||||||
|
return component.style(component.style().merge(FORMATTING_TEMPLATE, Style.Merge.Strategy.IF_ABSENT_ON_TARGET));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package net.momirealms.customfishing.adventure.component;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import xyz.xenondevs.inventoryaccess.component.ComponentWrapper;
|
||||||
|
|
||||||
|
public class ShadedAdventureComponentWrapper implements ComponentWrapper {
|
||||||
|
|
||||||
|
public static final ShadedAdventureComponentWrapper EMPTY = new ShadedAdventureComponentWrapper(Component.empty());
|
||||||
|
|
||||||
|
private final Component component;
|
||||||
|
|
||||||
|
public ShadedAdventureComponentWrapper(Component component) {
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String serializeToJson() {
|
||||||
|
return GsonComponentSerializer.gson().serialize(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ComponentWrapper localized(@NotNull String lang) {
|
||||||
|
if (!Languages.getInstance().doesServerSideTranslations())
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return new ShadedAdventureComponentWrapper(ShadedAdventureShadedComponentLocalizer.getInstance().localize(lang, component));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ComponentWrapper withoutPreFormatting() {
|
||||||
|
return new ShadedAdventureComponentWrapper(ShadedAdventureComponentUtils.withoutPreFormatting(component));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ShadedAdventureComponentWrapper clone() {
|
||||||
|
try {
|
||||||
|
return (ShadedAdventureComponentWrapper) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package net.momirealms.customfishing.adventure.component;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.*;
|
||||||
|
|
||||||
|
public class ShadedAdventureShadedComponentLocalizer extends ShadedComponentLocalizer<Component> {
|
||||||
|
|
||||||
|
private static final ShadedAdventureShadedComponentLocalizer INSTANCE = new ShadedAdventureShadedComponentLocalizer();
|
||||||
|
|
||||||
|
private ShadedAdventureShadedComponentLocalizer() {
|
||||||
|
super(Component::text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShadedAdventureShadedComponentLocalizer getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Override
|
||||||
|
public Component localize(String lang, Component component) {
|
||||||
|
if (!(component instanceof BuildableComponent))
|
||||||
|
throw new IllegalStateException("Component is not a BuildableComponent");
|
||||||
|
|
||||||
|
return localize(lang, (BuildableComponent) component);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("NonExtendableApiUsage")
|
||||||
|
private <C extends BuildableComponent<C, B>, B extends ComponentBuilder<C, B>> BuildableComponent<?, ?> localize(String lang, BuildableComponent<C, B> component) {
|
||||||
|
ComponentBuilder<?, ?> builder;
|
||||||
|
if (component instanceof TranslatableComponent) {
|
||||||
|
builder = localizeTranslatable(lang, (TranslatableComponent) component).toBuilder();
|
||||||
|
} else {
|
||||||
|
builder = component.toBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.mapChildrenDeep(child -> {
|
||||||
|
if (child instanceof TranslatableComponent)
|
||||||
|
return localizeTranslatable(lang, (TranslatableComponent) child);
|
||||||
|
return child;
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BuildableComponent<?, ?> localizeTranslatable(String lang, TranslatableComponent component) {
|
||||||
|
var formatString = Languages.getInstance().getFormatString(lang, component.key());
|
||||||
|
if (formatString == null)
|
||||||
|
return component;
|
||||||
|
|
||||||
|
var children = decomposeFormatString(lang, formatString, component, component.args());
|
||||||
|
return Component.textOfChildren(children.toArray(ComponentLike[]::new)).style(component.style());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package net.momirealms.customfishing.adventure.component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
abstract class ShadedComponentLocalizer<T> {
|
||||||
|
|
||||||
|
private static final Pattern FORMAT_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?([A-Za-z%]|$)");
|
||||||
|
|
||||||
|
private Function<String, T> componentCreator;
|
||||||
|
|
||||||
|
public ShadedComponentLocalizer(Function<String, T> componentCreator) {
|
||||||
|
this.componentCreator = componentCreator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComponentCreator(Function<String, T> componentCreator) {
|
||||||
|
this.componentCreator = componentCreator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract T localize(String lang, T component);
|
||||||
|
|
||||||
|
protected List<T> decomposeFormatString(String lang, String formatString, T component, List<T> args) {
|
||||||
|
var matcher = FORMAT_PATTERN.matcher(formatString);
|
||||||
|
|
||||||
|
var components = new ArrayList<T>();
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var nextArgIdx = 0;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
while (matcher.find(i)) {
|
||||||
|
var start = matcher.start();
|
||||||
|
var end = matcher.end();
|
||||||
|
|
||||||
|
// check for escaped %
|
||||||
|
var matchedStr = formatString.substring(i, start);
|
||||||
|
if ("%%".equals(matchedStr)) {
|
||||||
|
sb.append('%');
|
||||||
|
} else {
|
||||||
|
// check for invalid format, only %s is supported
|
||||||
|
var argType = matcher.group(2);
|
||||||
|
if (!"s".equals(argType)) {
|
||||||
|
throw new IllegalStateException("Unsupported format: '" + matchedStr + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve argument index
|
||||||
|
var argIdxStr = matcher.group(1);
|
||||||
|
var argIdx = argIdxStr == null ? nextArgIdx++ : Integer.parseInt(argIdxStr) - 1;
|
||||||
|
|
||||||
|
// validate argument index
|
||||||
|
if (argIdx < 0)
|
||||||
|
throw new IllegalStateException("Invalid argument index: " + argIdx);
|
||||||
|
|
||||||
|
// append the text before the argument
|
||||||
|
sb.append(formatString, i, start);
|
||||||
|
// add text component
|
||||||
|
components.add(componentCreator.apply(sb.toString()));
|
||||||
|
// add argument component
|
||||||
|
components.add(args.size() <= argIdx ? componentCreator.apply("") : localize(lang, args.get(argIdx)));
|
||||||
|
// clear string builder
|
||||||
|
sb.setLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start next search after matcher end index
|
||||||
|
i = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the text after the last argument
|
||||||
|
if (i < formatString.length()) {
|
||||||
|
sb.append(formatString, i, formatString.length());
|
||||||
|
components.add(componentCreator.apply(sb.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package net.momirealms.customfishing.command.sub;
|
package net.momirealms.customfishing.command.sub;
|
||||||
|
|
||||||
import dev.jorel.commandapi.CommandAPICommand;
|
import dev.jorel.commandapi.CommandAPICommand;
|
||||||
|
import net.momirealms.customfishing.api.CustomFishingPlugin;
|
||||||
|
import net.momirealms.customfishing.gui.SelectFileGUI;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class GUIEditorCommand {
|
public class GUIEditorCommand {
|
||||||
|
|
||||||
@@ -8,15 +12,8 @@ public class GUIEditorCommand {
|
|||||||
|
|
||||||
public CommandAPICommand getEditorCommand() {
|
public CommandAPICommand getEditorCommand() {
|
||||||
return new CommandAPICommand("edit")
|
return new CommandAPICommand("edit")
|
||||||
.withSubcommands(
|
.executesPlayer((player, arg) -> {
|
||||||
|
new SelectFileGUI(player, new File(CustomFishingPlugin.get().getDataFolder(), "contents"));
|
||||||
);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private CommandAPICommand getLootCommand() {
|
|
||||||
return new CommandAPICommand("loot")
|
|
||||||
.withSubcommands(
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
package net.momirealms.customfishing.gui;
|
||||||
|
|
||||||
|
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
|
||||||
|
import net.momirealms.customfishing.adventure.component.ShadedAdventureComponentWrapper;
|
||||||
|
import net.momirealms.customfishing.api.CustomFishingPlugin;
|
||||||
|
import net.momirealms.customfishing.api.util.LogUtils;
|
||||||
|
import net.momirealms.customfishing.gui.icon.BackGroundItem;
|
||||||
|
import net.momirealms.customfishing.gui.icon.BackToFolderItem;
|
||||||
|
import net.momirealms.customfishing.gui.icon.NextPageItem;
|
||||||
|
import net.momirealms.customfishing.gui.icon.PreviousPageItem;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import xyz.xenondevs.invui.gui.Gui;
|
||||||
|
import xyz.xenondevs.invui.gui.PagedGui;
|
||||||
|
import xyz.xenondevs.invui.gui.structure.Markers;
|
||||||
|
import xyz.xenondevs.invui.item.Item;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.AbstractItem;
|
||||||
|
import xyz.xenondevs.invui.item.impl.SimpleItem;
|
||||||
|
import xyz.xenondevs.invui.window.AnvilWindow;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ItemEditor {
|
||||||
|
|
||||||
|
private static final String SEARCH = "Search";
|
||||||
|
private final Player player;
|
||||||
|
private final YamlConfiguration yaml;
|
||||||
|
private String prefix;
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
public ItemEditor(Player player, File file) {
|
||||||
|
this.yaml = YamlConfiguration.loadConfiguration(file);
|
||||||
|
this.player = player;
|
||||||
|
this.file = file;
|
||||||
|
this.prefix = SEARCH;
|
||||||
|
this.reOpenWithFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reOpenWithFilter() {
|
||||||
|
Item border = new SimpleItem(new ItemBuilder(Material.AIR));
|
||||||
|
Gui upperGui = Gui.normal()
|
||||||
|
.setStructure(
|
||||||
|
"a # #"
|
||||||
|
)
|
||||||
|
.addIngredient('a', new SimpleItem(new ItemBuilder(Material.NAME_TAG).setDisplayName(prefix)))
|
||||||
|
.addIngredient('#', border)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var gui = PagedGui.items()
|
||||||
|
.setStructure(
|
||||||
|
"x x x x x x x x x",
|
||||||
|
"x x x x x x x x x",
|
||||||
|
"x x x x x x x x x",
|
||||||
|
"# # a # c # b # #"
|
||||||
|
)
|
||||||
|
.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL)
|
||||||
|
.addIngredient('#', new BackGroundItem())
|
||||||
|
.addIngredient('a', new PreviousPageItem())
|
||||||
|
.addIngredient('b', new NextPageItem())
|
||||||
|
.addIngredient('c', new BackToFolderItem(file.getParentFile()))
|
||||||
|
.setContent(getItemList())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var temp = prefix;
|
||||||
|
var window = AnvilWindow.split()
|
||||||
|
.setViewer(player)
|
||||||
|
.setTitle(new ShadedAdventureComponentWrapper(
|
||||||
|
AdventureManagerImpl.getInstance().getComponentFromMiniMessage("Select item to edit")
|
||||||
|
))
|
||||||
|
.addRenameHandler(s -> {
|
||||||
|
if (s.equals(temp)) return;
|
||||||
|
prefix = s;
|
||||||
|
reOpenWithFilter();
|
||||||
|
})
|
||||||
|
.setUpperGui(upperGui)
|
||||||
|
.setLowerGui(gui)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
window.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Item> getItemList() {
|
||||||
|
List<Item> itemList = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, Object> entry : this.yaml.getValues(false).entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
if (entry.getValue() instanceof ConfigurationSection section) {
|
||||||
|
if (!prefix.equals(SEARCH) && !entry.getKey().startsWith(prefix)) continue;
|
||||||
|
String material = section.getString("material");
|
||||||
|
if (material != null) {
|
||||||
|
if (material.contains(":")) {
|
||||||
|
ItemStack itemStack = CustomFishingPlugin.get().getItemManager().buildAnyPluginItemByID(player, material);
|
||||||
|
if (itemStack != null) {
|
||||||
|
ItemBuilder itemBuilder = new ItemBuilder(itemStack.getType());
|
||||||
|
itemBuilder.setCustomModelData(itemStack.getItemMeta().getCustomModelData());
|
||||||
|
itemBuilder.setCustomModelData(section.getInt("custom-model-data"));
|
||||||
|
itemList.add(new ItemInList(key, itemBuilder, this));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ItemBuilder itemBuilder = new ItemBuilder(Material.valueOf(material.toUpperCase(Locale.ENGLISH)));
|
||||||
|
itemBuilder.setCustomModelData(section.getInt("custom-model-data"));
|
||||||
|
itemList.add(new ItemInList(key, itemBuilder, this));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itemList.add(new ItemInList(key, new ItemBuilder(Material.STRUCTURE_VOID), this));
|
||||||
|
}
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeKey(String key) {
|
||||||
|
yaml.set(key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
yaml.save(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogUtils.warn("Failed to save file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ItemInList extends AbstractItem {
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
private final ItemBuilder itemBuilder;
|
||||||
|
private final ItemEditor itemEditor;
|
||||||
|
|
||||||
|
public ItemInList(String key, ItemBuilder itemBuilder, ItemEditor itemEditor) {
|
||||||
|
this.key = key;
|
||||||
|
this.itemBuilder = itemBuilder;
|
||||||
|
this.itemEditor = itemEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider() {
|
||||||
|
return itemBuilder.setDisplayName(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
key
|
||||||
|
))).addLoreLines(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
"<green>Left click to edit"
|
||||||
|
))).addLoreLines(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
"<red>Right click to delete"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||||
|
if (clickType.isLeftClick()) {
|
||||||
|
|
||||||
|
} else if (clickType.isRightClick()) {
|
||||||
|
this.itemEditor.removeKey(key);
|
||||||
|
this.itemEditor.save();
|
||||||
|
this.itemEditor.reOpenWithFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package net.momirealms.customfishing.gui;
|
||||||
|
|
||||||
|
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
|
||||||
|
import net.momirealms.customfishing.adventure.component.ShadedAdventureComponentWrapper;
|
||||||
|
import net.momirealms.customfishing.gui.icon.*;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import xyz.xenondevs.invui.animation.impl.SequentialAnimation;
|
||||||
|
import xyz.xenondevs.invui.gui.Gui;
|
||||||
|
import xyz.xenondevs.invui.gui.ScrollGui;
|
||||||
|
import xyz.xenondevs.invui.gui.SlotElement;
|
||||||
|
import xyz.xenondevs.invui.gui.structure.Markers;
|
||||||
|
import xyz.xenondevs.invui.item.Item;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.AbstractItem;
|
||||||
|
import xyz.xenondevs.invui.window.Window;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
|
||||||
|
public class SelectFileGUI {
|
||||||
|
|
||||||
|
public SelectFileGUI(Player player, File folder) {
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
Deque<Item> items = new ArrayDeque<>();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isFile() && file.getName().endsWith(".yml")) {
|
||||||
|
items.addLast(new FileItem(file));
|
||||||
|
} else if (file.isDirectory()) {
|
||||||
|
items.addFirst(new FolderItem(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Gui gui = ScrollGui.items()
|
||||||
|
.setStructure(
|
||||||
|
"x x x x x x x x u",
|
||||||
|
"x x x x x x x x #",
|
||||||
|
"x x x x x x x x b",
|
||||||
|
"x x x x x x x x #",
|
||||||
|
"x x x x x x x x d"
|
||||||
|
)
|
||||||
|
.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL)
|
||||||
|
.addIngredient('#', new BackGroundItem())
|
||||||
|
.addIngredient('u', new ScrollUpItem())
|
||||||
|
.addIngredient('d', new ScrollDownItem())
|
||||||
|
.addIngredient('b', new BackToFolderItem(folder.getParentFile()))
|
||||||
|
.setContent(items.stream().toList())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Window window = Window.single()
|
||||||
|
.setViewer(player)
|
||||||
|
.setTitle(new ShadedAdventureComponentWrapper(
|
||||||
|
AdventureManagerImpl.getInstance().getComponentFromMiniMessage("Select file")
|
||||||
|
))
|
||||||
|
.setGui(gui)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
gui.playAnimation(new SequentialAnimation(1, true), slotElement -> {
|
||||||
|
if (slotElement instanceof SlotElement.ItemSlotElement itemSlotElement) {
|
||||||
|
return !(itemSlotElement.getItem() instanceof Icon);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FileItem extends AbstractItem {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
public FileItem(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider() {
|
||||||
|
return new ItemBuilder(Material.PAPER).setDisplayName(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
"<#FDF5E6>" + file.getName()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||||
|
String path = file.getPath();
|
||||||
|
String[] split = path.split("\\\\");
|
||||||
|
String type = split[3];
|
||||||
|
switch (type) {
|
||||||
|
case "item" -> {
|
||||||
|
new ItemEditor(player, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FolderItem extends AbstractItem {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
public FolderItem(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider() {
|
||||||
|
return new ItemBuilder(Material.BOOK).setDisplayName(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
"<#D2B48C><b>" + file.getName()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||||
|
new SelectFileGUI(player, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.AbstractItem;
|
||||||
|
|
||||||
|
public class BackGroundItem extends AbstractItem implements Icon {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider() {
|
||||||
|
return new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
|
||||||
|
import net.momirealms.customfishing.adventure.component.ShadedAdventureComponentWrapper;
|
||||||
|
import net.momirealms.customfishing.gui.SelectFileGUI;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.AbstractItem;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BackToFolderItem extends AbstractItem implements Icon {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
public BackToFolderItem(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider() {
|
||||||
|
if (file != null && file.getPath().startsWith("plugins\\CustomFishing\\contents")) {
|
||||||
|
return new ItemBuilder(Material.ORANGE_STAINED_GLASS_PANE)
|
||||||
|
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
"<#FF8C00>Back to parent folder"
|
||||||
|
)))
|
||||||
|
.setLore(List.of(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
|
||||||
|
"<#FFA500>-> " + file.getName()
|
||||||
|
))));
|
||||||
|
} else {
|
||||||
|
return new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||||
|
if (file != null && file.getPath().startsWith("plugins\\CustomFishing\\contents"))
|
||||||
|
new SelectFileGUI(player, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
public interface Icon {
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import xyz.xenondevs.invui.gui.PagedGui;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.controlitem.PageItem;
|
||||||
|
|
||||||
|
public class NextPageItem extends PageItem implements Icon {
|
||||||
|
|
||||||
|
public NextPageItem() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider(PagedGui<?> gui) {
|
||||||
|
ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
|
||||||
|
builder.setDisplayName("§7Next page")
|
||||||
|
.addLoreLines(gui.hasNextPage()
|
||||||
|
? "§7Go to page §e" + (gui.getCurrentPage() + 2) + "§7/§e" + gui.getPageAmount()
|
||||||
|
: "§cThere are no more pages");
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import xyz.xenondevs.invui.gui.PagedGui;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.controlitem.PageItem;
|
||||||
|
|
||||||
|
public class PreviousPageItem extends PageItem implements Icon {
|
||||||
|
|
||||||
|
public PreviousPageItem() {
|
||||||
|
super(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider(PagedGui<?> gui) {
|
||||||
|
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
|
||||||
|
builder.setDisplayName("§7Previous page")
|
||||||
|
.addLoreLines(gui.hasPreviousPage()
|
||||||
|
? "§7Go to page §e" + gui.getCurrentPage() + "§7/§e" + gui.getPageAmount()
|
||||||
|
: "§cYou can't go further back");
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import xyz.xenondevs.invui.gui.ScrollGui;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.controlitem.ScrollItem;
|
||||||
|
|
||||||
|
public class ScrollDownItem extends ScrollItem implements Icon {
|
||||||
|
|
||||||
|
public ScrollDownItem() {
|
||||||
|
super(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider(ScrollGui<?> gui) {
|
||||||
|
ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
|
||||||
|
builder.setDisplayName("§7Scroll down");
|
||||||
|
if (!gui.canScroll(1))
|
||||||
|
builder.addLoreLines("§cYou can't scroll further down");
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net.momirealms.customfishing.gui.icon;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import xyz.xenondevs.invui.gui.ScrollGui;
|
||||||
|
import xyz.xenondevs.invui.item.ItemProvider;
|
||||||
|
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||||
|
import xyz.xenondevs.invui.item.impl.controlitem.ScrollItem;
|
||||||
|
|
||||||
|
public class ScrollUpItem extends ScrollItem implements Icon {
|
||||||
|
|
||||||
|
public ScrollUpItem() {
|
||||||
|
super(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemProvider getItemProvider(ScrollGui<?> gui) {
|
||||||
|
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
|
||||||
|
builder.setDisplayName("§7Scroll up");
|
||||||
|
if (!gui.canScroll(-1))
|
||||||
|
builder.addLoreLines("§cYou've reached the top");
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,6 @@ package net.momirealms.customfishing.mechanic.competition.ranking;
|
|||||||
import net.momirealms.customfishing.api.common.Pair;
|
import net.momirealms.customfishing.api.common.Pair;
|
||||||
import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer;
|
import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer;
|
||||||
import net.momirealms.customfishing.api.mechanic.competition.Ranking;
|
import net.momirealms.customfishing.api.mechanic.competition.Ranking;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import net.momirealms.customfishing.api.common.Pair;
|
|||||||
import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer;
|
import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer;
|
||||||
import net.momirealms.customfishing.api.mechanic.competition.Ranking;
|
import net.momirealms.customfishing.api.mechanic.competition.Ranking;
|
||||||
import net.momirealms.customfishing.storage.method.database.nosql.RedisManager;
|
import net.momirealms.customfishing.storage.method.database.nosql.RedisManager;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.resps.Tuple;
|
import redis.clients.jedis.resps.Tuple;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user