org.bukkit.BanList#net.kyori.text.TextComponent源码实例Demo

下面列出了org.bukkit.BanList#net.kyori.text.TextComponent 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: PGM   文件: PrettyPaginatedResult.java
/**
 * Displays a list of items based on the page to an audience
 *
 * @param audience to display data to
 * @param data to display
 * @param page where the data is located
 * @throws CommandException no match exceptions
 */
public void display(Audience audience, List<? extends T> data, int page) throws CommandException {
  if (data.size() == 0) {
    audience.sendMessage(TextComponent.of(formatEmpty()));
    return;
  }

  int maxPages = data.size() / this.resultsPerPage + 1;

  if (data.size() % this.resultsPerPage == 0) {
    maxPages--;
  }

  if (page <= 0 || page > maxPages)
    throw new CommandException("Unknown page selected! " + maxPages + " total pages.");

  StringBuilder message = new StringBuilder(header + "\n");
  for (int i = resultsPerPage * (page - 1);
      i < this.resultsPerPage * page && i < data.size();
      i++) {
    message.append(format(data.get(i), i));
    if (i != (data.size() - 1)) message.append("\n");
  }
  audience.sendMessage(TextComponent.of(message.toString()));
}
 
源代码2 项目: GriefDefender   文件: SignUtil.java
public static List<Text> createSellSignLines(double price) {
    List<Text> colorLines = new ArrayList<>(4);
    final DecimalFormat format = new DecimalFormat("0.#");
    final TextComponent headerComponent = TextComponent.builder()
                .append("[", TextColor.GRAY)
                .append("GD", TextColor.AQUA)
                .append("-", TextColor.GRAY)
                .append("sell", TextColor.DARK_BLUE)
                .append("]", TextColor.GRAY)
                .build();

    colorLines.add(SpongeUtil.getSpongeText(headerComponent));
    colorLines.add(SpongeUtil.getSpongeText(MessageCache.getInstance().ECONOMY_SIGN_SELL_DESCRIPTION));
    colorLines.add(SpongeUtil.getSpongeText(TextComponent.builder().append("$" + format.format(price), TextColor.RED).build()));
    colorLines.add(SpongeUtil.getSpongeText(MessageCache.getInstance().ECONOMY_SIGN_SELL_FOOTER));
    return colorLines;
}
 
源代码3 项目: PGM   文件: Core.java
@Override
public Component getTouchMessage(@Nullable ParticipantState toucher, boolean self) {
  // Core has same touch messages as Destroyable
  if (toucher == null) {
    return TranslatableComponent.of(
        "destroyable.touch.owned",
        TextComponent.empty(),
        getComponentName(),
        getOwner().getName());
  } else if (self) {
    return TranslatableComponent.of(
        "destroyable.touch.owned.you",
        TextComponent.empty(),
        getComponentName(),
        getOwner().getName());
  } else {
    return TranslatableComponent.of(
        "destroyable.touch.owned.player",
        toucher.getName(NameStyle.COLOR),
        getComponentName(),
        getOwner().getName());
  }
}
 
源代码4 项目: GriefDefender   文件: GDClaimManager.java
@Override
public List<Claim> getClaimsByName(String name) {
    List<Claim> claimList = new ArrayList<>();
    for (Claim worldClaim : this.getWorldClaims()) {
        Component claimName = worldClaim.getName().orElse(null);
        if (claimName != null && claimName != TextComponent.empty()) {
            if (PlainComponentSerializer.INSTANCE.serialize(claimName).equalsIgnoreCase(name)) {
                claimList.add(worldClaim);
            }
        }
        // check children
        for (Claim child : ((GDClaim) worldClaim).getChildren(true)) {
            if (child.getUniqueId().toString().equals(name)) {
                claimList.add(child);
            }
        }
    }
    return claimList;
}
 
