001/* 002 * PermissionsEx 003 * Copyright (C) zml and PermissionsEx contributors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package ca.stellardrift.permissionsex.minecraft.command; 018 019import ca.stellardrift.permissionsex.context.ContextValue; 020import ca.stellardrift.permissionsex.impl.util.PCollections; 021import cloud.commandframework.Command; 022import cloud.commandframework.arguments.CommandArgument; 023import cloud.commandframework.arguments.StaticArgument; 024import net.kyori.adventure.text.Component; 025import net.kyori.adventure.text.format.NamedTextColor; 026import net.kyori.adventure.text.format.TextColor; 027import net.kyori.adventure.util.ComponentMessageThrowable; 028import org.checkerframework.checker.nullness.qual.Nullable; 029 030import java.util.List; 031import java.util.Map; 032import java.util.Set; 033 034import static net.kyori.adventure.text.Component.text; 035 036/** 037 * Message creators for use in command output. 038 */ 039public final class Formats { 040 public static final Component COMMA = text(","); 041 private static final Component BOOL_TRUE = Messages.FORMATTER_BOOLEAN_TRUE.bTr() 042 .color(NamedTextColor.GREEN) 043 .build(); 044 045 private static final Component BOOL_FALSE = Messages.FORMATTER_BOOLEAN_FALSE.bTr() 046 .color(NamedTextColor.RED) 047 .build(); 048 049 private Formats() { 050 } 051 052 /** 053 * Represent a permission and its value in a user-visible way. 054 * 055 * The output will appear as {@code <permisison>=<value>}. 056 * 057 * @param permission the permission 058 * @param value its value, listed and used for colouring 059 * @return the formatted permission 060 * @since 2.0.0 061 */ 062 public static Component permission(final String permission, final int value) { 063 final NamedTextColor color; 064 if (value > 0) { 065 color = NamedTextColor.GREEN; 066 } else if (value < 0) { 067 color = NamedTextColor.RED; 068 } else { 069 color = NamedTextColor.GRAY; 070 } 071 return text() 072 .append(text(permission, color)) 073 .append(MessageFormatter.EQUALS_SIGN) 074 .append(text(value)) 075 .build(); 076 } 077 078 public static Component permissionValue(final int value) { 079 final NamedTextColor color; 080 if (value > 0) { 081 color = NamedTextColor.GREEN; 082 } else if (value < 0) { 083 color = NamedTextColor.RED; 084 } else { 085 color = NamedTextColor.GRAY; 086 } 087 return text(value, color); 088 } 089 090 public static Component option(final String option, final String value) { 091 return text() 092 .content(option) 093 .append(MessageFormatter.EQUALS_SIGN) 094 .append(text(value)) 095 .build(); 096 } 097 098 public static Component bool(final boolean value) { 099 return value ? BOOL_TRUE : BOOL_FALSE; 100 } 101 102 public static Component contexts(final Set<ContextValue<?>> contexts) { 103 if (contexts.isEmpty()) { 104 return Messages.COMMON_ARGS_CONTEXT_GLOBAL.tr(); 105 } else { 106 return Component.join(COMMA, contexts); 107 } 108 } 109 110 /** 111 * Format the specified command, filling in arguments as provided until the first unset 112 * non-static argument is encountered. 113 * 114 * @param command the command to format 115 * @param placeholders arguments to fill in 116 * @return the formatted command 117 */ 118 public static String formatCommand(final Command<?> command, final Map<CommandArgument<?, ?>, String> placeholders) { 119 return formatCommand(command.getArguments(), placeholders); 120 } 121 122 /** 123 * Format the specified command, filling in arguments as provided until the first unset 124 * non-static argument is encountered. 125 * 126 * @param command the command to format 127 * @param placeholders arguments to fill in 128 * @return the formatted command 129 */ 130 public static String formatCommand(final Command.Builder<?> command, final Map<CommandArgument<?, ?>, String> placeholders) { 131 return formatCommand(command.build().getArguments(), placeholders); // TODO: can we do this without building the command? 132 } 133 134 /** 135 * Format the specified command, filling in arguments as provided until the first unset 136 * non-static argument is encountered. 137 * 138 * @param arguments the base arguments 139 * @param placeholders arguments to fill in 140 * @return the formatted command 141 */ 142 private static String formatCommand(final List<? extends CommandArgument<?, ?>> arguments, final Map<CommandArgument<?, ?>, String> placeholders) { 143 final StringBuilder builder = new StringBuilder("/"); 144 for (final CommandArgument<?, ?> argument : arguments) { 145 if (argument instanceof StaticArgument<?>) { 146 builder.append(argument.getName()); 147 } else { 148 final @Nullable String value = placeholders.get(argument); 149 if (value == null) { 150 break; 151 } 152 builder.append(value); 153 } 154 builder.append(" "); 155 } 156 return builder.toString(); 157 } 158 159 public static String formatCommand( 160 final Command<?> command, 161 final CommandArgument<?, ?> arg1, final String val1 162 ) { 163 return formatCommand(command, PCollections.map(arg1, val1)); 164 } 165 166 public static String formatCommand( 167 final Command<?> command, 168 final CommandArgument<?, ?> arg1, final String val1, 169 final CommandArgument<?, ?> arg2, final String val2 170 ) { 171 return formatCommand(command, PCollections.<CommandArgument<?, ?>, String>map(arg1, val1).plus(arg2, val2)); 172 } 173 174 public static Component message(final Throwable throwable) { 175 if (throwable instanceof ComponentMessageThrowable) { 176 final @Nullable Component msg = ((ComponentMessageThrowable) throwable).componentMessage(); 177 return msg == null ? text("null") : msg; 178 } else { 179 return text(throwable.getMessage()); 180 } 181 } 182 183 public static TextColor lerp(final float pct, final TextColor from, final TextColor to) { 184 // https://github.com/KyoriPowered/adventure/pull/215 185 return TextColor.color( 186 Math.round(from.red() + pct * (to.red() - from.red())), 187 Math.round(from.green() + pct * (to.green() - from.green())), 188 Math.round(from.blue() + pct * (to.blue() - from.blue())) 189 ); 190 } 191 192}