SteamWar/SpigotCore
Archiviert
13
0

Add SchematicSelector #132

Zusammengeführt
Lixfel hat 16 Commits von schematic_selector nach master 2021-12-02 08:38:43 +01:00 zusammengeführt
4 geänderte Dateien mit 577 neuen und 0 gelöschten Zeilen
Nur Änderungen aus Commit 22df0035c4 werden angezeigt - Alle Commits anzeigen

Datei anzeigen

@ -0,0 +1,438 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2021 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.util;
import com.google.common.collect.Lists;
import de.steamwar.inventory.*;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType;
import de.steamwar.sql.SteamwarUser;
import lombok.*;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class SchematicSelector {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

M U L T I L I N G

M U L T I L I N G
@Getter
private final Player player;
@Getter
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Warum public?

Warum public?
private final SteamwarUser user;
@Getter
private final Consumer<SchematicNode> callback;
@Getter
private final SelectorTarget target;
@Getter
private final SelectorFilter filter = new SelectorFilter();
private SchematicSelectorInjectable injectable;
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Getter macht keinen Sinn, keine Klasse außerhalb kann ohne Reflections auf Parameter von SelectorTarget zugreifen.

Getter macht keinen Sinn, keine Klasse außerhalb kann ohne Reflections auf Parameter von SelectorTarget zugreifen.
private boolean useHooks;
@Setter
@Getter
private PublicMode publicMode = PublicMode.ALL;
@Setter
@Getter
private String title = "{0} auswahl: {1}";
@Setter
@Getter
private boolean singleDirOpen;
public SchematicSelector(Player player, SelectorTarget target, Consumer<SchematicNode> callback) {
this.player = player;
this.user = SteamwarUser.get(player.getUniqueId());
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Hast du für solche Sachen nicht eigentlich den SchematicSelectorInjectable?

Hast du für solche Sachen nicht eigentlich den SchematicSelectorInjectable?
this.target = target;
this.callback = callback;
this.singleDirOpen = !target.target.isDirs();
}
public SchematicSelector(Player player, SelectorTarget target, SchematicSelectorInjectable injectable, Consumer<SchematicNode> callback) {
this(player, target, callback);
this.useHooks = true;
this.injectable = injectable;
}
public void open() {
if(useHooks) {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

useHooks ist eine ganz schlechte Variable, weil du dafür, dass du diese Variable hast, jede menge ifs zur Verhaltensänderung brauchst. Wie wäre es damit, immer einen default-SchematicSelectorInjectable zu instanziieren? Dann brauchst du kein useHooks und kannst dir auch die ganzen ifs sparen.

useHooks ist eine ganz schlechte Variable, weil du dafür, dass du diese Variable hast, jede menge ifs zur Verhaltensänderung brauchst. Wie wäre es damit, immer einen default-SchematicSelectorInjectable zu instanziieren? Dann brauchst du kein useHooks und kannst dir auch die ganzen ifs sparen.
injectable.onSelectorCreate(this);
}
openList(null, publicMode == PublicMode.PUBLIC_ONLY);
}
private void openList(SchematicNode parent, boolean publics) {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Könntest du evtl die Megamethoden in kleinere Methoden aufteilen, damit man einen besseren Überblick hat? Und ggf. schauen, ob man nicht noch etwas vereinfachen kann.

Könntest du evtl die Megamethoden in kleinere Methoden aufteilen, damit man einen besseren Überblick hat? Und ggf. schauen, ob man nicht noch etwas vereinfachen kann.
List<SchematicNode> nodes = new ArrayList<>();
if(filter.isFilter()) {
nodes.addAll(SchematicNode.getAllSchematicsAccessibleByUser(publics?0:user.getId()));
nodes.removeIf(node -> {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Statt überall publics als Parameter durchzutragen: Wie wäre es damit, im Falle einer Publicauflistung den SteamwarUser auf Public (aka id 0) zu setzen? Ein Parameter und viele Fallunterscheidungen weniger, oder?

Statt überall publics als Parameter durchzutragen: Wie wäre es damit, im Falle einer Publicauflistung den SteamwarUser auf Public (aka id 0) zu setzen? Ein Parameter und viele Fallunterscheidungen weniger, oder?
if(useHooks) {
Veraltet
Review

Warum hier unterscheiden und nicht vereinfachen, indem immer gefiltert (ggf. mit leerem Filter) wird?

Warum hier unterscheiden und nicht vereinfachen, indem immer gefiltert (ggf. mit leerem Filter) wird?
Veraltet
Review

Beim Filtern werden Alle Schematics gefiltert, was es etwas unnötig machen würde für normales anzeigen von Ordnern, alle Schematics zu laden.

Beim Filtern werden Alle Schematics gefiltert, was es etwas unnötig machen würde für normales anzeigen von Ordnern, alle Schematics zu laden.
injectable.onNodeFilter(this, node);
}
return !filter.matches(node);
});
if(target.target == SelectorTarget.Target.DIRECTORY) {
nodes.removeIf(node -> !node.isDir());
}
if(target.target == SelectorTarget.Target.SCHEMATIC_TYPE) {
nodes.removeIf(node -> node.isDir() || !node.getType().equals(target.type.toDB()));
}
} else {
switch (target.target) {
case DIRECTORY:
if(parent == null) {
nodes.addAll(SchematicNode.getSchematicsAccessibleByUser(publics?0:user.getId(), null));
nodes.removeIf(node -> !node.isDir());
} else {
nodes.addAll(SchematicNode.getSchematicDirectoryInNode(parent.getId()));
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Statt title==null? evtl. title defaultmäßig = () -> DEFAULT_TITLE; setzen?

Statt title==null? evtl. title defaultmäßig = () -> DEFAULT_TITLE; setzen?
}
break;
case SCHEMATIC_TYPE:
nodes.addAll(SchematicNode.getAccessibleSchematicsOfTypeInParent(publics?0:user.getId(), target.type.toDB(), parent==null?0:parent.getId()));
if(target.rank >= 0) {
nodes.removeIf(node -> node.getRank() > target.rank);
}
break;
default:
nodes.addAll(SchematicNode.getSchematicsAccessibleByUser(publics?0:user.getId(), parent == null?0:parent.getId()));
}
if(singleDirOpen && nodes.size() == 1 && nodes.get(0).isDir()) {
openList(nodes.get(0), publics);
return;
}
}
List<SWListInv.SWListEntry<SchematicNode>> list = new ArrayList<>();
if(parent != null) {
list.add(new SWListInv.SWListEntry<>(new SWItem(Material.ARROW, "§eZurück", clickType -> {}), null));
}
for (SchematicNode node : nodes) {
if(node.getName().equals("//copy")) continue;
Material m;
if (node.getItem().isEmpty())
m = node.isDir()?SWItem.getMaterial("CHEST"):SWItem.getMaterial("CAULDRON_ITEM");
else
m = SWItem.getMaterial(node.getItem());
String name = "§" + (filter.getName().isEmpty()?"e":"7") + node.getName();
if(!filter.getName().isEmpty()) {
name = name.replace(filter.getName(), "§e" + filter.getName() + "§7");
}
SWItem item = new SWItem(m, name, Collections.singletonList(node.isDir() ? "§9Ordner" : "§7" + node.getSchemtype().name()), !node.isDir() && !node.getSchemtype().writeable(), click -> {
});
if(!node.isDir()) {
if(node.getRank() > 0)
item.setLore(Lists.newArrayList("§7" + node.getSchemtype().name(), "§8Rang " + node.getRank()));
}
list.add(new SWListInv.SWListEntry<>(item, node));
}
SWListInv<SchematicNode> inv = new SWListInv<>(player, MessageFormat.format(title, target.target.getName(), filter.getName().isEmpty()?(parent == null?"/":parent.generateBreadcrumbs(user)):filter.getName()), false, list, (clickType, node) -> {
if(node == null) {
openList(getParent(parent), publics);
return;
}
if(node.isDir()) {
if(filter.isFilter() && target.target.isDirs()) {
player.closeInventory();
callback.accept(node);
return;
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Eigentlich gehören auch ColorCodes in die Messages mit rein... Weil du kannst dir nicht sicher sein, dass die Farbe in einem anderen Kulturraum nicht eine andere Bedeutung hat...

Eigentlich gehören auch ColorCodes in die Messages mit rein... Weil du kannst dir nicht sicher sein, dass die Farbe in einem anderen Kulturraum nicht eine andere Bedeutung hat...
}
filter.reset();
openList(node, publics);
return;
}
player.closeInventory();
callback.accept(node);
});
if(publicMode == PublicMode.ALL) {
if(publics) {
inv.setItem(48, Material.BUCKET, "§7Eigene Schematics", clickType -> openList(null, false));
} else {
inv.setItem(48, Material.GLASS, "§7Public Schematics", clickType -> openList(null, true));
}
}
if(target.target.isDirs()) {
inv.setItem(49, SWItem.getDye(10), "§7Ordner auswählen", clickType -> {
player.closeInventory();
callback.accept(parent);
});
}
if(!publics) {
inv.setItem(50, Material.CHEST, "§7Neuer Ordner", clickType -> createFolderIn(parent));
}
inv.setItem(51, Material.NAME_TAG, "§7Filter", clickType -> openFilter(publics));
if(useHooks) {
injectable.onListRender(this, inv, parent);
}
inv.open();
}
private void createFolderIn(SchematicNode parent) {
SWAnvilInv inv = new SWAnvilInv(player, "Ordner Erstellen");
inv.setItem(Material.CHEST);
inv.setCallback(s -> {
if(useHooks) {
if(injectable.onFolderCreate(this, s)) {
SchematicNode.createSchematicDirectory(user.getId(), s, parent==null?0:parent.getId());
openList(parent, false);
}
} else {
SchematicNode.createSchematicDirectory(user.getId(), s, parent==null?0:parent.getId());
openList(parent, false);
}
});
inv.open();
}
private void openFilter(boolean publics) {
Lixfel markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Ich würde evtl. nur einen Filter/eine Suche anbieten, welche dafür sowohl nach passenden Besitzern, Namen, Typen und Items zeitgleich durchsucht. Das dürfte für 99% aller Useranfragen völlig gleichwertig sein und den Usern stets einen Klick ersparen.

Ich würde evtl. nur einen Filter/eine Suche anbieten, welche dafür sowohl nach passenden Besitzern, Namen, Typen und Items zeitgleich durchsucht. Das dürfte für 99% aller Useranfragen völlig gleichwertig sein und den Usern stets einen Klick ersparen.
SWInventory inv = new SWInventory(player, 9, "Filter");
InvCallback nameCallback = clickType -> {
if(clickType.isRightClick()) {
filter.setName("");
openFilter(publics);
} else {
SWAnvilInv swAnvilInv = new SWAnvilInv(player, "Name eingeben");
swAnvilInv.setItem(Material.NAME_TAG);
swAnvilInv.setCallback(s -> {
filter.setName(s);
openFilter(publics);
});
swAnvilInv.open();
}
};
if(filter.getName().isEmpty()) {
inv.setItem(0, Material.NAME_TAG, "§7Nach namen suchen...", nameCallback);
} else {
inv.setItem(0, Material.NAME_TAG, "§7Nach namen suchen...", Collections.singletonList("§7Suchwort: §e" + filter.getName()), true, nameCallback);
}
InvCallback ownerCallback = clickType -> {
if(clickType.isRightClick()) {
filter.setOwner(null);
openFilter(publics);
} else {
SWAnvilInv swAnvilInv = new SWAnvilInv(player, "Besitzer eingeben");
swAnvilInv.setItem(Material.PLAYER_HEAD);
swAnvilInv.setCallback(s -> {
filter.setOwner(SteamwarUser.get(s).getId());
openFilter(publics);
});
swAnvilInv.open();
}
};
if(filter.getOwner() == null) {
inv.setItem(1, Material.PLAYER_HEAD, "§7Nach Besitzer suchen...", ownerCallback);
} else {
SteamwarUser user = SteamwarUser.get(filter.getOwner());
SWItem item = SWItem.getPlayerSkull(user.getUserName());
item.setName("§7Nach Besitzer suchen...");
item.setEnchanted(true);
item.setLore(Collections.singletonList("§7Besitzer: §e" + user.getUserName()));
item.setCallback(ownerCallback);
inv.setItem(1, item);
}
if(target.target != SelectorTarget.Target.SCHEMATIC_TYPE) {
InvCallback schemTypeCallback = clickType -> {
if(clickType.isRightClick()) {
filter.setType(null);
openFilter(publics);
} else {
List<SWListInv.SWListEntry<SchematicType>> types = new ArrayList<>();
SchematicType.values().forEach(schematicType -> {
types.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial("STONE_BUTTON"), "§e" + schematicType.name(), Collections.emptyList(), schematicType.fightType(), n -> {}), schematicType));
});
SWListInv<SchematicType> listInv = new SWListInv<>(player, "Typ wählen...", types, (clickType1, schematicType) -> {
filter.setType(schematicType);
openFilter(publics);
});
listInv.open();
}
};
if(filter.getType() == null) {
inv.setItem(2, SWItem.getMaterial("STONE_BUTTON"), "§7Nach Typ Filtern...", schemTypeCallback);
} else {
inv.setItem(2, SWItem.getMaterial("STONE_BUTTON"), "§7Nach Typ Filtern...", Collections.singletonList("§7Typ: §e" + filter.getType().name()), true, schemTypeCallback);
}
}
InvCallback materialCallback = clickType -> {
if(clickType.isRightClick()) {
filter.setItem(null);
openFilter(publics);
} else {
UtilGui.openMaterialSelector(player, material -> {
filter.setItem(material);
openFilter(publics);
});
}
};
final int iSlot = target.target== SelectorTarget.Target.SCHEMATIC_TYPE?2:3;
if(filter.getItem() == null) {
inv.setItem(iSlot, Material.STONE, "§7Nach Item Filtern...", materialCallback);
} else {
inv.setItem(iSlot, filter.getItem(), "§7Nach Item Filtern...", Collections.singletonList("§7Item: §e" + filter.getItem().name()), true, materialCallback);
}
inv.setItem(7, SWItem.getDye(1), "§eAbbrechen", clickType -> {
filter.reset();
openList(null, publics);
});
inv.setItem(8, SWItem.getDye(10), "§eSuchen...", clickType -> {
filter.setFilter(true);
if(useHooks) {
injectable.onFilterApply(this);
}
openList(null, publics);
});
if(useHooks) {
injectable.onFilterRender(this, inv);
}
inv.open();
}
private static SchematicNode getParent(SchematicNode node) {
if(node.getParent() == null) {
return null;
}
return node.getParentNode();
}
public static SelectorTarget selectSchematic() {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Wenn diese Funktionen public sind, sollte auch SelectorTarget public sein

Wenn diese Funktionen public sind, sollte auch SelectorTarget public sein
return new SelectorTarget(SelectorTarget.Target.SCHEMATIC, null, -1);
}
public static SelectorTarget selectDirectory() {
return new SelectorTarget(SelectorTarget.Target.DIRECTORY, null, -1);
}
public static SelectorTarget selectSchematicNode() {
return new SelectorTarget(SelectorTarget.Target.SCHEMATIC_NODE, null, -1);
}
public static SelectorTarget selectSchematicType(SchematicType type) {
return new SelectorTarget(SelectorTarget.Target.SCHEMATIC_TYPE, type, -1);
}
public static SelectorTarget selectSchematicTypeWithRank(SchematicType type, int rank) {
return new SelectorTarget(SelectorTarget.Target.SCHEMATIC_TYPE, type, rank);
}
private static class SelectorTarget {
private final Target target;
private final SchematicType type;
private final int rank;
private SelectorTarget(Target target, SchematicType type, int rank) {
this.target = target;
this.type = type;
this.rank = rank;
}
@AllArgsConstructor
private enum Target {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Klasse in der Klasse der Klasse? :/

Klasse in der Klasse der Klasse? :/
SCHEMATIC("Schematic", false),
DIRECTORY("Ordner", true),
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Multiling.

Multiling.
SCHEMATIC_NODE("Schematic/Ordner", true),
SCHEMATIC_TYPE("Schematic", false);
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Dopplung von SCHEMATIC?

Dopplung von SCHEMATIC?
@Getter
private String name;
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Nachdem alles private im Inneren ist, macht das keinerlei Sinn, das public zu stellen

Nachdem alles private im Inneren ist, macht das keinerlei Sinn, das public zu stellen
@Getter
private boolean dirs;
}
}
@NoArgsConstructor
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Hast du hierfür nicht deinen schönen @AllArgsConstructor?