源代码5 项目: GriefDefender   文件: ComponentConfigSerializer.java
@Override
public Component deserialize(TypeToken<?> type, ConfigurationNode node) throws ObjectMappingException {
    if (node.getString() == null || node.getString().isEmpty()) {
        return TextComponent.empty();
    }
    if (node.getString().contains("text=")) {
        // Try sponge data
        StringWriter writer = new StringWriter();

        GsonConfigurationLoader gsonLoader = GsonConfigurationLoader.builder()
                .setIndent(0)
                .setSink(() -> new BufferedWriter(writer))
                .setHeaderMode(HeaderMode.NONE)
                .build();

        try {
            gsonLoader.save(node);
        } catch (IOException e) {
            throw new ObjectMappingException(e);
        }
        return GsonComponentSerializer.INSTANCE.deserialize(writer.toString());
    }

    return LegacyComponentSerializer.legacy().deserialize(node.getString(), '&');
}
 
源代码6 项目: GriefDefender   文件: EconomyUtil.java
public void sellCancelConfirmation(CommandSender src, Claim claim, Sign sign) {
    final Player player = (Player) src;
    final GDClaim gdClaim = (GDClaim) claim;
    // check sell access
    if (gdClaim.allowEdit(player) != null) {
        GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().CLAIM_NOT_YOURS);
        return;
    }

    final Component sellCancelConfirmationText = TextComponent.builder()
            .append("\n[")
            .append(MessageCache.getInstance().LABEL_CONFIRM.color(TextColor.GREEN))
            .append("]\n")
            .clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(src, createSellCancelConfirmed(src, claim, sign), true)))
            .build();
    final Component message = TextComponent.builder()
            .append(MessageCache.getInstance().ECONOMY_CLAIM_SALE_CANCEL_CONFIRMATION)
            .append("\n")
            .append(sellCancelConfirmationText)
            .build();
    GriefDefenderPlugin.sendMessage(src, message);
}
 
源代码7 项目: PGM   文件: ChatDispatcher.java
public static void broadcastAdminChatMessage(
    Component message, Match match, Optional<Sound> sound) {
  TextComponent formatted = ADMIN_CHAT_PREFIX.append(message);
  match.getPlayers().stream()
      .filter(AC_FILTER)
      .forEach(
          mp -> {
            // If provided a sound, play if setting allows
            sound.ifPresent(
                s -> {
                  if (canPlaySound(mp)) {
                    mp.playSound(s);
                  }
                });
            mp.sendMessage(formatted);
          });
  Audience.get(Bukkit.getConsoleSender()).sendMessage(formatted);
}
 
源代码8 项目: PGM   文件: FreeForAllCommand.java
@Command(
    aliases = {"min"},
    desc = "Set the min players on a team",
    usage = "<team> (reset | <min-players>)",
    perms = Permissions.RESIZE)
public void min(Audience audience, Match match, String minPlayers) {
  final FreeForAllMatchModule ffa = getFfa(match);
  if (minPlayers.equalsIgnoreCase("reset")) {
    ffa.setMaxPlayers(null, null);
  } else {
    ffa.setMinPlayers(TextParser.parseInteger(minPlayers, Range.atLeast(0)));
  }

  audience.sendMessage(
      TranslatableComponent.of(
          "match.resize.max",
          TranslatableComponent.of("match.info.players", TextColor.YELLOW),
          TextComponent.of(ffa.getMinPlayers(), TextColor.AQUA)));
}
 
源代码9 项目: PGM   文件: Carried.java
@Override
public void leaveState() {
  SidebarMatchModule smm = this.flag.getMatch().getModule(SidebarMatchModule.class);
  if (smm != null) smm.stopBlinkingGoal(this.flag);

  this.carrier.showHotbar(TextComponent.empty());

  this.carrier.getInventory().remove(this.flag.getBannerItem());
  this.carrier.getInventory().setHelmet(this.helmetItem);

  this.flag
      .getMatch()
      .getModule(KitMatchModule.class)
      .lockArmorSlot(this.carrier, ArmorType.HELMET, this.helmetLocked);

  Kit kit = this.flag.getDefinition().getDropKit();
  if (kit != null) this.carrier.applyKit(kit, false);
  kit = this.flag.getDefinition().getCarryKit();
  if (kit != null) kit.remove(this.carrier);

  super.leaveState();
}
 
