diff --git a/common/src/main/java/me/lucko/luckperms/common/command/access/CommandPermission.java b/common/src/main/java/me/lucko/luckperms/common/command/access/CommandPermission.java index 530881fa..8a0e79f5 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/access/CommandPermission.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/access/CommandPermission.java @@ -88,10 +88,14 @@ public enum CommandPermission { USER_META_UNSET_TEMP("meta.unsettemp", USER), USER_META_ADD_PREFIX("meta.addprefix", USER), USER_META_ADD_SUFFIX("meta.addsuffix", USER), + USER_META_SET_PREFIX("meta.setprefix", USER), + USER_META_SET_SUFFIX("meta.setsuffix", USER), USER_META_REMOVE_PREFIX("meta.removeprefix", USER), USER_META_REMOVE_SUFFIX("meta.removesuffix", USER), USER_META_ADD_TEMP_PREFIX("meta.addtempprefix", USER), USER_META_ADD_TEMP_SUFFIX("meta.addtempsuffix", USER), + USER_META_SET_TEMP_PREFIX("meta.settempprefix", USER), + USER_META_SET_TEMP_SUFFIX("meta.settempsuffix", USER), USER_META_REMOVE_TEMP_PREFIX("meta.removetempprefix", USER), USER_META_REMOVE_TEMP_SUFFIX("meta.removetempsuffix", USER), USER_META_CLEAR("meta.clear", USER), @@ -127,10 +131,14 @@ public enum CommandPermission { GROUP_META_UNSET_TEMP("meta.unsettemp", GROUP), GROUP_META_ADD_PREFIX("meta.addprefix", GROUP), GROUP_META_ADD_SUFFIX("meta.addsuffix", GROUP), + GROUP_META_SET_PREFIX("meta.setprefix", GROUP), + GROUP_META_SET_SUFFIX("meta.setsuffix", GROUP), GROUP_META_REMOVE_PREFIX("meta.removeprefix", GROUP), GROUP_META_REMOVE_SUFFIX("meta.removesuffix", GROUP), GROUP_META_ADD_TEMP_PREFIX("meta.addtempprefix", GROUP), GROUP_META_ADD_TEMP_SUFFIX("meta.addtempsuffix", GROUP), + GROUP_META_SET_TEMP_PREFIX("meta.settempprefix", GROUP), + GROUP_META_SET_TEMP_SUFFIX("meta.settempsuffix", GROUP), GROUP_META_REMOVE_TEMP_PREFIX("meta.removetempprefix", GROUP), GROUP_META_REMOVE_TEMP_SUFFIX("meta.removetempsuffix", GROUP), GROUP_META_CLEAR("meta.clear", GROUP), diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java index b701fa38..714511e4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java @@ -44,10 +44,14 @@ public class CommandMeta extends SharedMainCommand + * 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.commands.generic.meta; + +import me.lucko.luckperms.api.ChatMetaType; +import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.DataMutateResult; +import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; +import me.lucko.luckperms.common.caching.type.MetaAccumulator; +import me.lucko.luckperms.common.command.CommandResult; +import me.lucko.luckperms.common.command.abstraction.CommandException; +import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; +import me.lucko.luckperms.common.command.access.ArgumentPermissions; +import me.lucko.luckperms.common.command.access.CommandPermission; +import me.lucko.luckperms.common.command.utils.ArgumentParser; +import me.lucko.luckperms.common.command.utils.MessageUtils; +import me.lucko.luckperms.common.command.utils.StorageAssistant; +import me.lucko.luckperms.common.locale.LocaleManager; +import me.lucko.luckperms.common.locale.command.CommandSpec; +import me.lucko.luckperms.common.locale.message.Message; +import me.lucko.luckperms.common.model.Group; +import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.common.node.factory.NodeFactory; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.sender.Sender; +import me.lucko.luckperms.common.utils.Predicates; +import me.lucko.luckperms.common.utils.TextUtils; + +import net.kyori.text.TextComponent; +import net.kyori.text.event.HoverEvent; + +import java.util.List; +import java.util.OptionalInt; + +public class MetaSetChatMeta extends SharedSubCommand { + private final ChatMetaType type; + + public MetaSetChatMeta(LocaleManager locale, ChatMetaType type) { + super( + type == ChatMetaType.PREFIX ? CommandSpec.META_SETPREFIX.localize(locale) : CommandSpec.META_SETSUFFIX.localize(locale), + "set" + type.name().toLowerCase(), + type == ChatMetaType.PREFIX ? CommandPermission.USER_META_SET_PREFIX : CommandPermission.USER_META_SET_SUFFIX, + type == ChatMetaType.PREFIX ? CommandPermission.GROUP_META_SET_PREFIX : CommandPermission.GROUP_META_SET_SUFFIX, + Predicates.is(0) + ); + this.type = type; + } + + @Override + public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List args, String label, CommandPermission permission) throws CommandException { + if (ArgumentPermissions.checkModifyPerms(plugin, sender, permission, holder)) { + Message.COMMAND_NO_PERMISSION.send(sender); + return CommandResult.NO_PERMISSION; + } + + int priority = ArgumentParser.parseIntOrElse(0, args, Integer.MIN_VALUE); + String meta; + MutableContextSet context; + + if (priority == Integer.MIN_VALUE) { + // priority wasn't defined, meta is at index 0, contexts at index 1 + meta = ArgumentParser.parseString(0, args); + context = ArgumentParser.parseContext(1, args, plugin); + } else { + // priority was defined, meta should be at index 1, contexts at index 2 + if (args.size() <= 1) { + sendDetailedUsage(sender); + return CommandResult.INVALID_ARGS; + } + + meta = ArgumentParser.parseString(1, args); + context = ArgumentParser.parseContext(2, args, plugin); + } + + if (ArgumentPermissions.checkContext(plugin, sender, permission, context)) { + Message.COMMAND_NO_PERMISSION.send(sender); + return CommandResult.NO_PERMISSION; + } + + // remove all other prefixes/suffixes set in these contexts + holder.removeIf(context, this.type::matches); + + // determine the priority to set at + if (priority == Integer.MIN_VALUE) { + MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.of(context, Contexts.global().getSettings())); + priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1; + + if (holder instanceof Group) { + OptionalInt weight = holder.getWeight(); + if (weight.isPresent() && weight.getAsInt() > priority) { + priority = weight.getAsInt(); + } + } + } + + DataMutateResult result = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withExtraContext(context).build()); + if (result.asBoolean()) { + TextComponent.Builder builder = Message.ADD_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFriendlyName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); + HoverEvent event = new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextUtils.fromLegacy( + "¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta, + '¥' + )); + builder.applyDeep(c -> c.hoverEvent(event)); + sender.sendMessage(builder.build()); + + ExtendedLogEntry.build().actor(sender).acted(holder) + .action("meta" , "set" + this.type.name().toLowerCase(), priority, meta, context) + .build().submit(plugin, sender); + + StorageAssistant.save(holder, sender, plugin); + return CommandResult.SUCCESS; + } else { + Message.ALREADY_HAS_CHAT_META.send(sender, holder.getFriendlyName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); + return CommandResult.STATE_ERROR; + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java new file mode 100644 index 00000000..4dbd02ac --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java @@ -0,0 +1,155 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.commands.generic.meta; + +import me.lucko.luckperms.api.ChatMetaType; +import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.DataMutateResult; +import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; +import me.lucko.luckperms.common.caching.type.MetaAccumulator; +import me.lucko.luckperms.common.command.CommandResult; +import me.lucko.luckperms.common.command.abstraction.CommandException; +import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; +import me.lucko.luckperms.common.command.access.ArgumentPermissions; +import me.lucko.luckperms.common.command.access.CommandPermission; +import me.lucko.luckperms.common.command.utils.ArgumentParser; +import me.lucko.luckperms.common.command.utils.MessageUtils; +import me.lucko.luckperms.common.command.utils.StorageAssistant; +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.locale.LocaleManager; +import me.lucko.luckperms.common.locale.command.CommandSpec; +import me.lucko.luckperms.common.locale.message.Message; +import me.lucko.luckperms.common.model.Group; +import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.common.model.TemporaryModifier; +import me.lucko.luckperms.common.node.factory.NodeFactory; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.sender.Sender; +import me.lucko.luckperms.common.utils.DurationFormatter; +import me.lucko.luckperms.common.utils.Predicates; +import me.lucko.luckperms.common.utils.TextUtils; + +import net.kyori.text.TextComponent; +import net.kyori.text.event.HoverEvent; + +import java.util.List; +import java.util.Map; +import java.util.OptionalInt; + +public class MetaSetTempChatMeta extends SharedSubCommand { + private final ChatMetaType type; + + public MetaSetTempChatMeta(LocaleManager locale, ChatMetaType type) { + super( + type == ChatMetaType.PREFIX ? CommandSpec.META_SETTEMP_PREFIX.localize(locale) : CommandSpec.META_SETTEMP_SUFFIX.localize(locale), + "settemp" + type.name().toLowerCase(), + type == ChatMetaType.PREFIX ? CommandPermission.USER_META_SET_TEMP_PREFIX : CommandPermission.USER_META_SET_TEMP_SUFFIX, + type == ChatMetaType.PREFIX ? CommandPermission.GROUP_META_SET_TEMP_PREFIX : CommandPermission.GROUP_META_SET_TEMP_SUFFIX, + Predicates.inRange(0, 1) + ); + this.type = type; + } + + @Override + public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List args, String label, CommandPermission permission) throws CommandException { + if (ArgumentPermissions.checkModifyPerms(plugin, sender, permission, holder)) { + Message.COMMAND_NO_PERMISSION.send(sender); + return CommandResult.NO_PERMISSION; + } + + int priority = ArgumentParser.parseIntOrElse(0, args, Integer.MIN_VALUE); + String meta; + long duration; + TemporaryModifier modifier; + MutableContextSet context; + + if (priority == Integer.MIN_VALUE) { + // priority wasn't defined, meta is at index 0, duration at index 1 + meta = ArgumentParser.parseString(0, args); + duration = ArgumentParser.parseDuration(1, args); + modifier = ArgumentParser.parseTemporaryModifier(2, args).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR)); + context = ArgumentParser.parseContext(2, args, plugin); + } else { + // priority was defined, meta should be at index 1, duration at index 2 + if (args.size() <= 2) { + sendDetailedUsage(sender); + return CommandResult.INVALID_ARGS; + } + + meta = ArgumentParser.parseString(1, args); + duration = ArgumentParser.parseDuration(2, args); + modifier = ArgumentParser.parseTemporaryModifier(3, args).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR)); + context = ArgumentParser.parseContext(3, args, plugin); + } + + if (ArgumentPermissions.checkContext(plugin, sender, permission, context)) { + Message.COMMAND_NO_PERMISSION.send(sender); + return CommandResult.NO_PERMISSION; + } + + // remove all other prefixes/suffixes set in these contexts + holder.removeIf(context, this.type::matches); + + // determine the priority to set at + if (priority == Integer.MIN_VALUE) { + MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.of(context, Contexts.global().getSettings())); + priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1; + + if (holder instanceof Group) { + OptionalInt weight = holder.getWeight(); + if (weight.isPresent() && weight.getAsInt() > priority) { + priority = weight.getAsInt(); + } + } + } + + Map.Entry ret = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).setExpiry(duration).withExtraContext(context).build(), modifier); + + if (ret.getKey().asBoolean()) { + duration = ret.getValue().getExpiryUnixTime(); + + TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFriendlyName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); + HoverEvent event = new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextUtils.fromLegacy( + "¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta, + '¥' + )); + builder.applyDeep(c -> c.hoverEvent(event)); + sender.sendMessage(builder.build()); + + ExtendedLogEntry.build().actor(sender).acted(holder) + .action("meta" , "settemp" + this.type.name().toLowerCase(), priority, meta, duration, context) + .build().submit(plugin, sender); + + StorageAssistant.save(holder, sender, plugin); + return CommandResult.SUCCESS; + } else { + Message.ALREADY_HAS_TEMP_CHAT_META.send(sender, holder.getFriendlyName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); + return CommandResult.STATE_ERROR; + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/locale/command/CommandSpec.java b/common/src/main/java/me/lucko/luckperms/common/locale/command/CommandSpec.java index 543afc5e..d5f9983d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/locale/command/CommandSpec.java +++ b/common/src/main/java/me/lucko/luckperms/common/locale/command/CommandSpec.java @@ -341,6 +341,20 @@ public enum CommandSpec { Argument.create("context...", false, "the contexts to add the suffix in") ) ), + META_SETPREFIX("Sets a prefix", + Argument.list( + Argument.create("priority", false, "the priority to set the prefix at"), + Argument.create("prefix", true, "the prefix string"), + Argument.create("context...", false, "the contexts to set the prefix in") + ) + ), + META_SETSUFFIX("Sets a suffix", + Argument.list( + Argument.create("priority", false, "the priority to set the suffix at"), + Argument.create("suffix", true, "the suffix string"), + Argument.create("context...", false, "the contexts to set the suffix in") + ) + ), META_REMOVEPREFIX("Removes a prefix", Argument.list( Argument.create("priority", true, "the priority to remove the prefix at"), @@ -371,6 +385,22 @@ public enum CommandSpec { Argument.create("context...", false, "the contexts to add the suffix in") ) ), + META_SETTEMP_PREFIX("Sets a prefix temporarily", + Argument.list( + Argument.create("priority", true, "the priority to set the prefix at"), + Argument.create("prefix", true, "the prefix string"), + Argument.create("duration", true, "the duration until the prefix expires"), + Argument.create("context...", false, "the contexts to set the prefix in") + ) + ), + META_SETTEMP_SUFFIX("Sets a suffix temporarily", + Argument.list( + Argument.create("priority", true, "the priority to set the suffix at"), + Argument.create("suffix", true, "the suffix string"), + Argument.create("duration", true, "the duration until the suffix expires"), + Argument.create("context...", false, "the contexts to set the suffix in") + ) + ), META_REMOVETEMP_PREFIX("Removes a temporary prefix", Argument.list( Argument.create("priority", true, "the priority to remove the prefix at"), diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java index 5dd6c1e7..b45f0b8c 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java @@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import me.lucko.luckperms.api.ChatMetaType; +import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Tristate; @@ -360,7 +361,7 @@ public class HolderSubjectData implements LPSubjectData { () -> this.holder.unsetTransientPermission(n) )); - MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, this.service.getPlugin().getContextManager().formContexts(contexts)); + MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, Contexts.of(contexts, Contexts.global().getSettings())); int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0); priority += 10;