added settings with technicalTab toggle
This commit is contained in:
parent
c01ae32f1f
commit
70058c552d
@ -17,6 +17,7 @@ import eu.mhsl.craftattack.spawn.appliances.help.Help;
|
||||
import eu.mhsl.craftattack.spawn.appliances.playerlimit.PlayerLimit;
|
||||
import eu.mhsl.craftattack.spawn.appliances.report.Report;
|
||||
import eu.mhsl.craftattack.spawn.appliances.restart.Restart;
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||
import eu.mhsl.craftattack.spawn.appliances.tablist.Tablist;
|
||||
import eu.mhsl.craftattack.spawn.appliances.titleClear.TitleClear;
|
||||
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
|
||||
@ -59,7 +60,8 @@ public final class Main extends JavaPlugin {
|
||||
new DisplayName(),
|
||||
new Debug(),
|
||||
new Fleischerchest(),
|
||||
new CustomAdvancements()
|
||||
new CustomAdvancements(),
|
||||
new Settings()
|
||||
);
|
||||
|
||||
Bukkit.getLogger().info("Loading appliances...");
|
||||
|
@ -0,0 +1,81 @@
|
||||
package eu.mhsl.craftattack.spawn.appliances.settings;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.Setting;
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.settings.TechnicalTablistSetting;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class Settings extends Appliance {
|
||||
public enum Key {
|
||||
TechnicalTab,
|
||||
}
|
||||
|
||||
public record OpenSettingsInventory(Inventory inventory, List<Setting<?>> settings) {}
|
||||
private final WeakHashMap<Player, OpenSettingsInventory> openSettingsInventories = new WeakHashMap<>();
|
||||
private final WeakHashMap<Player, List<Setting<?>>> settingsCache = new WeakHashMap<>();
|
||||
|
||||
private List<Setting<?>> getSettings(Player player) {
|
||||
if(settingsCache.containsKey(player)) return settingsCache.get(player);
|
||||
|
||||
List<Setting<?>> settings = List.of(
|
||||
new TechnicalTablistSetting()
|
||||
);
|
||||
|
||||
settings.forEach(setting -> setting.initializeFromPlayer(player));
|
||||
this.settingsCache.put(player, settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
public <T> T getSetting(Player player, Key key, Class<T> clazz) {
|
||||
Setting<?> setting = getSettings(player).stream()
|
||||
.filter(s -> s.getKey().equals(key))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
|
||||
if(!clazz.equals(setting.dataType())) throw new IllegalStateException("Tried to retrieve Setting with Datatype " + clazz.getSimpleName() + " but expected " + setting.dataType().getSimpleName());
|
||||
if(!clazz.isInstance(setting.state())) throw new ClassCastException(clazz.getSimpleName() + " is not an instance of " + setting.dataType().getSimpleName());
|
||||
return clazz.cast(setting.state());
|
||||
}
|
||||
|
||||
public void openSettings(Player player) {
|
||||
Inventory inventory = Bukkit.createInventory(null, 9, Component.text("Einstellungen"));
|
||||
List<Setting<?>> settings = getSettings(player);
|
||||
settings.forEach(setting -> inventory.addItem(setting.buildItem()));
|
||||
player.openInventory(inventory);
|
||||
this.openSettingsInventories.put(player, new OpenSettingsInventory(inventory, settings));
|
||||
}
|
||||
|
||||
public void onSettingsClose(Player player) {
|
||||
if(!openSettingsInventories.containsKey(player)) return;
|
||||
openSettingsInventories.remove(player);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
public boolean hasSettingsOpen(Player player) {
|
||||
return this.openSettingsInventories.containsKey(player);
|
||||
}
|
||||
|
||||
public OpenSettingsInventory getOpenInventory(Player player) {
|
||||
if(!hasSettingsOpen(player)) throw new RuntimeException("Cannot retrieve data from closed Settings inventory!");
|
||||
return this.openSettingsInventories.get(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull List<Listener> eventHandlers() {
|
||||
return List.of(new SettingsInventoryListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull List<ApplianceCommand<?>> commands() {
|
||||
return List.of(new SettingsCommand());
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package eu.mhsl.craftattack.spawn.appliances.settings;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SettingsCommand extends ApplianceCommand.PlayerChecked<Settings> {
|
||||
public SettingsCommand() {
|
||||
super("settings");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
|
||||
getAppliance().openSettings(getPlayer());
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package eu.mhsl.craftattack.spawn.appliances.settings;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
public class SettingsInventoryListener extends ApplianceListener<Settings> {
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if(!getAppliance().hasSettingsOpen(player)) return;
|
||||
event.setCancelled(true);
|
||||
|
||||
Settings.OpenSettingsInventory openInventory = getAppliance().getOpenInventory(player);
|
||||
openInventory.settings().stream()
|
||||
.filter(setting -> setting.buildItem().equals(event.getCurrentItem()))
|
||||
.findFirst()
|
||||
.ifPresent(setting -> {
|
||||
setting.triggerChange(player);
|
||||
openInventory.inventory().setItem(event.getSlot(), setting.buildItem());
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
getAppliance().onSettingsClose((Player) event.getPlayer());
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package eu.mhsl.craftattack.spawn.appliances.settings.datatypes;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BoolSetting extends Setting<Boolean> {
|
||||
private boolean state;
|
||||
|
||||
public BoolSetting(Settings.Key key) {
|
||||
super(key);
|
||||
}
|
||||
|
||||
protected abstract String title();
|
||||
protected abstract String description();
|
||||
|
||||
@Override
|
||||
public void fromStorage(PersistentDataContainer container) {
|
||||
this.state = Boolean.TRUE.equals(container.get(getNamespacedKey(), PersistentDataType.BOOLEAN));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toStorage(PersistentDataContainer container, Boolean value) {
|
||||
container.set(getNamespacedKey(), PersistentDataType.BOOLEAN, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemMeta buildMeta(ItemMeta meta) {
|
||||
meta.displayName(Component.text(title(), NamedTextColor.WHITE));
|
||||
meta.lore(List.of(
|
||||
Component.empty()
|
||||
.append(Component.text("Status: ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(this.state ? "An" : "Aus", this.state ? NamedTextColor.GREEN : NamedTextColor.RED)),
|
||||
Component.empty(),
|
||||
Component.text(description(), NamedTextColor.GRAY)
|
||||
));
|
||||
return meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void change() {
|
||||
this.state = !this.state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> dataType() {
|
||||
return Boolean.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean state() {
|
||||
return state;
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package eu.mhsl.craftattack.spawn.appliances.settings.datatypes;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.Main;
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
|
||||
public abstract class Setting<TDataType> {
|
||||
private final Settings.Key key;
|
||||
|
||||
public Setting(Settings.Key key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public NamespacedKey getNamespacedKey() {
|
||||
return new NamespacedKey(Main.instance(), key.name());
|
||||
}
|
||||
|
||||
public Settings.Key getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void initializeFromPlayer(Player p) {
|
||||
fromStorage(p.getPersistentDataContainer());
|
||||
}
|
||||
|
||||
public void triggerChange(Player p) {
|
||||
this.change();
|
||||
toStorage(p.getPersistentDataContainer(), this.state());
|
||||
}
|
||||
|
||||
public ItemStack buildItem() {
|
||||
ItemStack stack = new ItemStack(icon(), 1);
|
||||
stack.setItemMeta(buildMeta(stack.getItemMeta()));
|
||||
return stack;
|
||||
}
|
||||
|
||||
protected abstract Material icon();
|
||||
public abstract ItemMeta buildMeta(ItemMeta meta);
|
||||
protected abstract void change();
|
||||
protected abstract void fromStorage(PersistentDataContainer container);
|
||||
protected abstract void toStorage(PersistentDataContainer container, TDataType value);
|
||||
public abstract Class<?> dataType();
|
||||
public abstract TDataType state();
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.BoolSetting;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class TechnicalTablistSetting extends BoolSetting {
|
||||
public TechnicalTablistSetting() {
|
||||
super(Settings.Key.TechnicalTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "Technische Informationen";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String description() {
|
||||
return "Zeige erweiterte Informationen und Statistiken in der Tabliste an";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Material icon() {
|
||||
return Material.COMMAND_BLOCK_MINECART;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.tablist;
|
||||
import eu.mhsl.craftattack.spawn.Main;
|
||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||
import eu.mhsl.craftattack.spawn.appliances.report.Report;
|
||||
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
|
||||
import eu.mhsl.craftattack.spawn.util.statistics.NetworkMonitor;
|
||||
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
|
||||
import eu.mhsl.craftattack.spawn.util.IteratorUtil;
|
||||
@ -20,7 +21,6 @@ import java.util.List;
|
||||
|
||||
|
||||
public class Tablist extends Appliance {
|
||||
private final int refreshRate = Ticks.TICKS_PER_SECOND * 3;
|
||||
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 7 ", 7, 3);
|
||||
private NetworkMonitor networkMonitor;
|
||||
|
||||
@ -30,12 +30,13 @@ public class Tablist extends Appliance {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
int tabRefreshRate = 3;
|
||||
this.networkMonitor = new NetworkMonitor(localConfig().getString("interface"), Duration.ofSeconds(1));
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||
Main.instance(),
|
||||
() -> IteratorUtil.onlinePlayers(this::updateHeader),
|
||||
refreshRate,
|
||||
refreshRate
|
||||
tabRefreshRate * Ticks.TICKS_PER_SECOND,
|
||||
tabRefreshRate * Ticks.TICKS_PER_SECOND
|
||||
);
|
||||
}
|
||||
|
||||
@ -50,17 +51,23 @@ public class Tablist extends Appliance {
|
||||
}
|
||||
|
||||
private void updateHeader(Player player) {
|
||||
player.sendPlayerListHeader(
|
||||
Component.newline()
|
||||
boolean detailedInfo = queryAppliance(Settings.class).getSetting(player, Settings.Key.TechnicalTab, Boolean.class);
|
||||
Component header = Component.newline()
|
||||
.append(serverName.getRainbowState()).appendNewline()
|
||||
.append(Component.text("mhsl.eu", NamedTextColor.GOLD)).appendNewline().appendNewline()
|
||||
.append(ComponentUtil.getFormattedMSPT()).appendNewline().appendNewline()
|
||||
.append(ComponentUtil.getFormattedTickTimes(detailedInfo)).appendNewline();
|
||||
|
||||
if(detailedInfo) {
|
||||
header = header
|
||||
.appendNewline()
|
||||
.append(ComponentUtil.getFormattedPing(player)).appendNewline()
|
||||
.append(ComponentUtil.getFormattedNetworkStats(
|
||||
this.networkMonitor.getTraffic(),
|
||||
this.networkMonitor.getPackets())
|
||||
).appendNewline()
|
||||
);
|
||||
).appendNewline();
|
||||
}
|
||||
|
||||
player.sendPlayerListHeader(header);
|
||||
}
|
||||
|
||||
private void updateFooter(Player player) {
|
||||
|
@ -2,6 +2,8 @@ package eu.mhsl.craftattack.spawn.util.text;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.util.statistics.NetworkMonitor;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentBuilder;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -39,7 +41,7 @@ public class ComponentUtil {
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Component getFormattedMSPT() {
|
||||
public static Component getFormattedTickTimes(boolean detailed) {
|
||||
long[] times = Bukkit.getServer().getTickTimes();
|
||||
float mspt = ((float) Arrays.stream(times).sum() / times.length) * 1.0E-6f;
|
||||
float roundedMspt = Math.round(mspt * 100f) / 100f;
|
||||
@ -50,12 +52,18 @@ public class ComponentUtil {
|
||||
TextColor percentageColor = ColorUtil.mapGreenToRed(loadPercentage, 80, 100, true);
|
||||
TextColor tpsColor = ColorUtil.mapGreenToRed(roundedTPS, 15, 20, false);
|
||||
|
||||
return Component.text()
|
||||
ComponentBuilder<TextComponent, TextComponent.Builder> tickTimes = Component.text()
|
||||
.append(Component.text("Serverlast: ", NamedTextColor.GRAY))
|
||||
.append(Component.text(loadPercentage + "% ", percentageColor))
|
||||
.appendNewline()
|
||||
.appendNewline();
|
||||
|
||||
if(detailed) {
|
||||
tickTimes
|
||||
.append(Component.text(roundedMspt + "mspt", msptColor))
|
||||
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||
.append(Component.text(" | ", NamedTextColor.GRAY));
|
||||
}
|
||||
|
||||
return tickTimes
|
||||
.append(Component.text(roundedTPS + "tps", tpsColor))
|
||||
.build();
|
||||
}
|
||||
|
@ -36,3 +36,4 @@ commands:
|
||||
kick:
|
||||
panicBan:
|
||||
vogelfrei:
|
||||
settings:
|
Loading…
x
Reference in New Issue
Block a user