源代码10 项目: PGM   文件: ListCommand.java
private void sendTeamInfo(
    Audience viewer,
    CommandSender sender,
    Component teamName,
    Collection<MatchPlayer> players,
    int max) {
  Component teamLine =
      TextComponent.builder()
          .append(teamName)
          .append(": ", TextColor.GRAY)
          .append(Integer.toString(getSize(players, false)))
          .append(
              max != -1
                  ? TextComponent.of("/" + Integer.toString(max), TextColor.GRAY)
                  : TextComponent.empty())
          .append(
              getSize(players, true) > 0 && sender.hasPermission(Permissions.STAFF)
                  ? formatVanishCount(players)
                  : TextComponent.empty())
          .build();
  viewer.sendMessage(teamLine);
  if (!players.isEmpty()) {
    viewer.sendMessage(formatNames(players, sender));
  }
}
 
源代码11 项目: GriefDefender   文件: GriefDefenderPlugin.java
public static void sendMessage(CommandSource src, Component message) {
    if (src == null) {
        return;
    }
    if (NMSUtil.getInstance().isFakePlayer(src)) {
        return;
    }
    if (message == TextComponent.empty() || message == null) {
        return;
    }

    if (src == null) {
        GriefDefenderPlugin.getInstance().getLogger().warn(PlainComponentSerializer.INSTANCE.serialize(message));
    } else {
        TextAdapter.sendComponent(src, message);
    }
}
 
源代码12 项目: GriefDefender   文件: SignUtil.java
public static void setClaimForSale(Claim claim, Player player, Sign sign, double price) {
    if (claim.isWilderness()) {
        GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().ECONOMY_CLAIM_NOT_FOR_SALE);
        return;
    }

    // if not owner of claim, validate perms
    if (((GDClaim) claim).allowEdit(player) != null || !player.hasPermission(GDPermissions.COMMAND_CLAIM_INFO_OTHERS)) {
        TextAdapter.sendComponent(player, MessageCache.getInstance().CLAIM_NOT_YOURS);
        return;
    }

    final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.ECONOMY_CLAIM_SALE_CONFIRMATION,
            ImmutableMap.of(
            "amount", price));
    GriefDefenderPlugin.sendMessage(player, message);

    final Component saleConfirmationText = TextComponent.builder("")
            .append("\n[")
            .append("Confirm", TextColor.GREEN)
            .append("]\n")
            .clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createSaleConfirmationConsumer(player, claim, sign, price))))
            .build();
    GriefDefenderPlugin.sendMessage(player, saleConfirmationText);
}
 
源代码13 项目: GriefDefender   文件: CommandRestoreNature.java
@CommandAlias("modenature")
@Description("Switches the shovel tool to restoration mode.")
@Subcommand("mode nature")
public void execute(Player player) {
    if (true) {
        GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().FEATURE_NOT_AVAILABLE);
        return;
    }

    if (!NMSUtil.getInstance().hasItemInOneHand(player, GriefDefenderPlugin.getInstance().modificationTool)) {
        TextAdapter.sendComponent(player, GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.TOOL_NOT_EQUIPPED,
                ImmutableMap.of("tool", TextComponent.of(GriefDefenderPlugin.getInstance().modificationTool.getName().toLowerCase(), TextColor.GREEN))));
        return;
    }

    final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
    playerData.shovelMode = ShovelTypes.RESTORE;
    GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().MODE_NATURE);
}
 
源代码14 项目: GriefDefender   文件: ClaimOptionBase.java
private Component getHoverContextComponent(Set<Context> contexts) {
    if (contexts.isEmpty()) {
        return TextComponent.empty();
    }

    TextComponent.Builder builder = TextComponent.builder()
                .append("\n\nContexts: \n");

    for (Context context : contexts) {
        final String key = context.getKey();
        final String value = context.getValue();
        TextColor keyColor = TextColor.AQUA;
        builder.append(key, keyColor)
                .append("=", TextColor.WHITE)
                .append(value.replace("minecraft:", ""), TextColor.GRAY)
                .append("\n");
    }

    return builder.build();
}
 
