removed static reference to server in annotation parser

This commit is contained in:
gnembon committed 2023-02-08 21:13:14 +01:00
1 parent 75d94b0570
commit aea76d9764
10 files changed
+64 -40

No files matched your search

@@ -20,7 +20,6 @@ import org.apache.commons.lang3.ClassUtils;
import com.google.common.base.Suppliers;
import carpet.CarpetExtension;
import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Fluff.AbstractLazyFunction;
@@ -85,7 +84,7 @@ public final class AnnotationParser
* <p>Parses a given {@link Class} and registers its annotated methods, the ones with the {@link ScarpetFunction} annotation,
* to be used in the Scarpet language.</p>
*
* <p><b>Only call this method once per class per lifetime of the JVM!</b> (for example, at {@link CarpetExtension#onGameStarted()} or
* <p><b>Only call this method once per class per lifetime of the JVM!</b> (for example, at {@link carpet.CarpetExtension#onGameStarted()} or
* {@link ModInitializer#onInitialize()}).</p>
*
* <p>There is a set of requirements for the class and its methods:</p>
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import carpet.script.Context;
import carpet.script.value.ListValue;
import carpet.script.value.Value;
@@ -32,17 +33,17 @@ final class ListConverter<T> implements ValueConverter<List<T>>
}
@Override
public List<T> convert(final Value value)
public List<T> convert(final Value value, final Context context)
{
return value instanceof ListValue ? convertListValue((ListValue) value) : allowSingletonCreation ? convertSingleton(value) : null;
return value instanceof ListValue ? convertListValue((ListValue) value, context) : allowSingletonCreation ? convertSingleton(value, context) : null;
}
private List<T> convertListValue(final ListValue values)
private List<T> convertListValue(final ListValue values, final Context context)
{
final List<T> list = new ArrayList<>(values.getItems().size());
for (final Value value : values)
{
final T converted = itemConverter.convert(value);
final T converted = itemConverter.convert(value, context);
if (converted == null)
{
return null;
@@ -52,9 +53,9 @@ final class ListConverter<T> implements ValueConverter<List<T>>
return list;
}
private List<T> convertSingleton(final Value val)
private List<T> convertSingleton(final Value val, final Context context)
{
final T converted = itemConverter.convert(val);
final T converted = itemConverter.convert(val, context);
if (converted == null)
{
return null;
@@ -276,7 +276,7 @@ public interface Locator
private abstract static class AbstractLocator<R> implements ValueConverter<R>, Locator
{
@Override
public R convert(final Value value)
public R convert(final Value value, final Context context)
{
throw new UnsupportedOperationException("Cannot call a locator in a parameter that doesn't contain a context!");
}
@@ -37,15 +37,15 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
}
@Override
public Map<K, V> convert(final Value value)
public Map<K, V> convert(final Value value, final Context context)
{
final Map<K, V> result = new HashMap<>();
if (value instanceof MapValue)
{
for (final Entry<Value, Value> entry : ((MapValue) value).getMap().entrySet())
{
final K key = keyConverter.convert(entry.getKey());
final V val = valueConverter.convert(entry.getValue());
final K key = keyConverter.convert(entry.getKey(), context);
final V val = valueConverter.convert(entry.getValue(), context);
if (key == null || val == null)
{
return null;
@@ -105,14 +105,14 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
}
@Override
public Map<K, V> convert(final Value value) {
return value instanceof MapValue ? super.convert(value)
: value instanceof ListValue ? convertList(((ListValue)value).getItems())
public Map<K, V> convert(final Value value, final Context context) {
return value instanceof MapValue ? super.convert(value, context)
: value instanceof ListValue ? convertList(((ListValue)value).getItems(), context)
: null; // Multiparam mode can only be used in evalAndConvert
}
private Map<K, V> convertList(final List<Value> valueList)
private Map<K, V> convertList(final List<Value> valueList, final Context context)
{
if (valueList.size() % 2 == 1)
{
@@ -122,8 +122,8 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
final Iterator<Value> val = valueList.iterator();
while (val.hasNext())
{
final K key = keyConverter.convert(val.next());
final V value = valueConverter.convert(val.next());
final K key = keyConverter.convert(val.next(), context);
final V value = valueConverter.convert(val.next(), context);
if (key == null || value == null)
{
return null;
@@ -143,11 +143,11 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
final Value val = valueIterator.next();
if (!acceptMultiParam || val instanceof MapValue || (val instanceof ListValue && !(keyConverter instanceof ListConverter)))
{
return convert(val); // @KeyValuePairs Map<List<Something>, Boolean> will not support list consumption
return convert(val, context); // @KeyValuePairs Map<List<Something>, Boolean> will not support list consumption
}
final Map<K, V> map = new HashMap<>();
K key = keyConverter.convert(val); //First pair is manual since we got it to check for a different conversion mode
K key = keyConverter.convert(val, context); //First pair is manual since we got it to check for a different conversion mode
V value = valueConverter.checkAndConvert(valueIterator, context, theLazyT);
if (key == null || value == null)
{
@@ -50,13 +50,13 @@ final class OptionalConverter<R> implements ValueConverter<Optional<R>>
* {@link #checkAndConvert(Iterator, Context, Context.Type)} and is only used as a fallback in types that don't support it.
*/
@Override
public Optional<R> convert(final Value value)
public Optional<R> convert(final Value value, final Context context)
{
if (value.isNull())
{
return Optional.empty();
}
final R converted = typeConverter.convert(value);
final R converted = typeConverter.convert(value, context);
if (converted == null)
{
return null;
@@ -6,7 +6,6 @@ import java.util.Objects;
import java.util.function.Function;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -148,7 +148,7 @@ public interface Param
@Override public String getTypeName() { return null; }
@Override
public Context convert(final Value value)
public Context convert(final Value value, final Context context)
{
throw new UnsupportedOperationException("Called convert() with Value in Context Provider converter, where only checkAndConvert is supported");
}
@@ -175,7 +175,7 @@ public interface Param
@Override public String getTypeName() { return null; }
@Override
public Context.Type convert(final Value value)
public Context.Type convert(final Value value, final Context context)
{
throw new UnsupportedOperationException("Called convert() with a Value in TheLazyT Provider, where only checkAndConvert is supported");
}
@@ -2,12 +2,15 @@ package carpet.script.annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import carpet.script.CarpetContext;
import carpet.script.Context;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import carpet.CarpetServer;
import carpet.script.exception.InternalExpressionException;
import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue;
@@ -31,9 +34,9 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
private static final Map<Class<?>, SimpleTypeConverter<? extends Value, ?>> byResult = new HashMap<>();
static
{
registerType(Value.class, ServerPlayer.class, val -> EntityValue.getPlayerByValue(CarpetServer.minecraft_server, val), "online player");
registerType(Value.class, ServerPlayer.class, (v, c) -> EntityValue.getPlayerByValue(((CarpetContext)c).server(), v), "online player");
registerType(EntityValue.class, Entity.class, EntityValue::getEntity, "entity");
registerType(Value.class, Level.class, val -> ValueConversions.dimFromValue(val, CarpetServer.minecraft_server), "dimension");
registerType(Value.class, Level.class, (v, c) -> ValueConversions.dimFromValue(v, ((CarpetContext)c).server()), "dimension");
registerType(Value.class, Component.class, FormattedTextValue::getTextByValue, "text");
registerType(Value.class, String.class, Value::getString, "string"); // Check out @Param.Strict for more specific types
@@ -44,7 +47,7 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
registerType(Value.class, Boolean.class, Value::getBoolean, "boolean"); // Check out @Param.Strict for more specific types
}
private final Function<T, R> converter;
private final BiFunction<T, Context, R> converter;
private final Class<T> valueClass;
private final String typeName;
@@ -58,7 +61,7 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
* @param inputType The required type for the input {@link Value}
* @param converter The function to convert an instance of inputType into R.
*/
public SimpleTypeConverter(final Class<T> inputType, final Function<T, R> converter, final String typeName)
public SimpleTypeConverter(final Class<T> inputType, final BiFunction<T, Context, R> converter, final String typeName)
{
super();
this.converter = converter;
@@ -66,6 +69,14 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
this.typeName = typeName;
}
public SimpleTypeConverter(final Class<T> inputType, final Function<T, R> converter, final String typeName)
{
super();
this.converter = (v, c) -> converter.apply(v);
this.valueClass = inputType;
this.typeName = typeName;
}
@Override
public String getTypeName()
{
@@ -87,9 +98,9 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
@Override
@SuppressWarnings("unchecked") // more than checked. not using class.cast because then "method is too big" for inlining, because javac is useless
public R convert(final Value value) // and adds millions of casts. This one is even removed
public R convert(final Value value, final Context context) // and adds millions of casts. This one is even removed
{
return valueClass.isInstance(value) ? converter.apply((T)value) : null;
return valueClass.isInstance(value) ? converter.apply((T)value, context) : null;
}
/**
@@ -99,15 +110,21 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
* @param <R> The type of the resulting object
* @param requiredInputType The {@link Class} of {@code <T>}
* @param outputType The {@link Class} of {@code <R>>}
* @param converter A function that converts from the given {@link Value} subtype to the given type. Should ideally return {@code null}
* @param converter A bi function that converts from the given {@link Value} subtype to the given type. Should ideally return {@code null}
* when given {@link Value} cannot be converted to the {@code <R>}, to follow the {@link ValueConverter} contract, but it
* can also throw an {@link InternalExpressionException} by itself if really necessary.
* @param typeName The name of the type, following the conventions of {@link ValueConverter#getTypeName()}
*/
public static <T extends Value, R> void registerType(final Class<T> requiredInputType, final Class<R> outputType,
final Function<T, R> converter, final String typeName)
final BiFunction<T, Context, R> converter, final String typeName)
{
final SimpleTypeConverter<T, R> type = new SimpleTypeConverter<>(requiredInputType, converter, typeName);
byResult.put(outputType, type);
}
public static <T extends Value, R> void registerType(final Class<T> requiredInputType, final Class<R> outputType,
final Function<T, R> converter, final String typeName)
{
registerType(requiredInputType, outputType, (val, ctx) -> converter.apply(val), typeName);
}
}
@@ -3,6 +3,7 @@ package carpet.script.annotation;
import java.util.HashMap;
import java.util.Map;
import carpet.script.Context;
import carpet.script.value.AbstractListValue;
import carpet.script.value.BlockValue;
import carpet.script.value.BooleanValue;
@@ -79,7 +80,7 @@ public final class ValueCaster<R> implements ValueConverter<R> // R always exten
@Override
@SuppressWarnings("unchecked") // more than checked, see SimpleTypeConverter#converter for reasoning
public R convert(final Value value)
public R convert(final Value value, final Context context)
{
if (!outputType.isInstance(value))
{
@@ -50,6 +50,7 @@ public interface ValueConverter<R>
* trying to convert to anything else, where it would be recommended to tell the user the name of the final type instead.</p>
*
* @param value The {@link Value} to convert
* @param context
* @return The converted value, or {@code null} if the conversion failed in the process
* @apiNote <p>While most implementations of this method should and will return the type from this method, implementations that <b>require</b>
* parameters from {@link #checkAndConvert(Iterator, Context, Context.Type)} or that require multiple parameters may decide to throw
@@ -59,10 +60,16 @@ public interface ValueConverter<R>
* <p>Implementations can also provide different implementations for this and {@link #checkAndConvert(Iterator, Context, Context.Type)}, in case
* they can support it in some situations that can't be used else, such as inside of lists or maps, although they should try to provide
* in {@link #checkAndConvert(Iterator, Context, Context.Type)} at least the same conversion as the one from this method.</p>
* <p>Even with the above reasons, {@link ValueConverter} users should try to implement {@link #convert(Value)} whenever possible instead of
* <p>Even with the above reasons, {@link ValueConverter} users should try to implement {@link #convert(Value, Context)} whenever possible instead of
* {@link #checkAndConvert(Iterator, Context, Context.Type)}, since it allows its usage in generics of lists and maps.</p>
*/
@Nullable R convert(Value value);
@Nullable R convert(Value value, final Context context);
@Deprecated(forRemoval = true)
default R convert(final Value value)
{
return convert(value, null);
}
/**
* <p>Returns whether this {@link ValueConverter} consumes a variable number of elements from the {@link Iterator} passed to it via
@@ -176,17 +183,17 @@ public interface ValueConverter<R>
* providers like {@link Context}. <p>Implementations can also use more than a single parameter when being called with this function,
* but in such case they must implement {@link #valueConsumption()} to return how many parameters do they consume at minimum, and, if
* they may consume variable arguments, implement {@link #consumesVariableArgs()}</p> <p>This method holds the same nullability
* constraints as {@link #convert(Value)}</p>
* constraints as {@link #convert(Value, Context)}</p>
* @param valueIterator An {@link Iterator} holding the {@link Value} to convert in next position
* @param context The {@link Context} this function has been called with. This was used when this passed lazy values instead in order to
* evaluate, now it's used to get the context
* @param contextType The {@link Context.Type} that the original function was called with
* @return The next {@link Value} (s) converted to the type {@code <R>} of this {@link ValueConverter}
* @implNote This method's default implementation runs the {@link #convert(Value)} function in the next {@link Value} ignoring {@link Context} and
* @implNote This method's default implementation runs the {@link #convert(Value, Context)} function in the next {@link Value} ignoring {@link Context} and
* {@code theLazyT}.
*/
default R checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type contextType)
{
return !valueIterator.hasNext() ? null : convert(valueIterator.next());
return !valueIterator.hasNext() ? null : convert(valueIterator.next(), context);
}
}