Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
3fe1be1ee0 | |||
1374329d8b | |||
5427e2a401 | |||
1d6a3f976e | |||
5bdbaa351a | |||
334dc3852f | |||
265b014cd6 | |||
3499dfdabc | |||
09a5692b84 | |||
a0f81879db | |||
75d4f84884 | |||
e9efb7cd34 | |||
c35325c5a7 | |||
085696476a | |||
fabaf5a7ae | |||
17fd61e8b9 | |||
7dc0315469 | |||
21611dd90d | |||
22b4be2baf | |||
46e05d7e32 | |||
a89ed1fb39 | |||
8028a8556b | |||
6ba13a1ced | |||
5c3c3045eb | |||
223c70b28e | |||
e152f85bf4 | |||
5719a8ec4c | |||
3248704950 | |||
0068097f55 | |||
46f85d37ab | |||
94d74e7794 | |||
2c8182e552 | |||
ccf3e527d9 | |||
914485c67b | |||
0bd029db20 | |||
1e729af5e6 | |||
e35156bea9 | |||
ad5dabc712 | |||
4fb4429f8b | |||
58ee5a0756 |
26
pom.xml
26
pom.xml
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>net.knarcraft</groupId>
|
<groupId>net.knarcraft</groupId>
|
||||||
<artifactId>KnarLib</artifactId>
|
<artifactId>KnarLib</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.2.7-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>KnarLib</name>
|
<name>KnarLib</name>
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.2.4</version>
|
<version>3.3.0</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
@ -39,6 +39,20 @@
|
|||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.jetbrains.annotations</pattern>
|
||||||
|
<shadedPattern>net.knarcraft.knarlib.lib.annotations</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>org.jetbrains:annotations</artifact>
|
||||||
|
<includes>
|
||||||
|
<include>org/jetbrains/annotations/**</include>
|
||||||
|
</includes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@ -81,7 +95,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>spigot-api</artifactId>
|
||||||
<version>1.19.4-R0.1-SNAPSHOT</version>
|
<version>1.20.6-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -90,5 +104,11 @@
|
|||||||
<version>5.9.2</version>
|
<version>5.9.2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>24.0.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -4,6 +4,9 @@ import net.knarcraft.knarlib.property.ColorConversion;
|
|||||||
import net.knarcraft.knarlib.util.ColorHelper;
|
import net.knarcraft.knarlib.util.ColorHelper;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A formatter for formatting displayed messages
|
* A formatter for formatting displayed messages
|
||||||
@ -15,6 +18,9 @@ public final class StringFormatter {
|
|||||||
private final Translator translator;
|
private final Translator translator;
|
||||||
private ChatColor successColor = ChatColor.GREEN;
|
private ChatColor successColor = ChatColor.GREEN;
|
||||||
private ChatColor errorColor = ChatColor.DARK_RED;
|
private ChatColor errorColor = ChatColor.DARK_RED;
|
||||||
|
private String namePrefix = "[";
|
||||||
|
private String nameSuffix = "]";
|
||||||
|
private ColorConversion colorConversion = ColorConversion.NORMAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new string formatter
|
* Instantiates a new string formatter
|
||||||
@ -24,22 +30,45 @@ public final class StringFormatter {
|
|||||||
* @param pluginName <p>The name of the using plugin (used for the message prefix)</p>
|
* @param pluginName <p>The name of the using plugin (used for the message prefix)</p>
|
||||||
* @param translator <p>The translator to use for translating messages</p>
|
* @param translator <p>The translator to use for translating messages</p>
|
||||||
*/
|
*/
|
||||||
public StringFormatter(String pluginName, Translator translator) {
|
public StringFormatter(@NotNull String pluginName, @NotNull Translator translator) {
|
||||||
this.pluginName = pluginName;
|
this.pluginName = pluginName;
|
||||||
this.translator = translator;
|
this.translator = translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type of color conversion to use for translated messages
|
||||||
|
*
|
||||||
|
* @param colorConversion <p>The color conversion to use</p>
|
||||||
|
*/
|
||||||
|
public void setColorConversion(@NotNull ColorConversion colorConversion) {
|
||||||
|
this.colorConversion = colorConversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the prefix used in front of the plugin name. Normally just "["
|
||||||
|
*
|
||||||
|
* @param namePrefix <p>The new name prefix</p>
|
||||||
|
*/
|
||||||
|
public void setNamePrefix(@NotNull String namePrefix) {
|
||||||
|
this.namePrefix = namePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the suffix used after the plugin name. Normally just "]"
|
||||||
|
*
|
||||||
|
* @param nameSuffix <p>The new name suffix</p>
|
||||||
|
*/
|
||||||
|
public void setNameSuffix(@NotNull String nameSuffix) {
|
||||||
|
this.nameSuffix = nameSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the color to prepend when using displaySuccessMessage
|
* Sets the color to prepend when using displaySuccessMessage
|
||||||
*
|
*
|
||||||
* @param color <p>The color to use</p>
|
* @param color <p>The color to use</p>
|
||||||
*/
|
*/
|
||||||
public void setSuccessColor(ChatColor color) {
|
public void setSuccessColor(@NotNull ChatColor color) {
|
||||||
if (color != null) {
|
this.successColor = color;
|
||||||
this.successColor = color;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Success color cannot be null");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,12 +76,8 @@ public final class StringFormatter {
|
|||||||
*
|
*
|
||||||
* @param color <p>The color to use</p>
|
* @param color <p>The color to use</p>
|
||||||
*/
|
*/
|
||||||
public void setErrorColor(ChatColor color) {
|
public void setErrorColor(@NotNull ChatColor color) {
|
||||||
if (color != null) {
|
this.errorColor = color;
|
||||||
this.errorColor = color;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Error color cannot be null");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,8 +86,8 @@ public final class StringFormatter {
|
|||||||
* @param sender <p>The command sender to display the message to</p>
|
* @param sender <p>The command sender to display the message to</p>
|
||||||
* @param message <p>The translatable message to display</p>
|
* @param message <p>The translatable message to display</p>
|
||||||
*/
|
*/
|
||||||
public void displayNeutralMessage(CommandSender sender, TranslatableMessage message) {
|
public void displayNeutralMessage(@NotNull CommandSender sender, @NotNull TranslatableMessage message) {
|
||||||
sender.sendMessage(getFormattedMessage(this.translator.getTranslatedMessage(message)));
|
displayNeutralMessage(sender, this.translator.getTranslatedMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,7 +96,7 @@ public final class StringFormatter {
|
|||||||
* @param sender <p>The command sender to display the message to</p>
|
* @param sender <p>The command sender to display the message to</p>
|
||||||
* @param message <p>The raw message to display</p>
|
* @param message <p>The raw message to display</p>
|
||||||
*/
|
*/
|
||||||
public void displayNeutralMessage(CommandSender sender, String message) {
|
public void displayNeutralMessage(@NotNull CommandSender sender, @NotNull String message) {
|
||||||
sender.sendMessage(getFormattedMessage(message));
|
sender.sendMessage(getFormattedMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,8 +106,8 @@ public final class StringFormatter {
|
|||||||
* @param sender <p>The command sender to display the message to</p>
|
* @param sender <p>The command sender to display the message to</p>
|
||||||
* @param message <p>The translatable message to display</p>
|
* @param message <p>The translatable message to display</p>
|
||||||
*/
|
*/
|
||||||
public void displaySuccessMessage(CommandSender sender, TranslatableMessage message) {
|
public void displaySuccessMessage(@NotNull CommandSender sender, @NotNull TranslatableMessage message) {
|
||||||
sender.sendMessage(successColor + getFormattedMessage(this.translator.getTranslatedMessage(message)));
|
displaySuccessMessage(sender, this.translator.getTranslatedMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,8 +116,12 @@ public final class StringFormatter {
|
|||||||
* @param sender <p>The command sender to display the message to</p>
|
* @param sender <p>The command sender to display the message to</p>
|
||||||
* @param message <p>The raw message to display</p>
|
* @param message <p>The raw message to display</p>
|
||||||
*/
|
*/
|
||||||
public void displaySuccessMessage(CommandSender sender, String message) {
|
public void displaySuccessMessage(@NotNull CommandSender sender, @NotNull String message) {
|
||||||
sender.sendMessage(successColor + getFormattedMessage(message));
|
if (!this.namePrefix.equals("[") || !this.nameSuffix.equals("]")) {
|
||||||
|
sender.sendMessage(getFormattedMessage(successColor + message));
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(successColor + getFormattedMessage(message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,8 +130,8 @@ public final class StringFormatter {
|
|||||||
* @param sender <p>The command sender to display the message to</p>
|
* @param sender <p>The command sender to display the message to</p>
|
||||||
* @param message <p>The translatable message to display</p>
|
* @param message <p>The translatable message to display</p>
|
||||||
*/
|
*/
|
||||||
public void displayErrorMessage(CommandSender sender, TranslatableMessage message) {
|
public void displayErrorMessage(@NotNull CommandSender sender, @NotNull TranslatableMessage message) {
|
||||||
sender.sendMessage(errorColor + getFormattedMessage(this.translator.getTranslatedMessage(message)));
|
displayErrorMessage(sender, this.translator.getTranslatedMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,8 +140,33 @@ public final class StringFormatter {
|
|||||||
* @param sender <p>The command sender to display the message to</p>
|
* @param sender <p>The command sender to display the message to</p>
|
||||||
* @param message <p>The raw message to display</p>
|
* @param message <p>The raw message to display</p>
|
||||||
*/
|
*/
|
||||||
public void displayErrorMessage(CommandSender sender, String message) {
|
public void displayErrorMessage(@NotNull CommandSender sender, @NotNull String message) {
|
||||||
sender.sendMessage(errorColor + getFormattedMessage(message));
|
if (!this.namePrefix.equals("[") || !this.nameSuffix.equals("]")) {
|
||||||
|
sender.sendMessage(getFormattedMessage(errorColor + message));
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(errorColor + getFormattedMessage(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the raw, un-formatted translation of the given translatable message
|
||||||
|
*
|
||||||
|
* @param translatableMessage <p>The message to get the translation of</p>
|
||||||
|
* @return <p>The raw translation</p>
|
||||||
|
*/
|
||||||
|
public @NotNull String getUnFormattedMessage(@NotNull TranslatableMessage translatableMessage) {
|
||||||
|
return this.translator.getTranslatedMessage(translatableMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the un-formatted translation of the given translatable message, with translated color codes
|
||||||
|
*
|
||||||
|
* @param translatableMessage <p>The message to get the colored translation of</p>
|
||||||
|
* @return <p>The colored raw translation</p>
|
||||||
|
*/
|
||||||
|
public @NotNull String getUnFormattedColoredMessage(@NotNull TranslatableMessage translatableMessage) {
|
||||||
|
return ColorHelper.translateColorCodes(this.translator.getTranslatedMessage(translatableMessage),
|
||||||
|
this.colorConversion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,7 +177,8 @@ public final class StringFormatter {
|
|||||||
* @param replacement <p>The replacement value</p>
|
* @param replacement <p>The replacement value</p>
|
||||||
* @return <p>The input string with the placeholder replaced</p>
|
* @return <p>The input string with the placeholder replaced</p>
|
||||||
*/
|
*/
|
||||||
public String replacePlaceholder(TranslatableMessage translatableMessage, String placeholder, String replacement) {
|
public String replacePlaceholder(@NotNull TranslatableMessage translatableMessage, @NotNull String placeholder,
|
||||||
|
@NotNull String replacement) {
|
||||||
return replacePlaceholder(this.translator.getTranslatedMessage(translatableMessage), placeholder, replacement);
|
return replacePlaceholder(this.translator.getTranslatedMessage(translatableMessage), placeholder, replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,8 +190,22 @@ public final class StringFormatter {
|
|||||||
* @param replacements <p>The replacement values</p>
|
* @param replacements <p>The replacement values</p>
|
||||||
* @return <p>The input string with placeholders replaced</p>
|
* @return <p>The input string with placeholders replaced</p>
|
||||||
*/
|
*/
|
||||||
public String replacePlaceholders(TranslatableMessage translatableMessage, String[] placeholders,
|
public String replacePlaceholders(@NotNull TranslatableMessage translatableMessage, @NotNull String[] placeholders,
|
||||||
String[] replacements) {
|
@NotNull String[] replacements) {
|
||||||
|
return replacePlaceholders(this.translator.getTranslatedMessage(translatableMessage), List.of(placeholders),
|
||||||
|
List.of(replacements));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces placeholders in a translatable message
|
||||||
|
*
|
||||||
|
* @param translatableMessage <p>The translatable message to replace in</p>
|
||||||
|
* @param placeholders <p>The placeholders to replace</p>
|
||||||
|
* @param replacements <p>The replacement values</p>
|
||||||
|
* @return <p>The input string with placeholders replaced</p>
|
||||||
|
*/
|
||||||
|
public String replacePlaceholders(@NotNull TranslatableMessage translatableMessage, @NotNull List<String> placeholders,
|
||||||
|
@NotNull List<String> replacements) {
|
||||||
return replacePlaceholders(this.translator.getTranslatedMessage(translatableMessage), placeholders, replacements);
|
return replacePlaceholders(this.translator.getTranslatedMessage(translatableMessage), placeholders, replacements);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +217,8 @@ public final class StringFormatter {
|
|||||||
* @param replacement <p>The replacement value</p>
|
* @param replacement <p>The replacement value</p>
|
||||||
* @return <p>The input string with the placeholder replaced</p>
|
* @return <p>The input string with the placeholder replaced</p>
|
||||||
*/
|
*/
|
||||||
public static String replacePlaceholder(String input, String placeholder, String replacement) {
|
public static String replacePlaceholder(@NotNull String input, @NotNull String placeholder,
|
||||||
|
@NotNull String replacement) {
|
||||||
return input.replace(placeholder, replacement);
|
return input.replace(placeholder, replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,9 +230,23 @@ public final class StringFormatter {
|
|||||||
* @param replacements <p>The replacement values</p>
|
* @param replacements <p>The replacement values</p>
|
||||||
* @return <p>The input string with placeholders replaced</p>
|
* @return <p>The input string with placeholders replaced</p>
|
||||||
*/
|
*/
|
||||||
public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
|
public static String replacePlaceholders(@NotNull String input, @NotNull String[] placeholders,
|
||||||
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
|
@NotNull String[] replacements) {
|
||||||
input = replacePlaceholder(input, placeholders[i], replacements[i]);
|
return replacePlaceholders(input, List.of(placeholders), List.of(replacements));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces placeholders in a string
|
||||||
|
*
|
||||||
|
* @param input <p>The input string to replace in</p>
|
||||||
|
* @param placeholders <p>The placeholders to replace</p>
|
||||||
|
* @param replacements <p>The replacement values</p>
|
||||||
|
* @return <p>The input string with placeholders replaced</p>
|
||||||
|
*/
|
||||||
|
public static String replacePlaceholders(@NotNull String input, @NotNull List<String> placeholders,
|
||||||
|
@NotNull List<String> replacements) {
|
||||||
|
for (int i = 0; i < Math.min(placeholders.size(), replacements.size()); i++) {
|
||||||
|
input = replacePlaceholder(input, placeholders.get(i), replacements.get(i));
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
@ -173,13 +257,11 @@ public final class StringFormatter {
|
|||||||
* @param message <p>The message to format</p>
|
* @param message <p>The message to format</p>
|
||||||
* @return <p>The formatted message</p>
|
* @return <p>The formatted message</p>
|
||||||
*/
|
*/
|
||||||
private String getFormattedMessage(String message) {
|
private String getFormattedMessage(@NotNull String message) {
|
||||||
message = ColorHelper.translateColorCodes(message, ColorConversion.NORMAL);
|
message = ColorHelper.translateColorCodes(message, this.colorConversion);
|
||||||
if (this.pluginName == null) {
|
String coloredPrefix = ColorHelper.translateColorCodes(namePrefix + this.pluginName +
|
||||||
return message;
|
nameSuffix, this.colorConversion);
|
||||||
} else {
|
return coloredPrefix + " " + ChatColor.RESET + message;
|
||||||
return "[" + this.pluginName + "] " + ChatColor.RESET + message;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package net.knarcraft.knarlib.formatting;
|
package net.knarcraft.knarlib.formatting;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -25,7 +28,7 @@ public final class StringReplacer {
|
|||||||
*
|
*
|
||||||
* @param replacementInput <p>The input string to replace placeholders for</p>
|
* @param replacementInput <p>The input string to replace placeholders for</p>
|
||||||
*/
|
*/
|
||||||
public StringReplacer(String replacementInput) {
|
public StringReplacer(@NotNull String replacementInput) {
|
||||||
this.replacementInput = replacementInput;
|
this.replacementInput = replacementInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +38,7 @@ public final class StringReplacer {
|
|||||||
* @param placeholder <p>The placeholder to replace</p>
|
* @param placeholder <p>The placeholder to replace</p>
|
||||||
* @param value <p>The replacement value</p>
|
* @param value <p>The replacement value</p>
|
||||||
*/
|
*/
|
||||||
public void add(String placeholder, String value) {
|
public void add(@NotNull String placeholder, @NotNull String value) {
|
||||||
this.replacements.put(placeholder, value);
|
this.replacements.put(placeholder, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +47,7 @@ public final class StringReplacer {
|
|||||||
*
|
*
|
||||||
* @param placeholder <p>The placeholder to remove</p>
|
* @param placeholder <p>The placeholder to remove</p>
|
||||||
*/
|
*/
|
||||||
public void remove(String placeholder) {
|
public void remove(@NotNull String placeholder) {
|
||||||
this.replacements.remove(placeholder);
|
this.replacements.remove(placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +58,7 @@ public final class StringReplacer {
|
|||||||
*
|
*
|
||||||
* @return <p>The string with placeholders replaced</p>
|
* @return <p>The string with placeholders replaced</p>
|
||||||
*/
|
*/
|
||||||
public String replace() {
|
public @NotNull String replace() {
|
||||||
if (replacementInput == null) {
|
if (replacementInput == null) {
|
||||||
throw new IllegalStateException("This method cannot be run without a defined string");
|
throw new IllegalStateException("This method cannot be run without a defined string");
|
||||||
}
|
}
|
||||||
@ -68,9 +71,9 @@ public final class StringReplacer {
|
|||||||
* @param input <p>The string to replace placeholders in</p>
|
* @param input <p>The string to replace placeholders in</p>
|
||||||
* @return <p>The string with placeholders replaced</p>
|
* @return <p>The string with placeholders replaced</p>
|
||||||
*/
|
*/
|
||||||
public String replace(String input) {
|
public @NotNull String replace(@NotNull String input) {
|
||||||
return StringFormatter.replacePlaceholders(input, replacements.keySet().toArray(new String[0]),
|
return StringFormatter.replacePlaceholders(input, new ArrayList<>(replacements.keySet()),
|
||||||
replacements.values().toArray(new String[0]));
|
new ArrayList<>(replacements.values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.knarcraft.knarlib.formatting;
|
package net.knarcraft.knarlib.formatting;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -28,7 +30,7 @@ public final class TimeFormatter {
|
|||||||
* @param duration <p>The duration, in seconds, to display</p>
|
* @param duration <p>The duration, in seconds, to display</p>
|
||||||
* @return <p>The string used for displaying this sign's duration</p>
|
* @return <p>The string used for displaying this sign's duration</p>
|
||||||
*/
|
*/
|
||||||
public static String getDurationString(Translator translator, long duration) {
|
public static String getDurationString(@NotNull Translator translator, long duration) {
|
||||||
//Initialize time units once, and only if this method is actually used
|
//Initialize time units once, and only if this method is actually used
|
||||||
if (sortedUnits == null) {
|
if (sortedUnits == null) {
|
||||||
initializeUnits(translator);
|
initializeUnits(translator);
|
||||||
@ -76,8 +78,8 @@ public final class TimeFormatter {
|
|||||||
* @param castToInt <p>Whether to cast the duration to an int</p>
|
* @param castToInt <p>Whether to cast the duration to an int</p>
|
||||||
* @return <p>The formatted duration string</p>
|
* @return <p>The formatted duration string</p>
|
||||||
*/
|
*/
|
||||||
private static String formatDurationString(double duration, Translator translator,
|
private static String formatDurationString(double duration, @NotNull Translator translator,
|
||||||
TranslatableMessage translatableMessage, boolean castToInt) {
|
@NotNull TranslatableMessage translatableMessage, boolean castToInt) {
|
||||||
String durationFormat = translator.getTranslatedMessage(TranslatableTimeUnit.DURATION_FORMAT);
|
String durationFormat = translator.getTranslatedMessage(TranslatableTimeUnit.DURATION_FORMAT);
|
||||||
durationFormat = replacePlaceholder(durationFormat, "{unit}",
|
durationFormat = replacePlaceholder(durationFormat, "{unit}",
|
||||||
translator.getTranslatedMessage(translatableMessage));
|
translator.getTranslatedMessage(translatableMessage));
|
||||||
@ -88,7 +90,7 @@ public final class TimeFormatter {
|
|||||||
/**
|
/**
|
||||||
* Initializes the mapping of available time units for formatting permission sign duration
|
* Initializes the mapping of available time units for formatting permission sign duration
|
||||||
*/
|
*/
|
||||||
private static void initializeUnits(Translator translator) {
|
private static void initializeUnits(@NotNull Translator translator) {
|
||||||
//Register each time unit with a registered singular and plural translation
|
//Register each time unit with a registered singular and plural translation
|
||||||
timeUnits = new HashMap<>();
|
timeUnits = new HashMap<>();
|
||||||
registerTimeUnit(translator, 315360000, TranslatableTimeUnit.UNIT_DECADE, TranslatableTimeUnit.UNIT_DECADES);
|
registerTimeUnit(translator, 315360000, TranslatableTimeUnit.UNIT_DECADE, TranslatableTimeUnit.UNIT_DECADES);
|
||||||
@ -102,7 +104,7 @@ public final class TimeFormatter {
|
|||||||
TranslatableTimeUnit.UNIT_SECONDS);
|
TranslatableTimeUnit.UNIT_SECONDS);
|
||||||
|
|
||||||
//As now and seconds are the base units, those must be registered to use getDurationString
|
//As now and seconds are the base units, those must be registered to use getDurationString
|
||||||
if (!registeredSeconds || !hasTranslation(translator, TranslatableTimeUnit.UNIT_NOW)) {
|
if (!registeredSeconds || !translator.hasTranslation(TranslatableTimeUnit.UNIT_NOW)) {
|
||||||
throw new IllegalStateException("A translation is missing for UNIT_SECOND, UNIT_SECONDS or UNIT_NOW");
|
throw new IllegalStateException("A translation is missing for UNIT_SECOND, UNIT_SECONDS or UNIT_NOW");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,11 +123,12 @@ public final class TimeFormatter {
|
|||||||
* @param plural <p>The translatable time unit to use for the plural form</p>
|
* @param plural <p>The translatable time unit to use for the plural form</p>
|
||||||
* @return <p>True if the time unit was registered. False if a translation is missing</p>
|
* @return <p>True if the time unit was registered. False if a translation is missing</p>
|
||||||
*/
|
*/
|
||||||
private static boolean registerTimeUnit(Translator translator, double seconds, TranslatableTimeUnit singular,
|
private static boolean registerTimeUnit(@NotNull Translator translator, double seconds,
|
||||||
TranslatableTimeUnit plural) {
|
@NotNull TranslatableTimeUnit singular,
|
||||||
|
@NotNull TranslatableTimeUnit plural) {
|
||||||
String singularTranslation = translator.getTranslatedMessage(singular);
|
String singularTranslation = translator.getTranslatedMessage(singular);
|
||||||
String pluralTranslation = translator.getTranslatedMessage(plural);
|
String pluralTranslation = translator.getTranslatedMessage(plural);
|
||||||
if (hasTranslation(translator, singular) && hasTranslation(translator, plural)) {
|
if (translator.hasTranslation(singular) && translator.hasTranslation(plural)) {
|
||||||
timeUnits.put(seconds, new TranslatableTimeUnit[]{singular, plural});
|
timeUnits.put(seconds, new TranslatableTimeUnit[]{singular, plural});
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -133,16 +136,4 @@ public final class TimeFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the given translatable message has a registered translation
|
|
||||||
*
|
|
||||||
* @param translator <p>The translator to check</p>
|
|
||||||
* @param translatableMessage <p>The translatable message to check</p>
|
|
||||||
* @return <p>True if a non-empty translation has been registered</p>
|
|
||||||
*/
|
|
||||||
private static boolean hasTranslation(Translator translator, TranslatableMessage translatableMessage) {
|
|
||||||
String translation = translator.getTranslatedMessage(translatableMessage);
|
|
||||||
return translation != null && !translation.isBlank();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.knarcraft.knarlib.formatting;
|
package net.knarcraft.knarlib.formatting;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A message which can be translated
|
* A message which can be translated
|
||||||
*/
|
*/
|
||||||
@ -13,7 +15,7 @@ public interface TranslatableMessage {
|
|||||||
*
|
*
|
||||||
* @return <p>The name of this translatable message</p>
|
* @return <p>The name of this translatable message</p>
|
||||||
*/
|
*/
|
||||||
String name();
|
@NotNull String name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all translatable messages
|
* Gets all translatable messages
|
||||||
@ -22,6 +24,6 @@ public interface TranslatableMessage {
|
|||||||
*
|
*
|
||||||
* @return <p>All translatable messages</p>
|
* @return <p>All translatable messages</p>
|
||||||
*/
|
*/
|
||||||
TranslatableMessage[] getAllMessages();
|
@NotNull TranslatableMessage[] getAllMessages();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.knarcraft.knarlib.formatting;
|
package net.knarcraft.knarlib.formatting;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum containing all translatable time units
|
* An enum containing all translatable time units
|
||||||
*
|
*
|
||||||
@ -10,7 +12,7 @@ package net.knarcraft.knarlib.formatting;
|
|||||||
public enum TranslatableTimeUnit implements TranslatableMessage {
|
public enum TranslatableTimeUnit implements TranslatableMessage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The format for displaying the exact duration of a blacksmith's cool-down or delay
|
* The format for displaying the duration of something
|
||||||
*/
|
*/
|
||||||
DURATION_FORMAT,
|
DURATION_FORMAT,
|
||||||
|
|
||||||
@ -101,7 +103,7 @@ public enum TranslatableTimeUnit implements TranslatableMessage {
|
|||||||
;
|
;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TranslatableMessage[] getAllMessages() {
|
public @NotNull TranslatableMessage[] getAllMessages() {
|
||||||
return TranslatableTimeUnit.values();
|
return TranslatableTimeUnit.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,12 @@ import net.knarcraft.knarlib.util.ColorHelper;
|
|||||||
import net.knarcraft.knarlib.util.FileHelper;
|
import net.knarcraft.knarlib.util.FileHelper;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -41,7 +41,7 @@ public final class Translator {
|
|||||||
*
|
*
|
||||||
* @param translatableMessage <p>A translatable message in the category to register</p>
|
* @param translatableMessage <p>A translatable message in the category to register</p>
|
||||||
*/
|
*/
|
||||||
public void registerMessageCategory(TranslatableMessage translatableMessage) {
|
public void registerMessageCategory(@NotNull TranslatableMessage translatableMessage) {
|
||||||
messageCategories.add(translatableMessage);
|
messageCategories.add(translatableMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,12 +54,8 @@ public final class Translator {
|
|||||||
*
|
*
|
||||||
* @param colorConversion <p>The color conversion to be used</p>
|
* @param colorConversion <p>The color conversion to be used</p>
|
||||||
*/
|
*/
|
||||||
public void setColorConversion(ColorConversion colorConversion) {
|
public void setColorConversion(@NotNull ColorConversion colorConversion) {
|
||||||
if (colorConversion != null) {
|
this.colorConversion = colorConversion;
|
||||||
this.colorConversion = colorConversion;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Color conversion cannot be null");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,7 +65,8 @@ public final class Translator {
|
|||||||
* @param fallbackLanguage <p>The default language to fall back on in the case of missing translations</p>
|
* @param fallbackLanguage <p>The default language to fall back on in the case of missing translations</p>
|
||||||
* @param selectedLanguage <p>The currently selected language</p>
|
* @param selectedLanguage <p>The currently selected language</p>
|
||||||
*/
|
*/
|
||||||
public void loadLanguages(File dataFolder, String fallbackLanguage, String selectedLanguage) {
|
public void loadLanguages(@NotNull File dataFolder, @NotNull String fallbackLanguage,
|
||||||
|
@NotNull String selectedLanguage) {
|
||||||
backupTranslatedMessages = loadTranslatedMessages(fallbackLanguage);
|
backupTranslatedMessages = loadTranslatedMessages(fallbackLanguage);
|
||||||
translatedMessages = loadCustomTranslatedMessages(dataFolder, selectedLanguage);
|
translatedMessages = loadCustomTranslatedMessages(dataFolder, selectedLanguage);
|
||||||
if (translatedMessages == null) {
|
if (translatedMessages == null) {
|
||||||
@ -77,13 +74,24 @@ public final class Translator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given translatable message has a translation
|
||||||
|
*
|
||||||
|
* @param translatableMessage <p>The translatable message to check</p>
|
||||||
|
* @return <p>True if the message has a translation</p>
|
||||||
|
*/
|
||||||
|
public boolean hasTranslation(@NotNull TranslatableMessage translatableMessage) {
|
||||||
|
return backupTranslatedMessages.containsKey(translatableMessage) &&
|
||||||
|
!backupTranslatedMessages.get(translatableMessage).isBlank();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a translated version of the given translatable message
|
* Gets a translated version of the given translatable message
|
||||||
*
|
*
|
||||||
* @param translatableMessage <p>The message to translate</p>
|
* @param translatableMessage <p>The message to translate</p>
|
||||||
* @return <p>The translated message</p>
|
* @return <p>The translated message</p>
|
||||||
*/
|
*/
|
||||||
public String getTranslatedMessage(TranslatableMessage translatableMessage) {
|
public @NotNull String getTranslatedMessage(@NotNull TranslatableMessage translatableMessage) {
|
||||||
if (translatedMessages == null) {
|
if (translatedMessages == null) {
|
||||||
return "Translated strings not loaded";
|
return "Translated strings not loaded";
|
||||||
}
|
}
|
||||||
@ -104,7 +112,7 @@ public final class Translator {
|
|||||||
* @param language <p>The language chosen by the user</p>
|
* @param language <p>The language chosen by the user</p>
|
||||||
* @return <p>A mapping of all strings for the given language</p>
|
* @return <p>A mapping of all strings for the given language</p>
|
||||||
*/
|
*/
|
||||||
public Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
|
public @Nullable Map<TranslatableMessage, String> loadTranslatedMessages(@NotNull String language) {
|
||||||
try {
|
try {
|
||||||
BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
|
BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
|
||||||
return loadTranslatableMessages(language, reader);
|
return loadTranslatableMessages(language, reader);
|
||||||
@ -121,10 +129,8 @@ public final class Translator {
|
|||||||
* @param language <p>The selected language</p>
|
* @param language <p>The selected language</p>
|
||||||
* @return <p>The loaded translated strings, or null if no custom language file exists</p>
|
* @return <p>The loaded translated strings, or null if no custom language file exists</p>
|
||||||
*/
|
*/
|
||||||
public Map<TranslatableMessage, String> loadCustomTranslatedMessages(File dataFolder, String language) {
|
public @Nullable Map<TranslatableMessage, String> loadCustomTranslatedMessages(@NotNull File dataFolder,
|
||||||
if (dataFolder == null) {
|
@NotNull String language) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
File strings = new File(dataFolder, "strings.yml");
|
File strings = new File(dataFolder, "strings.yml");
|
||||||
if (!strings.exists()) {
|
if (!strings.exists()) {
|
||||||
Bukkit.getLogger().log(Level.FINEST, "Strings file not found");
|
Bukkit.getLogger().log(Level.FINEST, "Strings file not found");
|
||||||
@ -133,9 +139,9 @@ public final class Translator {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Bukkit.getLogger().log(Level.INFO, "Loading custom strings...");
|
Bukkit.getLogger().log(Level.INFO, "Loading custom strings...");
|
||||||
return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(
|
return loadTranslatableMessages(language,
|
||||||
new FileInputStream(strings))));
|
FileHelper.getBufferedReaderFromString(strings.toPath().toString()));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException exception) {
|
||||||
Bukkit.getLogger().log(Level.WARNING, "Unable to load custom messages");
|
Bukkit.getLogger().log(Level.WARNING, "Unable to load custom messages");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -148,7 +154,8 @@ public final class Translator {
|
|||||||
* @param reader <p>The buffered reader to read from</p>
|
* @param reader <p>The buffered reader to read from</p>
|
||||||
* @return <p>The loaded translated strings</p>
|
* @return <p>The loaded translated strings</p>
|
||||||
*/
|
*/
|
||||||
private Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
|
private @NotNull Map<TranslatableMessage, String> loadTranslatableMessages(@NotNull String language,
|
||||||
|
@NotNull BufferedReader reader) {
|
||||||
Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
|
Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
|
||||||
|
|
||||||
|
168
src/main/java/net/knarcraft/knarlib/particle/ParticleConfig.java
Normal file
168
src/main/java/net/knarcraft/knarlib/particle/ParticleConfig.java
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
package net.knarcraft.knarlib.particle;
|
||||||
|
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A configuration describing a particle
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ParticleConfig {
|
||||||
|
|
||||||
|
private final ParticleMode particleMode;
|
||||||
|
private final Particle particleType;
|
||||||
|
private final int particleAmount;
|
||||||
|
private final double particleDensity;
|
||||||
|
private final double heightOffset;
|
||||||
|
private final double offsetX;
|
||||||
|
private final double offsetY;
|
||||||
|
private final double offsetZ;
|
||||||
|
private final double extra;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new particle config
|
||||||
|
*
|
||||||
|
* @param particlesSection <p>The configuration section containing the particle's settings</p>
|
||||||
|
*/
|
||||||
|
public ParticleConfig(@NotNull ConfigurationSection particlesSection) {
|
||||||
|
@NotNull Particle particleType;
|
||||||
|
try {
|
||||||
|
particleType = Particle.valueOf(particlesSection.getString("type"));
|
||||||
|
} catch (IllegalArgumentException | NullPointerException exception) {
|
||||||
|
particleType = Particle.ASH;
|
||||||
|
}
|
||||||
|
this.particleType = particleType;
|
||||||
|
this.particleAmount = particlesSection.getInt("amount", 30);
|
||||||
|
this.offsetX = particlesSection.getDouble("offsetX", 0.5);
|
||||||
|
this.offsetY = particlesSection.getDouble("offsetY", 1);
|
||||||
|
this.offsetZ = particlesSection.getDouble("offsetZ", 0.5);
|
||||||
|
this.heightOffset = particlesSection.getDouble("heightOffset", 0.5);
|
||||||
|
this.extra = particlesSection.getDouble("extra", 0);
|
||||||
|
ParticleMode particleMode;
|
||||||
|
try {
|
||||||
|
particleMode = ParticleMode.valueOf(particlesSection.getString("mode"));
|
||||||
|
} catch (IllegalArgumentException | NullPointerException exception) {
|
||||||
|
particleMode = ParticleMode.SINGLE;
|
||||||
|
}
|
||||||
|
this.particleMode = particleMode;
|
||||||
|
|
||||||
|
// Make sure particle density is between 1 (inclusive) and 0 (exclusive)
|
||||||
|
double particleDensity = particlesSection.getDouble("particleDensity", 0.1);
|
||||||
|
if (particleDensity <= 0) {
|
||||||
|
particleDensity = 0.1;
|
||||||
|
} else if (particleDensity > 360) {
|
||||||
|
particleDensity = 360;
|
||||||
|
}
|
||||||
|
this.particleDensity = particleDensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new particle config
|
||||||
|
*
|
||||||
|
* @param particleMode <p>The mode to use when spawning the particle</p>
|
||||||
|
* @param particleType <p>The type of particle to spawn</p>
|
||||||
|
* @param particleAmount <p>The amount of particles to spawn at once</p>
|
||||||
|
* @param particleDensity <p>The density of the particles, if spawning a shape</p>
|
||||||
|
* @param heightOffset <p>The offset above the block to spawn the particle</p>
|
||||||
|
* @param offsetX <p>The x-offset/spread of the spawned particles</p>
|
||||||
|
* @param offsetY <p>The y-offset/spread of the spawned particles</p>
|
||||||
|
* @param offsetZ <p>The z-offset/spread of the spawned particles</p>
|
||||||
|
* @param extra <p>Extra data for the particle. Usage depends on the particle type.</p>
|
||||||
|
*/
|
||||||
|
public ParticleConfig(@NotNull ParticleMode particleMode, @NotNull Particle particleType, int particleAmount,
|
||||||
|
double particleDensity, double heightOffset, double offsetX, double offsetY, double offsetZ,
|
||||||
|
double extra) {
|
||||||
|
this.particleMode = particleMode;
|
||||||
|
this.particleType = particleType;
|
||||||
|
this.particleAmount = particleAmount;
|
||||||
|
this.particleDensity = particleDensity;
|
||||||
|
this.heightOffset = heightOffset;
|
||||||
|
this.offsetX = offsetX;
|
||||||
|
this.offsetY = offsetY;
|
||||||
|
this.offsetZ = offsetZ;
|
||||||
|
this.extra = extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mode to use when drawing/spawning the particle(s)
|
||||||
|
*
|
||||||
|
* @return <p>The particle mode</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleMode getParticleMode() {
|
||||||
|
return particleMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of particle to spawn
|
||||||
|
*
|
||||||
|
* @return <p>The particle type</p>
|
||||||
|
*/
|
||||||
|
public @NotNull Particle getParticleType() {
|
||||||
|
return particleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of particles to spawn
|
||||||
|
*
|
||||||
|
* @return <p>The amount of particles</p>
|
||||||
|
*/
|
||||||
|
public int getParticleAmount() {
|
||||||
|
return particleAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The density of particles to use in shapes closer to 0 causes larger density
|
||||||
|
*
|
||||||
|
* @return <p>The particle density</p>
|
||||||
|
*/
|
||||||
|
public double getParticleDensity() {
|
||||||
|
return particleDensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of blocks above the block the particle(s) should spawn
|
||||||
|
*
|
||||||
|
* @return <p>The y-offset</p>
|
||||||
|
*/
|
||||||
|
public double getHeightOffset() {
|
||||||
|
return heightOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset/spread of particles in the x-direction
|
||||||
|
*
|
||||||
|
* @return <p>The x-offset</p>
|
||||||
|
*/
|
||||||
|
public double getOffsetX() {
|
||||||
|
return offsetX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset/spread of particles in the y-direction
|
||||||
|
*
|
||||||
|
* @return <p>The y-offset</p>
|
||||||
|
*/
|
||||||
|
public double getOffsetY() {
|
||||||
|
return offsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset/spread of particles in the z-direction
|
||||||
|
*
|
||||||
|
* @return <p>The z-offset</p>
|
||||||
|
*/
|
||||||
|
public double getOffsetZ() {
|
||||||
|
return offsetZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extra value to set for the particle. Exactly what it does depends on the particle.
|
||||||
|
*
|
||||||
|
* @return <p>The particle's extra value</p>
|
||||||
|
*/
|
||||||
|
public double getExtra() {
|
||||||
|
return extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
package net.knarcraft.knarlib.particle;
|
||||||
|
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for creating particle configurations
|
||||||
|
*
|
||||||
|
* <p>The default behavior will spawn a single particle with no offset or extra data, and density 1.</p>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class ParticleConfigBuilder {
|
||||||
|
|
||||||
|
private final Particle particleType;
|
||||||
|
private ParticleMode particleMode = ParticleMode.SINGLE;
|
||||||
|
private int particleAmount = 1;
|
||||||
|
private double particleDensity = 1;
|
||||||
|
private double heightOffset = 0;
|
||||||
|
private double offsetX = 0;
|
||||||
|
private double offsetY = 0;
|
||||||
|
private double offsetZ = 0;
|
||||||
|
private double extra = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new particle config builder
|
||||||
|
*
|
||||||
|
* @param particleType <p>The type of particle to spawn</p>
|
||||||
|
*/
|
||||||
|
public ParticleConfigBuilder(@NotNull Particle particleType) {
|
||||||
|
this.particleType = particleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the mode to use when spawning the particles
|
||||||
|
*
|
||||||
|
* @param particleMode <p>The mode to use</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setMode(@NotNull ParticleMode particleMode) {
|
||||||
|
this.particleMode = particleMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the amount of particles to spawn
|
||||||
|
*
|
||||||
|
* @param particleAmount <p>The number/amount of particles to spawn</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setAmount(int particleAmount) {
|
||||||
|
this.particleAmount = particleAmount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the density of the particles to spawn
|
||||||
|
*
|
||||||
|
* @param particleDensity <p>The new density</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setDensity(double particleDensity) {
|
||||||
|
this.particleDensity = particleDensity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the x,y,z offsets of the spawned particles
|
||||||
|
*
|
||||||
|
* <p>These values control the spread of the spawned particles</p>
|
||||||
|
*
|
||||||
|
* @param offsetX <p>The offset in the x-direction</p>
|
||||||
|
* @param offsetY <p>The offset in the y-direction</p>
|
||||||
|
* @param offsetZ <p>The offset in the z-direction</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setOffsets(double offsetX, double offsetY, double offsetZ) {
|
||||||
|
this.offsetX = offsetX;
|
||||||
|
this.offsetY = offsetY;
|
||||||
|
this.offsetZ = offsetZ;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the x offset of the spawned particles
|
||||||
|
*
|
||||||
|
* @param offsetX <p>The offset in the x-direction</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setXOffset(double offsetX) {
|
||||||
|
this.offsetX = offsetX;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the y offset of the spawned particles
|
||||||
|
*
|
||||||
|
* @param offsetY <p>The offset in the y-direction</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setYOffset(double offsetY) {
|
||||||
|
this.offsetY = offsetY;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the z offset of the spawned particles
|
||||||
|
*
|
||||||
|
* @param offsetZ <p>The offset in the z-direction</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setZOffset(double offsetZ) {
|
||||||
|
this.offsetZ = offsetZ;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the extra data for the spawned particles
|
||||||
|
*
|
||||||
|
* @param extra <p>The extra data to set</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setExtra(double extra) {
|
||||||
|
this.extra = extra;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the height offset for the spawned particles
|
||||||
|
*
|
||||||
|
* @param heightOffset <p>The height offset to use</p>
|
||||||
|
* @return <p>This particle configuration builder</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfigBuilder setHeightOffset(double heightOffset) {
|
||||||
|
this.heightOffset = heightOffset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the particle configuration
|
||||||
|
*
|
||||||
|
* @return <p>The built particle configuration</p>
|
||||||
|
*/
|
||||||
|
public @NotNull ParticleConfig build() {
|
||||||
|
return new ParticleConfig(particleMode, particleType, particleAmount, particleDensity, heightOffset, offsetX,
|
||||||
|
offsetY, offsetZ, extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package net.knarcraft.knarlib.particle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mode used for spawning one or more particle(s)
|
||||||
|
*/
|
||||||
|
public enum ParticleMode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the set amount of particles on a single point in the world
|
||||||
|
*/
|
||||||
|
SINGLE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the set amount of particles in a square around the block
|
||||||
|
*/
|
||||||
|
SQUARE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the set amount of particles in a circle around the block
|
||||||
|
*/
|
||||||
|
CIRCLE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the set amount of particles in a pyramid centered on the block
|
||||||
|
*/
|
||||||
|
PYRAMID,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the set amount of particles in a sphere centered on the block
|
||||||
|
*/
|
||||||
|
SPHERE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the set amount of particles in a cube centered on the block
|
||||||
|
*/
|
||||||
|
CUBE,
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
package net.knarcraft.knarlib.particle;
|
||||||
|
|
||||||
|
import net.knarcraft.knarlib.util.ParticleHelper;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A runnable tasks that spawns particles at the given blocks
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ParticleSpawner implements Runnable {
|
||||||
|
|
||||||
|
private final ParticleConfig particleConfig;
|
||||||
|
private final Map<Material, ParticleConfig> materialConfigs;
|
||||||
|
private final Collection<Block> blocks;
|
||||||
|
private final Supplier<Collection<Block>> blockSupplier;
|
||||||
|
private final UUID storedCalculationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new particle spawner
|
||||||
|
*
|
||||||
|
* @param particleConfig <p>The configuration for the particle to spawn</p>
|
||||||
|
* @param materialConfigs <p>Extra particle configurations for specific materials</p>
|
||||||
|
* @param blocks <p>The blocks to spawn particles on</p>
|
||||||
|
*/
|
||||||
|
public ParticleSpawner(@NotNull ParticleConfig particleConfig,
|
||||||
|
@Nullable Map<Material, ParticleConfig> materialConfigs, @NotNull Collection<Block> blocks) {
|
||||||
|
this.particleConfig = particleConfig;
|
||||||
|
this.materialConfigs = materialConfigs;
|
||||||
|
this.blocks = blocks;
|
||||||
|
this.blockSupplier = null;
|
||||||
|
|
||||||
|
this.storedCalculationId = UUID.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new particle spawner
|
||||||
|
*
|
||||||
|
* @param particleConfig <p>The configuration for the particle to spawn</p>
|
||||||
|
* @param materialConfigs <p>Extra particle configurations for specific materials</p>
|
||||||
|
* @param blockSupplier <p>The supplier supplying the blocks to spawn particles on</p>
|
||||||
|
*/
|
||||||
|
public ParticleSpawner(@NotNull ParticleConfig particleConfig,
|
||||||
|
@Nullable Map<Material, ParticleConfig> materialConfigs,
|
||||||
|
@NotNull Supplier<Collection<Block>> blockSupplier) {
|
||||||
|
this.particleConfig = particleConfig;
|
||||||
|
this.materialConfigs = materialConfigs;
|
||||||
|
this.blocks = null;
|
||||||
|
this.blockSupplier = blockSupplier;
|
||||||
|
|
||||||
|
this.storedCalculationId = UUID.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id used for stored calculations
|
||||||
|
*
|
||||||
|
* <p>You should run ParticleHelper.clearStoredCalculations(id) with this id when discarding this particle spawner
|
||||||
|
* to prevent a memory leak.</p>
|
||||||
|
*
|
||||||
|
* @return <p>The id used for stored calculations</p>
|
||||||
|
*/
|
||||||
|
public @NotNull UUID getStoredCalculationId() {
|
||||||
|
return this.storedCalculationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Use the static collection of blocks, or a dynamically changing supplier
|
||||||
|
Collection<Block> blocksToSpawnOn;
|
||||||
|
if (blocks != null) {
|
||||||
|
blocksToSpawnOn = blocks;
|
||||||
|
} else if (blockSupplier != null) {
|
||||||
|
blocksToSpawnOn = blockSupplier.get();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("There is a bug in the plugin code. Please contact the developer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Block block : blocksToSpawnOn) {
|
||||||
|
// Ignore blocks in unloaded chunks
|
||||||
|
if (!block.getChunk().isLoaded()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = block.getLocation().clone();
|
||||||
|
World world = location.getWorld();
|
||||||
|
if (world == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
spawnParticleForBlock(block, world, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the defined particle for the given block
|
||||||
|
*
|
||||||
|
* @param block <p>The block to spawn a particle effect for</p>
|
||||||
|
* @param world <p>The world the block belongs to</p>
|
||||||
|
* @param location <p>A clone of the block's location</p>
|
||||||
|
*/
|
||||||
|
private void spawnParticleForBlock(@NotNull Block block, @NotNull World world, @NotNull Location location) {
|
||||||
|
double blockHeight = ParticleHelper.getBlockHeight(block);
|
||||||
|
ParticleConfig activeConfig = getParticleConfig(block.getType());
|
||||||
|
|
||||||
|
switch (activeConfig.getParticleMode()) {
|
||||||
|
case SINGLE -> ParticleHelper.spawnParticle(world, location.clone().add(0.5,
|
||||||
|
activeConfig.getHeightOffset(), 0.5), activeConfig, blockHeight);
|
||||||
|
case SQUARE -> ParticleHelper.drawSquare(world, location, activeConfig, blockHeight);
|
||||||
|
case CIRCLE -> ParticleHelper.drawCircle(world, location, activeConfig, blockHeight, storedCalculationId);
|
||||||
|
case PYRAMID -> ParticleHelper.drawPyramid(world, location, activeConfig, blockHeight, storedCalculationId);
|
||||||
|
case SPHERE -> ParticleHelper.drawSphere(world, location, activeConfig, blockHeight, storedCalculationId);
|
||||||
|
case CUBE -> ParticleHelper.drawCube(world, location, activeConfig, blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the particle config to use for the current block's material
|
||||||
|
*
|
||||||
|
* @param material <p>The material of the block to get a configuration for</p>
|
||||||
|
* @return <p>The particle config to use</p>
|
||||||
|
*/
|
||||||
|
private @NotNull ParticleConfig getParticleConfig(@NotNull Material material) {
|
||||||
|
if (this.materialConfigs == null) {
|
||||||
|
return this.particleConfig;
|
||||||
|
}
|
||||||
|
ParticleConfig materialConfig = this.materialConfigs.get(material);
|
||||||
|
if (materialConfig != null) {
|
||||||
|
return materialConfig;
|
||||||
|
}
|
||||||
|
return this.particleConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package net.knarcraft.knarlib.particle;
|
||||||
|
|
||||||
|
import net.knarcraft.knarlib.util.ParticleHelper;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task for spawning trails behind players
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ParticleTrailSpawner implements Runnable {
|
||||||
|
|
||||||
|
private final Set<UUID> playersWithTrails = new HashSet<>();
|
||||||
|
private final Map<UUID, Particle> playerParticles = new HashMap<>();
|
||||||
|
private final Random random = new Random();
|
||||||
|
private final Particle particle;
|
||||||
|
private final List<Particle> randomTrailTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new particle trail spawner
|
||||||
|
*
|
||||||
|
* @param particle <p>The type of particle used for the trail</p>
|
||||||
|
* @param randomTrailTypes <p>The types of particles to use for random trails</p>
|
||||||
|
*/
|
||||||
|
public ParticleTrailSpawner(@NotNull Particle particle, @NotNull List<Particle> randomTrailTypes) {
|
||||||
|
this.particle = particle;
|
||||||
|
this.randomTrailTypes = randomTrailTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Set<UUID> offlinePlayers = new HashSet<>();
|
||||||
|
for (UUID playerId : playersWithTrails) {
|
||||||
|
// Clear offline players from the list
|
||||||
|
Player player = Bukkit.getPlayer(playerId);
|
||||||
|
if (player == null) {
|
||||||
|
offlinePlayers.add(playerId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the world and location to spawn the particle at
|
||||||
|
Location playerLocation = player.getLocation();
|
||||||
|
World playerWorld = playerLocation.getWorld();
|
||||||
|
if (playerWorld == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide on which type of particle to spawn
|
||||||
|
Particle spawnParticle = playerParticles.get(playerId);
|
||||||
|
if (spawnParticle == null) {
|
||||||
|
spawnParticle = this.particle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn a trail particle
|
||||||
|
ParticleConfig particleConfig = new ParticleConfigBuilder(spawnParticle).build();
|
||||||
|
ParticleHelper.spawnParticle(playerWorld, playerLocation, particleConfig, 0);
|
||||||
|
}
|
||||||
|
playersWithTrails.removeAll(offlinePlayers);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the trail behind the player with the given id
|
||||||
|
*
|
||||||
|
* @param playerId <p>The id of the player to remove the trail for</p>
|
||||||
|
*/
|
||||||
|
public void removeTrail(@NotNull UUID playerId) {
|
||||||
|
this.playersWithTrails.remove(playerId);
|
||||||
|
this.playerParticles.remove(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a random trail behind the player with the given id
|
||||||
|
*
|
||||||
|
* @param playerId <p>The id of the player to add the trail to</p>
|
||||||
|
*/
|
||||||
|
public void startRandomTrail(@NotNull UUID playerId) {
|
||||||
|
this.playerParticles.put(playerId, randomParticle());
|
||||||
|
this.playersWithTrails.add(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a trail behind the player with the given id
|
||||||
|
*
|
||||||
|
* @param playerId <p>The id of the player to add the trail to</p>
|
||||||
|
* @param particle <p>The particle to spawn, or null for the particle specified in the constructor</p>
|
||||||
|
*/
|
||||||
|
public void startTrail(@NotNull UUID playerId, @Nullable Particle particle) {
|
||||||
|
this.playerParticles.put(playerId, particle);
|
||||||
|
this.playersWithTrails.add(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a random particle from random the specified trail types
|
||||||
|
*
|
||||||
|
* @return <p>A random particle, or EGG_CRACK if no random trail types have been specified</p>
|
||||||
|
*/
|
||||||
|
private @NotNull Particle randomParticle() {
|
||||||
|
if (this.randomTrailTypes.isEmpty()) {
|
||||||
|
return Particle.EGG_CRACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Particle spawnParticle = null;
|
||||||
|
while (spawnParticle == null || spawnParticle.getDataType() != Void.class) {
|
||||||
|
spawnParticle = randomTrailTypes.get(random.nextInt(randomTrailTypes.size()));
|
||||||
|
}
|
||||||
|
return spawnParticle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package net.knarcraft.knarlib.util;
|
|||||||
import net.knarcraft.knarlib.property.ColorConversion;
|
import net.knarcraft.knarlib.property.ColorConversion;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -25,7 +26,7 @@ public final class ColorHelper {
|
|||||||
* @param color <p>The color to invert</p>
|
* @param color <p>The color to invert</p>
|
||||||
* @return <p>The inverted color</p>
|
* @return <p>The inverted color</p>
|
||||||
*/
|
*/
|
||||||
public static Color invert(Color color) {
|
public static @NotNull Color invert(@NotNull Color color) {
|
||||||
return color.setRed(255 - color.getRed()).setGreen(255 - color.getGreen()).setBlue(255 - color.getBlue());
|
return color.setRed(255 - color.getRed()).setGreen(255 - color.getGreen()).setBlue(255 - color.getBlue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ public final class ColorHelper {
|
|||||||
* @param color <p>The color to convert into a chat color</p>
|
* @param color <p>The color to convert into a chat color</p>
|
||||||
* @return <p>The resulting chat color</p>
|
* @return <p>The resulting chat color</p>
|
||||||
*/
|
*/
|
||||||
public static ChatColor fromColor(Color color) {
|
public static @NotNull ChatColor fromColor(@NotNull Color color) {
|
||||||
return ChatColor.of(String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue()));
|
return ChatColor.of(String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ public final class ColorHelper {
|
|||||||
* @param colorConversion <p>The type of color conversion to apply before stripping</p>
|
* @param colorConversion <p>The type of color conversion to apply before stripping</p>
|
||||||
* @return <p>The message without color codes</p>
|
* @return <p>The message without color codes</p>
|
||||||
*/
|
*/
|
||||||
public static String stripColorCodes(String message, ColorConversion colorConversion) {
|
public static @NotNull String stripColorCodes(@NotNull String message, @NotNull ColorConversion colorConversion) {
|
||||||
return ChatColor.stripColor(translateColorCodes(message, colorConversion));
|
return ChatColor.stripColor(translateColorCodes(message, colorConversion));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ public final class ColorHelper {
|
|||||||
* @param colorConversion <p>The type of color conversion to apply</p>
|
* @param colorConversion <p>The type of color conversion to apply</p>
|
||||||
* @return <p>The string with color codes applied</p>
|
* @return <p>The string with color codes applied</p>
|
||||||
*/
|
*/
|
||||||
public static String translateColorCodes(String message, ColorConversion colorConversion) {
|
public static @NotNull String translateColorCodes(@NotNull String message, @NotNull ColorConversion colorConversion) {
|
||||||
return switch (colorConversion) {
|
return switch (colorConversion) {
|
||||||
case NONE -> message;
|
case NONE -> message;
|
||||||
case NORMAL -> ChatColor.translateAlternateColorCodes('&', message);
|
case NORMAL -> ChatColor.translateAlternateColorCodes('&', message);
|
||||||
@ -85,7 +86,7 @@ public final class ColorHelper {
|
|||||||
* @param onlyRGB <p>Whether to only convert RGB (hexadecimal) color codes. If false, &[a-f0-9] will be converted as well.</p>
|
* @param onlyRGB <p>Whether to only convert RGB (hexadecimal) color codes. If false, &[a-f0-9] will be converted as well.</p>
|
||||||
* @return <p>The message with color codes translated</p>
|
* @return <p>The message with color codes translated</p>
|
||||||
*/
|
*/
|
||||||
private static String translateAllColorCodes(String message, boolean onlyRGB) {
|
private static @NotNull String translateAllColorCodes(@NotNull String message, boolean onlyRGB) {
|
||||||
if (!onlyRGB) {
|
if (!onlyRGB) {
|
||||||
message = ChatColor.translateAlternateColorCodes('&', message);
|
message = ChatColor.translateAlternateColorCodes('&', message);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.knarcraft.knarlib.util;
|
package net.knarcraft.knarlib.util;
|
||||||
|
|
||||||
import net.knarcraft.knarlib.property.ColorConversion;
|
import net.knarcraft.knarlib.property.ColorConversion;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -12,7 +14,9 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +37,7 @@ public final class FileHelper {
|
|||||||
* @return <p>A buffered read for reading the file</p>
|
* @return <p>A buffered read for reading the file</p>
|
||||||
* @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
|
* @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
|
||||||
*/
|
*/
|
||||||
public static BufferedReader getBufferedReaderForInternalFile(String file) throws FileNotFoundException {
|
public static @NotNull BufferedReader getBufferedReaderForInternalFile(@NotNull String file) throws FileNotFoundException {
|
||||||
InputStream inputStream = getInputStreamForInternalFile(file);
|
InputStream inputStream = getInputStreamForInternalFile(file);
|
||||||
if (inputStream == null) {
|
if (inputStream == null) {
|
||||||
throw new FileNotFoundException("Unable to read the given file");
|
throw new FileNotFoundException("Unable to read the given file");
|
||||||
@ -50,7 +54,7 @@ public final class FileHelper {
|
|||||||
* @param file <p>The file to read</p>
|
* @param file <p>The file to read</p>
|
||||||
* @return <p>An input stream for the file</p>
|
* @return <p>An input stream for the file</p>
|
||||||
*/
|
*/
|
||||||
public static InputStream getInputStreamForInternalFile(String file) {
|
public static @Nullable InputStream getInputStreamForInternalFile(@NotNull String file) {
|
||||||
return FileHelper.class.getResourceAsStream(file);
|
return FileHelper.class.getResourceAsStream(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +65,7 @@ public final class FileHelper {
|
|||||||
* @return <p>A buffered reader reading the file</p>
|
* @return <p>A buffered reader reading the file</p>
|
||||||
* @throws FileNotFoundException <p>If the given file does not exist</p>
|
* @throws FileNotFoundException <p>If the given file does not exist</p>
|
||||||
*/
|
*/
|
||||||
public static BufferedReader getBufferedReaderFromString(String file) throws FileNotFoundException {
|
public static @NotNull BufferedReader getBufferedReaderFromString(@NotNull String file) throws FileNotFoundException {
|
||||||
FileInputStream fileInputStream = new FileInputStream(file);
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
return getBufferedReaderFromInputStream(fileInputStream);
|
return getBufferedReaderFromInputStream(fileInputStream);
|
||||||
}
|
}
|
||||||
@ -72,19 +76,19 @@ public final class FileHelper {
|
|||||||
* @param inputStream <p>The input stream to read</p>
|
* @param inputStream <p>The input stream to read</p>
|
||||||
* @return <p>A buffered reader reading the input stream</p>
|
* @return <p>A buffered reader reading the input stream</p>
|
||||||
*/
|
*/
|
||||||
public static BufferedReader getBufferedReaderFromInputStream(InputStream inputStream) {
|
public static @NotNull BufferedReader getBufferedReaderFromInputStream(@NotNull InputStream inputStream) {
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
|
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
|
||||||
return new BufferedReader(inputStreamReader);
|
return new BufferedReader(inputStreamReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a buffered writer from a string pointing to a file
|
* Gets a buffered writer from a buffered reader
|
||||||
*
|
*
|
||||||
* @param file <p>The file to write to</p>
|
* @param file <p>The file to write to</p>
|
||||||
* @return <p>A buffered writer writing to the file</p>
|
* @return <p>A buffered writer writing to the file</p>
|
||||||
* @throws FileNotFoundException <p>If the file does not exist</p>
|
* @throws FileNotFoundException <p>If the file does not exist</p>
|
||||||
*/
|
*/
|
||||||
public static BufferedWriter getBufferedWriterFromString(String file) throws FileNotFoundException {
|
public static @NotNull BufferedWriter getBufferedWriterFromString(@NotNull String file) throws FileNotFoundException {
|
||||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||||
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
|
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
|
||||||
return new BufferedWriter(outputStreamWriter);
|
return new BufferedWriter(outputStreamWriter);
|
||||||
@ -99,9 +103,38 @@ public final class FileHelper {
|
|||||||
* @return <p>A map containing the read pairs</p>
|
* @return <p>A map containing the read pairs</p>
|
||||||
* @throws IOException <p>If unable to read from the stream</p>
|
* @throws IOException <p>If unable to read from the stream</p>
|
||||||
*/
|
*/
|
||||||
public static Map<String, String> readKeyValuePairs(BufferedReader bufferedReader, String separator,
|
@NotNull
|
||||||
ColorConversion colorConversion) throws IOException {
|
public static Map<String, String> readKeyValuePairs(@NotNull BufferedReader bufferedReader,
|
||||||
|
@NotNull String separator,
|
||||||
|
@NotNull ColorConversion colorConversion) throws IOException {
|
||||||
Map<String, String> readPairs = new HashMap<>();
|
Map<String, String> readPairs = new HashMap<>();
|
||||||
|
List<String> lines = readLines(bufferedReader);
|
||||||
|
|
||||||
|
for (String line : lines) {
|
||||||
|
int separatorIndex = line.indexOf(separator);
|
||||||
|
if (separatorIndex == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read the line
|
||||||
|
String key = line.substring(0, separatorIndex);
|
||||||
|
String value = ColorHelper.translateColorCodes(line.substring(separatorIndex + 1), colorConversion);
|
||||||
|
readPairs.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return readPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads all lines from a buffered reader
|
||||||
|
*
|
||||||
|
* @param bufferedReader <p>The buffered reader to read</p>
|
||||||
|
* @return <p>A list of the read lines</p>
|
||||||
|
* @throws IOException <p>If unable to read from the stream</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static List<String> readLines(@NotNull BufferedReader bufferedReader) throws IOException {
|
||||||
|
List<String> readLines = new ArrayList<>();
|
||||||
|
|
||||||
String line = bufferedReader.readLine();
|
String line = bufferedReader.readLine();
|
||||||
boolean firstLine = true;
|
boolean firstLine = true;
|
||||||
@ -112,22 +145,17 @@ public final class FileHelper {
|
|||||||
firstLine = false;
|
firstLine = false;
|
||||||
}
|
}
|
||||||
//Split at first separator
|
//Split at first separator
|
||||||
int separatorIndex = line.indexOf(separator);
|
if (line.isEmpty()) {
|
||||||
if (separatorIndex == -1) {
|
|
||||||
line = bufferedReader.readLine();
|
line = bufferedReader.readLine();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read the line
|
readLines.add(line);
|
||||||
String key = line.substring(0, separatorIndex);
|
|
||||||
String value = ColorHelper.translateColorCodes(line.substring(separatorIndex + 1), colorConversion);
|
|
||||||
readPairs.put(key, value);
|
|
||||||
|
|
||||||
line = bufferedReader.readLine();
|
line = bufferedReader.readLine();
|
||||||
}
|
}
|
||||||
bufferedReader.close();
|
bufferedReader.close();
|
||||||
|
|
||||||
return readPairs;
|
return readLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,7 +164,7 @@ public final class FileHelper {
|
|||||||
* @param string <p>The string to remove the BOM from</p>
|
* @param string <p>The string to remove the BOM from</p>
|
||||||
* @return <p>A string guaranteed without a BOM</p>
|
* @return <p>A string guaranteed without a BOM</p>
|
||||||
*/
|
*/
|
||||||
private static String removeUTF8BOM(String string) {
|
private static @NotNull String removeUTF8BOM(@NotNull String string) {
|
||||||
String UTF8_BOM = "\uFEFF";
|
String UTF8_BOM = "\uFEFF";
|
||||||
if (string.startsWith(UTF8_BOM)) {
|
if (string.startsWith(UTF8_BOM)) {
|
||||||
string = string.substring(1);
|
string = string.substring(1);
|
||||||
|
121
src/main/java/net/knarcraft/knarlib/util/MaterialHelper.java
Normal file
121
src/main/java/net/knarcraft/knarlib/util/MaterialHelper.java
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package net.knarcraft.knarlib.util;
|
||||||
|
|
||||||
|
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.Tag;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class for dealing with and parsing materials
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class MaterialHelper {
|
||||||
|
|
||||||
|
private MaterialHelper() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the materials specified in the given list
|
||||||
|
*
|
||||||
|
* @param materials <p>The list of material strings to load</p>
|
||||||
|
* @param tagPrefix <p>The prefix differentiating a tag from a material</p>
|
||||||
|
* @param logger <p>The logger to use for logging parsing errors</p>
|
||||||
|
*/
|
||||||
|
public static @NotNull Set<Material> loadMaterialList(@NotNull List<?> materials, @NotNull String tagPrefix,
|
||||||
|
@NotNull Logger logger) {
|
||||||
|
Set<Material> parsedMaterials = new HashSet<>();
|
||||||
|
for (Object value : materials) {
|
||||||
|
if (!(value instanceof String string)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedMaterials.addAll(loadMaterialString(string, tagPrefix, logger));
|
||||||
|
}
|
||||||
|
return parsedMaterials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string representing a material or a material tag
|
||||||
|
*
|
||||||
|
* @param materialString <p>The material string to parse</p>
|
||||||
|
* @param tagPrefix <p>The prefix differentiating a tag from a material</p>
|
||||||
|
* @param logger <p>The logger to use for logging parsing errors</p>
|
||||||
|
* @return <p>The materials defined by the material string, or an empty list if none were found</p>
|
||||||
|
*/
|
||||||
|
public static @NotNull Set<Material> loadMaterialString(@NotNull String materialString, @NotNull String tagPrefix,
|
||||||
|
@NotNull Logger logger) {
|
||||||
|
Set<Material> parsedMaterials = new HashSet<>();
|
||||||
|
// Try to parse a material tag first
|
||||||
|
if (parseMaterialTag(parsedMaterials, materialString, tagPrefix, logger)) {
|
||||||
|
return parsedMaterials;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to parse a material name
|
||||||
|
Material matched = loadMaterialString(materialString, logger);
|
||||||
|
if (matched != null) {
|
||||||
|
parsedMaterials.add(matched);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedMaterials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string representing a material
|
||||||
|
*
|
||||||
|
* @param materialString <p>The material string to parse</p>
|
||||||
|
* @param logger <p>The logger to use for logging parsing errors</p>
|
||||||
|
* @return <p>The material defined by the material string, or null if not found</p>
|
||||||
|
*/
|
||||||
|
public static @Nullable Material loadMaterialString(@NotNull String materialString, @NotNull Logger logger) {
|
||||||
|
// Try to parse a material name
|
||||||
|
Material matched = Material.matchMaterial(materialString.replace("-", "_"));
|
||||||
|
if (matched != null) {
|
||||||
|
return matched;
|
||||||
|
} else {
|
||||||
|
logger.log(Level.WARNING, StringFormatter.replacePlaceholder("Unable to parse material: {material}",
|
||||||
|
"{material}", materialString));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to parse the material tag in the specified material name
|
||||||
|
*
|
||||||
|
* @param targetSet <p>The set all parsed materials should be added to</p>
|
||||||
|
* @param materialName <p>The material name that might be a material tag</p>
|
||||||
|
* @param tagPrefix <p>The prefix differentiating a tag from a material</p>
|
||||||
|
* @param logger <p>The logger to use for logging parsing errors</p>
|
||||||
|
* @return <p>True if a tag was found</p>
|
||||||
|
*/
|
||||||
|
private static boolean parseMaterialTag(@NotNull Set<Material> targetSet, @NotNull String materialName,
|
||||||
|
@NotNull String tagPrefix, @NotNull Logger logger) {
|
||||||
|
Pattern pattern = Pattern.compile("^" + Pattern.quote(tagPrefix) + "([a-zA-Z_]+)");
|
||||||
|
Matcher matcher = pattern.matcher(materialName);
|
||||||
|
if (matcher.find()) {
|
||||||
|
// The material is a material tag
|
||||||
|
Tag<Material> tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.minecraft(
|
||||||
|
matcher.group(1).toLowerCase()), Material.class);
|
||||||
|
if (tag != null) {
|
||||||
|
targetSet.addAll(tag.getValues());
|
||||||
|
} else {
|
||||||
|
logger.log(Level.WARNING, StringFormatter.replacePlaceholder(
|
||||||
|
"Unable to parse material: {material}", "{material}", materialName));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
242
src/main/java/net/knarcraft/knarlib/util/ParticleHelper.java
Normal file
242
src/main/java/net/knarcraft/knarlib/util/ParticleHelper.java
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
package net.knarcraft.knarlib.util;
|
||||||
|
|
||||||
|
import net.knarcraft.knarlib.particle.ParticleConfig;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class for spawning particle effects
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ParticleHelper {
|
||||||
|
|
||||||
|
private static final Map<UUID, Vector[]> pyramidVectors = new HashMap<>();
|
||||||
|
private static final Map<UUID, Double[][]> circleCoordinates = new HashMap<>();
|
||||||
|
private static final Map<UUID, Double[][]> sphereCoordinates = new HashMap<>();
|
||||||
|
|
||||||
|
private ParticleHelper() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any stored calculations for the given id
|
||||||
|
*
|
||||||
|
* <p>If you frequently change the id without clearing, you'll create a memory leak!</p>
|
||||||
|
*
|
||||||
|
* @param id <p>The id specified when generating a shape</p>
|
||||||
|
*/
|
||||||
|
public static void clearStoredCalculations(UUID id) {
|
||||||
|
pyramidVectors.remove(id);
|
||||||
|
circleCoordinates.remove(id);
|
||||||
|
sphereCoordinates.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a cube of particles at the given location
|
||||||
|
*
|
||||||
|
* <p>It is recommended to only spawn one particle with no spread, and a density between 1 and 0.01</p>
|
||||||
|
*
|
||||||
|
* @param world <p>The world to spawn the particles in</p>
|
||||||
|
* @param location <p>The location of the block to spawn the particles at</p>
|
||||||
|
* @param particleConfig <p>The configuration describing the particle to spawn</p>
|
||||||
|
* @param blockHeight <p>The height of the block to spawn the particle above</p>
|
||||||
|
*/
|
||||||
|
public static void drawCube(@NotNull World world, @NotNull Location location, @NotNull ParticleConfig particleConfig,
|
||||||
|
double blockHeight) {
|
||||||
|
// Draw the top and bottom of the cube
|
||||||
|
drawSquare(world, location, particleConfig, blockHeight);
|
||||||
|
drawSquare(world, location.clone().add(0, 1, 0), particleConfig, blockHeight);
|
||||||
|
|
||||||
|
for (double y = 0; y <= 1; y += particleConfig.getParticleDensity()) {
|
||||||
|
double height = particleConfig.getHeightOffset() + y;
|
||||||
|
spawnParticle(world, location.clone().add(0, height, 0), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, location.clone().add(0, height, 1), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, location.clone().add(1, height, 0), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, location.clone().add(1, height, 1), particleConfig, blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a sphere of particles at the given location
|
||||||
|
*
|
||||||
|
* <p>It is recommended to only spawn one particle with no spread, and a density between 4 and 0.1</p>
|
||||||
|
*
|
||||||
|
* @param world <p>The world to spawn the particles in</p>
|
||||||
|
* @param location <p>The location of the block to spawn the particles at</p>
|
||||||
|
* @param particleConfig <p>The configuration describing the particle to spawn</p>
|
||||||
|
* @param blockHeight <p>The height of the block to spawn the particle above</p>
|
||||||
|
* @param storedCalculationsId <p>An id for stored calculations. Use clearStoredCalculations with this id later.</p>
|
||||||
|
*/
|
||||||
|
public static void drawSphere(@NotNull World world, @NotNull Location location, @NotNull ParticleConfig particleConfig,
|
||||||
|
double blockHeight, UUID storedCalculationsId) {
|
||||||
|
// For spheres, densities below 0.1 has weird bugs such as blinking in and out of existence, and floating point
|
||||||
|
// errors when calculating the length of circleCoordinates
|
||||||
|
double density = Math.max(1, particleConfig.getParticleDensity());
|
||||||
|
// Store calculations for improved efficiency
|
||||||
|
if (sphereCoordinates.get(storedCalculationsId) == null) {
|
||||||
|
int length = (int) Math.ceil((180 / density));
|
||||||
|
Double[][] coordinates = new Double[length * 3][];
|
||||||
|
double height = particleConfig.getHeightOffset() + 0.5;
|
||||||
|
int i = 0;
|
||||||
|
for (double x = 0; x < 180; x += density) {
|
||||||
|
if (i >= coordinates.length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double cos = 0.5 * Math.cos(x);
|
||||||
|
double sin = 0.5 * Math.sin(x);
|
||||||
|
coordinates[i++] = new Double[]{sin + 0.5, height, cos + 0.5};
|
||||||
|
coordinates[i++] = new Double[]{sin + 0.5, height + cos, 0.5};
|
||||||
|
coordinates[i++] = new Double[]{0.5, height + sin, cos + 0.5};
|
||||||
|
}
|
||||||
|
sphereCoordinates.put(storedCalculationsId, coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn particles on the stored locations, relative to the launchpad
|
||||||
|
for (Double[] sphereCoordinate : sphereCoordinates.get(storedCalculationsId)) {
|
||||||
|
spawnParticle(world, location.clone().add(sphereCoordinate[0], sphereCoordinate[1], sphereCoordinate[2]),
|
||||||
|
particleConfig, blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a pyramid of particles at the given location
|
||||||
|
*
|
||||||
|
* <p>It is recommended to only spawn one particle with no spread, and a density between 1 and 0.01</p>
|
||||||
|
*
|
||||||
|
* @param world <p>The world to spawn the particles in</p>
|
||||||
|
* @param location <p>The location of the block to spawn the particles at</p>
|
||||||
|
* @param particleConfig <p>The configuration describing the particle to spawn</p>
|
||||||
|
* @param blockHeight <p>The height of the block to spawn the particle above</p>
|
||||||
|
* @param storedCalculationsId <p>An id for stored calculations. Use clearStoredCalculations with this id later.</p>
|
||||||
|
*/
|
||||||
|
public static void drawPyramid(@NotNull World world, @NotNull Location location, @NotNull ParticleConfig particleConfig,
|
||||||
|
double blockHeight, UUID storedCalculationsId) {
|
||||||
|
// Draw the bottom of the pyramid
|
||||||
|
drawSquare(world, location, particleConfig, blockHeight);
|
||||||
|
|
||||||
|
// Store calculations for improved efficiency
|
||||||
|
if (pyramidVectors.get(storedCalculationsId) == null) {
|
||||||
|
// The 0.5 offsets are required for the angle of the pyramid's 4 lines to be correct
|
||||||
|
double height = particleConfig.getHeightOffset();
|
||||||
|
double coordinateMin = -0.5 * height;
|
||||||
|
double coordinateMax = 1 + (0.5 * height);
|
||||||
|
|
||||||
|
Vector[] vectors = new Vector[5];
|
||||||
|
// The vector from the origin to the top of the pyramid
|
||||||
|
vectors[0] = new Vector(0.5, 1 + height, 0.5);
|
||||||
|
// The vectors from the top of the pyramid towards each corner
|
||||||
|
vectors[1] = new Vector(coordinateMin, 0, coordinateMin).subtract(vectors[0]).normalize();
|
||||||
|
vectors[2] = new Vector(coordinateMax, 0, coordinateMin).subtract(vectors[0]).normalize();
|
||||||
|
vectors[3] = new Vector(coordinateMin, 0, coordinateMax).subtract(vectors[0]).normalize();
|
||||||
|
vectors[4] = new Vector(coordinateMax, 0, coordinateMax).subtract(vectors[0]).normalize();
|
||||||
|
pyramidVectors.put(storedCalculationsId, vectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector[] storedVectors = pyramidVectors.get(storedCalculationsId);
|
||||||
|
Location topLocation = location.clone().add(storedVectors[0]);
|
||||||
|
for (double x = 0; x <= 1.2; x += particleConfig.getParticleDensity()) {
|
||||||
|
spawnParticle(world, topLocation.clone().add(storedVectors[1].clone().multiply(x)), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, topLocation.clone().add(storedVectors[2].clone().multiply(x)), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, topLocation.clone().add(storedVectors[3].clone().multiply(x)), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, topLocation.clone().add(storedVectors[4].clone().multiply(x)), particleConfig, blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a circle of particles at the given location
|
||||||
|
*
|
||||||
|
* <p>It is recommended to only spawn one particle with no spread, and a density between 4 and 0.1</p>
|
||||||
|
*
|
||||||
|
* @param world <p>The world to spawn the particles in</p>
|
||||||
|
* @param location <p>The location of the block to spawn the particles at</p>
|
||||||
|
* @param particleConfig <p>The configuration describing the particle to spawn</p>
|
||||||
|
* @param blockHeight <p>The height of the block to spawn the particle above</p>
|
||||||
|
* @param storedCalculationsId <p>An id for stored calculations. Use clearStoredCalculations with this id later.</p>
|
||||||
|
*/
|
||||||
|
public static void drawCircle(@NotNull World world, @NotNull Location location, @NotNull ParticleConfig particleConfig,
|
||||||
|
double blockHeight, UUID storedCalculationsId) {
|
||||||
|
// For circles, densities below 0.1 has weird bugs such as blinking in and out of existence, and floating point
|
||||||
|
// errors when calculating the length of circleCoordinates
|
||||||
|
double density = Math.max(1, particleConfig.getParticleDensity());
|
||||||
|
// Store calculations for improved efficiency
|
||||||
|
if (circleCoordinates.get(storedCalculationsId) == null) {
|
||||||
|
Double[][] coordinates = new Double[(int) Math.ceil((180 / density))][];
|
||||||
|
int i = 0;
|
||||||
|
for (double x = 0; x < 180; x += density) {
|
||||||
|
if (i >= coordinates.length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
coordinates[i++] = new Double[]{(0.5 * Math.sin(x)) + 0.5, (0.5 * Math.cos(x)) + 0.5};
|
||||||
|
}
|
||||||
|
circleCoordinates.put(storedCalculationsId, coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn particles on the stored locations, relative to the launchpad
|
||||||
|
for (Double[] circleCoordinate : circleCoordinates.get(storedCalculationsId)) {
|
||||||
|
spawnParticle(world, location.clone().add(circleCoordinate[0], particleConfig.getHeightOffset(),
|
||||||
|
circleCoordinate[1]), particleConfig, blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a square of particles at the given location
|
||||||
|
*
|
||||||
|
* <p>It is recommended to only spawn one particle with no spread, and a density between 1 and 0.01</p>
|
||||||
|
*
|
||||||
|
* @param world <p>The world to spawn the particles in</p>
|
||||||
|
* @param location <p>The location of the block to spawn the particles at</p>
|
||||||
|
* @param particleConfig <p>The configuration describing the particle to spawn</p>
|
||||||
|
* @param blockHeight <p>The height of the block to spawn the particle above</p>
|
||||||
|
*/
|
||||||
|
public static void drawSquare(@NotNull World world, @NotNull Location location, @NotNull ParticleConfig particleConfig,
|
||||||
|
double blockHeight) {
|
||||||
|
for (double x = 0; x <= 1; x += particleConfig.getParticleDensity()) {
|
||||||
|
spawnParticle(world, location.clone().add(x, particleConfig.getHeightOffset(), 0), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, location.clone().add(x, particleConfig.getHeightOffset(), 1), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, location.clone().add(0, particleConfig.getHeightOffset(), x), particleConfig, blockHeight);
|
||||||
|
spawnParticle(world, location.clone().add(1, particleConfig.getHeightOffset(), x), particleConfig, blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns the specified particle at the given location
|
||||||
|
*
|
||||||
|
* @param world <p>The world to spawn the particle in</p>
|
||||||
|
* @param location <p>The location to spawn the particle at</p>
|
||||||
|
* @param particleConfig <p>The configuration describing the particle to spawn</p>
|
||||||
|
* @param blockHeight <p>The height of the block to spawn the particle above</p>
|
||||||
|
*/
|
||||||
|
public static void spawnParticle(@NotNull World world, @NotNull Location location,
|
||||||
|
@NotNull ParticleConfig particleConfig, double blockHeight) {
|
||||||
|
world.spawnParticle(particleConfig.getParticleType(),
|
||||||
|
location.add(0, blockHeight, 0), particleConfig.getParticleAmount(),
|
||||||
|
particleConfig.getOffsetX(), particleConfig.getOffsetY(), particleConfig.getOffsetZ(),
|
||||||
|
particleConfig.getExtra());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the height of the block at the given location
|
||||||
|
*
|
||||||
|
* @param block <p>The block to check</p>
|
||||||
|
* @return <p>The height of the block</p>
|
||||||
|
*/
|
||||||
|
public static double getBlockHeight(@NotNull Block block) {
|
||||||
|
double maxY = 0;
|
||||||
|
for (BoundingBox boundingBox : block.getCollisionShape().getBoundingBoxes()) {
|
||||||
|
if (boundingBox.getMaxY() > maxY) {
|
||||||
|
maxY = boundingBox.getMaxY();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,11 @@
|
|||||||
package net.knarcraft.knarlib.util;
|
package net.knarcraft.knarlib.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for getting string lists required for auto-completion
|
* Helper class for getting string lists required for auto-completion
|
||||||
@ -12,6 +16,58 @@ public final class TabCompletionHelper {
|
|||||||
private TabCompletionHelper() {
|
private TabCompletionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds available tab-completions for a list where several comma-separated values are allowed
|
||||||
|
*
|
||||||
|
* <p>If, for example, the available values are [fish,potatoes,stew,strawberries], and the player has already typed
|
||||||
|
* "fish,potatoes,", then available tab-completions become fish,potatoes,stew and fish,potatoes,strawberries.</p>
|
||||||
|
*
|
||||||
|
* @param values <p>The available tab-completion values</p>
|
||||||
|
* @param typedText <p>The text the player has typed</p>
|
||||||
|
* @param filterer <p>The filterer (filterMatching) to use to filter by typed text</p>
|
||||||
|
* @return <p>Available tab-completions</p>
|
||||||
|
*/
|
||||||
|
public static @NotNull List<String> getStringList(@NotNull List<String> values, @NotNull String typedText,
|
||||||
|
@Nullable BiFunction<List<String>, String, List<String>> filterer) {
|
||||||
|
if (typedText.isBlank() || !typedText.contains(",")) {
|
||||||
|
if (filterer != null) {
|
||||||
|
return filterer.apply(values, typedText);
|
||||||
|
} else {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The argument base is everything the player has typed, until the last comma
|
||||||
|
List<String> arguments = List.of(typedText.split(","));
|
||||||
|
String base;
|
||||||
|
List<String> baseArguments;
|
||||||
|
if (typedText.endsWith(",")) {
|
||||||
|
baseArguments = arguments;
|
||||||
|
} else {
|
||||||
|
baseArguments = arguments.subList(0, arguments.size() - 1);
|
||||||
|
}
|
||||||
|
base = String.join(",", baseArguments) + ",";
|
||||||
|
String lastArgument = arguments.get(arguments.size() - 1);
|
||||||
|
|
||||||
|
// Filter available values by the text after the last comma only
|
||||||
|
List<String> filtered;
|
||||||
|
if (filterer != null && !typedText.endsWith(",")) {
|
||||||
|
filtered = filterer.apply(new ArrayList<>(values), lastArgument);
|
||||||
|
} else {
|
||||||
|
filtered = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any already used values
|
||||||
|
List<String> unused = new ArrayList<>();
|
||||||
|
for (String string : filtered) {
|
||||||
|
if (!baseArguments.contains(string)) {
|
||||||
|
unused.add(base + string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds tab complete values that contain the typed text
|
* Finds tab complete values that contain the typed text
|
||||||
*
|
*
|
||||||
@ -19,7 +75,7 @@ public final class TabCompletionHelper {
|
|||||||
* @param typedText <p>The text the player has started typing</p>
|
* @param typedText <p>The text the player has started typing</p>
|
||||||
* @return <p>The given string values that contain the player's typed text</p>
|
* @return <p>The given string values that contain the player's typed text</p>
|
||||||
*/
|
*/
|
||||||
public static List<String> filterMatchingContains(List<String> values, String typedText) {
|
public static @NotNull List<String> filterMatchingContains(@NotNull List<String> values, @NotNull String typedText) {
|
||||||
List<String> configValues = new ArrayList<>();
|
List<String> configValues = new ArrayList<>();
|
||||||
for (String value : values) {
|
for (String value : values) {
|
||||||
if (value.toLowerCase().contains(typedText.toLowerCase())) {
|
if (value.toLowerCase().contains(typedText.toLowerCase())) {
|
||||||
@ -36,7 +92,7 @@ public final class TabCompletionHelper {
|
|||||||
* @param typedText <p>The text the player has started typing</p>
|
* @param typedText <p>The text the player has started typing</p>
|
||||||
* @return <p>The given string values that start with the player's typed text</p>
|
* @return <p>The given string values that start with the player's typed text</p>
|
||||||
*/
|
*/
|
||||||
public static List<String> filterMatchingStartsWith(List<String> values, String typedText) {
|
public static @NotNull List<String> filterMatchingStartsWith(@NotNull List<String> values, @NotNull String typedText) {
|
||||||
List<String> configValues = new ArrayList<>();
|
List<String> configValues = new ArrayList<>();
|
||||||
for (String value : values) {
|
for (String value : values) {
|
||||||
if (value.toLowerCase().startsWith(typedText.toLowerCase())) {
|
if (value.toLowerCase().startsWith(typedText.toLowerCase())) {
|
||||||
@ -46,4 +102,15 @@ public final class TabCompletionHelper {
|
|||||||
return configValues;
|
return configValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the "base" string from the given arguments, not including the incomplete last argument
|
||||||
|
*
|
||||||
|
* @param arguments <p>The string arguments to get the base of</p>
|
||||||
|
* @return <p>The base string</p>
|
||||||
|
*/
|
||||||
|
private static @NotNull String getBase(@NotNull List<String> arguments) {
|
||||||
|
List<String> baseArray = arguments.subList(0, arguments.size() - 1);
|
||||||
|
return String.join(",", baseArray) + ",";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package net.knarcraft.knarlib.util;
|
|||||||
|
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -33,8 +35,9 @@ public final class UpdateChecker {
|
|||||||
* @param getVersionSupplier <p>The supplier used to get the current plugin version</p>
|
* @param getVersionSupplier <p>The supplier used to get the current plugin version</p>
|
||||||
* @param setVersionMethod <p>A method to call with the new version as an argument. Can be used to alert admins about an available update or similar.</p>
|
* @param setVersionMethod <p>A method to call with the new version as an argument. Can be used to alert admins about an available update or similar.</p>
|
||||||
*/
|
*/
|
||||||
public static void checkForUpdate(Plugin plugin, String apiResourceURL, Supplier<String> getVersionSupplier,
|
public static void checkForUpdate(@NotNull Plugin plugin, @NotNull String apiResourceURL,
|
||||||
Consumer<String> setVersionMethod) {
|
@NotNull Supplier<String> getVersionSupplier,
|
||||||
|
@Nullable Consumer<String> setVersionMethod) {
|
||||||
BukkitScheduler scheduler = plugin.getServer().getScheduler();
|
BukkitScheduler scheduler = plugin.getServer().getScheduler();
|
||||||
scheduler.runTaskAsynchronously(plugin, () -> UpdateChecker.queryAPI(plugin, apiResourceURL, getVersionSupplier,
|
scheduler.runTaskAsynchronously(plugin, () -> UpdateChecker.queryAPI(plugin, apiResourceURL, getVersionSupplier,
|
||||||
setVersionMethod));
|
setVersionMethod));
|
||||||
@ -48,8 +51,9 @@ public final class UpdateChecker {
|
|||||||
* @param getVersionMethod <p>The supplier used to get the current plugin version</p>
|
* @param getVersionMethod <p>The supplier used to get the current plugin version</p>
|
||||||
* @param setVersionMethod <p>A method to call with the new version as an argument. Can be used to alert admins about an available update or similar.</p>
|
* @param setVersionMethod <p>A method to call with the new version as an argument. Can be used to alert admins about an available update or similar.</p>
|
||||||
*/
|
*/
|
||||||
private static void queryAPI(Plugin plugin, String APIResourceURL, Supplier<String> getVersionMethod,
|
private static void queryAPI(@NotNull Plugin plugin, @NotNull String APIResourceURL,
|
||||||
Consumer<String> setVersionMethod) {
|
@NotNull Supplier<String> getVersionMethod,
|
||||||
|
@Nullable Consumer<String> setVersionMethod) {
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = new URL(APIResourceURL).openStream();
|
InputStream inputStream = new URL(APIResourceURL).openStream();
|
||||||
BufferedReader reader = FileHelper.getBufferedReaderFromInputStream(inputStream);
|
BufferedReader reader = FileHelper.getBufferedReaderFromInputStream(inputStream);
|
||||||
@ -77,7 +81,7 @@ public final class UpdateChecker {
|
|||||||
* @param oldVersion <p>The old (current) plugin version</p>
|
* @param oldVersion <p>The old (current) plugin version</p>
|
||||||
* @return <p>The string to display</p>
|
* @return <p>The string to display</p>
|
||||||
*/
|
*/
|
||||||
public static String getUpdateAvailableString(String newVersion, String oldVersion) {
|
public static @NotNull String getUpdateAvailableString(@NotNull String newVersion, @NotNull String oldVersion) {
|
||||||
return String.format(updateNotice, newVersion, oldVersion);
|
return String.format(updateNotice, newVersion, oldVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ public final class UpdateChecker {
|
|||||||
* @param newVersion <p>The new version to check</p>
|
* @param newVersion <p>The new version to check</p>
|
||||||
* @return <p>True if the new version is higher than the old one</p>
|
* @return <p>True if the new version is higher than the old one</p>
|
||||||
*/
|
*/
|
||||||
public static boolean isVersionHigher(String oldVersion, String newVersion) {
|
public static boolean isVersionHigher(@NotNull String oldVersion, @NotNull String newVersion) {
|
||||||
oldVersion = removeNonNumericCharacters(oldVersion);
|
oldVersion = removeNonNumericCharacters(oldVersion);
|
||||||
newVersion = removeNonNumericCharacters(newVersion);
|
newVersion = removeNonNumericCharacters(newVersion);
|
||||||
String[] oldVersionParts = oldVersion.split("\\.");
|
String[] oldVersionParts = oldVersion.split("\\.");
|
||||||
@ -110,7 +114,7 @@ public final class UpdateChecker {
|
|||||||
* @param versionString <p>The version string to clean</p>
|
* @param versionString <p>The version string to clean</p>
|
||||||
* @return <p>The string with non-numeric characters replaced</p>
|
* @return <p>The string with non-numeric characters replaced</p>
|
||||||
*/
|
*/
|
||||||
private static String removeNonNumericCharacters(String versionString) {
|
private static @NotNull String removeNonNumericCharacters(@NotNull String versionString) {
|
||||||
return versionString.replaceAll("[^0-9.]", "");
|
return versionString.replaceAll("[^0-9.]", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
package net.knarcraft.knarlib.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the tab-completion helper
|
||||||
|
*/
|
||||||
|
public class TabCompletionHelperTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringListUnfilteredTest() {
|
||||||
|
List<String> input = List.of("a", "b", "c", "d");
|
||||||
|
List<String> result = TabCompletionHelper.getStringList(input, "a,b,", null);
|
||||||
|
List<String> expected = List.of("a,b,c", "a,b,d");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringListUnfilteredTest2() {
|
||||||
|
List<String> input = List.of("a", "b", "c", "d");
|
||||||
|
List<String> result = TabCompletionHelper.getStringList(input, "a,b", null);
|
||||||
|
List<String> expected = List.of("a,b", "a,c", "a,d");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringListContainsTest() {
|
||||||
|
List<String> input = List.of("ape", "ball", "car", "donut");
|
||||||
|
List<String> result = TabCompletionHelper.getStringList(input, "ball,donut,r",
|
||||||
|
TabCompletionHelper::filterMatchingContains);
|
||||||
|
List<String> expected = List.of("ball,donut,car");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringListContainsTest2() {
|
||||||
|
List<String> input = List.of("ape", "ball", "car", "donut");
|
||||||
|
List<String> result = TabCompletionHelper.getStringList(input, "ball,donut,",
|
||||||
|
TabCompletionHelper::filterMatchingContains);
|
||||||
|
List<String> expected = List.of("ball,donut,ape", "ball,donut,car");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringListStartsWithTest() {
|
||||||
|
List<String> input = List.of("ape", "ball", "car", "donut");
|
||||||
|
List<String> result = TabCompletionHelper.getStringList(input, "ball,donut,a",
|
||||||
|
TabCompletionHelper::filterMatchingStartsWith);
|
||||||
|
List<String> expected = List.of("ball,donut,ape");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringListStartsWithTest2() {
|
||||||
|
List<String> input = List.of("ape", "ball", "car", "donut");
|
||||||
|
List<String> result = TabCompletionHelper.getStringList(input, "ball,donut,",
|
||||||
|
TabCompletionHelper::filterMatchingStartsWith);
|
||||||
|
List<String> expected = List.of("ball,donut,ape", "ball,donut,car");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filterMatchingContainsTest() {
|
||||||
|
List<String> input = List.of("fish", "ape", "banana", "toy", "human", "stick", "potato", "detergent", "magazine");
|
||||||
|
List<String> result = TabCompletionHelper.filterMatchingContains(input, "a");
|
||||||
|
List<String> expected = List.of("ape", "banana", "human", "potato", "magazine");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filterMatchingStartsWithTest() {
|
||||||
|
List<String> input = List.of("fish", "ape", "banana", "toy", "human", "stick", "potato", "detergent", "magazine");
|
||||||
|
List<String> result = TabCompletionHelper.filterMatchingStartsWith(input, "a");
|
||||||
|
List<String> expected = List.of("ape");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user