源代码15 项目: GriefDefender   文件: CommandClaimInfo.java
public Component getClickableInfoText(CommandSender src, Claim claim, int titleId, Component infoText) {
    Component onClickText = MessageCache.getInstance().CLAIMINFO_UI_CLICK_TOGGLE;
    boolean hasPermission = true;
    if (src instanceof Player) {
        Component denyReason = ((GDClaim) claim).allowEdit((Player) src);
        if (denyReason != null) {
            onClickText = denyReason;
            hasPermission = false;
        }
    }

    TextComponent.Builder textBuilder = TextComponent.builder()
            .append(infoText)
            .hoverEvent(HoverEvent.showText(onClickText));
    if (hasPermission) {
        textBuilder.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimInfoConsumer(src, claim, titleId))));
    }
    return textBuilder.build();
}
 
源代码16 项目: Geyser   文件: GeyserVelocityCommandExecutor.java
@Override
public void execute(CommandSource source, String[] args) {
    if (args.length > 0) {
        if (getCommand(args[0]) != null) {
            if (!source.hasPermission(getCommand(args[0]).getPermission())) {
                source.sendMessage(TextComponent.of(ChatColor.RED + "You do not have permission to execute this command!"));
                return;
            }
            getCommand(args[0]).execute(new VelocityCommandSender(source), args);
        }
    } else {
        getCommand("help").execute(new VelocityCommandSender(source), args);
    }
}
 
源代码17 项目: GriefDefender   文件: GDFlagDefinition.java
@Override
public Builder reset() {
    this.enabled = true;
    this.isAdmin = false;
    this.contexts = new HashSet<>();
    this.data = new ArrayList<>();
    this.displayName = "";
    this.groupName = "";
    this.defaultValue = Tristate.UNDEFINED;
    this.description = TextComponent.empty();
    this.subject = GriefDefenderPlugin.DEFAULT_HOLDER;
    return this;
}
 
源代码18 项目: GriefDefender   文件: GDFlag.java
private Component createDescription() {
    final Component description = GriefDefenderPlugin.getInstance().messageData.getMessage("flag-description-" + this.name.toLowerCase());
    if (description != null) {
        return description;
    }
    return TextComponent.of("Not defined.");
}
 
源代码19 项目: GriefDefender   文件: UIHelper.java
public static Component getPermissionMenuTypeHoverText(FlagContextHolder flagHolder, MenuType menuType) {
    if (flagHolder.getType() == MenuType.DEFAULT && menuType == MenuType.CLAIM) {
        return TextComponent.builder()
                .append(MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.FLAG_NOT_SET, 
                        ImmutableMap.of("flag", TextComponent.of(flagHolder.getFlag().getName(), TextColor.GREEN),
                                        "value", TextComponent.of(flagHolder.getValue(), TextColor.LIGHT_PURPLE)))).build();
    }

    return getPermissionMenuTypeHoverText(menuType);
}
 
源代码20 项目: GriefDefender   文件: GDDebugData.java
public void addRecord(String flag, String trust, String source, String target, String location, String user, String contexts, Tristate result) {
    // markdown uses '__' for strong formatting, so underscores must be escaped
    user = user.replace("_", "\\_");
    if (this.records.size() < MAX_LINES) {
        this.records.add("| " + flag + " | " + trust + " | " + source + " | " + target + " | " + location + " | " + user + " | " + contexts + " | " + result + " | ");
    } else {
        TextAdapter.sendComponent(this.source, TextComponent.builder("").append("MAX DEBUG LIMIT REACHED!").append("\n")
                .append("Pasting output...", TextColor.GREEN).build());
        this.pasteRecords();
        this.records.clear();
        GriefDefenderPlugin.getInstance().getDebugUserMap().clear();
        GriefDefenderPlugin.debugActive = false;
        TextAdapter.sendComponent(this.source, TextComponent.builder("").append(GD_TEXT).append("Debug ", TextColor.GRAY).append("OFF", TextColor.RED).build());
    }
}
 
源代码21 项目: PGM   文件: Dead.java
@Override
protected Component getSubtitle() {
  long ticks = ticksUntilRespawn();
  if (ticks > 0) {
    return TranslatableComponent.of(
        spawnRequested ? "death.respawn.confirmed.time" : "death.respawn.unconfirmed.time",
        TextComponent.of(String.format("%.1f", (ticks / (float) 20)), TextColor.AQUA));
  } else {
    return super.getSubtitle();
  }
}
 