Hast du hierfür nicht deinen schönen @AllArgsConstructor?
@Getter
@Setter
public static class SelectorFilter {
private boolean filter;
private String name = "";
private Integer owner = null;
private SchematicType type = null;
private Material item = null;
public void reset() {
name = "";
owner = null;
type = null;
item = null;
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Die Klasse ist private. Wozu getter?

Die Klasse ist private. Wozu getter?
filter = false;
}
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Klasse private, wozu public?

Klasse private, wozu public?
public boolean matches(SchematicNode node) {
boolean matches = true;
if(!name.isEmpty()) {
if(!node.getName().contains(name)) {
matches = false;
}
}
if(owner != null) {
if(node.getOwner() != owner) {
matches = false;
}
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Warum bei name mit "", bei allen anderen Werten aber mit null?

Warum bei name mit "", bei allen anderen Werten aber mit null?
}
if(type != null) {
if(node.isDir() || !node.getType().equals(type.toDB())) {
matches = false;
}
}
if(item != null) {
String i;
if(node.getItem().isEmpty()) {
i = node.isDir()?"CHEST":"CAULDRON";
} else {
i = node.getItem();
}
if(!item.name().equals(i)) {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Bitte die geschachtelten ifs zusammenfassen.

Bitte die geschachtelten ifs zusammenfassen.
matches = false;
}
}
return matches;
}
}
public enum PublicMode {
ALL,
PRIVATE_ONLY,
PUBLIC_ONLY
}
}

