misc cleanup
This commit is contained in:
parent
3453f05aca
commit
c13b01da01
@ -28,10 +28,10 @@ package me.lucko.luckperms.bukkit.compat;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public final class ReflectionUtil {
|
||||
private static final String SERVER_VERSION = _getServerVersion();
|
||||
private static final String SERVER_VERSION = getServerVersion();
|
||||
private static final boolean CHAT_COMPATIBLE = !SERVER_VERSION.startsWith(".v1_7_");
|
||||
|
||||
private static String _getServerVersion() {
|
||||
private static String getServerVersion() {
|
||||
Class<?> server = Bukkit.getServer().getClass();
|
||||
if (!server.getSimpleName().equals("CraftServer")) {
|
||||
return ".";
|
||||
@ -45,16 +45,12 @@ public final class ReflectionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getServerVersion() {
|
||||
return SERVER_VERSION;
|
||||
}
|
||||
|
||||
public static boolean isChatCompatible() {
|
||||
return CHAT_COMPATIBLE;
|
||||
}
|
||||
|
||||
public static String nms(String className) {
|
||||
return "net.minecraft.server" + getServerVersion() + className;
|
||||
return "net.minecraft.server" + SERVER_VERSION + className;
|
||||
}
|
||||
|
||||
public static Class<?> nmsClass(String className) throws ClassNotFoundException {
|
||||
@ -62,7 +58,7 @@ public final class ReflectionUtil {
|
||||
}
|
||||
|
||||
public static String obc(String className) {
|
||||
return "org.bukkit.craftbukkit" + getServerVersion() + className;
|
||||
return "org.bukkit.craftbukkit" + SERVER_VERSION + className;
|
||||
}
|
||||
|
||||
public static Class<?> obcClass(String className) throws ClassNotFoundException {
|
||||
|
@ -32,13 +32,13 @@ import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class BukkitMigrationUtils {
|
||||
public final class BukkitUuids {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static UUID lookupUuid(ProgressLogger log, String s) {
|
||||
UUID uuid = Uuids.parseNullable(s);
|
||||
if (uuid == null) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
uuid = Bukkit.getOfflinePlayer(s).getUniqueId();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
@ -50,6 +50,6 @@ public final class BukkitMigrationUtils {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
private BukkitMigrationUtils() {}
|
||||
private BukkitUuids() {}
|
||||
|
||||
}
|
@ -155,7 +155,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
Iterators.iterate(world.getAll(CalculableType.USER), user -> {
|
||||
// There is no mention of UUIDs in the API. I assume that name = uuid. idk?
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, user.getName());
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, user.getName());
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
|
||||
AtomicInteger userWorldCount = new AtomicInteger(0);
|
||||
Iterators.iterate(wdh.getUserList(), user -> {
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, user.getUUID());
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, user.getUUID());
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public class MigrationPermissionsBukkit extends SubCommand<Object> {
|
||||
ConfigurationSection usersSection = config.getConfigurationSection("users");
|
||||
|
||||
Iterators.iterate(usersSection.getKeys(false), key -> {
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, key);
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, key);
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
int userWeight = maxWeight + 5;
|
||||
|
||||
Iterators.iterate(manager.getUsers(), user -> {
|
||||
UUID u = BukkitMigrationUtils.lookupUuid(log, user.getIdentifier());
|
||||
UUID u = BukkitUuids.lookupUuid(log, user.getIdentifier());
|
||||
if (u == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
// store user data for later
|
||||
Set<Membership> members = entity.getMemberships();
|
||||
for (Membership membership : members) {
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, membership.getMember());
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, membership.getMember());
|
||||
if (uuid == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@ -353,7 +352,7 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
@Override
|
||||
public ExtendedLogEntry build() {
|
||||
if (this.timestamp == 0L) {
|
||||
timestamp(DateUtil.unixSecondsNow());
|
||||
timestamp(System.currentTimeMillis() / 1000L);
|
||||
}
|
||||
|
||||
Objects.requireNonNull(this.actor, "actor");
|
||||
|
@ -36,7 +36,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.references.HolderType;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.Storage;
|
||||
import me.lucko.luckperms.common.utils.Cycle;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
@ -52,10 +51,14 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -180,13 +183,8 @@ public class Exporter implements Runnable {
|
||||
|
||||
write(writer, "# Export users");
|
||||
|
||||
// divide into 16 pools.
|
||||
Cycle<List<UUID>> userPools = new Cycle<>(nInstances(32, ArrayList::new));
|
||||
for (UUID uuid : users) {
|
||||
userPools.next().add(uuid);
|
||||
}
|
||||
|
||||
this.log.log("Split users into " + userPools.getBacking().size() + " threads for export.");
|
||||
// create a threadpool to process the users concurrently
|
||||
ExecutorService executor = Executors.newFixedThreadPool(32);
|
||||
|
||||
// Setup a file writing lock. We don't want multiple threads writing at the same time.
|
||||
// The write function accepts a list of strings, as we want a user's data to be grouped together.
|
||||
@ -203,61 +201,69 @@ public class Exporter implements Runnable {
|
||||
}
|
||||
};
|
||||
|
||||
// A set of futures, which are really just the threads we need to wait for.
|
||||
// A set of futures, which are really just the processes we need to wait for.
|
||||
Set<CompletableFuture<Void>> futures = new HashSet<>();
|
||||
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
|
||||
// iterate through each user sublist.
|
||||
for (List<UUID> subList : userPools.getBacking()) {
|
||||
|
||||
// register and start a new thread to process the sublist
|
||||
// iterate through each user.
|
||||
for (UUID uuid : users) {
|
||||
// register a task for the user, and schedule it's execution with the pool
|
||||
futures.add(CompletableFuture.runAsync(() -> {
|
||||
// actually export the user. this output will be fed to the writing function when we have all of the user's data.
|
||||
List<String> output = new ArrayList<>();
|
||||
|
||||
// iterate through each user in the sublist, and grab their data.
|
||||
for (UUID uuid : subList) {
|
||||
try {
|
||||
// actually export the user. this output will be fed to the writing function when we have all of the user's data.
|
||||
List<String> output = new ArrayList<>();
|
||||
User user = this.plugin.getStorage().loadUser(uuid, null).join();
|
||||
output.add("# Export user: " + user.getUuid().toString() + " - " + user.getName().orElse("unknown username"));
|
||||
|
||||
User user = this.plugin.getStorage().loadUser(uuid, null).join();
|
||||
output.add("# Export user: " + user.getUuid().toString() + " - " + user.getName().orElse("unknown username"));
|
||||
|
||||
boolean inDefault = false;
|
||||
for (Node node : user.getEnduringNodes().values()) {
|
||||
if (node.isGroupNode() && node.getGroupName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
|
||||
inDefault = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
output.add("/lp " + NodeFactory.nodeAsCommand(node, user.getUuid().toString(), HolderType.USER, true));
|
||||
}
|
||||
|
||||
if (!user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME).equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
|
||||
output.add("/lp user " + user.getUuid().toString() + " switchprimarygroup " + user.getPrimaryGroup().getStoredValue().get());
|
||||
}
|
||||
|
||||
if (!inDefault) {
|
||||
output.add("/lp user " + user.getUuid().toString() + " parent remove default");
|
||||
}
|
||||
|
||||
this.plugin.getUserManager().cleanup(user);
|
||||
writeFunction.accept(output);
|
||||
|
||||
this.log.logProgress("Exported {} users so far.", userCount.incrementAndGet());
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
boolean inDefault = false;
|
||||
for (Node node : user.getEnduringNodes().values()) {
|
||||
if (node.isGroupNode() && node.getGroupName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
|
||||
inDefault = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
output.add("/lp " + NodeFactory.nodeAsCommand(node, user.getUuid().toString(), HolderType.USER, true));
|
||||
}
|
||||
}, this.plugin.getBootstrap().getScheduler().async()));
|
||||
|
||||
if (!user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME).equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
|
||||
output.add("/lp user " + user.getUuid().toString() + " switchprimarygroup " + user.getPrimaryGroup().getStoredValue().get());
|
||||
}
|
||||
|
||||
if (!inDefault) {
|
||||
output.add("/lp user " + user.getUuid().toString() + " parent remove default");
|
||||
}
|
||||
|
||||
this.plugin.getUserManager().cleanup(user);
|
||||
writeFunction.accept(output);
|
||||
|
||||
userCount.incrementAndGet();
|
||||
}, executor));
|
||||
}
|
||||
|
||||
// all of the threads have been scheduled now and are running. we just need to wait for them all to complete
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
|
||||
CompletableFuture<Void> overallFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
overallFuture.get(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
// abnormal error - just break
|
||||
e.printStackTrace();
|
||||
break;
|
||||
} catch (TimeoutException e) {
|
||||
// still executing - send a progress report and continue waiting
|
||||
this.log.logAllProgress("Exported {} users so far.", userCount.get());
|
||||
continue;
|
||||
}
|
||||
|
||||
// process is complete
|
||||
break;
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
|
||||
this.log.log("Exported " + userCount.get() + " users.");
|
||||
|
||||
writer.flush();
|
||||
this.log.getListeners().forEach(l -> Message.LOG_EXPORT_SUCCESS.send(l, this.filePath.toFile().getAbsolutePath()));
|
||||
|
||||
@ -265,12 +271,4 @@ public class Exporter implements Runnable {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> List<T> nInstances(int count, Supplier<T> supplier) {
|
||||
List<T> ret = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
ret.add(supplier.get());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -113,10 +113,10 @@ public class Importer implements Runnable {
|
||||
// join the update task future before scheduling command executions
|
||||
updateTask.join();
|
||||
|
||||
// build a list of commands to be executed by each thread
|
||||
// create a threadpool for the processing
|
||||
ExecutorService executor = Executors.newFixedThreadPool(128);
|
||||
|
||||
// A set of futures, which are really just the threads we need to wait for.
|
||||
// A set of futures, which are really just the processes we need to wait for.
|
||||
Set<CompletableFuture<Void>> futures = new HashSet<>();
|
||||
|
||||
AtomicInteger processedCount = new AtomicInteger(0);
|
||||
|
@ -32,7 +32,7 @@ import me.lucko.luckperms.common.command.abstraction.CommandException;
|
||||
import me.lucko.luckperms.common.model.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.DataConstraints;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DateParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -101,19 +101,23 @@ public class ArgumentParser {
|
||||
duration = Long.parseLong(args.get(index));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(index), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
duration = DateParser.parseDate(args.get(index), true);
|
||||
} catch (IllegalArgumentException e1) {
|
||||
throw new InvalidDateException(args.get(index));
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
if (shouldExpire(duration)) {
|
||||
throw new PastDateException();
|
||||
}
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
private static boolean shouldExpire(long unixTime) {
|
||||
return unixTime < (System.currentTimeMillis() / 1000L);
|
||||
}
|
||||
|
||||
public static Optional<TemporaryModifier> parseTemporaryModifier(int index, List<String> args) {
|
||||
if (index < 0 || index >= args.size()) {
|
||||
return Optional.empty();
|
||||
|
@ -48,7 +48,7 @@ import me.lucko.luckperms.common.model.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
|
||||
@ -95,7 +95,7 @@ public class MetaAddTempChatMeta extends SharedSubCommand {
|
||||
if (ret.getKey().asBoolean()) {
|
||||
duration = ret.getValue().getExpiryUnixTime();
|
||||
|
||||
TextComponent.Builder builder = TextUtils.fromLegacy(Message.ADD_TEMP_CHATMETA_SUCCESS.asString(plugin.getLocaleManager(), holder.getFriendlyName(), this.type.name().toLowerCase(), meta, priority, DateUtil.formatDateDiff(duration), MessageUtils.contextSetToString(context)), CommandManager.SECTION_CHAR).toBuilder();
|
||||
TextComponent.Builder builder = TextUtils.fromLegacy(Message.ADD_TEMP_CHATMETA_SUCCESS.asString(plugin.getLocaleManager(), holder.getFriendlyName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(context)), CommandManager.SECTION_CHAR).toBuilder();
|
||||
HoverEvent event = new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextUtils.fromLegacy(
|
||||
"¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta,
|
||||
'¥'
|
||||
|
@ -46,7 +46,7 @@ import me.lucko.luckperms.common.model.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
|
||||
@ -93,7 +93,7 @@ public class MetaSetTemp extends SharedSubCommand {
|
||||
holder.clearMetaKeys(key, context, true);
|
||||
duration = holder.setPermission(n, modifier).getValue().getExpiryUnixTime();
|
||||
|
||||
TextComponent.Builder builder = TextUtils.fromLegacy(Message.SET_META_TEMP_SUCCESS.asString(plugin.getLocaleManager(), key, value, holder.getFriendlyName(), DateUtil.formatDateDiff(duration), MessageUtils.contextSetToString(context)), CommandManager.SECTION_CHAR).toBuilder();
|
||||
TextComponent.Builder builder = TextUtils.fromLegacy(Message.SET_META_TEMP_SUCCESS.asString(plugin.getLocaleManager(), key, value, holder.getFriendlyName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(context)), CommandManager.SECTION_CHAR).toBuilder();
|
||||
HoverEvent event = new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextUtils.fromLegacy(
|
||||
TextUtils.joinNewline("¥3Raw key: ¥r" + key, "¥3Raw value: ¥r" + value),
|
||||
'¥'
|
||||
|
@ -47,7 +47,7 @@ import me.lucko.luckperms.common.model.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -96,7 +96,7 @@ public class ParentAddTemp extends SharedSubCommand {
|
||||
|
||||
if (ret.getKey().asBoolean()) {
|
||||
duration = ret.getValue().getExpiryUnixTime();
|
||||
Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getFriendlyName(), DateUtil.formatDateDiff(duration), MessageUtils.contextSetToString(context));
|
||||
Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getFriendlyName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(context));
|
||||
|
||||
ExtendedLogEntry.build().actor(sender).acted(holder)
|
||||
.action("parent", "addtemp", group.getName(), duration, context)
|
||||
|
@ -45,7 +45,7 @@ import me.lucko.luckperms.common.node.NodeWithContextComparator;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
@ -115,7 +115,7 @@ public class ParentInfo extends SharedSubCommand {
|
||||
for (LocalizedNode node : content) {
|
||||
String s = "&3> &a" + node.getGroupName() + MessageUtils.getAppendableNodeContextString(node);
|
||||
if (node.isTemporary()) {
|
||||
s += "\n&2 expires in " + DateUtil.formatDateDiff(node.getExpiryUnixTime());
|
||||
s += "\n&2 expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime());
|
||||
}
|
||||
|
||||
TextComponent message = TextUtils.fromLegacy(s, CommandManager.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(holder, label, node)).build();
|
||||
|
@ -45,7 +45,7 @@ import me.lucko.luckperms.common.node.NodeWithContextComparator;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
@ -120,7 +120,7 @@ public class PermissionInfo extends SharedSubCommand {
|
||||
for (LocalizedNode node : content) {
|
||||
String s = "&3> " + (node.getValuePrimitive() ? "&a" : "&c") + node.getPermission() + (sender.isConsole() ? " &7(" + node.getValuePrimitive() + "&7)" : "") + MessageUtils.getAppendableNodeContextString(node);
|
||||
if (node.isTemporary()) {
|
||||
s += "\n&2- expires in " + DateUtil.formatDateDiff(node.getExpiryUnixTime());
|
||||
s += "\n&2- expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime());
|
||||
}
|
||||
|
||||
TextComponent message = TextUtils.fromLegacy(s, CommandManager.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(holder, label, node)).build();
|
||||
|
@ -46,7 +46,7 @@ import me.lucko.luckperms.common.model.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -87,7 +87,7 @@ public class PermissionSetTemp extends SharedSubCommand {
|
||||
|
||||
if (result.getKey().asBoolean()) {
|
||||
duration = result.getValue().getExpiryUnixTime();
|
||||
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, value, holder.getFriendlyName(), DateUtil.formatDateDiff(duration), MessageUtils.contextSetToString(context));
|
||||
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, value, holder.getFriendlyName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(context));
|
||||
|
||||
ExtendedLogEntry.build().actor(sender).acted(holder)
|
||||
.action("permission", "settemp", node, value, duration, context)
|
||||
|
@ -37,7 +37,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -83,7 +83,7 @@ public class GroupInfo extends SubCommand<Group> {
|
||||
Message.INFO_TEMP_PARENT_HEADER.send(sender);
|
||||
for (Node node : tempParents) {
|
||||
Message.EMPTY.send(sender, "&f- &3> &f" + node.getGroupName() + MessageUtils.getAppendableNodeContextString(node));
|
||||
Message.EMPTY.send(sender, "&f- &2- expires in " + DateUtil.formatDateDiff(node.getExpiryUnixTime()));
|
||||
Message.EMPTY.send(sender, "&f- &2- expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()));
|
||||
}
|
||||
}
|
||||
return CommandResult.SUCCESS;
|
||||
|
@ -46,7 +46,7 @@ import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.references.HolderType;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
@ -150,7 +150,7 @@ public class GroupListMembers extends SubCommand<Group> {
|
||||
return "";
|
||||
}
|
||||
|
||||
return " &8(&7expires in " + DateUtil.formatDateDiff(node.getExpiryUnixTime()) + "&8)";
|
||||
return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()) + "&8)";
|
||||
}
|
||||
|
||||
private static Consumer<BuildableComponent.Builder<? ,?>> makeFancy(String holderName, HolderType holderType, String label, HeldPermission<?> perm) {
|
||||
|
@ -37,7 +37,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.DataConstraints;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -90,12 +90,12 @@ public class LogGroupHistory extends SubCommand<Log> {
|
||||
String name = entries.values().stream().findAny().get().getActedName();
|
||||
Message.LOG_HISTORY_GROUP_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
long now = DateUtil.unixSecondsNow();
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, ExtendedLogEntry> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DateUtil.formatTimeBrief(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
e.getValue().getActorFriendlyString(),
|
||||
Character.toString(e.getValue().getType().getCode()),
|
||||
e.getValue().getActedFriendlyString(),
|
||||
|
@ -37,7 +37,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.DataConstraints;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.Uuids;
|
||||
|
||||
@ -139,12 +139,12 @@ public class LogRecent extends SubCommand<Log> {
|
||||
Message.LOG_RECENT_HEADER.send(sender, page, maxPage);
|
||||
}
|
||||
|
||||
long now = DateUtil.unixSecondsNow();
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, ExtendedLogEntry> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DateUtil.formatTimeBrief(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
e.getValue().getActorFriendlyString(),
|
||||
Character.toString(e.getValue().getType().getCode()),
|
||||
e.getValue().getActedFriendlyString(),
|
||||
|
@ -35,7 +35,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -81,12 +81,12 @@ public class LogSearch extends SubCommand<Log> {
|
||||
SortedMap<Integer, ExtendedLogEntry> entries = log.getSearch(page, query, ENTRIES_PER_PAGE);
|
||||
Message.LOG_SEARCH_HEADER.send(sender, query, page, maxPage);
|
||||
|
||||
long now = DateUtil.unixSecondsNow();
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, ExtendedLogEntry> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DateUtil.formatTimeBrief(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
e.getValue().getActorFriendlyString(),
|
||||
Character.toString(e.getValue().getType().getCode()),
|
||||
e.getValue().getActedFriendlyString(),
|
||||
|
@ -37,7 +37,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.DataConstraints;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -90,12 +90,12 @@ public class LogTrackHistory extends SubCommand<Log> {
|
||||
String name = entries.values().stream().findAny().get().getActedName();
|
||||
Message.LOG_HISTORY_TRACK_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
long now = DateUtil.unixSecondsNow();
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, ExtendedLogEntry> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DateUtil.formatTimeBrief(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
e.getValue().getActorFriendlyString(),
|
||||
Character.toString(e.getValue().getType().getCode()),
|
||||
e.getValue().getActedFriendlyString(),
|
||||
|
@ -37,7 +37,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.DataConstraints;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.Uuids;
|
||||
|
||||
@ -119,12 +119,12 @@ public class LogUserHistory extends SubCommand<Log> {
|
||||
String name = entries.values().stream().findAny().get().getActedName();
|
||||
Message.LOG_HISTORY_USER_HEADER.send(sender, name, page, maxPage);
|
||||
|
||||
long now = DateUtil.unixSecondsNow();
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
for (Map.Entry<Integer, ExtendedLogEntry> e : entries.entrySet()) {
|
||||
long time = e.getValue().getTimestamp();
|
||||
Message.LOG_ENTRY.send(sender,
|
||||
e.getKey(),
|
||||
DateUtil.formatTimeBrief(now - time),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format(now - time),
|
||||
e.getValue().getActorFriendlyString(),
|
||||
Character.toString(e.getValue().getType().getCode()),
|
||||
e.getValue().getActedFriendlyString(),
|
||||
|
@ -45,7 +45,7 @@ import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.node.NodeModel;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.web.WebEditor;
|
||||
|
||||
@ -141,7 +141,7 @@ public class ApplyEditsCommand extends SingleCommand {
|
||||
|
||||
private static String formatNode(Node n) {
|
||||
return n.getPermission() + " &7(" + (n.getValuePrimitive() ? "&a" : "&c") + n.getValuePrimitive() + "&7)" + MessageUtils.getAppendableNodeContextString(n) +
|
||||
(n.isTemporary() ? " &7(" + DateUtil.formatDateDiffShort(n.getExpiryUnixTime()) + ")" : "");
|
||||
(n.isTemporary() ? " &7(" + DurationFormatter.CONCISE.formatDateDiff(n.getExpiryUnixTime()) + ")" : "");
|
||||
}
|
||||
|
||||
private static Map.Entry<Set<Node>, Set<Node>> diff(Set<Node> before, Set<Node> after) {
|
||||
|
@ -35,7 +35,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -66,7 +66,7 @@ public class InfoCommand extends SingleCommand {
|
||||
plugin.getContextManager().getStaticContextString().orElse("None"),
|
||||
plugin.getBootstrap().getPlayerCount(),
|
||||
plugin.getConnectionListener().getUniqueConnections().size(),
|
||||
DateUtil.formatTimeBrief((System.currentTimeMillis() - plugin.getBootstrap().getStartupTime()) / 1000L),
|
||||
DurationFormatter.CONCISE_LOW_ACCURACY.format((System.currentTimeMillis() - plugin.getBootstrap().getStartupTime()) / 1000L),
|
||||
plugin.getUserManager().getAll().size(),
|
||||
plugin.getGroupManager().getAll().size(),
|
||||
plugin.getTrackManager().getAll().size()
|
||||
|
@ -45,7 +45,7 @@ import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.references.HolderType;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
@ -149,7 +149,7 @@ public class SearchCommand extends SingleCommand {
|
||||
return "";
|
||||
}
|
||||
|
||||
return " &8(&7expires in " + DateUtil.formatDateDiff(node.getExpiryUnixTime()) + "&8)";
|
||||
return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()) + "&8)";
|
||||
}
|
||||
|
||||
private static Consumer<BuildableComponent.Builder<?, ?>> makeFancy(String holderName, HolderType holderType, String label, HeldPermission<?> perm) {
|
||||
|
@ -42,7 +42,7 @@ import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@ -93,7 +93,7 @@ public class UserInfo extends SubCommand<User> {
|
||||
Message.INFO_TEMP_PARENT_HEADER.send(sender);
|
||||
for (Node node : tempParents) {
|
||||
Message.EMPTY.send(sender, "&f- &3> &f" + node.getGroupName() + MessageUtils.getAppendableNodeContextString(node));
|
||||
Message.EMPTY.send(sender, "&f- &2- expires in " + DateUtil.formatDateDiff(node.getExpiryUnixTime()));
|
||||
Message.EMPTY.send(sender, "&f- &2- expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,12 @@
|
||||
|
||||
package me.lucko.luckperms.common.event;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
||||
import me.lucko.luckperms.api.event.Cancellable;
|
||||
import me.lucko.luckperms.api.event.EventBus;
|
||||
@ -34,7 +39,8 @@ import me.lucko.luckperms.api.event.LuckPermsEvent;
|
||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -42,13 +48,42 @@ import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Simple implementation of EventBus.
|
||||
*/
|
||||
public class LuckPermsEventBus implements EventBus {
|
||||
|
||||
/**
|
||||
* The plugin instance
|
||||
*/
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
/**
|
||||
* The api provider instance
|
||||
*/
|
||||
private final LuckPermsApiProvider apiProvider;
|
||||
|
||||
private final Map<Class<? extends LuckPermsEvent>, Set<LuckPermsEventHandler<?>>> handlerMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* The registered handlers in this event bus
|
||||
*/
|
||||
private final Multimap<Class<? extends LuckPermsEvent>, LuckPermsEventHandler<?>> handlerMap = Multimaps.newSetMultimap(new ConcurrentHashMap<>(), ConcurrentHashMap::newKeySet);
|
||||
|
||||
/**
|
||||
* A cache of event class --> applicable handlers.
|
||||
*
|
||||
* A registered "handler" will be passed all possible events it can handle, according to
|
||||
* {@link Class#isAssignableFrom(Class)}.
|
||||
*/
|
||||
private final LoadingCache<Class<? extends LuckPermsEvent>, List<LuckPermsEventHandler<?>>> handlerCache = Caffeine.newBuilder()
|
||||
.build(eventClass -> {
|
||||
ImmutableList.Builder<LuckPermsEventHandler<?>> matched = ImmutableList.builder();
|
||||
LuckPermsEventBus.this.handlerMap.asMap().forEach((clazz, handlers) -> {
|
||||
if (clazz.isAssignableFrom(eventClass)) {
|
||||
matched.addAll(handlers);
|
||||
}
|
||||
});
|
||||
return matched.build();
|
||||
});
|
||||
|
||||
public LuckPermsEventBus(LuckPermsPlugin plugin, LuckPermsApiProvider apiProvider) {
|
||||
this.plugin = plugin;
|
||||
@ -68,36 +103,28 @@ public class LuckPermsEventBus implements EventBus {
|
||||
throw new IllegalArgumentException("class " + eventClass.getName() + " does not implement LuckPermsEvent");
|
||||
}
|
||||
|
||||
Set<LuckPermsEventHandler<?>> handlers = this.handlerMap.computeIfAbsent(eventClass, c -> ConcurrentHashMap.newKeySet());
|
||||
|
||||
LuckPermsEventHandler<T> eventHandler = new LuckPermsEventHandler<>(this, eventClass, handler);
|
||||
handlers.add(eventHandler);
|
||||
this.handlerMap.put(eventClass, eventHandler);
|
||||
this.handlerCache.invalidateAll();
|
||||
|
||||
return eventHandler;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuckPermsEvent> Set<EventHandler<T>> getHandlers(@Nonnull Class<T> eventClass) {
|
||||
Set<LuckPermsEventHandler<?>> handlers = this.handlerMap.get(eventClass);
|
||||
if (handlers == null) {
|
||||
return ImmutableSet.of();
|
||||
} else {
|
||||
ImmutableSet.Builder<EventHandler<T>> ret = ImmutableSet.builder();
|
||||
for (LuckPermsEventHandler<?> handler : handlers) {
|
||||
ret.add((EventHandler<T>) handler);
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
Collection<LuckPermsEventHandler<?>> handlers = this.handlerMap.asMap().get(eventClass);
|
||||
ImmutableSet.Builder<EventHandler<T>> ret = ImmutableSet.builder();
|
||||
for (LuckPermsEventHandler<?> handler : handlers) {
|
||||
//noinspection unchecked
|
||||
ret.add((EventHandler<T>) handler);
|
||||
}
|
||||
return ret.build();
|
||||
}
|
||||
|
||||
public void unregisterHandler(LuckPermsEventHandler<?> handler) {
|
||||
Set<LuckPermsEventHandler<?>> handlers = this.handlerMap.get(handler.getEventClass());
|
||||
if (handlers != null) {
|
||||
handlers.remove(handler);
|
||||
}
|
||||
this.handlerMap.remove(handler.getEventClass(), handler);
|
||||
this.handlerCache.invalidateAll();
|
||||
}
|
||||
|
||||
public void fireEvent(LuckPermsEvent event) {
|
||||
@ -105,12 +132,13 @@ public class LuckPermsEventBus implements EventBus {
|
||||
((AbstractEvent) event).setApi(this.apiProvider);
|
||||
}
|
||||
|
||||
for (Map.Entry<Class<? extends LuckPermsEvent>, Set<LuckPermsEventHandler<?>>> ent : this.handlerMap.entrySet()) {
|
||||
if (!ent.getKey().isAssignableFrom(event.getClass())) {
|
||||
continue;
|
||||
}
|
||||
List<LuckPermsEventHandler<?>> handlers = this.handlerCache.get(event.getClass());
|
||||
if (handlers == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ent.getValue().forEach(h -> h.handle(event));
|
||||
for (LuckPermsEventHandler<?> handler : handlers) {
|
||||
handler.handle(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,6 @@ import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -248,12 +247,12 @@ public final class ImmutableNode implements Node {
|
||||
@Override
|
||||
public long getSecondsTilExpiry() {
|
||||
checkState(isTemporary(), "Node does not have an expiry time.");
|
||||
return this.expireAt - DateUtil.unixSecondsNow();
|
||||
return this.expireAt - System.currentTimeMillis() / 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExpired() {
|
||||
return isTemporary() && this.expireAt < DateUtil.unixSecondsNow();
|
||||
return isTemporary() && this.expireAt < System.currentTimeMillis() / 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,16 +58,16 @@ public final class LegacyNodeFactory {
|
||||
private static final String[] GENERIC_DELIMITERS = new String[]{".", "/", "-", "$"};
|
||||
|
||||
// legacy node format delimiters
|
||||
private static final Pattern LEGACY_SERVER_DELIM = PatternCache.compileDelimitedMatcher("/", "\\");
|
||||
private static final Pattern LEGACY_SERVER_DELIM = PatternCache.compileDelimiterPattern("/", "\\");
|
||||
private static final Splitter LEGACY_SERVER_SPLITTER = Splitter.on(LEGACY_SERVER_DELIM).limit(2);
|
||||
private static final Pattern LEGACY_WORLD_DELIM = PatternCache.compileDelimitedMatcher("-", "\\");
|
||||
private static final Pattern LEGACY_WORLD_DELIM = PatternCache.compileDelimiterPattern("-", "\\");
|
||||
private static final Splitter LEGACY_WORLD_SPLITTER = Splitter.on(LEGACY_WORLD_DELIM).limit(2);
|
||||
private static final Pattern LEGACY_EXPIRY_DELIM = PatternCache.compileDelimitedMatcher("$", "\\");
|
||||
private static final Pattern LEGACY_EXPIRY_DELIM = PatternCache.compileDelimiterPattern("$", "\\");
|
||||
private static final Splitter LEGACY_EXPIRY_SPLITTER = Splitter.on(LEGACY_EXPIRY_DELIM).limit(2);
|
||||
private static final Pattern LEGACY_CONTEXT_DELIM = PatternCache.compileDelimitedMatcher(")", "\\");
|
||||
private static final Pattern LEGACY_CONTEXT_DELIM = PatternCache.compileDelimiterPattern(")", "\\");
|
||||
private static final Splitter CONTEXT_SPLITTER = Splitter.on(LEGACY_CONTEXT_DELIM).limit(2);
|
||||
private static final Pattern LEGACY_CONTEXT_PAIR_DELIM = PatternCache.compileDelimitedMatcher(",", "\\");
|
||||
private static final Pattern LEGACY_CONTEXT_PAIR_PART_DELIM = PatternCache.compileDelimitedMatcher("=", "\\");
|
||||
private static final Pattern LEGACY_CONTEXT_PAIR_DELIM = PatternCache.compileDelimiterPattern(",", "\\");
|
||||
private static final Pattern LEGACY_CONTEXT_PAIR_PART_DELIM = PatternCache.compileDelimiterPattern("=", "\\");
|
||||
private static final Splitter.MapSplitter LEGACY_CONTEXT_PART_SPLITTER = Splitter.on(LEGACY_CONTEXT_PAIR_DELIM)
|
||||
.withKeyValueSeparator(Splitter.on(LEGACY_CONTEXT_PAIR_PART_DELIM));
|
||||
|
||||
|
@ -56,7 +56,7 @@ public final class NodeFactory {
|
||||
private static final String WEIGHT_NODE_MARKER = WEIGHT_KEY + ".";
|
||||
|
||||
// used to split prefix/suffix/meta nodes
|
||||
private static final Splitter META_SPLITTER = Splitter.on(PatternCache.compileDelimitedMatcher(".", "\\")).limit(2);
|
||||
private static final Splitter META_SPLITTER = Splitter.on(PatternCache.compileDelimiterPattern(".", "\\")).limit(2);
|
||||
|
||||
public static Node.Builder builder(String s) {
|
||||
return new NodeBuilder(s);
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -57,8 +55,6 @@ public final class DataConstraints {
|
||||
|
||||
public static final Predicate<String> TRACK_NAME_TEST_ALLOW_SPACE = s -> !s.isEmpty() && s.length() <= MAX_TRACK_NAME_LENGTH;
|
||||
|
||||
public static final Predicate<Long> TIME_TEST = unixTime -> !DateUtil.shouldExpire(unixTime);
|
||||
|
||||
public static final Predicate<String> SERVER_NAME_TEST = s -> !s.isEmpty() && s.length() <= MAX_SERVER_LENGTH && !s.contains(" ");
|
||||
|
||||
public static final Predicate<String> WORLD_NAME_TEST = s -> !s.isEmpty() && s.length() <= MAX_WORLD_LENGTH;
|
||||
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A cycle of elements, backed by a list. All operations are thread safe.
|
||||
*
|
||||
* @param <E> the element type
|
||||
*/
|
||||
public class Cycle<E> {
|
||||
|
||||
/**
|
||||
* The list that backs this instance
|
||||
*/
|
||||
private final List<E> objects;
|
||||
|
||||
/**
|
||||
* The number of elements in the cycle
|
||||
*/
|
||||
private final int size;
|
||||
|
||||
/**
|
||||
* The current position of the cursor
|
||||
*/
|
||||
private final AtomicInteger cursor = new AtomicInteger(0);
|
||||
|
||||
public Cycle(List<E> objects) {
|
||||
if (objects == null || objects.isEmpty()) {
|
||||
throw new IllegalArgumentException("List of objects cannot be null/empty.");
|
||||
}
|
||||
this.objects = ImmutableList.copyOf(objects);
|
||||
this.size = this.objects.size();
|
||||
}
|
||||
|
||||
public int cursor() {
|
||||
return this.cursor.get();
|
||||
}
|
||||
|
||||
public E current() {
|
||||
return this.objects.get(cursor());
|
||||
}
|
||||
|
||||
public E next() {
|
||||
return this.objects.get(this.cursor.updateAndGet(i -> {
|
||||
int n = i + 1;
|
||||
if (n >= this.size) {
|
||||
return 0;
|
||||
}
|
||||
return n;
|
||||
}));
|
||||
}
|
||||
|
||||
public E previous() {
|
||||
return this.objects.get(this.cursor.updateAndGet(i -> {
|
||||
if (i == 0) {
|
||||
return this.size - 1;
|
||||
}
|
||||
return i - 1;
|
||||
}));
|
||||
}
|
||||
|
||||
public List<E> getBacking() {
|
||||
return this.objects;
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Translates unix timestamps / durations into a readable format
|
||||
*
|
||||
* @author khobbits, drtshock, vemacs
|
||||
* see: https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
|
||||
*/
|
||||
public final class DateParser {
|
||||
private static final Pattern TIME_PATTERN = Pattern.compile("(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE);
|
||||
private static final int MAX_YEARS = 100000;
|
||||
|
||||
/**
|
||||
* Converts a time string to a unix timestamp
|
||||
*
|
||||
* @param time the time string
|
||||
* @param future if the date is in the future, as opposed to the past
|
||||
* @return a unix timestamp
|
||||
* @throws IllegalArgumentException if the date input was invalid
|
||||
*/
|
||||
public static long parseDate(String time, boolean future) throws IllegalArgumentException {
|
||||
Matcher matcher = TIME_PATTERN.matcher(time);
|
||||
int years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0;
|
||||
|
||||
boolean found = false;
|
||||
while (matcher.find()) {
|
||||
if (matcher.group() == null || matcher.group().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < matcher.groupCount(); i++) {
|
||||
if (matcher.group(i) != null && !matcher.group(i).isEmpty()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (matcher.group(1) != null && !matcher.group(1).isEmpty()) {
|
||||
years = Integer.parseInt(matcher.group(1));
|
||||
}
|
||||
if (matcher.group(2) != null && !matcher.group(2).isEmpty()) {
|
||||
months = Integer.parseInt(matcher.group(2));
|
||||
}
|
||||
if (matcher.group(3) != null && !matcher.group(3).isEmpty()) {
|
||||
weeks = Integer.parseInt(matcher.group(3));
|
||||
}
|
||||
if (matcher.group(4) != null && !matcher.group(4).isEmpty()) {
|
||||
days = Integer.parseInt(matcher.group(4));
|
||||
}
|
||||
if (matcher.group(5) != null && !matcher.group(5).isEmpty()) {
|
||||
hours = Integer.parseInt(matcher.group(5));
|
||||
}
|
||||
if (matcher.group(6) != null && !matcher.group(6).isEmpty()) {
|
||||
minutes = Integer.parseInt(matcher.group(6));
|
||||
}
|
||||
if (matcher.group(7) != null && !matcher.group(7).isEmpty()) {
|
||||
seconds = Integer.parseInt(matcher.group(7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
Calendar c = new GregorianCalendar();
|
||||
if (years > 0) {
|
||||
if (years > MAX_YEARS) {
|
||||
years = MAX_YEARS;
|
||||
}
|
||||
c.add(Calendar.YEAR, years * (future ? 1 : -1));
|
||||
}
|
||||
if (months > 0) {
|
||||
c.add(Calendar.MONTH, months * (future ? 1 : -1));
|
||||
}
|
||||
if (weeks > 0) {
|
||||
c.add(Calendar.WEEK_OF_YEAR, weeks * (future ? 1 : -1));
|
||||
}
|
||||
if (days > 0) {
|
||||
c.add(Calendar.DAY_OF_MONTH, days * (future ? 1 : -1));
|
||||
}
|
||||
if (hours > 0) {
|
||||
c.add(Calendar.HOUR_OF_DAY, hours * (future ? 1 : -1));
|
||||
}
|
||||
if (minutes > 0) {
|
||||
c.add(Calendar.MINUTE, minutes * (future ? 1 : -1));
|
||||
}
|
||||
if (seconds > 0) {
|
||||
c.add(Calendar.SECOND, seconds * (future ? 1 : -1));
|
||||
}
|
||||
|
||||
Calendar max = new GregorianCalendar();
|
||||
max.add(Calendar.YEAR, 10);
|
||||
|
||||
if (c.after(max)) {
|
||||
return (max.getTimeInMillis() / 1000) + 1;
|
||||
}
|
||||
return (c.getTimeInMillis() / 1000) + 1;
|
||||
}
|
||||
|
||||
private DateParser() {}
|
||||
|
||||
}
|
@ -1,262 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All credit to Essentials / EssentialsX for this class
|
||||
* https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
|
||||
* https://github.com/essentials/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Translates unix timestamps / durations into a readable format
|
||||
*/
|
||||
public final class DateUtil {
|
||||
private static final Pattern TIME_PATTERN = Pattern.compile("(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE);
|
||||
private static final int MAX_YEARS = 100000;
|
||||
|
||||
public static long unixSecondsNow() {
|
||||
return System.currentTimeMillis() / 1000L;
|
||||
}
|
||||
|
||||
public static boolean shouldExpire(long unixTime) {
|
||||
return unixTime < (unixSecondsNow());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a time string to a unix timestamp
|
||||
*
|
||||
* @param time the time string
|
||||
* @param future if the date is in the future, as opposed to the past
|
||||
* @return a unix timestamp
|
||||
* @throws IllegalDateException if the date input was invalid
|
||||
*/
|
||||
public static long parseDateDiff(String time, boolean future) throws IllegalDateException {
|
||||
Matcher m = TIME_PATTERN.matcher(time);
|
||||
int years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0;
|
||||
boolean found = false;
|
||||
while (m.find()) {
|
||||
if (m.group() == null || m.group().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < m.groupCount(); i++) {
|
||||
if (m.group(i) != null && !m.group(i).isEmpty()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (m.group(1) != null && !m.group(1).isEmpty()) {
|
||||
years = Integer.parseInt(m.group(1));
|
||||
}
|
||||
if (m.group(2) != null && !m.group(2).isEmpty()) {
|
||||
months = Integer.parseInt(m.group(2));
|
||||
}
|
||||
if (m.group(3) != null && !m.group(3).isEmpty()) {
|
||||
weeks = Integer.parseInt(m.group(3));
|
||||
}
|
||||
if (m.group(4) != null && !m.group(4).isEmpty()) {
|
||||
days = Integer.parseInt(m.group(4));
|
||||
}
|
||||
if (m.group(5) != null && !m.group(5).isEmpty()) {
|
||||
hours = Integer.parseInt(m.group(5));
|
||||
}
|
||||
if (m.group(6) != null && !m.group(6).isEmpty()) {
|
||||
minutes = Integer.parseInt(m.group(6));
|
||||
}
|
||||
if (m.group(7) != null && !m.group(7).isEmpty()) {
|
||||
seconds = Integer.parseInt(m.group(7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
throw new IllegalDateException();
|
||||
}
|
||||
Calendar c = new GregorianCalendar();
|
||||
if (years > 0) {
|
||||
if (years > MAX_YEARS) {
|
||||
years = MAX_YEARS;
|
||||
}
|
||||
c.add(Calendar.YEAR, years * (future ? 1 : -1));
|
||||
}
|
||||
if (months > 0) {
|
||||
c.add(Calendar.MONTH, months * (future ? 1 : -1));
|
||||
}
|
||||
if (weeks > 0) {
|
||||
c.add(Calendar.WEEK_OF_YEAR, weeks * (future ? 1 : -1));
|
||||
}
|
||||
if (days > 0) {
|
||||
c.add(Calendar.DAY_OF_MONTH, days * (future ? 1 : -1));
|
||||
}
|
||||
if (hours > 0) {
|
||||
c.add(Calendar.HOUR_OF_DAY, hours * (future ? 1 : -1));
|
||||
}
|
||||
if (minutes > 0) {
|
||||
c.add(Calendar.MINUTE, minutes * (future ? 1 : -1));
|
||||
}
|
||||
if (seconds > 0) {
|
||||
c.add(Calendar.SECOND, seconds * (future ? 1 : -1));
|
||||
}
|
||||
Calendar max = new GregorianCalendar();
|
||||
max.add(Calendar.YEAR, 10);
|
||||
if (c.after(max)) {
|
||||
return (max.getTimeInMillis() / 1000) + 1;
|
||||
}
|
||||
return (c.getTimeInMillis() / 1000) + 1;
|
||||
}
|
||||
|
||||
private static int dateDiff(int type, Calendar fromDate, Calendar toDate, boolean future) {
|
||||
int year = Calendar.YEAR;
|
||||
|
||||
int fromYear = fromDate.get(year);
|
||||
int toYear = toDate.get(year);
|
||||
if (Math.abs(fromYear - toYear) > MAX_YEARS) {
|
||||
toDate.set(year, fromYear + (future ? MAX_YEARS : -MAX_YEARS));
|
||||
}
|
||||
|
||||
int diff = 0;
|
||||
long savedDate = fromDate.getTimeInMillis();
|
||||
while ((future && !fromDate.after(toDate)) || (!future && !fromDate.before(toDate))) {
|
||||
savedDate = fromDate.getTimeInMillis();
|
||||
fromDate.add(type, future ? 1 : -1);
|
||||
diff++;
|
||||
}
|
||||
diff--;
|
||||
fromDate.setTimeInMillis(savedDate);
|
||||
return diff;
|
||||
}
|
||||
|
||||
public static String formatDateDiff(long seconds) {
|
||||
Calendar now = new GregorianCalendar();
|
||||
Calendar then = new GregorianCalendar();
|
||||
then.setTimeInMillis(seconds * 1000L);
|
||||
return DateUtil.formatDateDiff(now, then);
|
||||
}
|
||||
|
||||
public static String formatDateDiffShort(long seconds) {
|
||||
long now = unixSecondsNow();
|
||||
return formatTimeShort(seconds - now);
|
||||
}
|
||||
|
||||
public static String formatTimeShort(long seconds) {
|
||||
if (seconds <= 0) {
|
||||
return "0s";
|
||||
}
|
||||
|
||||
long minute = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
long hour = minute / 60;
|
||||
minute = minute % 60;
|
||||
long day = hour / 24;
|
||||
hour = hour % 24;
|
||||
|
||||
StringBuilder time = new StringBuilder();
|
||||
if (day != 0) {
|
||||
time.append(day).append("d ");
|
||||
}
|
||||
if (hour != 0) {
|
||||
time.append(hour).append("h ");
|
||||
}
|
||||
if (minute != 0) {
|
||||
time.append(minute).append("m ");
|
||||
}
|
||||
if (seconds != 0) {
|
||||
time.append(seconds).append("s");
|
||||
}
|
||||
|
||||
return time.toString().trim();
|
||||
}
|
||||
|
||||
public static String formatTimeBrief(long seconds) {
|
||||
if (seconds <= 0) {
|
||||
return "0s";
|
||||
}
|
||||
|
||||
long minute = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
long hour = minute / 60;
|
||||
minute = minute % 60;
|
||||
long day = hour / 24;
|
||||
hour = hour % 24;
|
||||
|
||||
StringBuilder time = new StringBuilder();
|
||||
if (day != 0) {
|
||||
time.append(day).append("d ");
|
||||
time.append(hour).append("h ");
|
||||
} else if (hour != 0) {
|
||||
time.append(hour).append("h ");
|
||||
time.append(minute).append("m ");
|
||||
} else if (minute != 0) {
|
||||
time.append(minute).append("m ");
|
||||
time.append(seconds).append("s");
|
||||
} else if (seconds != 0) {
|
||||
time.append(seconds).append("s");
|
||||
}
|
||||
|
||||
return time.toString().trim();
|
||||
}
|
||||
|
||||
private static String formatDateDiff(Calendar fromDate, Calendar toDate) {
|
||||
boolean future = false;
|
||||
if (toDate.equals(fromDate)) {
|
||||
return "now";
|
||||
}
|
||||
if (toDate.after(fromDate)) {
|
||||
future = true;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int[] types = new int[]{Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND};
|
||||
String[] names = new String[]{"year", "years", "month", "months", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds"};
|
||||
int accuracy = 0;
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (accuracy > 2) {
|
||||
break;
|
||||
}
|
||||
int diff = dateDiff(types[i], fromDate, toDate, future);
|
||||
if (diff > 0) {
|
||||
accuracy++;
|
||||
sb.append(" ").append(diff).append(" ").append(names[i * 2 + (diff > 1 ? 1 : 0)]);
|
||||
}
|
||||
}
|
||||
if (sb.length() == 0) {
|
||||
return "now";
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
public static class IllegalDateException extends Exception {
|
||||
|
||||
}
|
||||
|
||||
private DateUtil() {}
|
||||
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
/**
|
||||
* Formats durations to a readable form
|
||||
*
|
||||
* @author khobbits, drtshock, vemacs
|
||||
* see: https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
|
||||
*/
|
||||
public enum DurationFormatter {
|
||||
|
||||
CONCISE {
|
||||
private final String[] names = new String[]{"y", "y", "m", "m", "d", "d", "h", "h", "m", "m", "s", "s"};
|
||||
|
||||
@Override
|
||||
public String format(Calendar from, Calendar to) {
|
||||
return dateDiff(from, to, 4, this.names);
|
||||
}
|
||||
},
|
||||
|
||||
CONCISE_LOW_ACCURACY {
|
||||
private final String[] names = new String[]{"y", "y", "m", "m", "d", "d", "h", "h", "m", "m", "s", "s"};
|
||||
|
||||
@Override
|
||||
public String format(Calendar from, Calendar to) {
|
||||
return dateDiff(from, to, 2, this.names);
|
||||
}
|
||||
},
|
||||
|
||||
LONG {
|
||||
private final String[] names = new String[]{"year", "years", "month", "months", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds"};
|
||||
|
||||
@Override
|
||||
public String format(Calendar from, Calendar to) {
|
||||
return dateDiff(from, to, 4, this.names);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The calender type magic numbers to use when formatting
|
||||
*/
|
||||
private static final int[] CALENDAR_TYPES = new int[] {
|
||||
Calendar.YEAR,
|
||||
Calendar.MONTH,
|
||||
Calendar.DAY_OF_MONTH,
|
||||
Calendar.HOUR_OF_DAY,
|
||||
Calendar.MINUTE,
|
||||
Calendar.SECOND
|
||||
};
|
||||
|
||||
private static final int MAX_YEARS = 100000;
|
||||
|
||||
/**
|
||||
* Formats the difference between two dates
|
||||
*
|
||||
* @param from the start date
|
||||
* @param to the end date
|
||||
* @param maxAccuracy how accurate the output should be (how many sections it'll have)
|
||||
* @param names the names to use to format each of the corresponding {@link #CALENDAR_TYPES}
|
||||
* @return a formatted string
|
||||
*/
|
||||
private static String dateDiff(Calendar from, Calendar to, int maxAccuracy, String[] names) {
|
||||
boolean future = false;
|
||||
if (to.equals(from)) {
|
||||
return "now";
|
||||
}
|
||||
if (to.after(from)) {
|
||||
future = true;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int accuracy = 0;
|
||||
for (int i = 0; i < CALENDAR_TYPES.length; i++) {
|
||||
if (accuracy > maxAccuracy) {
|
||||
break;
|
||||
}
|
||||
|
||||
int diff = dateDiff(CALENDAR_TYPES[i], from, to, future);
|
||||
if (diff > 0) {
|
||||
accuracy++;
|
||||
sb.append(" ").append(diff).append(" ").append(names[i * 2 + (diff > 1 ? 1 : 0)]);
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.length() == 0) {
|
||||
return "now";
|
||||
}
|
||||
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
private static int dateDiff(int type, Calendar fromDate, Calendar toDate, boolean future) {
|
||||
int year = Calendar.YEAR;
|
||||
|
||||
int fromYear = fromDate.get(year);
|
||||
int toYear = toDate.get(year);
|
||||
if (Math.abs(fromYear - toYear) > MAX_YEARS) {
|
||||
toDate.set(year, fromYear + (future ? MAX_YEARS : -MAX_YEARS));
|
||||
}
|
||||
|
||||
int diff = 0;
|
||||
long savedDate = fromDate.getTimeInMillis();
|
||||
while ((future && !fromDate.after(toDate)) || (!future && !fromDate.before(toDate))) {
|
||||
savedDate = fromDate.getTimeInMillis();
|
||||
fromDate.add(type, future ? 1 : -1);
|
||||
diff++;
|
||||
}
|
||||
|
||||
diff--;
|
||||
fromDate.setTimeInMillis(savedDate);
|
||||
return diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the time difference between two dates
|
||||
*
|
||||
* @param from the start date
|
||||
* @param to the end date
|
||||
* @return the formatted duration string
|
||||
*/
|
||||
public abstract String format(Calendar from, Calendar to);
|
||||
|
||||
/**
|
||||
* Formats a duration, in seconds
|
||||
*
|
||||
* @param seconds the duration
|
||||
* @return the formatted duration string
|
||||
*/
|
||||
public String format(long seconds) {
|
||||
Calendar from = new GregorianCalendar();
|
||||
from.setTimeInMillis(0);
|
||||
|
||||
Calendar to = new GregorianCalendar();
|
||||
to.setTimeInMillis(seconds * 1000L);
|
||||
|
||||
return format(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the duration between the current time and the given unix timestamp
|
||||
*
|
||||
* @param unixTimestamp the timestamp, in seconds
|
||||
* @return the formatted duration string
|
||||
*/
|
||||
public String formatDateDiff(long unixTimestamp) {
|
||||
long now = System.currentTimeMillis() / 1000L;
|
||||
return format(unixTimestamp - now);
|
||||
}
|
||||
}
|
@ -27,47 +27,56 @@ package me.lucko.luckperms.common.utils;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public final class PatternCache {
|
||||
|
||||
private static final NullablePattern NULL_PATTERN = new NullablePattern(null);
|
||||
|
||||
private static final LoadingCache<String, NullablePattern> CACHE = Caffeine.newBuilder().build(s -> {
|
||||
try {
|
||||
return new NullablePattern(Pattern.compile(s));
|
||||
} catch (PatternSyntaxException e) {
|
||||
return NULL_PATTERN;
|
||||
}
|
||||
});
|
||||
|
||||
private static final LoadingCache<Map.Entry<String, String>, String> DELIMITER_CACHE = Caffeine.newBuilder()
|
||||
.build(e -> {
|
||||
// note the reversed order
|
||||
return "(?<!" + Pattern.quote(e.getValue()) + ")" + Pattern.quote(e.getKey());
|
||||
private static final LoadingCache<String, CachedPattern> CACHE = Caffeine.newBuilder()
|
||||
.build(s -> {
|
||||
try {
|
||||
return new CachedPattern(Pattern.compile(s));
|
||||
} catch (PatternSyntaxException e) {
|
||||
return new CachedPattern(e);
|
||||
}
|
||||
});
|
||||
|
||||
public static Pattern compile(String regex) {
|
||||
return CACHE.get(regex).pattern;
|
||||
CachedPattern pattern = CACHE.get(regex);
|
||||
Objects.requireNonNull(pattern, "pattern");
|
||||
if (pattern.ex != null) {
|
||||
throw pattern.ex;
|
||||
} else {
|
||||
return pattern.instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static String buildDelimitedMatcher(String delim, String esc) {
|
||||
return DELIMITER_CACHE.get(Maps.immutableEntry(delim, esc));
|
||||
/**
|
||||
* Compiles delimiter pattern with the given escape sequence.
|
||||
*
|
||||
* @param delimiter the delimiter (the thing separating components)
|
||||
* @param escape the string used to escape the delimiter where the pattern shouldn't match
|
||||
* @return a pattern
|
||||
*/
|
||||
public static Pattern compileDelimiterPattern(String delimiter, String escape) {
|
||||
String pattern = "(?<!" + Pattern.quote(escape) + ")" + Pattern.quote(delimiter);
|
||||
return compile(pattern);
|
||||
}
|
||||
|
||||
public static Pattern compileDelimitedMatcher(String delim, String esc) {
|
||||
return compile(buildDelimitedMatcher(delim, esc));
|
||||
}
|
||||
private static final class CachedPattern {
|
||||
private final Pattern instance;
|
||||
private final PatternSyntaxException ex;
|
||||
|
||||
private static final class NullablePattern {
|
||||
private final Pattern pattern;
|
||||
public CachedPattern(Pattern instance) {
|
||||
this.instance = instance;
|
||||
this.ex = null;
|
||||
}
|
||||
|
||||
public NullablePattern(Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
public CachedPattern(PatternSyntaxException ex) {
|
||||
this.instance = null;
|
||||
this.ex = ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ import me.lucko.luckperms.common.command.CommandManager;
|
||||
import me.lucko.luckperms.common.command.utils.MessageUtils;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.StackTracePrinter;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
import me.lucko.luckperms.common.utils.gson.JArray;
|
||||
@ -181,7 +181,7 @@ public class VerboseListener {
|
||||
String startDate = DATE_FORMAT.format(new Date(this.startTime));
|
||||
String endDate = DATE_FORMAT.format(new Date(now));
|
||||
long secondsTaken = (now - this.startTime) / 1000L;
|
||||
String duration = DateUtil.formatTimeShort(secondsTaken);
|
||||
String duration = DurationFormatter.CONCISE.format(secondsTaken);
|
||||
|
||||
String filter;
|
||||
if (this.filter.isBlank()){
|
||||
|
Loading…
Reference in New Issue
Block a user