源代码22 项目: GriefDefender   文件: GDClaim.java
public Component getFriendlyNameType(ClaimType claimType, boolean upper) {
    if (claimType == ClaimTypes.ADMIN) {
        if (upper) {
            return TextComponent.of(claimType.getName().toUpperCase(), TextColor.RED);
        }
        return TextComponent.of("Admin", TextColor.RED);
    }

    if (claimType == ClaimTypes.BASIC) {
        if (upper) {
            return TextComponent.of(claimType.getName().toUpperCase(), TextColor.YELLOW);
        }
        return TextComponent.of("Basic", TextColor.YELLOW);
    }

    if (claimType == ClaimTypes.SUBDIVISION) {
        if (upper) {
            return TextComponent.of(claimType.getName().toUpperCase(), TextColor.AQUA);
        }
        return TextComponent.of("Subdivision", TextColor.AQUA);
    }

    if (upper) {
        return TextComponent.of(claimType.getName().toUpperCase(), TextColor.GREEN);
    }
    return TextComponent.of("Town", TextColor.GREEN);
}
 
源代码23 项目: PGM   文件: MapCommand.java
private Component createTagsComponent(Collection<MapTag> tags) {
  checkNotNull(tags);

  Builder result = TextComponent.builder().append(mapInfoLabel("map.info.tags"));
  MapTag[] mapTags = tags.toArray(new MapTag[0]);
  for (int i = 0; i < mapTags.length; i++) {
    if (i != 0) {
      result.append(TextComponent.space());
    }

    String mapTag = mapTags[i].getId();

    Component tag =
        TextComponent.builder()
            .append("#")
            .append(mapTag)
            .clickEvent(ClickEvent.runCommand("/maps -t " + mapTag))
            .hoverEvent(
                HoverEvent.showText(
                    TranslatableComponent.of(
                        "map.info.mapTag.hover",
                        TextColor.GRAY,
                        TextComponent.of(mapTag, TextColor.GOLD))))
            .build();

    result.append(tag);
  }
  return result.color(TextColor.GOLD).build();
}
 
源代码24 项目: PGM   文件: MatchAnnouncer.java
@EventHandler(priority = EventPriority.MONITOR)
public void onMatchEnd(final MatchFinishEvent event) {
  Match match = event.getMatch();

  // broadcast match finish message
  for (MatchPlayer viewer : match.getPlayers()) {
    Component title, subtitle = TextComponent.empty();
    if (event.getWinner() == null) {
      title = TranslatableComponent.of("broadcast.gameOver");
    } else {
      title =
          TranslatableComponent.of(
              event.getWinner().isNamePlural()
                  ? "broadcast.gameOver.teamWinners"
                  : "broadcast.gameOver.teamWinner",
              event.getWinner().getName());

      if (event.getWinner() == viewer.getParty()) {
        // Winner
        viewer.playSound(SOUND_MATCH_WIN);
        if (viewer.getParty() instanceof Team) {
          subtitle = TranslatableComponent.of("broadcast.gameOver.teamWon", TextColor.GREEN);
        }
      } else if (viewer.getParty() instanceof Competitor) {
        // Loser
        viewer.playSound(SOUND_MATCH_LOSE);
        if (viewer.getParty() instanceof Team) {
          subtitle = TranslatableComponent.of("broadcast.gameOver.teamLost", TextColor.RED);
        }
      } else {
        // Observer
        viewer.playSound(SOUND_MATCH_WIN);
      }
    }

    viewer.showTitle(title, subtitle, 0, 40, 40);
    viewer.sendMessage(title);
    if (subtitle != null) viewer.sendMessage(subtitle);
  }
}
 
源代码25 项目: GriefDefender   文件: BanCategory.java
public void addEntityBan(String id, Component reason) {
    if (id == null) {
        return;
    }
    if (reason == null) {
        reason = TextComponent.empty();
    }
    this.entities.put(id, reason);
}
 
源代码26 项目: PGM   文件: ModerationCommand.java
private void sendWarning(MatchPlayer target, String reason) {
  Component titleWord = TranslatableComponent.of("misc.warning", TextColor.DARK_RED);
  Component title =
      TextComponent.builder().append(WARN_SYMBOL).append(titleWord).append(WARN_SYMBOL).build();
  Component subtitle = formatPunishmentReason(reason).color(TextColor.GOLD);

  target.showTitle(title, subtitle, 5, 200, 10);
  target.playSound(WARN_SOUND);
}
 
