diff --git a/SpigotCore_Main/src/SpigotCore.properties b/SpigotCore_Main/src/SpigotCore.properties index e36969f..28628df 100644 --- a/SpigotCore_Main/src/SpigotCore.properties +++ b/SpigotCore_Main/src/SpigotCore.properties @@ -26,6 +26,14 @@ SCHEM_SELECTOR_PUB= SCHEM_SELECTOR_SEL_DIR=§7Ordner auswählen SCHEM_SELECTOR_NEW_DIR=§7Neuer Ordner SCHEM_SELECTOR_FILTER=§7Filter +SCHEM_SELECTOR_SORTING=§7Sortierung +SCHEM_SELECTOR_SORTING_CURRENT=§7Aktuell: §e{0} +SCHEM_SELECTOR_SORTING_NAME=Name +SCHEM_SELECTOR_SORTING_TYPE=Schematic-Typ +SCHEM_SELECTOR_SORTING_UPDATE=Letztes Update +SCHEM_SELECTOR_SORTING_DIRECTION=§7Richtung: §e{0} +SCHEM_SELECTOR_SORTING_ASC=Aufsteigend +SCHEM_SELECTOR_SORTING_DSC=Absteigend SCHEM_SELECTOR_ITEM_NAME=§e{0} SCHEM_SELECTOR_ITEM_NAME_FILTER=§7{0} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index e2a8f01..1783303 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -332,6 +332,6 @@ public abstract class SWCommand { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) protected @interface StaticValue { - String value(); + String[] value() default {}; } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 98ddcf6..dbe616a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -163,8 +163,9 @@ public class SWCommandUtils { GUARD_FUNCTIONS.putIfAbsent(name, guardChecker); } - public static TypeMapper createMapper(String value) { - return createMapper((s) -> value.equals(s) ? value : null, s -> Collections.singletonList(value)); + public static TypeMapper createMapper(String... values) { + List strings = Arrays.asList(values); + return createMapper((s) -> strings.contains(s) ? s : null, s -> strings); } public static TypeMapper createMapper(Function mapper, Function> tabCompleter) { diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 0db26e8..997cdea 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -45,7 +45,7 @@ class SubCommand { GuardChecker guardChecker; Class varArgType = null; private boolean help; - boolean noTabComplete = false; + boolean noTabComplete; SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker, boolean help, String[] description, boolean noTabComplete) { this.swCommand = swCommand; @@ -71,7 +71,8 @@ class SubCommand { } SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); - if (clazz.isEnum() && mapper == null && !MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) { + SWCommand.ClassMapper classMapper = parameter.getAnnotation(SWCommand.ClassMapper.class); + if (clazz.isEnum() && mapper == null && classMapper == null && !MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) { Class> enumClass = (Class>) clazz; List tabCompletes = new ArrayList<>(); for (Enum enumConstant : enumClass.getEnumConstants()) { @@ -82,7 +83,9 @@ class SubCommand { } String name = clazz.getTypeName(); - if (mapper != null) { + if (classMapper != null) { + name = classMapper.value().getTypeName(); + } else if (mapper != null) { name = mapper.value(); } else { SWCommand.StaticValue staticValue = parameter.getAnnotation(SWCommand.StaticValue.class); @@ -100,6 +103,21 @@ class SubCommand { } private GuardChecker getGuardChecker(Parameter parameter, Map localGuardChecker) { + SWCommand.ClassGuard classGuard = parameter.getAnnotation(SWCommand.ClassGuard.class); + if (classGuard != null) { + if (classGuard.value() == null) { + String s = parameter.getType().getTypeName(); + if (parameter.isVarArgs()) { + s = parameter.getType().getComponentType().getTypeName(); + } + return localGuardChecker.getOrDefault(s, GUARD_FUNCTIONS.getOrDefault(s, null)); + } + GuardChecker current = localGuardChecker.getOrDefault(classGuard.value().getTypeName(), GUARD_FUNCTIONS.getOrDefault(classGuard.value().getTypeName(), null)); + if (current == null) { + Bukkit.getLogger().log(Level.WARNING, () -> "The guard checker with name '" + classGuard.value().getTypeName() + "' is neither a local guard checker nor a global one"); + } + return current; + } SWCommand.Guard guard = parameter.getAnnotation(SWCommand.Guard.class); if (guard != null) { if (guard.value() == null || guard.value().isEmpty()) { diff --git a/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java index ca508f6..1b22d4d 100644 --- a/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java +++ b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java @@ -29,14 +29,13 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.function.Consumer; public class SchematicSelector { + private static final Sorting[] all_sortings = Sorting.values(); + @Getter private final Player player; @Getter @@ -57,6 +56,8 @@ public class SchematicSelector { @Getter @Setter private int depth = 0; + private Sorting sorting = Sorting.NAME; + private boolean invertSorting = false; public SchematicSelector(Player player, SelectorTarget target, Consumer callback) { this.player = player; @@ -80,7 +81,7 @@ public class SchematicSelector { } private void openList(SchematicNode parent) { - List nodes = filter.isFilter()?getFilteredSchematics():getSchematicList(parent); + List nodes = applySorting(filter.isFilter()?getFilteredSchematics():getSchematicList(parent)); if(sdoTrigger) { sdoTrigger = false; @@ -123,6 +124,17 @@ public class SchematicSelector { inv.setItem(50, Material.CHEST, Core.MESSAGE.parse("SCHEM_SELECTOR_NEW_DIR", player), clickType -> createFolderIn(parent)); } inv.setItem(51, Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER", player), clickType -> openFilter()); + inv.setItem(47, sorting.mat, Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING", player), List.of( + Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING_CURRENT", player, sorting.parseName(player)), + Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING_DIRECTION", player, Core.MESSAGE.parse(invertSorting?"SCHEM_SELECTOR_SORTING_DSC":"SCHEM_SELECTOR_SORTING_ASC", player)) + ), invertSorting, click -> { + if(click.isLeftClick()) { + cycleSorting(); + } else { + invertSorting = !invertSorting; + } + openList(parent); + }); injectable.onListRender(this, inv, parent); inv.open(); @@ -173,6 +185,28 @@ public class SchematicSelector { callback.accept(node); } + private void cycleSorting() { + int next = sorting.ordinal() + 1; + if(next >= all_sortings.length) { + next = 0; + } + sorting = all_sortings[next]; + } + + private List applySorting(List nodes) { + if(sorting == Sorting.NAME && !invertSorting) { + return nodes; + } + + Comparator comparator = sorting.comparator; + if(invertSorting) { + comparator = comparator.reversed(); + } + + nodes.sort(comparator); + return nodes; + } + private SWListInv.SWListEntry renderItem(SchematicNode node) { Material m = SWItem.getMaterial(node.getItem()); @@ -399,8 +433,8 @@ public class SchematicSelector { SCHEMATIC_NODE("SCHEM_SELECTOR_SCHEMATIC_NODE", true), SCHEMATIC_TYPE("SCHEM_SELECTOR_SCHEMATIC", false); - private String rawName; - private boolean dirs; + private final String rawName; + private final boolean dirs; private String getName(Player player) { return Core.MESSAGE.parse(rawName, player); @@ -461,4 +495,25 @@ public class SchematicSelector { PRIVATE_ONLY, PUBLIC_ONLY } + + @AllArgsConstructor + private enum Sorting { + NAME(Material.PAPER, "SCHEM_SELECTOR_SORTING_NAME", Comparator.comparing(SchematicNode::getName)), + TYPE(Material.CAULDRON, "SCHEM_SELECTOR_SORTING_TYPE", (o1, o2) -> { + if(o1.isDir() || o2.isDir()) { + return Boolean.compare(o1.isDir(), o2.isDir()); + } else { + return o1.getSchemtype().name().compareTo(o2.getSchemtype().name()); + } + }), + LAST_UPDATED(Material.CLOCK, "SCHEM_SELECTOR_SORTING_UPDATE", Comparator.comparing(SchematicNode::getLastUpdate)); + + private final Material mat; + private final String name; + private final Comparator comparator; + + private String parseName(Player player) { + return Core.MESSAGE.parse(name, player); + } + } }