mirror of
https://github.com/plexusorg/Plex.git
synced 2026-07-14 21:44:55 +00:00
Updater improvements, toggle pvp, Dialog API
This commit is contained in:
@@ -3,6 +3,7 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val paperApiVersion = "26.1.2"
|
val paperApiVersion = "26.1.2"
|
||||||
|
val supportedMinecraftVersions = listOf("26.1", "26.1.1", "26.1.2", "26.2")
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
@@ -132,7 +133,7 @@ tasks {
|
|||||||
property("buildNumber", if (System.getenv("BUILD_NUMBER") != null) System.getenv("BUILD_NUMBER") else getBuildNumber())
|
property("buildNumber", if (System.getenv("BUILD_NUMBER") != null) System.getenv("BUILD_NUMBER") else getBuildNumber())
|
||||||
property("date", SimpleDateFormat("MM/dd/yyyy '<light_purple>at<gold>' hh:mm:ss a z").format(Date()))
|
property("date", SimpleDateFormat("MM/dd/yyyy '<light_purple>at<gold>' hh:mm:ss a z").format(Date()))
|
||||||
property("gitCommit", indraGit.commit().get().name)
|
property("gitCommit", indraGit.commit().get().name)
|
||||||
property("minecraftVersion", paperApiVersion)
|
property("minecraftVersion", supportedMinecraftVersions.joinToString(","))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|||||||
import dev.plex.command.ServerCommand;
|
import dev.plex.command.ServerCommand;
|
||||||
import dev.plex.command.ServerCommandContext;
|
import dev.plex.command.ServerCommandContext;
|
||||||
import dev.plex.command.exception.CommandFailException;
|
import dev.plex.command.exception.CommandFailException;
|
||||||
import dev.plex.menu.impl.MaterialMenu;
|
import dev.plex.menu.dialog.MaterialDialog;
|
||||||
import dev.plex.util.GameRuleUtil;
|
import dev.plex.util.GameRuleUtil;
|
||||||
import dev.plex.util.PlexLog;
|
import dev.plex.util.PlexLog;
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ public class DebugCMD extends ServerCommand
|
|||||||
{
|
{
|
||||||
return context.messageComponent("noPermissionConsole");
|
return context.messageComponent("noPermissionConsole");
|
||||||
}
|
}
|
||||||
new MaterialMenu().open(playerSender);
|
new MaterialDialog().open(playerSender);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return context.usage();
|
return context.usage();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import dev.plex.util.BuildInfo;
|
|||||||
import dev.plex.util.PlexLog;
|
import dev.plex.util.PlexLog;
|
||||||
import dev.plex.util.PlexUtils;
|
import dev.plex.util.PlexUtils;
|
||||||
import dev.plex.util.TimeUtils;
|
import dev.plex.util.TimeUtils;
|
||||||
|
import dev.plex.util.UpdateChecker;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -18,6 +19,7 @@ import io.papermc.paper.command.brigadier.CommandSourceStack;
|
|||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class PlexCMD extends ServerCommand
|
public class PlexCMD extends ServerCommand
|
||||||
@@ -69,7 +71,7 @@ public class PlexCMD extends ServerCommand
|
|||||||
context.send(sender, context.mmString("<light_purple>Authors: <gold>Telesphoreo, Taahh"));
|
context.send(sender, context.mmString("<light_purple>Authors: <gold>Telesphoreo, Taahh"));
|
||||||
context.send(sender, context.mmString("<light_purple>Built by: <gold>" + BuildInfo.getAuthor() + " <light_purple>on <gold>" + BuildInfo.getDate()));
|
context.send(sender, context.mmString("<light_purple>Built by: <gold>" + BuildInfo.getAuthor() + " <light_purple>on <gold>" + BuildInfo.getDate()));
|
||||||
context.send(sender, context.mmString("<light_purple>Run <gold>/plex modules <light_purple>to see a list of modules."));
|
context.send(sender, context.mmString("<light_purple>Run <gold>/plex modules <light_purple>to see a list of modules."));
|
||||||
plugin.getUpdateChecker().getUpdateStatusMessage(sender, true, 2);
|
plugin.getApi().scheduler().runAsync(() -> plugin.getUpdateChecker().getUpdateStatusMessage(sender, true, 2));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (args[0].equalsIgnoreCase("reload"))
|
if (args[0].equalsIgnoreCase("reload"))
|
||||||
@@ -111,12 +113,19 @@ public class PlexCMD extends ServerCommand
|
|||||||
else if (args[1].equalsIgnoreCase("update"))
|
else if (args[1].equalsIgnoreCase("update"))
|
||||||
{
|
{
|
||||||
context.checkPermission(sender, "plex.modules.update");
|
context.checkPermission(sender, "plex.modules.update");
|
||||||
for (PlexModule module : plugin.getModuleManager().getModules())
|
plugin.getApi().scheduler().runAsync(() ->
|
||||||
{
|
{
|
||||||
plugin.getUpdateChecker().updateModuleJar(sender, module);
|
for (PlexModule module : plugin.getModuleManager().getModules())
|
||||||
}
|
{
|
||||||
plugin.getModuleManager().reloadModules();
|
plugin.getUpdateChecker().updateModuleJar(sender, module);
|
||||||
return context.mmString("<green>All modules updated and reloaded!");
|
}
|
||||||
|
plugin.getApi().scheduler().runGlobal(() ->
|
||||||
|
{
|
||||||
|
plugin.getModuleManager().reloadModules();
|
||||||
|
sender.sendMessage(context.mmString("<green>All modules updated and reloaded!"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
else if (args[1].equalsIgnoreCase("install"))
|
else if (args[1].equalsIgnoreCase("install"))
|
||||||
{
|
{
|
||||||
@@ -126,7 +135,7 @@ public class PlexCMD extends ServerCommand
|
|||||||
return context.usage();
|
return context.usage();
|
||||||
}
|
}
|
||||||
String moduleName = args[2];
|
String moduleName = args[2];
|
||||||
plugin.getUpdateChecker().installModuleJar(sender, moduleName);
|
plugin.getApi().scheduler().runAsync(() -> plugin.getUpdateChecker().installModuleJar(sender, moduleName));
|
||||||
return context.mmString("<green>Installing module <yellow>" + moduleName + "<green>...");
|
return context.mmString("<green>Installing module <yellow>" + moduleName + "<green>...");
|
||||||
}
|
}
|
||||||
else if (args[1].equalsIgnoreCase("uninstall"))
|
else if (args[1].equalsIgnoreCase("uninstall"))
|
||||||
@@ -154,12 +163,22 @@ public class PlexCMD extends ServerCommand
|
|||||||
else if (args[0].equalsIgnoreCase("update"))
|
else if (args[0].equalsIgnoreCase("update"))
|
||||||
{
|
{
|
||||||
context.checkPermission(sender, "plex.update");
|
context.checkPermission(sender, "plex.update");
|
||||||
if (!plugin.getUpdateChecker().getUpdateStatusMessage(sender, false, 0))
|
plugin.getApi().scheduler().runAsync(() ->
|
||||||
{
|
{
|
||||||
return context.mmString("<red>Plex is already up to date!");
|
UpdateChecker.UpdateCheckResult result = plugin.getUpdateChecker().checkForUpdates(false);
|
||||||
}
|
if (result.status() == UpdateChecker.UpdateCheckStatus.UPDATE_AVAILABLE)
|
||||||
plugin.getUpdateChecker().updateJar(sender, "Plex", false);
|
{
|
||||||
return context.mmString("<red>Alert: Restart the server for the new JAR file to be applied.");
|
plugin.getUpdateChecker().updateJar(sender, result.metadata(), () -> sendMessage(sender, context.mmString("<red>Alert: Restart the server for the new JAR file to be applied.")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result.status() == UpdateChecker.UpdateCheckStatus.UP_TO_DATE)
|
||||||
|
{
|
||||||
|
sendMessage(sender, context.mmString("<red>Plex is already up to date!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plugin.getUpdateChecker().sendResultMessage(sender, result, 2);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -167,4 +186,14 @@ public class PlexCMD extends ServerCommand
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendMessage(CommandSender sender, Component message)
|
||||||
|
{
|
||||||
|
if (sender instanceof Player player)
|
||||||
|
{
|
||||||
|
plugin.getApi().scheduler().runEntity(player, () -> sender.sendMessage(message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plugin.getApi().scheduler().runGlobal(() -> sender.sendMessage(message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import dev.plex.command.ServerCommand;
|
|||||||
import dev.plex.command.ServerCommandContext;
|
import dev.plex.command.ServerCommandContext;
|
||||||
import dev.plex.command.exception.PlayerNotFoundException;
|
import dev.plex.command.exception.PlayerNotFoundException;
|
||||||
import dev.plex.command.source.RequiredCommandSource;
|
import dev.plex.command.source.RequiredCommandSource;
|
||||||
import dev.plex.menu.impl.PunishedPlayerMenu;
|
import dev.plex.menu.dialog.PunishmentDialog;
|
||||||
import dev.plex.menu.impl.PunishmentMenu;
|
|
||||||
import dev.plex.player.PlexPlayer;
|
import dev.plex.player.PlexPlayer;
|
||||||
|
|
||||||
|
|
||||||
@@ -45,9 +44,10 @@ public class PunishmentsCMD extends ServerCommand
|
|||||||
CommandSender sender = context.sender();
|
CommandSender sender = context.sender();
|
||||||
Player playerSender = context.player();
|
Player playerSender = context.player();
|
||||||
String[] args = context.args();
|
String[] args = context.args();
|
||||||
|
PunishmentDialog dialog = new PunishmentDialog(plugin.getPlayerService());
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
{
|
{
|
||||||
new PunishmentMenu(plugin.getPlayerService()).open(playerSender);
|
dialog.open(playerSender);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ public class PunishmentsCMD extends ServerCommand
|
|||||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(args[0]);
|
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(args[0]);
|
||||||
final PlexPlayer player = offlinePlayer.isOnline() ? context.getOnlinePlexPlayer(args[0]) : context.getOfflinePlexPlayer(offlinePlayer.getUniqueId());
|
final PlexPlayer player = offlinePlayer.isOnline() ? context.getOnlinePlexPlayer(args[0]) : context.getOfflinePlexPlayer(offlinePlayer.getUniqueId());
|
||||||
|
|
||||||
new PunishedPlayerMenu(player, plugin.getPlayerService()).open(playerSender);
|
dialog.open(playerSender, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package dev.plex.command.impl;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import dev.plex.command.ServerCommand;
|
import dev.plex.command.ServerCommand;
|
||||||
import dev.plex.command.ServerCommandContext;
|
import dev.plex.command.ServerCommandContext;
|
||||||
import dev.plex.menu.impl.ToggleMenu;
|
import dev.plex.menu.dialog.ToggleDialog;
|
||||||
import dev.plex.util.PlexUtils;
|
import dev.plex.util.PlexUtils;
|
||||||
|
|
||||||
|
|
||||||
@@ -47,19 +47,8 @@ public class ToggleCMD extends ServerCommand
|
|||||||
CommandSender sender = context.sender();
|
CommandSender sender = context.sender();
|
||||||
Player playerSender = context.player();
|
Player playerSender = context.player();
|
||||||
String[] args = context.args();
|
String[] args = context.args();
|
||||||
if (context.isConsole(sender) || playerSender == null)
|
if (args.length > 0)
|
||||||
{
|
{
|
||||||
if (args.length == 0)
|
|
||||||
{
|
|
||||||
sender.sendMessage(context.messageComponent("toggleAvailable"));
|
|
||||||
sender.sendMessage(toggleListItem(context, "toggleExplosions", "explosions"));
|
|
||||||
sender.sendMessage(toggleListItem(context, "toggleFluidSpread", "fluidspread"));
|
|
||||||
sender.sendMessage(toggleListItem(context, "toggleDrops", "drops"));
|
|
||||||
sender.sendMessage(toggleListItem(context, "toggleRedstone", "redstone"));
|
|
||||||
sender.sendMessage(toggleListItem(context, "togglePvp", "pvp"));
|
|
||||||
sender.sendMessage(toggleListItem(context, "toggleChat", "chat"));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch (args[0].toLowerCase())
|
switch (args[0].toLowerCase())
|
||||||
{
|
{
|
||||||
case "explosions" ->
|
case "explosions" ->
|
||||||
@@ -93,7 +82,18 @@ public class ToggleCMD extends ServerCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new ToggleMenu(plugin).open(playerSender);
|
if (context.isConsole(sender) || playerSender == null)
|
||||||
|
{
|
||||||
|
sender.sendMessage(context.messageComponent("toggleAvailable"));
|
||||||
|
sender.sendMessage(toggleListItem(context, "toggleExplosions", "explosions"));
|
||||||
|
sender.sendMessage(toggleListItem(context, "toggleFluidSpread", "fluidspread"));
|
||||||
|
sender.sendMessage(toggleListItem(context, "toggleDrops", "drops"));
|
||||||
|
sender.sendMessage(toggleListItem(context, "toggleRedstone", "redstone"));
|
||||||
|
sender.sendMessage(toggleListItem(context, "togglePvp", "pvp"));
|
||||||
|
sender.sendMessage(toggleListItem(context, "toggleChat", "chat"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
new ToggleDialog(plugin).open(playerSender);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import dev.plex.listener.impl.CommandListener;
|
|||||||
import dev.plex.listener.impl.DropListener;
|
import dev.plex.listener.impl.DropListener;
|
||||||
import dev.plex.listener.impl.FreezeListener;
|
import dev.plex.listener.impl.FreezeListener;
|
||||||
import dev.plex.listener.impl.GameModeListener;
|
import dev.plex.listener.impl.GameModeListener;
|
||||||
import dev.plex.listener.impl.MenuListener;
|
|
||||||
import dev.plex.listener.impl.MobListener;
|
import dev.plex.listener.impl.MobListener;
|
||||||
import dev.plex.listener.impl.MuteListener;
|
import dev.plex.listener.impl.MuteListener;
|
||||||
import dev.plex.listener.impl.PlayerListener;
|
import dev.plex.listener.impl.PlayerListener;
|
||||||
@@ -50,7 +49,6 @@ public class ListenerHandler
|
|||||||
register(() -> new DropListener(plugin));
|
register(() -> new DropListener(plugin));
|
||||||
register(() -> new FreezeListener(plugin));
|
register(() -> new FreezeListener(plugin));
|
||||||
register(() -> new GameModeListener(plugin));
|
register(() -> new GameModeListener(plugin));
|
||||||
register(() -> new MenuListener(plugin));
|
|
||||||
register(() -> new MobListener(plugin));
|
register(() -> new MobListener(plugin));
|
||||||
register(() -> new MuteListener(plugin));
|
register(() -> new MuteListener(plugin));
|
||||||
register(() -> new PlayerListener(plugin));
|
register(() -> new PlayerListener(plugin));
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package dev.plex.listener.impl;
|
|
||||||
|
|
||||||
import dev.plex.Plex;
|
|
||||||
import dev.plex.listener.ServerListenerBase;
|
|
||||||
import dev.plex.menu.AbstractMenu;
|
|
||||||
import dev.plex.menu.pagination.PageableMenu;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Taah
|
|
||||||
* @since 7:01 AM [02-09-2023]
|
|
||||||
*/
|
|
||||||
public class MenuListener extends ServerListenerBase
|
|
||||||
{
|
|
||||||
public MenuListener(Plex plugin)
|
|
||||||
{
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onClick(InventoryClickEvent event)
|
|
||||||
{
|
|
||||||
if (event.getClickedInventory() == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.getCurrentItem() == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(event.getWhoClicked() instanceof Player player))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractMenu.INVENTORIES.entrySet().stream().filter(entry -> entry.getKey().equals(event.getView().title()))
|
|
||||||
.findFirst()
|
|
||||||
.ifPresent(entry ->
|
|
||||||
{
|
|
||||||
if (entry.getValue() instanceof PageableMenu.Page page)
|
|
||||||
{
|
|
||||||
final ItemMeta meta = event.getCurrentItem().getItemMeta();
|
|
||||||
if (meta != null && meta.displayName() != null)
|
|
||||||
{
|
|
||||||
if (meta.displayName().equals(PageableMenu.previousItem().getItemMeta().displayName()))
|
|
||||||
{
|
|
||||||
page.parent().currentPage(page.parent().currentPage() - 1);
|
|
||||||
page.parent().open(player, page.parent().currentPage());
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (meta.displayName().equals(PageableMenu.nextItem().getItemMeta().displayName()))
|
|
||||||
{
|
|
||||||
page.parent().currentPage(page.parent().currentPage() + 1);
|
|
||||||
page.parent().open(player, page.parent().currentPage());
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (meta.displayName().equals(PageableMenu.closeItem().getItemMeta().displayName()))
|
|
||||||
{
|
|
||||||
player.closeInventory();
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.setCancelled(entry.getValue().onClick(event.getView(), event.getClickedInventory(), player, event.getCurrentItem()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
package dev.plex.menu;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import dev.plex.util.minimessage.SafeMiniMessage;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.InventoryView;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public abstract class AbstractMenu
|
|
||||||
{
|
|
||||||
public static final Map<Component, AbstractMenu> INVENTORIES = Maps.newHashMap();
|
|
||||||
private final Component name;
|
|
||||||
private final Inventory inventory;
|
|
||||||
|
|
||||||
public AbstractMenu(Component name, Rows rows)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
this.inventory = Bukkit.createInventory(null, rows.slots, name);
|
|
||||||
|
|
||||||
INVENTORIES.put(name, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractMenu(String name, Rows rows)
|
|
||||||
{
|
|
||||||
this(SafeMiniMessage.mmDeserializeWithoutEvents(name), rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean onClick(InventoryView view, Inventory inventory, Player player, ItemStack clicked);
|
|
||||||
|
|
||||||
public void open(Player player)
|
|
||||||
{
|
|
||||||
player.openInventory(this.inventory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Rows
|
|
||||||
{
|
|
||||||
ONE(9), TWO(18), THREE(27), FOUR(36), FIVE(45), SIX(54);
|
|
||||||
|
|
||||||
private final int slots;
|
|
||||||
|
|
||||||
Rows(int slots)
|
|
||||||
{
|
|
||||||
this.slots = slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int slots()
|
|
||||||
{
|
|
||||||
return this.slots;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package dev.plex.menu.dialog;
|
||||||
|
|
||||||
|
import io.papermc.paper.dialog.Dialog;
|
||||||
|
import io.papermc.paper.registry.data.dialog.ActionButton;
|
||||||
|
import io.papermc.paper.registry.data.dialog.DialogBase;
|
||||||
|
import io.papermc.paper.registry.data.dialog.action.DialogAction;
|
||||||
|
import io.papermc.paper.registry.data.dialog.body.DialogBody;
|
||||||
|
import io.papermc.paper.registry.data.dialog.type.DialogType;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.event.ClickCallback;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class MaterialDialog
|
||||||
|
{
|
||||||
|
private static final int PAGE_SIZE = 40;
|
||||||
|
private static final ClickCallback.Options CALLBACK_OPTIONS = ClickCallback.Options.builder()
|
||||||
|
.uses(1)
|
||||||
|
.lifetime(Duration.ofMinutes(5))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final List<Material> materials = Arrays.stream(Material.values())
|
||||||
|
.filter(material -> !material.isAir())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
public void open(Player player)
|
||||||
|
{
|
||||||
|
open(player, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void open(Player player, int page)
|
||||||
|
{
|
||||||
|
player.showDialog(create(page));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog create(int page)
|
||||||
|
{
|
||||||
|
int pageCount = Math.max(1, (int) Math.ceil(materials.size() / (double) PAGE_SIZE));
|
||||||
|
int currentPage = Math.max(0, Math.min(page, pageCount - 1));
|
||||||
|
int fromIndex = currentPage * PAGE_SIZE;
|
||||||
|
int toIndex = Math.min(fromIndex + PAGE_SIZE, materials.size());
|
||||||
|
List<ActionButton> actions = new ArrayList<>(materials.subList(fromIndex, toIndex).stream()
|
||||||
|
.map(material -> materialButton(material, currentPage))
|
||||||
|
.toList());
|
||||||
|
if (currentPage > 0)
|
||||||
|
{
|
||||||
|
actions.add(pageButton("Previous Page", currentPage - 1));
|
||||||
|
}
|
||||||
|
if (currentPage + 1 < pageCount)
|
||||||
|
{
|
||||||
|
actions.add(pageButton("Next Page", currentPage + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dialog.create(builder -> builder.empty()
|
||||||
|
.base(DialogBase.builder(Component.text("Materials"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.WAIT_FOR_RESPONSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(Component.text("Page " + (currentPage + 1) + " of " + pageCount))))
|
||||||
|
.build())
|
||||||
|
.type(DialogType.multiAction(actions, closeButton(), 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton materialButton(Material material, int page)
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text(material.name()))
|
||||||
|
.width(120)
|
||||||
|
.action(DialogAction.customClick((response, audience) ->
|
||||||
|
{
|
||||||
|
if (audience instanceof Player player)
|
||||||
|
{
|
||||||
|
player.sendMessage(Component.text(material.name()));
|
||||||
|
open(player, page);
|
||||||
|
}
|
||||||
|
}, CALLBACK_OPTIONS))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton pageButton(String label, int page)
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text(label))
|
||||||
|
.width(150)
|
||||||
|
.action(DialogAction.customClick((response, audience) ->
|
||||||
|
{
|
||||||
|
if (audience instanceof Player player)
|
||||||
|
{
|
||||||
|
open(player, page);
|
||||||
|
}
|
||||||
|
}, CALLBACK_OPTIONS))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton closeButton()
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text("Close"))
|
||||||
|
.width(150)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
package dev.plex.menu.dialog;
|
||||||
|
|
||||||
|
import dev.plex.player.PlayerService;
|
||||||
|
import dev.plex.player.PlexPlayer;
|
||||||
|
import dev.plex.punishment.Punishment;
|
||||||
|
import dev.plex.util.PlexUtils;
|
||||||
|
import dev.plex.util.TimeUtils;
|
||||||
|
import io.papermc.paper.dialog.Dialog;
|
||||||
|
import io.papermc.paper.registry.data.dialog.ActionButton;
|
||||||
|
import io.papermc.paper.registry.data.dialog.DialogBase;
|
||||||
|
import io.papermc.paper.registry.data.dialog.action.DialogAction;
|
||||||
|
import io.papermc.paper.registry.data.dialog.body.DialogBody;
|
||||||
|
import io.papermc.paper.registry.data.dialog.type.DialogType;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.event.ClickCallback;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class PunishmentDialog
|
||||||
|
{
|
||||||
|
private static final ClickCallback.Options CALLBACK_OPTIONS = ClickCallback.Options.builder()
|
||||||
|
.uses(1)
|
||||||
|
.lifetime(Duration.ofMinutes(5))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final PlayerService playerService;
|
||||||
|
|
||||||
|
public PunishmentDialog(PlayerService playerService)
|
||||||
|
{
|
||||||
|
this.playerService = playerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(Player player)
|
||||||
|
{
|
||||||
|
player.showDialog(playerListDialog());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(Player viewer, PlexPlayer punishedPlayer)
|
||||||
|
{
|
||||||
|
viewer.showDialog(playerPunishmentsDialog(punishedPlayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog playerListDialog()
|
||||||
|
{
|
||||||
|
List<ActionButton> actions = Bukkit.getOnlinePlayers().stream()
|
||||||
|
.map(this::playerButton)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return Dialog.create(builder -> builder.empty()
|
||||||
|
.base(DialogBase.builder(PlexUtils.messageComponent("punishmentMenuTitle"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.WAIT_FOR_RESPONSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(Component.text("Select an online player to view their punishments."))))
|
||||||
|
.build())
|
||||||
|
.type(DialogType.multiAction(actions, closeButton(), 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog playerPunishmentsDialog(PlexPlayer punishedPlayer)
|
||||||
|
{
|
||||||
|
List<DialogBody> body = new ArrayList<>();
|
||||||
|
List<Punishment> punishments = punishedPlayer.getPunishments();
|
||||||
|
|
||||||
|
if (punishments.isEmpty())
|
||||||
|
{
|
||||||
|
body.add(DialogBody.plainMessage(Component.text("No punishments found.")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
punishments.forEach(punishment -> body.add(DialogBody.plainMessage(punishmentSummary(punishment), 320)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dialog.create(builder -> builder.empty()
|
||||||
|
.base(DialogBase.builder(PlexUtils.messageComponent("punishedPlayerMenuTitle", punishedPlayer.getName()))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.WAIT_FOR_RESPONSE)
|
||||||
|
.body(body)
|
||||||
|
.build())
|
||||||
|
.type(DialogType.multiAction(List.of(backButton()), closeButton(), 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton playerButton(Player player)
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text(player.getName()))
|
||||||
|
.width(150)
|
||||||
|
.action(DialogAction.customClick((response, audience) -> openPunishments(audience, player), CALLBACK_OPTIONS))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton backButton()
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text("Back"))
|
||||||
|
.width(150)
|
||||||
|
.action(DialogAction.customClick((response, audience) ->
|
||||||
|
{
|
||||||
|
if (audience instanceof Player player)
|
||||||
|
{
|
||||||
|
open(player);
|
||||||
|
}
|
||||||
|
}, CALLBACK_OPTIONS))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton closeButton()
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text("Close"))
|
||||||
|
.width(150)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openPunishments(Audience audience, OfflinePlayer selectedPlayer)
|
||||||
|
{
|
||||||
|
if (!(audience instanceof Player viewer))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlexPlayer punishedPlayer = playerService.getPlayer(selectedPlayer.getUniqueId());
|
||||||
|
if (punishedPlayer == null)
|
||||||
|
{
|
||||||
|
viewer.sendMessage(PlexUtils.messageComponent("punishmentPlayerNotFound"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
open(viewer, punishedPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component punishmentSummary(Punishment punishment)
|
||||||
|
{
|
||||||
|
String punisher = punishment.getPunisher() == null ? "CONSOLE" : playerService.getNameByUUID(punishment.getPunisher());
|
||||||
|
return Component.text(punishment.getType().name() + "\n"
|
||||||
|
+ "By: " + punisher + "\n"
|
||||||
|
+ "Issued: " + TimeUtils.useTimezone(punishment.getIssueDate()) + "\n"
|
||||||
|
+ "Expire(d/s): " + TimeUtils.useTimezone(punishment.getEndDate()) + "\n"
|
||||||
|
+ "Reason: " + punishment.getReason());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package dev.plex.menu.dialog;
|
||||||
|
|
||||||
|
import dev.plex.Plex;
|
||||||
|
import dev.plex.util.PlexUtils;
|
||||||
|
import io.papermc.paper.dialog.Dialog;
|
||||||
|
import io.papermc.paper.registry.data.dialog.ActionButton;
|
||||||
|
import io.papermc.paper.registry.data.dialog.DialogBase;
|
||||||
|
import io.papermc.paper.registry.data.dialog.action.DialogAction;
|
||||||
|
import io.papermc.paper.registry.data.dialog.body.DialogBody;
|
||||||
|
import io.papermc.paper.registry.data.dialog.type.DialogType;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.event.ClickCallback;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class ToggleDialog
|
||||||
|
{
|
||||||
|
private static final ClickCallback.Options CALLBACK_OPTIONS = ClickCallback.Options.builder()
|
||||||
|
.uses(1)
|
||||||
|
.lifetime(Duration.ofMinutes(5))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final Plex plugin;
|
||||||
|
|
||||||
|
public ToggleDialog(Plex plugin)
|
||||||
|
{
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(Player player)
|
||||||
|
{
|
||||||
|
player.showDialog(create());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog create()
|
||||||
|
{
|
||||||
|
return Dialog.create(builder -> builder.empty()
|
||||||
|
.base(DialogBase.builder(PlexUtils.messageComponent("toggleMenuTitle"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.WAIT_FOR_RESPONSE)
|
||||||
|
.body(List.of(
|
||||||
|
DialogBody.plainMessage(statusLine("toggleExplosions", "explosions", true)),
|
||||||
|
DialogBody.plainMessage(statusLine("toggleFluidSpread", "fluidspread", false)),
|
||||||
|
DialogBody.plainMessage(statusLine("toggleDrops", "drops", false)),
|
||||||
|
DialogBody.plainMessage(statusLine("toggleRedstone", "redstone", false)),
|
||||||
|
DialogBody.plainMessage(statusLine("togglePvp", "pvp", false)),
|
||||||
|
DialogBody.plainMessage(Component.text(PlexUtils.messageString("toggleChat") + ": " + PlexUtils.messageString(plugin.toggles.getBoolean("chat") ? "stateOn" : "stateOff")))))
|
||||||
|
.build())
|
||||||
|
.type(DialogType.multiAction(List.of(
|
||||||
|
toggleButton("toggleExplosions", "toggleExplosionsLower", "explosions"),
|
||||||
|
toggleButton("toggleFluidSpread", "toggleFluidSpreadLower", "fluidspread"),
|
||||||
|
toggleButton("toggleDrops", "toggleDropsLower", "drops"),
|
||||||
|
toggleButton("toggleRedstone", "toggleRedstoneLower", "redstone"),
|
||||||
|
toggleButton("togglePvp", "togglePvpLower", "pvp"),
|
||||||
|
toggleButton("toggleChat", "toggleChatLower", "chat")),
|
||||||
|
closeButton(), 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton toggleButton(String nameKey, String lowerNameKey, String toggle)
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text(PlexUtils.messageString(nameKey)))
|
||||||
|
.tooltip(Component.text(PlexUtils.messageString(plugin.toggles.getBoolean(toggle) ? "stateEnabled" : "stateDisabled")))
|
||||||
|
.width(150)
|
||||||
|
.action(DialogAction.customClick((response, audience) -> toggle(audience, lowerNameKey, toggle), CALLBACK_OPTIONS))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionButton closeButton()
|
||||||
|
{
|
||||||
|
return ActionButton.builder(Component.text("Close"))
|
||||||
|
.width(150)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggle(Audience audience, String lowerNameKey, String toggle)
|
||||||
|
{
|
||||||
|
if (!(audience instanceof Player player) || !player.hasPermission("plex.toggle"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.toggles.set(toggle, !plugin.toggles.getBoolean(toggle));
|
||||||
|
if ("chat".equals(toggle))
|
||||||
|
{
|
||||||
|
PlexUtils.broadcast(PlexUtils.messageComponent("chatToggled", player.getName(), PlexUtils.messageString(plugin.toggles.getBoolean("chat") ? "stateOn" : "stateOff")));
|
||||||
|
}
|
||||||
|
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString(lowerNameKey)));
|
||||||
|
open(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component statusLine(String nameKey, String toggle, boolean enabledIsUnsafe)
|
||||||
|
{
|
||||||
|
return Component.text(PlexUtils.messageString(nameKey) + ": " + status(toggle, enabledIsUnsafe));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String status(String toggle, boolean enabledIsUnsafe)
|
||||||
|
{
|
||||||
|
if (enabledIsUnsafe)
|
||||||
|
{
|
||||||
|
return PlexUtils.messageString(plugin.toggles.getBoolean(toggle) ? "stateEnabledUnsafe" : "stateDisabledSafe");
|
||||||
|
}
|
||||||
|
return PlexUtils.messageString(plugin.toggles.getBoolean(toggle) ? "stateEnabled" : "stateDisabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package dev.plex.menu.impl;
|
|
||||||
|
|
||||||
import dev.plex.menu.AbstractMenu;
|
|
||||||
import dev.plex.menu.pagination.PageableMenu;
|
|
||||||
import dev.plex.util.item.ItemBuilder;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
public class MaterialMenu extends PageableMenu<Material>
|
|
||||||
{
|
|
||||||
public MaterialMenu()
|
|
||||||
{
|
|
||||||
super("<dark_aqua><bold>Materials", AbstractMenu.Rows.SIX);
|
|
||||||
onClick((inventoryView, inventory, player, itemStack) ->
|
|
||||||
{
|
|
||||||
player.sendMessage(itemStack.displayName());
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemStack toItem(Material object)
|
|
||||||
{
|
|
||||||
return new ItemBuilder(object).displayName("<blue>" + object.name()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Material> list()
|
|
||||||
{
|
|
||||||
return Arrays.stream(Material.values()).filter(material -> !material.isAir()).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package dev.plex.menu.impl;
|
|
||||||
|
|
||||||
import dev.plex.menu.AbstractMenu;
|
|
||||||
import dev.plex.menu.pagination.PageableMenu;
|
|
||||||
import dev.plex.player.PlayerService;
|
|
||||||
import dev.plex.player.PlexPlayer;
|
|
||||||
import dev.plex.punishment.Punishment;
|
|
||||||
import dev.plex.util.PlexUtils;
|
|
||||||
import dev.plex.util.TimeUtils;
|
|
||||||
import dev.plex.util.item.ItemBuilder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
public class PunishedPlayerMenu extends PageableMenu<Punishment>
|
|
||||||
{
|
|
||||||
private final PlexPlayer punishedPlayer;
|
|
||||||
private final PlayerService playerService;
|
|
||||||
|
|
||||||
public PunishedPlayerMenu(PlexPlayer player, PlayerService playerService)
|
|
||||||
{
|
|
||||||
super(PlexUtils.messageComponent("punishedPlayerMenuTitle", player.getName()), AbstractMenu.Rows.SIX);
|
|
||||||
this.punishedPlayer = player;
|
|
||||||
this.playerService = playerService;
|
|
||||||
onClick((inventoryView, itemStacks, player1, itemStack) -> true);
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemStack toItem(Punishment object)
|
|
||||||
{
|
|
||||||
return new ItemBuilder(Material.PAPER)
|
|
||||||
.displayName(PlexUtils.messageComponent("punishmentItemTitle", object.getType().name()))
|
|
||||||
.lore(PlexUtils.messageComponent("punishmentItemPunisher", object.getPunisher() == null ? "CONSOLE" : playerService.getNameByUUID(object.getPunisher())),
|
|
||||||
PlexUtils.messageComponent("punishmentItemIssued", TimeUtils.useTimezone(object.getIssueDate())),
|
|
||||||
PlexUtils.messageComponent("punishmentItemExpires", TimeUtils.useTimezone(object.getEndDate())),
|
|
||||||
PlexUtils.messageComponent("punishmentItemReason", object.getReason()))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Punishment> list()
|
|
||||||
{
|
|
||||||
return this.punishedPlayer.getPunishments();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package dev.plex.menu.impl;
|
|
||||||
|
|
||||||
import dev.plex.menu.AbstractMenu;
|
|
||||||
import dev.plex.menu.pagination.PageableMenu;
|
|
||||||
import dev.plex.player.PlayerService;
|
|
||||||
import dev.plex.player.PlexPlayer;
|
|
||||||
import dev.plex.util.PlexLog;
|
|
||||||
import dev.plex.util.PlexUtils;
|
|
||||||
import dev.plex.util.item.ItemBuilder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.SkullMeta;
|
|
||||||
|
|
||||||
public class PunishmentMenu extends PageableMenu<Player>
|
|
||||||
{
|
|
||||||
private final PlayerService playerService;
|
|
||||||
|
|
||||||
public PunishmentMenu(PlayerService playerService)
|
|
||||||
{
|
|
||||||
super(PlexUtils.messageComponent("punishmentMenuTitle"), AbstractMenu.Rows.SIX);
|
|
||||||
this.playerService = playerService;
|
|
||||||
PlexLog.debug("list: {0}", list().size());
|
|
||||||
onClick((inventoryView, itemStacks, player, itemStack) ->
|
|
||||||
{
|
|
||||||
if (itemStack.getType() != Material.PLAYER_HEAD)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
|
||||||
if (meta.getOwningPlayer() == null)
|
|
||||||
{
|
|
||||||
meta.setOwningPlayer(Bukkit.getOfflinePlayer("markbyron"));
|
|
||||||
}
|
|
||||||
PlexPlayer punishedPlayer = playerService.getPlayer(meta.getOwningPlayer().getUniqueId());
|
|
||||||
if (punishedPlayer == null)
|
|
||||||
{
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("punishmentPlayerNotFound"));
|
|
||||||
player.closeInventory();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
new PunishedPlayerMenu(punishedPlayer, playerService).open(player);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemStack toItem(Player object)
|
|
||||||
{
|
|
||||||
return new ItemBuilder(Material.PLAYER_HEAD).owner(object).displayName(PlexUtils.messageComponent("punishmentPlayerItem", object.getName())).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Player> list()
|
|
||||||
{
|
|
||||||
return Bukkit.getOnlinePlayers().stream().map(OfflinePlayer::getPlayer).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
package dev.plex.menu.impl;
|
|
||||||
|
|
||||||
import dev.plex.Plex;
|
|
||||||
import dev.plex.menu.AbstractMenu;
|
|
||||||
import dev.plex.util.PlexUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.InventoryView;
|
|
||||||
import org.bukkit.inventory.ItemFlag;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
|
|
||||||
public class ToggleMenu extends AbstractMenu
|
|
||||||
{
|
|
||||||
private final Plex plugin;
|
|
||||||
|
|
||||||
public ToggleMenu(Plex plugin)
|
|
||||||
{
|
|
||||||
super(PlexUtils.messageComponent("toggleMenuTitle"), Rows.ONE);
|
|
||||||
this.plugin = plugin;
|
|
||||||
resetExplosionItem(this.inventory());
|
|
||||||
resetFluidspreadItem(this.inventory());
|
|
||||||
resetDropsItem(this.inventory());
|
|
||||||
resetRedstoneItem(this.inventory());
|
|
||||||
resetPVPItem(this.inventory());
|
|
||||||
resetChatItem(this.inventory());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetExplosionItem(Inventory inventory)
|
|
||||||
{
|
|
||||||
ItemStack explosions = new ItemStack(Material.TNT);
|
|
||||||
ItemMeta explosionsItemMeta = explosions.getItemMeta();
|
|
||||||
explosionsItemMeta.displayName(PlexUtils.messageComponent("toggleMenuExplosionsName"));
|
|
||||||
explosionsItemMeta.lore(List.of(PlexUtils.messageComponent("toggleMenuExplosionsLore", status("explosions", true))));
|
|
||||||
explosions.setItemMeta(explosionsItemMeta);
|
|
||||||
inventory.setItem(0, explosions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetFluidspreadItem(Inventory inventory)
|
|
||||||
{
|
|
||||||
ItemStack water = new ItemStack(Material.WATER_BUCKET);
|
|
||||||
ItemMeta waterItemMeta = water.getItemMeta();
|
|
||||||
waterItemMeta.displayName(PlexUtils.messageComponent("toggleMenuFluidSpreadName"));
|
|
||||||
waterItemMeta.lore(List.of(PlexUtils.messageComponent("toggleMenuFluidSpreadLore", status("fluidspread", false))));
|
|
||||||
water.setItemMeta(waterItemMeta);
|
|
||||||
inventory.setItem(1, water);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetDropsItem(Inventory inventory)
|
|
||||||
{
|
|
||||||
ItemStack feather = new ItemStack(Material.FEATHER);
|
|
||||||
ItemMeta featherItemMeta = feather.getItemMeta();
|
|
||||||
featherItemMeta.displayName(PlexUtils.messageComponent("toggleMenuDropsName"));
|
|
||||||
featherItemMeta.lore(List.of(PlexUtils.messageComponent("toggleMenuDropsLore", status("drops", false))));
|
|
||||||
feather.setItemMeta(featherItemMeta);
|
|
||||||
inventory.setItem(2, feather);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetRedstoneItem(Inventory inventory)
|
|
||||||
{
|
|
||||||
ItemStack redstone = new ItemStack(Material.REDSTONE);
|
|
||||||
ItemMeta redstoneItemMeta = redstone.getItemMeta();
|
|
||||||
redstoneItemMeta.displayName(PlexUtils.messageComponent("toggleMenuRedstoneName"));
|
|
||||||
redstoneItemMeta.lore(List.of(PlexUtils.messageComponent("toggleMenuRedstoneLore", status("redstone", false))));
|
|
||||||
redstone.setItemMeta(redstoneItemMeta);
|
|
||||||
inventory.setItem(3, redstone);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetPVPItem(Inventory inventory)
|
|
||||||
{
|
|
||||||
ItemStack pvp = new ItemStack(Material.IRON_SWORD);
|
|
||||||
ItemMeta pvpItemMeta = pvp.getItemMeta();
|
|
||||||
pvpItemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
|
|
||||||
pvpItemMeta.displayName(PlexUtils.messageComponent("toggleMenuPvpName"));
|
|
||||||
pvpItemMeta.lore(List.of(PlexUtils.messageComponent("toggleMenuPvpLore", status("pvp", false))));
|
|
||||||
pvp.setItemMeta(pvpItemMeta);
|
|
||||||
inventory.setItem(4, pvp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetChatItem(Inventory inventory)
|
|
||||||
{
|
|
||||||
ItemStack chat = new ItemStack(Material.OAK_SIGN);
|
|
||||||
ItemMeta chatItemMeta = chat.getItemMeta();
|
|
||||||
chatItemMeta.displayName(PlexUtils.messageComponent("toggleMenuChatName"));
|
|
||||||
chatItemMeta.lore(List.of(PlexUtils.messageComponent("toggleMenuChatLore", PlexUtils.messageString(plugin.toggles.getBoolean("chat") ? "stateOn" : "stateOff"))));
|
|
||||||
chat.setItemMeta(chatItemMeta);
|
|
||||||
inventory.setItem(5, chat);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onClick(InventoryView view, Inventory inventory, Player player, ItemStack clicked)
|
|
||||||
{
|
|
||||||
if (!player.hasPermission("plex.toggle"))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (clicked.getType() == Material.TNT)
|
|
||||||
{
|
|
||||||
plugin.toggles.set("explosions", !plugin.toggles.getBoolean("explosions"));
|
|
||||||
resetExplosionItem(inventory);
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString("toggleExplosionsLower")));
|
|
||||||
}
|
|
||||||
if (clicked.getType() == Material.WATER_BUCKET)
|
|
||||||
{
|
|
||||||
plugin.toggles.set("fluidspread", !plugin.toggles.getBoolean("fluidspread"));
|
|
||||||
resetFluidspreadItem(inventory);
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString("toggleFluidSpreadLower")));
|
|
||||||
}
|
|
||||||
if (clicked.getType() == Material.FEATHER)
|
|
||||||
{
|
|
||||||
plugin.toggles.set("drops", !plugin.toggles.getBoolean("drops"));
|
|
||||||
resetDropsItem(inventory);
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString("toggleDropsLower")));
|
|
||||||
}
|
|
||||||
if (clicked.getType() == Material.REDSTONE)
|
|
||||||
{
|
|
||||||
plugin.toggles.set("redstone", !plugin.toggles.getBoolean("redstone"));
|
|
||||||
resetRedstoneItem(inventory);
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString("toggleRedstoneLower")));
|
|
||||||
}
|
|
||||||
if (clicked.getType() == Material.IRON_SWORD)
|
|
||||||
{
|
|
||||||
plugin.toggles.set("pvp", !plugin.toggles.getBoolean("pvp"));
|
|
||||||
resetPVPItem(inventory);
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString("togglePvpLower")));
|
|
||||||
}
|
|
||||||
if (clicked.getType() == Material.OAK_SIGN)
|
|
||||||
{
|
|
||||||
plugin.toggles.set("chat", !plugin.toggles.getBoolean("chat"));
|
|
||||||
PlexUtils.broadcast(PlexUtils.messageComponent("chatToggled", player.getName(), PlexUtils.messageString(plugin.toggles.getBoolean("chat") ? "stateOn" : "stateOff")));
|
|
||||||
resetChatItem(inventory);
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("toggleToggled", PlexUtils.messageString("toggleChatLower")));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String status(String toggle, boolean enabledIsUnsafe)
|
|
||||||
{
|
|
||||||
if (enabledIsUnsafe)
|
|
||||||
{
|
|
||||||
return PlexUtils.messageString(plugin.toggles.getBoolean(toggle) ? "stateEnabledUnsafe" : "stateDisabledSafe");
|
|
||||||
}
|
|
||||||
return PlexUtils.messageString(plugin.toggles.getBoolean(toggle) ? "stateEnabled" : "stateDisabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
package dev.plex.menu.pagination;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import dev.plex.menu.AbstractMenu;
|
|
||||||
import dev.plex.util.PlexUtils;
|
|
||||||
import dev.plex.util.function.ConditionalQuadConsumer;
|
|
||||||
import dev.plex.util.item.ItemBuilder;
|
|
||||||
import dev.plex.util.minimessage.SafeMiniMessage;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.InventoryView;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public abstract class PageableMenu<T>
|
|
||||||
{
|
|
||||||
protected final Map<Integer, Page> pages = Maps.newHashMap();
|
|
||||||
private final Component name;
|
|
||||||
private final AbstractMenu.Rows rows;
|
|
||||||
private final Inventory inventory;
|
|
||||||
private int currentPage;
|
|
||||||
private boolean initialized;
|
|
||||||
|
|
||||||
@Setter(AccessLevel.NONE)
|
|
||||||
private ConditionalQuadConsumer<InventoryView, Inventory, Player, ItemStack> onClick;
|
|
||||||
|
|
||||||
public PageableMenu(Component name, AbstractMenu.Rows rows)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
this.rows = rows;
|
|
||||||
this.inventory = Bukkit.createInventory(null, rows.slots(), name);
|
|
||||||
|
|
||||||
if (rows.slots() < AbstractMenu.Rows.TWO.slots())
|
|
||||||
{
|
|
||||||
throw new RuntimeException("A pageable menu must have at least two rows to compensate for the navigation!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void init()
|
|
||||||
{
|
|
||||||
this.initialized = true;
|
|
||||||
// Preload all needed pages, a better solution is probably just to dynamically create the pages as they go but no!
|
|
||||||
if (list().size() < (rows.slots() - 9))
|
|
||||||
{
|
|
||||||
final Page page = new Page(name.append(Component.space()).append(PlexUtils.mmDeserialize("(1)")), rows);
|
|
||||||
page.parent = this;
|
|
||||||
page.inventory().setItem(rows.slots() - 5, closeItem());
|
|
||||||
this.pages.put(0, page);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Math.ceil(list().size() / (double) (rows.slots() - 9)); i++)
|
|
||||||
{
|
|
||||||
final Page page = new Page(name.append(Component.space()).append(PlexUtils.mmDeserialize("(" + (i + 1) + ")")), rows);
|
|
||||||
page.parent = this;
|
|
||||||
if (i > 0) // If not first page set previous page button
|
|
||||||
{
|
|
||||||
page.inventory().setItem(rows.slots() - 6, previousItem());
|
|
||||||
}
|
|
||||||
page.inventory().setItem(rows.slots() - 5, closeItem());
|
|
||||||
if (i < (list().size() / (rows.slots() - 9)) - 1) // If not last page set next page button
|
|
||||||
{
|
|
||||||
page.inventory().setItem(rows.slots() - 4, nextItem());
|
|
||||||
}
|
|
||||||
this.pages.put(i, page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentSlotIndex = 0;
|
|
||||||
int currentPageIndex = 0;
|
|
||||||
int currentIndex = 0;
|
|
||||||
while (currentSlotIndex < rows.slots() - 9 && currentIndex < list().size())
|
|
||||||
{
|
|
||||||
final Page page = this.pages.get(currentPageIndex);
|
|
||||||
if (page == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
page.inventory().setItem(currentSlotIndex, toItem(list().get(currentIndex)));
|
|
||||||
currentIndex++;
|
|
||||||
currentSlotIndex++;
|
|
||||||
if (currentSlotIndex == rows.slots() - 9)
|
|
||||||
{
|
|
||||||
currentSlotIndex = 0;
|
|
||||||
currentPageIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (onClick != null) // To make sure this wasn't declared already
|
|
||||||
{
|
|
||||||
this.pages.forEach((integer, page) -> page.onClick(this.onClick));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PageableMenu(String name, AbstractMenu.Rows rows)
|
|
||||||
{
|
|
||||||
this(SafeMiniMessage.mmDeserializeWithoutEvents(name), rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract ItemStack toItem(T object);
|
|
||||||
|
|
||||||
protected abstract List<T> list();
|
|
||||||
|
|
||||||
public void open(Player player)
|
|
||||||
{
|
|
||||||
open(player, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void open(Player player, int pageNum)
|
|
||||||
{
|
|
||||||
if (!this.initialized)
|
|
||||||
{
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("pageableNotInitialized"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final Page page = this.pages.get(pageNum);
|
|
||||||
if (page == null)
|
|
||||||
{
|
|
||||||
player.sendMessage(PlexUtils.messageComponent("pageNotFound"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
player.openInventory(page.inventory());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onClick(ConditionalQuadConsumer<InventoryView, Inventory, Player, ItemStack> onClick)
|
|
||||||
{
|
|
||||||
this.onClick = onClick;
|
|
||||||
this.pages.forEach((integer, page) -> page.onClick(this.onClick));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ItemStack nextItem()
|
|
||||||
{
|
|
||||||
return new ItemBuilder(Material.FEATHER).displayName(PlexUtils.messageComponent("pageNext")).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ItemStack previousItem()
|
|
||||||
{
|
|
||||||
return new ItemBuilder(Material.FEATHER).displayName(PlexUtils.messageComponent("pagePrevious")).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ItemStack closeItem()
|
|
||||||
{
|
|
||||||
return new ItemBuilder(Material.BARRIER).displayName(PlexUtils.messageComponent("pageClose")).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public static class Page extends AbstractMenu
|
|
||||||
{
|
|
||||||
private ConditionalQuadConsumer<InventoryView, Inventory, Player, ItemStack> onClick;
|
|
||||||
private PageableMenu<?> parent;
|
|
||||||
|
|
||||||
private Page(Component name, Rows rows)
|
|
||||||
{
|
|
||||||
super(name, rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Page(String name, AbstractMenu.Rows rows)
|
|
||||||
{
|
|
||||||
this(SafeMiniMessage.mmDeserializeWithoutEvents(name), rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onClick(InventoryView view, Inventory inventory, Player player, ItemStack clicked)
|
|
||||||
{
|
|
||||||
return onClick.accept(view, inventory, player, clicked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,13 @@ package dev.plex.services.impl;
|
|||||||
|
|
||||||
import dev.plex.Plex;
|
import dev.plex.Plex;
|
||||||
import dev.plex.services.AbstractService;
|
import dev.plex.services.AbstractService;
|
||||||
|
import dev.plex.util.UpdateChecker;
|
||||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
public class UpdateCheckerService extends AbstractService
|
public class UpdateCheckerService extends AbstractService
|
||||||
{
|
{
|
||||||
private boolean newVersion = false;
|
private boolean notified = false;
|
||||||
|
|
||||||
public UpdateCheckerService(Plex plugin)
|
public UpdateCheckerService(Plex plugin)
|
||||||
{
|
{
|
||||||
@@ -17,11 +18,16 @@ public class UpdateCheckerService extends AbstractService
|
|||||||
@Override
|
@Override
|
||||||
public void run(ScheduledTask task)
|
public void run(ScheduledTask task)
|
||||||
{
|
{
|
||||||
if (!newVersion)
|
if (!notified)
|
||||||
{
|
{
|
||||||
if (plugin.getUpdateChecker().getUpdateStatusMessage(Bukkit.getConsoleSender(), false, 1))
|
UpdateChecker.UpdateCheckResult result = plugin.getUpdateChecker().checkForUpdates(false);
|
||||||
|
plugin.getUpdateChecker().sendResultMessage(Bukkit.getConsoleSender(), result, 1);
|
||||||
|
if (result.status() == UpdateChecker.UpdateCheckStatus.UPDATE_AVAILABLE
|
||||||
|
|| result.status() == UpdateChecker.UpdateCheckStatus.MINECRAFT_TOO_OLD
|
||||||
|
|| result.status() == UpdateChecker.UpdateCheckStatus.MINECRAFT_TOO_NEW
|
||||||
|
|| result.status() == UpdateChecker.UpdateCheckStatus.MINECRAFT_UNLISTED)
|
||||||
{
|
{
|
||||||
newVersion = true;
|
notified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,12 @@ public final class ArtifactMetadata
|
|||||||
return publishedAt;
|
return publishedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> validatePlex(UpdateChannel requestedChannel, String minecraftVersion)
|
public List<String> minecraftVersions()
|
||||||
|
{
|
||||||
|
return minecraftVersions == null ? List.of() : List.copyOf(minecraftVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> validatePlex(UpdateChannel requestedChannel)
|
||||||
{
|
{
|
||||||
Optional<String> commonError = validateCommon(requestedChannel);
|
Optional<String> commonError = validateCommon(requestedChannel);
|
||||||
if (commonError.isPresent())
|
if (commonError.isPresent())
|
||||||
@@ -84,9 +89,9 @@ public final class ArtifactMetadata
|
|||||||
{
|
{
|
||||||
return Optional.of("Plex metadata has unexpected artifact name " + name);
|
return Optional.of("Plex metadata has unexpected artifact name " + name);
|
||||||
}
|
}
|
||||||
if (minecraftVersions == null || !minecraftVersions.contains(minecraftVersion))
|
if (minecraftVersions == null || minecraftVersions.isEmpty())
|
||||||
{
|
{
|
||||||
return Optional.of("metadata does not include Minecraft version " + minecraftVersion);
|
return Optional.of("Plex metadata is missing minecraftVersions");
|
||||||
}
|
}
|
||||||
if (apiCompatibility == null)
|
if (apiCompatibility == null)
|
||||||
{
|
{
|
||||||
@@ -95,6 +100,20 @@ public final class ArtifactMetadata
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<String> validatePlex(UpdateChannel requestedChannel, String minecraftVersion)
|
||||||
|
{
|
||||||
|
Optional<String> plexError = validatePlex(requestedChannel);
|
||||||
|
if (plexError.isPresent())
|
||||||
|
{
|
||||||
|
return plexError;
|
||||||
|
}
|
||||||
|
if (!supportsMinecraftVersion(minecraftVersion))
|
||||||
|
{
|
||||||
|
return Optional.of("metadata does not include Minecraft version " + minecraftVersion);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<String> validateModule(UpdateChannel requestedChannel, String moduleName, int apiCompatibility)
|
public Optional<String> validateModule(UpdateChannel requestedChannel, String moduleName, int apiCompatibility)
|
||||||
{
|
{
|
||||||
Optional<String> commonError = validateCommon(requestedChannel);
|
Optional<String> commonError = validateCommon(requestedChannel);
|
||||||
@@ -185,6 +204,11 @@ public final class ArtifactMetadata
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean supportsMinecraftVersion(String minecraftVersion)
|
||||||
|
{
|
||||||
|
return minecraftVersions != null && minecraftVersions.contains(minecraftVersion);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isBlank(String value)
|
private static boolean isBlank(String value)
|
||||||
{
|
{
|
||||||
return value == null || value.isBlank();
|
return value == null || value.isBlank();
|
||||||
|
|||||||
@@ -37,6 +37,18 @@ public final class UpdateMetadataClient
|
|||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArtifactMetadata fetchPlexChannelLatest() throws MetadataException
|
||||||
|
{
|
||||||
|
String path = "/api/v1/projects/Plex/channels/" + channel.id() + "/latest.json";
|
||||||
|
ArtifactMetadata metadata = fetch(path);
|
||||||
|
Optional<String> validationError = metadata.validatePlex(channel);
|
||||||
|
if (validationError.isPresent())
|
||||||
|
{
|
||||||
|
throw new MetadataException(validationError.get(), false);
|
||||||
|
}
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
public ArtifactMetadata fetchModuleLatest(String moduleName, int apiCompatibility) throws MetadataException
|
public ArtifactMetadata fetchModuleLatest(String moduleName, int apiCompatibility) throws MetadataException
|
||||||
{
|
{
|
||||||
return fetchModuleLatest(moduleName, apiCompatibility, List.of());
|
return fetchModuleLatest(moduleName, apiCompatibility, List.of());
|
||||||
@@ -158,6 +170,11 @@ public final class UpdateMetadataClient
|
|||||||
{
|
{
|
||||||
private final boolean notFound;
|
private final boolean notFound;
|
||||||
|
|
||||||
|
public static MetadataException localError(String message)
|
||||||
|
{
|
||||||
|
return new MetadataException(message, false);
|
||||||
|
}
|
||||||
|
|
||||||
private MetadataException(String message, boolean notFound)
|
private MetadataException(String message, boolean notFound)
|
||||||
{
|
{
|
||||||
super(message);
|
super(message);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import java.nio.file.StandardCopyOption;
|
|||||||
import java.security.DigestInputStream;
|
import java.security.DigestInputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HexFormat;
|
import java.util.HexFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -36,6 +37,18 @@ public class UpdateChecker
|
|||||||
private ArtifactMetadata latestPlexMetadata;
|
private ArtifactMetadata latestPlexMetadata;
|
||||||
private UpdateMetadataClient.MetadataException latestPlexMetadataFailure;
|
private UpdateMetadataClient.MetadataException latestPlexMetadataFailure;
|
||||||
private long latestPlexMetadataFailureAtMillis;
|
private long latestPlexMetadataFailureAtMillis;
|
||||||
|
private ArtifactMetadata latestPlexChannelLatestMetadata;
|
||||||
|
private UpdateMetadataClient.MetadataException latestPlexChannelLatestMetadataFailure;
|
||||||
|
private long latestPlexChannelLatestMetadataFailureAtMillis;
|
||||||
|
|
||||||
|
public enum UpdateCheckStatus
|
||||||
|
{
|
||||||
|
UP_TO_DATE, UPDATE_AVAILABLE, MINECRAFT_TOO_OLD, MINECRAFT_TOO_NEW, MINECRAFT_UNLISTED, ERROR
|
||||||
|
}
|
||||||
|
|
||||||
|
public record UpdateCheckResult(UpdateCheckStatus status, ArtifactMetadata metadata, UpdateMetadataClient.MetadataException error)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public UpdateChecker(Plex plugin)
|
public UpdateChecker(Plex plugin)
|
||||||
{
|
{
|
||||||
@@ -44,56 +57,147 @@ public class UpdateChecker
|
|||||||
this.metadataClient = new UpdateMetadataClient(channel);
|
this.metadataClient = new UpdateMetadataClient(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UpdateCheckResult checkForUpdates(boolean useCache)
|
||||||
|
{
|
||||||
|
String runningMinecraftVersion = getRunningMinecraftVersion();
|
||||||
|
if (runningMinecraftVersion == null || runningMinecraftVersion.isBlank() || "unknown".equalsIgnoreCase(runningMinecraftVersion))
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.ERROR, null, UpdateMetadataClient.MetadataException.localError("running Minecraft version could not be determined"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ArtifactMetadata metadata = fetchLatestPlexMetadata(useCache, runningMinecraftVersion);
|
||||||
|
if (metadata.matchesCurrentBuild(plugin.getPluginMeta().getVersion(), BuildInfo.getNumber(), BuildInfo.getCommit()))
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.UP_TO_DATE, metadata, null);
|
||||||
|
}
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.UPDATE_AVAILABLE, metadata, null);
|
||||||
|
}
|
||||||
|
catch (UpdateMetadataClient.MetadataException e)
|
||||||
|
{
|
||||||
|
if (!e.notFound())
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.ERROR, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArtifactMetadata channelLatest;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
channelLatest = fetchPlexChannelLatestMetadata(useCache);
|
||||||
|
}
|
||||||
|
catch (UpdateMetadataClient.MetadataException e)
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.ERROR, null, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelLatest.matchesCurrentBuild(plugin.getPluginMeta().getVersion(), BuildInfo.getNumber(), BuildInfo.getCommit()))
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.UP_TO_DATE, channelLatest, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> supportedVersions = sortedSupportedVersions(channelLatest);
|
||||||
|
if (!supportedVersions.isEmpty())
|
||||||
|
{
|
||||||
|
String minimumVersion = supportedVersions.get(0);
|
||||||
|
String maximumVersion = supportedVersions.get(supportedVersions.size() - 1);
|
||||||
|
if (compareMinecraftVersions(runningMinecraftVersion, minimumVersion) < 0)
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.MINECRAFT_TOO_OLD, channelLatest, null);
|
||||||
|
}
|
||||||
|
if (compareMinecraftVersions(runningMinecraftVersion, maximumVersion) > 0)
|
||||||
|
{
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.MINECRAFT_TOO_NEW, channelLatest, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new UpdateCheckResult(UpdateCheckStatus.MINECRAFT_UNLISTED, channelLatest, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendResultMessage(CommandSender sender, UpdateCheckResult result, int verbosity)
|
||||||
|
{
|
||||||
|
switch (result.status())
|
||||||
|
{
|
||||||
|
case UP_TO_DATE:
|
||||||
|
if (verbosity == 2)
|
||||||
|
{
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateUpToDate", channel.id()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UPDATE_AVAILABLE:
|
||||||
|
if (verbosity >= 1)
|
||||||
|
{
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateAvailable", result.metadata().version(), channel.id()));
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateRunCommand"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MINECRAFT_TOO_OLD:
|
||||||
|
if (verbosity >= 1)
|
||||||
|
{
|
||||||
|
List<String> supportedVersions = sortedSupportedVersions(result.metadata());
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateRequiresNewerMinecraft",
|
||||||
|
result.metadata().version(), channel.id(), firstSupportedVersion(supportedVersions), getRunningMinecraftVersion(), String.join(", ", supportedVersions)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MINECRAFT_TOO_NEW:
|
||||||
|
if (verbosity >= 1)
|
||||||
|
{
|
||||||
|
List<String> supportedVersions = sortedSupportedVersions(result.metadata());
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateUnsupportedNewerMinecraft",
|
||||||
|
result.metadata().version(), channel.id(), lastSupportedVersion(supportedVersions), getRunningMinecraftVersion(), String.join(", ", supportedVersions)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MINECRAFT_UNLISTED:
|
||||||
|
if (verbosity >= 1)
|
||||||
|
{
|
||||||
|
List<String> supportedVersions = sortedSupportedVersions(result.metadata());
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateRequiresMinecraftVersion",
|
||||||
|
result.metadata().version(), channel.id(), String.join(", ", supportedVersions), getRunningMinecraftVersion()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
UpdateMetadataClient.MetadataException error = result.error();
|
||||||
|
if (error.notFound())
|
||||||
|
{
|
||||||
|
if (verbosity == 2)
|
||||||
|
{
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateMetadataNotFound", channel.id()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (verbosity >= 1)
|
||||||
|
{
|
||||||
|
sendMessage(sender, updateMetadataErrorComponent(error));
|
||||||
|
PlexLog.error("Unable to check for updates: {0}", error.getMessage());
|
||||||
|
if (error.getCause() != null)
|
||||||
|
{
|
||||||
|
error.getCause().printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If verbose is 0, it will display nothing
|
// If verbose is 0, it will display nothing
|
||||||
// If verbose is 1, it will only display a message if there is an update available
|
// If verbose is 1, it will only display a message if there is an update available
|
||||||
// If verbose is 2, it will display all messages
|
// If verbose is 2, it will display all messages
|
||||||
public boolean getUpdateStatusMessage(CommandSender sender, boolean cached, int verbosity)
|
public boolean getUpdateStatusMessage(CommandSender sender, boolean cached, int verbosity)
|
||||||
{
|
{
|
||||||
try
|
UpdateCheckResult result = checkForUpdates(cached);
|
||||||
{
|
sendResultMessage(sender, result, verbosity);
|
||||||
ArtifactMetadata metadata = fetchLatestPlexMetadata(cached);
|
return result.status() == UpdateCheckStatus.UPDATE_AVAILABLE;
|
||||||
if (metadata.matchesCurrentBuild(plugin.getPluginMeta().getVersion(), BuildInfo.getNumber(), BuildInfo.getCommit()))
|
|
||||||
{
|
|
||||||
if (verbosity == 2)
|
|
||||||
{
|
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateUpToDate", channel.id()));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbosity >= 1)
|
|
||||||
{
|
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateAvailable", metadata.version(), channel.id()));
|
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateRunCommand"));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (UpdateMetadataClient.MetadataException e)
|
|
||||||
{
|
|
||||||
if (verbosity == 2 || (verbosity >= 1 && !e.notFound()))
|
|
||||||
{
|
|
||||||
sendMessage(sender, updateMetadataErrorComponent(e));
|
|
||||||
}
|
|
||||||
if (!e.notFound())
|
|
||||||
{
|
|
||||||
PlexLog.error("Unable to check for updates: {0}", e.getMessage());
|
|
||||||
if (e.getCause() != null)
|
|
||||||
{
|
|
||||||
e.getCause().printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateJar(CommandSender sender, String name, boolean module)
|
public void updateJar(CommandSender sender, ArtifactMetadata metadata, Runnable onSuccess)
|
||||||
{
|
{
|
||||||
updateJar(sender, name, module, List.of());
|
File copyTo = new File(Bukkit.getUpdateFolderFile(), metadata.fileName());
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("updateDownloading", metadata.fileName()));
|
||||||
|
plugin.getApi().scheduler().runAsync(() -> downloadAndInstall(sender, metadata, copyTo, onSuccess));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void installModuleJar(CommandSender sender, String name)
|
public void installModuleJar(CommandSender sender, String name)
|
||||||
{
|
{
|
||||||
updateJar(sender, name, true, List.of(), () -> plugin.getApi().scheduler().runGlobal(() ->
|
updateJar(sender, name, List.of(), () -> plugin.getApi().scheduler().runGlobal(() ->
|
||||||
{
|
{
|
||||||
plugin.getModuleManager().reloadModules();
|
plugin.getModuleManager().reloadModules();
|
||||||
sendMessage(sender, PlexUtils.messageComponent("moduleRestartRequired"));
|
sendMessage(sender, PlexUtils.messageComponent("moduleRestartRequired"));
|
||||||
@@ -108,31 +212,20 @@ public class UpdateChecker
|
|||||||
sendMessage(sender, PlexUtils.messageComponent("moduleUpdateDisabled", moduleFile.getName()));
|
sendMessage(sender, PlexUtils.messageComponent("moduleUpdateDisabled", moduleFile.getName()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateJar(sender, moduleFile.getName(), true, moduleFile.getUpdateUrls());
|
updateJar(sender, moduleFile.getName(), moduleFile.getUpdateUrls());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateJar(CommandSender sender, String name, boolean module, List<String> moduleUpdateUrls)
|
private void updateJar(CommandSender sender, String name, List<String> moduleUpdateUrls)
|
||||||
{
|
{
|
||||||
updateJar(sender, name, module, moduleUpdateUrls, null);
|
updateJar(sender, name, moduleUpdateUrls, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateJar(CommandSender sender, String name, boolean module, List<String> moduleUpdateUrls, Runnable onSuccess)
|
private void updateJar(CommandSender sender, String name, List<String> moduleUpdateUrls, Runnable onSuccess)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ArtifactMetadata metadata = module
|
ArtifactMetadata metadata = metadataClient.fetchModuleLatest(name, plugin.getApi().compatibility().version(), moduleUpdateUrls);
|
||||||
? metadataClient.fetchModuleLatest(name, plugin.getApi().compatibility().version(), moduleUpdateUrls)
|
File copyTo = new File(plugin.getModulesFolder(), metadata.fileName());
|
||||||
: fetchLatestPlexMetadata(false);
|
|
||||||
|
|
||||||
if (!module && metadata.matchesCurrentBuild(plugin.getPluginMeta().getVersion(), BuildInfo.getNumber(), BuildInfo.getCommit()))
|
|
||||||
{
|
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateAlreadyUpToDate", channel.id()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File copyTo = module
|
|
||||||
? new File(plugin.getModulesFolder(), metadata.fileName())
|
|
||||||
: new File(Bukkit.getUpdateFolderFile(), metadata.fileName());
|
|
||||||
|
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateDownloading", metadata.fileName()));
|
sendMessage(sender, PlexUtils.messageComponent("updateDownloading", metadata.fileName()));
|
||||||
plugin.getApi().scheduler().runAsync(() -> downloadAndInstall(sender, metadata, copyTo, onSuccess));
|
plugin.getApi().scheduler().runAsync(() -> downloadAndInstall(sender, metadata, copyTo, onSuccess));
|
||||||
@@ -151,15 +244,15 @@ public class UpdateChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized ArtifactMetadata fetchLatestPlexMetadata(boolean cached) throws UpdateMetadataClient.MetadataException
|
private synchronized ArtifactMetadata fetchLatestPlexMetadata(boolean useCache, String runningMinecraftVersion) throws UpdateMetadataClient.MetadataException
|
||||||
{
|
{
|
||||||
if (cached)
|
if (useCache)
|
||||||
{
|
{
|
||||||
if (latestPlexMetadata != null)
|
if (latestPlexMetadata != null)
|
||||||
{
|
{
|
||||||
return latestPlexMetadata;
|
return latestPlexMetadata;
|
||||||
}
|
}
|
||||||
if (latestPlexMetadataFailure != null && isPlexMetadataFailureCacheFresh())
|
if (latestPlexMetadataFailure != null && isPlexMetadataFailureCacheFresh(latestPlexMetadataFailureAtMillis))
|
||||||
{
|
{
|
||||||
throw latestPlexMetadataFailure;
|
throw latestPlexMetadataFailure;
|
||||||
}
|
}
|
||||||
@@ -167,7 +260,7 @@ public class UpdateChecker
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
latestPlexMetadata = metadataClient.fetchPlexLatest(BuildInfo.getMinecraftVersion());
|
latestPlexMetadata = metadataClient.fetchPlexLatest(runningMinecraftVersion);
|
||||||
latestPlexMetadataFailure = null;
|
latestPlexMetadataFailure = null;
|
||||||
latestPlexMetadataFailureAtMillis = 0L;
|
latestPlexMetadataFailureAtMillis = 0L;
|
||||||
return latestPlexMetadata;
|
return latestPlexMetadata;
|
||||||
@@ -183,9 +276,116 @@ public class UpdateChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPlexMetadataFailureCacheFresh()
|
private synchronized ArtifactMetadata fetchPlexChannelLatestMetadata(boolean useCache) throws UpdateMetadataClient.MetadataException
|
||||||
{
|
{
|
||||||
return System.currentTimeMillis() - latestPlexMetadataFailureAtMillis < PLEX_METADATA_FAILURE_CACHE_MILLIS;
|
if (useCache)
|
||||||
|
{
|
||||||
|
if (latestPlexChannelLatestMetadata != null)
|
||||||
|
{
|
||||||
|
return latestPlexChannelLatestMetadata;
|
||||||
|
}
|
||||||
|
if (latestPlexChannelLatestMetadataFailure != null && isPlexMetadataFailureCacheFresh(latestPlexChannelLatestMetadataFailureAtMillis))
|
||||||
|
{
|
||||||
|
throw latestPlexChannelLatestMetadataFailure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
latestPlexChannelLatestMetadata = metadataClient.fetchPlexChannelLatest();
|
||||||
|
latestPlexChannelLatestMetadataFailure = null;
|
||||||
|
latestPlexChannelLatestMetadataFailureAtMillis = 0L;
|
||||||
|
return latestPlexChannelLatestMetadata;
|
||||||
|
}
|
||||||
|
catch (UpdateMetadataClient.MetadataException e)
|
||||||
|
{
|
||||||
|
if (latestPlexChannelLatestMetadata == null)
|
||||||
|
{
|
||||||
|
latestPlexChannelLatestMetadataFailure = e;
|
||||||
|
latestPlexChannelLatestMetadataFailureAtMillis = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> sortedSupportedVersions(ArtifactMetadata metadata)
|
||||||
|
{
|
||||||
|
List<String> supportedVersions = new ArrayList<>(metadata.minecraftVersions());
|
||||||
|
supportedVersions.sort(UpdateChecker::compareMinecraftVersions);
|
||||||
|
return supportedVersions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String firstSupportedVersion(List<String> supportedVersions)
|
||||||
|
{
|
||||||
|
return supportedVersions.isEmpty() ? "unknown" : supportedVersions.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String lastSupportedVersion(List<String> supportedVersions)
|
||||||
|
{
|
||||||
|
return supportedVersions.isEmpty() ? "unknown" : supportedVersions.get(supportedVersions.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int compareMinecraftVersions(String left, String right)
|
||||||
|
{
|
||||||
|
String[] leftParts = left.split("\\.");
|
||||||
|
String[] rightParts = right.split("\\.");
|
||||||
|
int length = Math.max(leftParts.length, rightParts.length);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
int leftPart = i < leftParts.length ? parseVersionPart(leftParts[i]) : 0;
|
||||||
|
int rightPart = i < rightParts.length ? parseVersionPart(rightParts[i]) : 0;
|
||||||
|
if (leftPart != rightPart)
|
||||||
|
{
|
||||||
|
return Integer.compare(leftPart, rightPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int parseVersionPart(String part)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Integer.parseInt(part);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException ignored)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPlexMetadataFailureCacheFresh(long failureAtMillis)
|
||||||
|
{
|
||||||
|
return System.currentTimeMillis() - failureAtMillis < PLEX_METADATA_FAILURE_CACHE_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRunningMinecraftVersion()
|
||||||
|
{
|
||||||
|
String version = Bukkit.getBukkitVersion();
|
||||||
|
int buildIndex = version.indexOf(".build");
|
||||||
|
if (buildIndex >= 0)
|
||||||
|
{
|
||||||
|
return version.substring(0, buildIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int separatorIndex = version.indexOf('-');
|
||||||
|
if (separatorIndex >= 0)
|
||||||
|
{
|
||||||
|
return version.substring(0, separatorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
String buildMinecraftVersion = BuildInfo.getMinecraftVersion();
|
||||||
|
int rangeIndex = buildMinecraftVersion.indexOf(" - ");
|
||||||
|
if (rangeIndex >= 0)
|
||||||
|
{
|
||||||
|
return buildMinecraftVersion.substring(0, rangeIndex);
|
||||||
|
}
|
||||||
|
int listIndex = buildMinecraftVersion.indexOf(',');
|
||||||
|
if (listIndex >= 0)
|
||||||
|
{
|
||||||
|
return buildMinecraftVersion.substring(0, listIndex);
|
||||||
|
}
|
||||||
|
return buildMinecraftVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadAndInstall(CommandSender sender, ArtifactMetadata metadata, File copyTo, Runnable onSuccess)
|
private void downloadAndInstall(CommandSender sender, ArtifactMetadata metadata, File copyTo, Runnable onSuccess)
|
||||||
|
|||||||
@@ -220,24 +220,6 @@ togglePvp: "PVP"
|
|||||||
togglePvpLower: "PVP"
|
togglePvpLower: "PVP"
|
||||||
toggleChat: "Chat"
|
toggleChat: "Chat"
|
||||||
toggleChatLower: "chat"
|
toggleChatLower: "chat"
|
||||||
toggleMenuExplosionsName: "<!italic><light_purple>Toggle explosions"
|
|
||||||
# 0 - The toggle status
|
|
||||||
toggleMenuExplosionsLore: "<!italic><yellow>Explosions are {0}"
|
|
||||||
toggleMenuFluidSpreadName: "<!italic><light_purple>Toggle fluid spread"
|
|
||||||
# 0 - The toggle status
|
|
||||||
toggleMenuFluidSpreadLore: "<!italic><yellow>Fluid spread is {0}"
|
|
||||||
toggleMenuDropsName: "<!italic><light_purple>Toggle drops"
|
|
||||||
# 0 - The toggle status
|
|
||||||
toggleMenuDropsLore: "<!italic><yellow>Drops are {0}"
|
|
||||||
toggleMenuRedstoneName: "<!italic><light_purple>Redstone"
|
|
||||||
# 0 - The toggle status
|
|
||||||
toggleMenuRedstoneLore: "<!italic><yellow>Redstone is {0}"
|
|
||||||
toggleMenuPvpName: "<!italic><light_purple>PVP"
|
|
||||||
# 0 - The toggle status
|
|
||||||
toggleMenuPvpLore: "<!italic><yellow>PVP is {0}"
|
|
||||||
toggleMenuChatName: "<!italic><light_purple>Toggle chat"
|
|
||||||
# 0 - The toggle status
|
|
||||||
toggleMenuChatLore: "<!italic><yellow>Chat is currently {0}"
|
|
||||||
specifyLoginMessage: "<red>Please specify a login message."
|
specifyLoginMessage: "<red>Please specify a login message."
|
||||||
# 0 - The login message
|
# 0 - The login message
|
||||||
setOwnLoginMessage: "<gray>Your login message is now:<newline><gray>> <reset>{0}"
|
setOwnLoginMessage: "<gray>Your login message is now:<newline><gray>> <reset>{0}"
|
||||||
@@ -312,27 +294,10 @@ prismRollbackMessage: "<gray>Rolled back {0} activities"
|
|||||||
# 0 - Error message returned from Prism
|
# 0 - Error message returned from Prism
|
||||||
prismRollbackError: "<red>Rollback failed: {0}"
|
prismRollbackError: "<red>Rollback failed: {0}"
|
||||||
prismNoResult: "<gray>No activities have been rolled back"
|
prismNoResult: "<gray>No activities have been rolled back"
|
||||||
pageNext: "<light_purple>Next Page"
|
|
||||||
pagePrevious: "<light_purple>Previous Page"
|
|
||||||
pageClose: "<red>Close"
|
|
||||||
pageableNotInitialized: "<red>Looks like this inventory was not initialized! Please contact a developer to report this."
|
|
||||||
pageNotFound: "<red>Could not find a page to open"
|
|
||||||
punishmentMenuTitle: "<aqua><bold>Punishments"
|
punishmentMenuTitle: "<aqua><bold>Punishments"
|
||||||
# 0 - The player
|
# 0 - The player
|
||||||
punishmentPlayerItem: "<!italic><yellow>{0}"
|
|
||||||
# 0 - The player
|
|
||||||
punishedPlayerMenuTitle: "<red><bold>Punishments - {0}"
|
punishedPlayerMenuTitle: "<red><bold>Punishments - {0}"
|
||||||
punishmentPlayerNotFound: '<red>This player does not exist. Try doing /punishments \<player> instead.'
|
punishmentPlayerNotFound: '<red>This player does not exist. Try doing /punishments \<player> instead.'
|
||||||
# 0 - The punishment type
|
|
||||||
punishmentItemTitle: "<!italic><red>{0}"
|
|
||||||
# 0 - The punisher
|
|
||||||
punishmentItemPunisher: "<!italic><red>By: <gold>{0}"
|
|
||||||
# 0 - The issue date
|
|
||||||
punishmentItemIssued: "<!italic><red>Issued: <gold>{0}"
|
|
||||||
# 0 - The expiration date
|
|
||||||
punishmentItemExpires: "<!italic><red>Expire(d/s): <gold>{0}"
|
|
||||||
# 0 - The reason
|
|
||||||
punishmentItemReason: "<!italic><red>Reason: <gold>{0}"
|
|
||||||
# 0 - The amount of active bans
|
# 0 - The amount of active bans
|
||||||
# 1 - The active ban list
|
# 1 - The active ban list
|
||||||
activeBansList: "<gold>Active Bans ({0}): <yellow>{1}"
|
activeBansList: "<gold>Active Bans ({0}): <yellow>{1}"
|
||||||
@@ -343,8 +308,6 @@ updateUpToDate: "<green>Plex is up to date on the {0} channel."
|
|||||||
# 1 - The channel
|
# 1 - The channel
|
||||||
updateAvailable: "<red>Plex {0} is available on the {1} channel."
|
updateAvailable: "<red>Plex {0} is available on the {1} channel."
|
||||||
updateRunCommand: "<red>Run: /plex update"
|
updateRunCommand: "<red>Run: /plex update"
|
||||||
# 0 - The channel
|
|
||||||
updateAlreadyUpToDate: "<red>Plex is already up to date on the {0} channel."
|
|
||||||
# 0 - The file name
|
# 0 - The file name
|
||||||
updateDownloading: "<green>Downloading latest JAR file: {0}"
|
updateDownloading: "<green>Downloading latest JAR file: {0}"
|
||||||
updateDownloaded: "<green>New JAR file downloaded and verified successfully."
|
updateDownloaded: "<green>New JAR file downloaded and verified successfully."
|
||||||
@@ -354,6 +317,23 @@ updateDirectoryFailed: "<red>Unable to create update directory: {0}"
|
|||||||
updateDownloadFailed: "<red>Something went wrong while downloading {0}. Please check the log for more information."
|
updateDownloadFailed: "<red>Something went wrong while downloading {0}. Please check the log for more information."
|
||||||
# 0 - The channel
|
# 0 - The channel
|
||||||
updateMetadataNotFound: "<red>No compatible update is available on the {0} channel."
|
updateMetadataNotFound: "<red>No compatible update is available on the {0} channel."
|
||||||
|
# 0 - The Plex version
|
||||||
|
# 1 - The channel
|
||||||
|
# 2 - The supported Minecraft versions
|
||||||
|
# 3 - The running Minecraft version
|
||||||
|
updateRequiresMinecraftVersion: "<yellow>No Plex build exists for Minecraft {3}. Plex {0} on the {1} channel supports Minecraft: {2}."
|
||||||
|
# 0 - The Plex version
|
||||||
|
# 1 - The channel
|
||||||
|
# 2 - The oldest supported Minecraft version
|
||||||
|
# 3 - The running Minecraft version
|
||||||
|
# 4 - The supported Minecraft versions
|
||||||
|
updateRequiresNewerMinecraft: "<yellow>Your server is running Minecraft {3}, which is older than any version supported by Plex {0} on the {1} channel (oldest supported: {2}). Supported versions: {4}."
|
||||||
|
# 0 - The Plex version
|
||||||
|
# 1 - The channel
|
||||||
|
# 2 - The newest supported Minecraft version
|
||||||
|
# 3 - The running Minecraft version
|
||||||
|
# 4 - The supported Minecraft versions
|
||||||
|
updateUnsupportedNewerMinecraft: "<yellow>No Plex build exists yet for Minecraft {3}. Plex {0} on the {1} channel supports up to Minecraft {2}. Supported versions: {4}."
|
||||||
# 0 - The error message
|
# 0 - The error message
|
||||||
updateMetadataError: "<red>There was an error checking update metadata: {0}"
|
updateMetadataError: "<red>There was an error checking update metadata: {0}"
|
||||||
moduleUpdateDisabled: "<yellow>Skipping {0}; module updates are disabled."
|
moduleUpdateDisabled: "<yellow>Skipping {0}; module updates are disabled."
|
||||||
|
|||||||
Reference in New Issue
Block a user