源代码27 项目: GriefDefender   文件: GriefDefenderPlugin.java
public static void sendMessage(CommandSender source, Component message) {
    if (message == TextComponent.empty() || message == null) {
        return;
    }

    if (source == null) {
        GriefDefenderPlugin.getInstance().getLogger().warning(PlainComponentSerializer.INSTANCE.serialize(message));
    } else {
        TextAdapter.sendComponent(source, message);
    }
}
 
源代码28 项目: PGM   文件: Mode.java
public Mode(
    final MaterialData material,
    final Duration after,
    final @Nullable String name,
    Duration showBefore) {
  this.material = material;
  this.after = after;
  this.name = name;
  this.componentName =
      TextComponent.of(name != null ? name : getPreformattedMaterialName(), TextColor.RED);
  this.showBefore = showBefore;
}
 
源代码29 项目: GriefDefender   文件: ChatCaptureUtil.java
public List<Component> generateChatSettings(Player player, GDClaim claim, String command, Component returnComponent) {
    final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
    List<Component> textList = new ArrayList<>();
    Component returnToClaimInfo = null;
    if (command.equals("claiminfo")) {
        returnToClaimInfo = TextComponent.builder()
                .append("[")
                .append(MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.UI_CLICK_RETURN_COMMAND, 
                        ImmutableMap.of("command", command)))
                .append("]")
            .clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createCommandConsumer(player, command, claim.getUniqueId().toString())))).build();
    } else if (command.equals("trustlist")) {
        returnToClaimInfo = TextComponent.builder()
                .append("[")
                .append(MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.UI_CLICK_RETURN_COMMAND, 
                        ImmutableMap.of("command", command)))
                .append("]")
            .clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createTrustListConsumer(player, claim, playerData, TrustTypes.NONE, returnComponent)))).build();
    } else {
        returnToClaimInfo = TextComponent.builder()
                .append("[")
                .append(MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.UI_CLICK_RETURN_COMMAND, 
                        ImmutableMap.of("command", command)))
                .append("]")
            .clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createCommandConsumer(player, command, "")))).build();
    }
    textList.add(returnToClaimInfo);
    for (Component chatLine : playerData.chatLines) {
        textList.add(chatLine);
    }

    int fillSize = 20 - (textList.size() + 2);
    for (int i = 0; i < fillSize; i++) {
        textList.add(TextComponent.of(" "));
    }
    return textList;
}
 
源代码30 项目: GriefDefender   文件: LuckPermsProvider.java
public PermissionResult setPermissionValue(GDPermissionHolder holder, String permission, Tristate value, Set<Context> contexts, boolean check, boolean save) {
    DataMutateResult result = null;
    if (check) {
        // If no server context exists, add global
        this.checkServerContext(contexts);
    }
    ImmutableContextSet set = this.getLPContexts(contexts).immutableCopy();
    final Node node = this.luckPermsApi.getNodeBuilderRegistry().forPermission().permission(permission).value(value.asBoolean()).context(set).build();
    final PermissionHolder permissionHolder = this.getLuckPermsHolder(holder);
    if (permissionHolder == null) {
        return new GDPermissionResult(ResultTypes.FAILURE);
    }

    if (value == Tristate.UNDEFINED) {
        result = permissionHolder.data().remove(node);
    } else {
        result = permissionHolder.data().add(node);
    }

    if (result.wasSuccessful()) {
        if (permissionHolder instanceof Group) {
            // If a group is changed, we invalidate all cache
            PermissionHolderCache.getInstance().invalidateAllPermissionCache();
        } else {
            // We need to invalidate cache outside of LP listener so we can guarantee proper result returns
            PermissionHolderCache.getInstance().getOrCreatePermissionCache(holder).invalidateAll();
        }

        if (save) {
            this.savePermissionHolder(permissionHolder);
        }

        return new GDPermissionResult(ResultTypes.SUCCESS, TextComponent.builder().append(result.name()).build());
    }

    return new GDPermissionResult(ResultTypes.FAILURE, TextComponent.builder().append(result.name()).build());
}