diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java index afc46cba346..360280e3d8a 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java @@ -45,6 +45,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; +import java.text.DecimalFormat; import java.util.Calendar; import java.util.UUID; @@ -53,6 +54,10 @@ public class DefaultFunctions { private static String str(double n) { return StringUtils.toString(n, 4); } + private static final String DEFAULT_NUMBER_FORMAT_STRING = "###,###"; + private static final DecimalFormat DEFAULT_NUMBER_FORMAT = new DecimalFormat(DEFAULT_NUMBER_FORMAT_STRING); + private static final ThreadLocal NUMBER_FORMAT = ThreadLocal.withInitial(DecimalFormat::new); + static { Parameter[] numberParam = new Parameter[] {new Parameter<>("n", DefaultClasses.NUMBER, true, null)}; @@ -583,6 +588,36 @@ public Boolean[] executeSimple(Object[][] params) { .examples("isNaN(0) # false", "isNaN(0/0) # true", "isNaN(sqrt(-1)) # true") .since("2.8.0"); + Functions.registerFunction(new SimpleJavaFunction("formatNumber", new Parameter[] { + new Parameter<>("number", DefaultClasses.NUMBER, true, null), + new Parameter<>("format", DefaultClasses.STRING, true, new SimpleLiteral(DEFAULT_NUMBER_FORMAT_STRING, true)) + }, DefaultClasses.STRING, true) { + @Override + public String[] executeSimple(Object[][] params) { + Number number = (Number) params[0][0]; + String format = (String) params[1][0]; + + if (DEFAULT_NUMBER_FORMAT_STRING.equals(format)) // shortcut + return CollectionUtils.array(DEFAULT_NUMBER_FORMAT.format(number)); + + try { + DecimalFormat numberFormat = NUMBER_FORMAT.get(); + numberFormat.applyPattern(format); + return CollectionUtils.array(numberFormat.format(number)); + } catch (IllegalArgumentException e) { +// Skript.warning("Invalid number format: " + format); // TODO find a better solution for such warnings/errors that doesn't spam the console + return null; + } + } + }).description("Converts numbers to human-readable format. By default, '###,###' (e.g. '123,456,789') will be used. For reference, see this " + + "article.") + .examples( + "command /formatnumber :", + "\taliases: fn", + "\ttrigger:", + "\t\tsend \"Formatted: %formatNumber(arg-1)%\" to sender" + ).since("INSERT VERSION"); + Functions.registerFunction(new SimpleJavaFunction("concat", new Parameter[] { new Parameter<>("texts", DefaultClasses.OBJECT, false, null) }, DefaultClasses.STRING, true) { diff --git a/src/test/skript/tests/regressions/4663-formatted numbers.sk b/src/test/skript/tests/regressions/4663-formatted numbers.sk new file mode 100644 index 00000000000..de4f15af23d --- /dev/null +++ b/src/test/skript/tests/regressions/4663-formatted numbers.sk @@ -0,0 +1,17 @@ +test "formatted numbers function": + set {_num1} to formatNumber(123456789) + assert {_num1} = "123,456,789" with "default number format failed ##1" + + set {_num2} to formatNumber(1234567) + assert {_num2} = "1,234,567" with "default number format failed ##2" + + set {_num3} to formatNumber(12345678, "##,##.00") + assert {_num3} = "1,2,3,4,5,6,7,8.00" with "custom number format failed ##1" + + set {_cFormat} to "####,####" + set {_num4} to formatNumber(12345678, {_cFormat}) + assert {_num4} = "12,34,56,78" with "custom number format failed ##2" + + set {_cFormat2} to "##,.##" + set {_num5} to formatNumber(12345678, {_cFormat2}) + assert {_num5} is not set with "custom number format failed ##3"