Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8515ff2b7b | ||
|
|
74aeaec257 | ||
|
|
0ce3d294d1 | ||
|
|
7c7052f5b9 | ||
|
|
a6b7dda82d |
@@ -527,9 +527,10 @@ public interface Eco {
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param context The context.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
* @return The value of the expression, or null if invalid.
|
||||
*/
|
||||
double evaluate(@NotNull String expression,
|
||||
@Nullable
|
||||
Double evaluate(@NotNull String expression,
|
||||
@NotNull PlaceholderContext context);
|
||||
|
||||
/**
|
||||
|
||||
@@ -98,6 +98,7 @@ public final class PlaceholderManager {
|
||||
// Storing as immutable set leads to slower times to register placeholders, but much
|
||||
// faster times to access registrations.
|
||||
Set<Placeholder> pluginPlaceholders = new HashSet<>(REGISTERED_PLACEHOLDERS.get(placeholder.getPlugin()));
|
||||
pluginPlaceholders.removeIf(p -> p.getPattern().equals(placeholder.getPattern()));
|
||||
pluginPlaceholders.add(placeholder);
|
||||
REGISTERED_PLACEHOLDERS.put(placeholder.getPlugin(), ImmutableSet.copyOf(pluginPlaceholders));
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@@ -251,12 +252,15 @@ public final class NumberUtils {
|
||||
@Nullable final Player player,
|
||||
@Nullable final PlaceholderInjectable context,
|
||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
||||
return Eco.get().evaluate(expression, new PlaceholderContext(
|
||||
player,
|
||||
null,
|
||||
context,
|
||||
additionalPlayers
|
||||
));
|
||||
return evaluateExpression(
|
||||
expression,
|
||||
new PlaceholderContext(
|
||||
player,
|
||||
null,
|
||||
context,
|
||||
additionalPlayers
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,6 +287,22 @@ public final class NumberUtils {
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return Objects.requireNonNullElse(
|
||||
evaluateExpressionOrNull(expression, context),
|
||||
0.0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression in a context.
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param context The context.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
@Nullable
|
||||
public static Double evaluateExpressionOrNull(@NotNull final String expression,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return Eco.get().evaluate(expression, context);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,3 +31,7 @@ fun evaluateExpression(expression: String) =
|
||||
/** @see NumberUtils.evaluateExpression */
|
||||
fun evaluateExpression(expression: String, context: PlaceholderContext) =
|
||||
NumberUtils.evaluateExpression(expression, context)
|
||||
|
||||
/** @see NumberUtils.evaluateExpressionOrNull */
|
||||
fun evaluateExpressionOrNull(expression: String, context: PlaceholderContext) =
|
||||
NumberUtils.evaluateExpressionOrNull(expression, context)
|
||||
|
||||
@@ -30,6 +30,8 @@ internal fun Any?.constrainConfigTypes(type: ConfigType): Any? = when (this) {
|
||||
this.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
is Float -> this.toDouble() // Should prevent !!float from being written
|
||||
else -> this
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.willfp.eco.core.placeholder.InjectablePlaceholder
|
||||
import com.willfp.eco.core.placeholder.Placeholder
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/*
|
||||
@@ -23,7 +22,7 @@ class PlaceholderParser {
|
||||
|
||||
private val placeholderLookupCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.SECONDS)
|
||||
.build<PlaceholderLookup, Optional<Placeholder>>()
|
||||
.build<PlaceholderLookup, Placeholder?>()
|
||||
|
||||
fun translatePlacholders(text: String, context: PlaceholderContext): String {
|
||||
return translatePlacholders(text, context, context.injectableContext.placeholderInjections)
|
||||
@@ -122,10 +121,10 @@ class PlaceholderParser {
|
||||
val lookup = PlaceholderLookup(args, plugin, injections)
|
||||
|
||||
val placeholder = placeholderLookupCache.get(lookup) {
|
||||
Optional.ofNullable(it.findMatchingPlaceholder())
|
||||
}.orElse(null) ?: return null
|
||||
it.findMatchingPlaceholder()
|
||||
}
|
||||
|
||||
return placeholder.getValue(args, context)
|
||||
return placeholder?.getValue(args, context)
|
||||
}
|
||||
|
||||
private fun translateEcoPlaceholdersIn(
|
||||
|
||||
@@ -10,11 +10,11 @@ class DelegatedExpressionHandler(
|
||||
plugin: EcoPlugin,
|
||||
private val handler: ExpressionHandler
|
||||
) : ExpressionHandler {
|
||||
private val evaluationCache: Cache<Int, Double> = Caffeine.newBuilder()
|
||||
private val evaluationCache: Cache<Int, Double?> = Caffeine.newBuilder()
|
||||
.expireAfterWrite(plugin.configYml.getInt("math-cache-ttl").toLong(), TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double? {
|
||||
// Peak performance (totally not having fun with bitwise operators)
|
||||
val hash = (((expression.hashCode() shl 5) - expression.hashCode()) xor
|
||||
(context.player?.uniqueId?.hashCode() ?: 0)
|
||||
@@ -22,7 +22,7 @@ class DelegatedExpressionHandler(
|
||||
|
||||
return evaluationCache.get(hash) {
|
||||
handler.evaluate(expression, context)
|
||||
.let { if (!it.isFinite()) 0.0 else it } // Fixes NaN bug.
|
||||
.let { if (it?.isFinite() != true) null else it } // Fixes NaN bug.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@ import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
private val min = Function("min", 2) {
|
||||
min(it[0], it[1])
|
||||
}
|
||||
@@ -25,8 +23,9 @@ private val max = Function("max", 2) {
|
||||
}
|
||||
|
||||
interface ExpressionHandler {
|
||||
fun evaluate(expression: String, context: PlaceholderContext): Double
|
||||
fun evaluate(expression: String, context: PlaceholderContext): Double?
|
||||
}
|
||||
|
||||
private fun String.fastToDoubleOrNull(): Double? {
|
||||
if (isEmpty()) {
|
||||
return null
|
||||
@@ -47,6 +46,7 @@ private fun String.fastToDoubleOrNull(): Double? {
|
||||
if (decimalIdx != -1) return null
|
||||
decimalIdx = idx
|
||||
}
|
||||
|
||||
in '0'..'9' -> {
|
||||
val number = (char.code - '0'.code).toDouble()
|
||||
if (decimalIdx != -1) {
|
||||
@@ -55,6 +55,7 @@ private fun String.fastToDoubleOrNull(): Double? {
|
||||
integerPart = integerPart * 10 + number
|
||||
}
|
||||
}
|
||||
|
||||
else -> return null
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ private fun String.fastToDoubleOrNull(): Double? {
|
||||
class ImmediatePlaceholderTranslationExpressionHandler(
|
||||
private val placeholderParser: PlaceholderParser
|
||||
) : ExpressionHandler {
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder()
|
||||
private val cache: Cache<String, CompiledExpression?> = Caffeine.newBuilder()
|
||||
.expireAfterAccess(500, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
@@ -78,25 +79,24 @@ class ImmediatePlaceholderTranslationExpressionHandler(
|
||||
addFunctions(min, max)
|
||||
}
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double? {
|
||||
val translatedExpression = placeholderParser.translatePlacholders(expression, context)
|
||||
|
||||
val compiled = cache.get(translatedExpression) {
|
||||
runCatching { Crunch.compileExpression(translatedExpression, env) }
|
||||
.getOrDefault(goToZero)
|
||||
runCatching { Crunch.compileExpression(translatedExpression, env) }.getOrNull()
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate() }.getOrDefault(0.0)
|
||||
return runCatching { compiled?.evaluate() }.getOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
class LazyPlaceholderTranslationExpressionHandler(
|
||||
private val placeholderParser: PlaceholderParser
|
||||
) : ExpressionHandler {
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder()
|
||||
private val cache: Cache<String, CompiledExpression?> = Caffeine.newBuilder()
|
||||
.build()
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double? {
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
|
||||
val placeholderValues = placeholderParser.parseIndividualPlaceholders(placeholders, context)
|
||||
@@ -107,9 +107,9 @@ class LazyPlaceholderTranslationExpressionHandler(
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
env.addFunctions(min, max)
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrNull()
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
return runCatching { compiled?.evaluate(*placeholderValues) }.getOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version = 6.62.1
|
||||
version = 6.63.0
|
||||
plugin-name = eco
|
||||
kotlin.code.style = official
|
||||
Reference in New Issue
Block a user