Datei anzeigen

@ -0,0 +1,39 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2021 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.util;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWListInv;
import de.steamwar.sql.SchematicNode;
public interface SchematicSelectorInjectable {
void onSelectorCreate(SchematicSelector selector);
void onListRender(SchematicSelector selector, SWListInv<SchematicNode> inv, SchematicNode parent);
void onFilterRender(SchematicSelector selector, SWInventory inventory);
void onFilterApply(SchematicSelector selector);
boolean onFolderCreate(SchematicSelector selector, String name);
void onNodeFilter(SchematicSelector selector, SchematicNode node);
}

Datei anzeigen

@ -0,0 +1,47 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2021 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.util;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWListInv;
import de.steamwar.sql.SchematicNode;
import org.bukkit.entity.Player;
public abstract class SchematicSelectorInjectableAdapter implements SchematicSelectorInjectable {
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Oh je. Jetzt wird das langsam wirklich BigCorporationJavaClassFactory.

Oh je. Jetzt wird das langsam wirklich BigCorporationJavaClassFactory.
Veraltet
Review

Ok, statt das so zu machen: Mach lieber im SchematicSelectorInjectable jede Funktion mit default void ... Default-Implementierungen, dann brauchst du keine separate abstract Class dafür...

Ok, statt das so zu machen: Mach lieber im SchematicSelectorInjectable jede Funktion mit default void ... Default-Implementierungen, dann brauchst du keine separate abstract Class dafür...
@Override
public void onSelectorCreate(SchematicSelector selector) {}
@Override
public void onListRender(SchematicSelector selector, SWListInv<SchematicNode> inv, SchematicNode parent) {}
@Override
public void onFilterRender(SchematicSelector selector, SWInventory inventory) {}
@Override
public void onFilterApply(SchematicSelector selector) {}
@Override
public boolean onFolderCreate(SchematicSelector selector, String name) {
return true;
}
@Override
public void onNodeFilter(SchematicSelector selector, SchematicNode node) {}
}

Datei anzeigen

@ -0,0 +1,53 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2021 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.util;
import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
@UtilityClass
public class UtilGui {
public static void openMaterialSelector(Player player, Consumer<Material> callback) {
openMaterialSelector(player, "Material auswählen", callback);
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Multiling?

Multiling?
}
public static void openMaterialSelector(Player player, String title, Consumer<Material> callback) {
List<SWListInv.SWListEntry<Material>> materials = new LinkedList<>();
for(Material material : Material.values()){
if(material.name().startsWith(Material.LEGACY_PREFIX))
continue;
SWItem item = new SWItem(material, "§7" + material.name());
Chaoscaot markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Multling? (Es müsste theoretisch möglich sein, dem Minecraft-Client das Material so zu übergeben, dass der Client das selbst übersetzt)

Multling? (Es müsste theoretisch möglich sein, dem Minecraft-Client das Material so zu übergeben, dass der Client das selbst übersetzt)
if(item.getItemMeta() != null && material.isItem()) {
materials.add(new SWListInv.SWListEntry<>(item, material));
}
}
SWListInv<Material> swListInv = new SWListInv<>(player, title, materials, (clickType3, material) -> callback.accept(material));
swListInv.open();
}
}