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 com.google.common.base.Suppliers;
import carpet.CarpetExtension;
import carpet.script.Context; import carpet.script.Context;
import carpet.script.Expression; import carpet.script.Expression;
import carpet.script.Fluff.AbstractLazyFunction; 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, * <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> * 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> * {@link ModInitializer#onInitialize()}).</p>
* *
* <p>There is a set of requirements for the class and its methods:</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.Collections;
import java.util.List; import java.util.List;
import carpet.script.Context;
import carpet.script.value.ListValue; import carpet.script.value.ListValue;
import carpet.script.value.Value; import carpet.script.value.Value;
@@ -32,17 +33,17 @@ final class ListConverter<T> implements ValueConverter<List<T>>
} }
@Override @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()); final List<T> list = new ArrayList<>(values.getItems().size());
for (final Value value : values) for (final Value value : values)
{ {
final T converted = itemConverter.convert(value); final T converted = itemConverter.convert(value, context);
if (converted == null) if (converted == null)
{ {
return null; return null;
@@ -52,9 +53,9 @@ final class ListConverter<T> implements ValueConverter<List<T>>
return list; 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) if (converted == null)
{ {
return null; return null;
@@ -276,7 +276,7 @@ public interface Locator
private abstract static class AbstractLocator<R> implements ValueConverter<R>, Locator private abstract static class AbstractLocator<R> implements ValueConverter<R>, Locator
{ {
@Override @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!"); 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 @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<>(); final Map<K, V> result = new HashMap<>();
if (value instanceof MapValue) if (value instanceof MapValue)
{ {
for (final Entry<Value, Value> entry : ((MapValue) value).getMap().entrySet()) for (final Entry<Value, Value> entry : ((MapValue) value).getMap().entrySet())
{ {
final K key = keyConverter.convert(entry.getKey()); final K key = keyConverter.convert(entry.getKey(), context);
final V val = valueConverter.convert(entry.getValue()); final V val = valueConverter.convert(entry.getValue(), context);
if (key == null || val == null) if (key == null || val == null)
{ {
return null; return null;
@@ -105,14 +105,14 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
} }
@Override @Override
public Map<K, V> convert(final Value value) { public Map<K, V> convert(final Value value, final Context context) {
return value instanceof MapValue ? super.convert(value) return value instanceof MapValue ? super.convert(value, context)
: value instanceof ListValue ? convertList(((ListValue)value).getItems()) : value instanceof ListValue ? convertList(((ListValue)value).getItems(), context)
: null; // Multiparam mode can only be used in evalAndConvert : 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) if (valueList.size() % 2 == 1)
{ {
@@ -122,8 +122,8 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
final Iterator<Value> val = valueList.iterator(); final Iterator<Value> val = valueList.iterator();
while (val.hasNext()) while (val.hasNext())
{ {
final K key = keyConverter.convert(val.next()); final K key = keyConverter.convert(val.next(), context);
final V value = valueConverter.convert(val.next()); final V value = valueConverter.convert(val.next(), context);
if (key == null || value == null) if (key == null || value == null)
{ {
return null; return null;
@@ -143,11 +143,11 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
final Value val = valueIterator.next(); final Value val = valueIterator.next();
if (!acceptMultiParam || val instanceof MapValue || (val instanceof ListValue && !(keyConverter instanceof ListConverter))) 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<>(); 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); V value = valueConverter.checkAndConvert(valueIterator, context, theLazyT);
if (key == null || value == null) 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. * {@link #checkAndConvert(Iterator, Context, Context.Type)} and is only used as a fallback in types that don't support it.
*/ */
@Override @Override
public Optional<R> convert(final Value value) public Optional<R> convert(final Value value, final Context context)
{ {
if (value.isNull()) if (value.isNull())
{ {
return Optional.empty(); return Optional.empty();
} }
final R converted = typeConverter.convert(value); final R converted = typeConverter.convert(value, context);
if (converted == null) if (converted == null)
{ {
return null; return null;
@@ -6,7 +6,6 @@ import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos; import net.minecraft.core.GlobalPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@@ -148,7 +148,7 @@ public interface Param
@Override public String getTypeName() { return null; } @Override public String getTypeName() { return null; }
@Override @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"); 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 String getTypeName() { return null; }
@Override @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"); 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.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import carpet.script.CarpetContext;
import carpet.script.Context;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import carpet.CarpetServer;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.script.value.EntityValue; import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue; 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<>(); private static final Map<Class<?>, SimpleTypeConverter<? extends Value, ?>> byResult = new HashMap<>();
static 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(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, Component.class, FormattedTextValue::getTextByValue, "text");
registerType(Value.class, String.class, Value::getString, "string"); // Check out @Param.Strict for more specific types 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 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 Class<T> valueClass;
private final String typeName; 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 inputType The required type for the input {@link Value}
* @param converter The function to convert an instance of inputType into R. * @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(); super();
this.converter = converter; this.converter = converter;
@@ -66,6 +69,14 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
this.typeName = typeName; 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 @Override
public String getTypeName() public String getTypeName()
{ {
@@ -87,9 +98,9 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
@Override @Override
@SuppressWarnings("unchecked") // more than checked. not using class.cast because then "method is too big" for inlining, because javac is useless @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 <R> The type of the resulting object
* @param requiredInputType The {@link Class} of {@code <T>} * @param requiredInputType The {@link Class} of {@code <T>}
* @param outputType The {@link Class} of {@code <R>>} * @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 * 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. * 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()} * @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, 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); final SimpleTypeConverter<T, R> type = new SimpleTypeConverter<>(requiredInputType, converter, typeName);
byResult.put(outputType, type); 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.HashMap;
import java.util.Map; import java.util.Map;
import carpet.script.Context;
import carpet.script.value.AbstractListValue; import carpet.script.value.AbstractListValue;
import carpet.script.value.BlockValue; import carpet.script.value.BlockValue;
import carpet.script.value.BooleanValue; import carpet.script.value.BooleanValue;
@@ -79,7 +80,7 @@ public final class ValueCaster<R> implements ValueConverter<R> // R always exten
@Override @Override
@SuppressWarnings("unchecked") // more than checked, see SimpleTypeConverter#converter for reasoning @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)) 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> * 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 value The {@link Value} to convert
* @param context
* @return The converted value, or {@code null} if the conversion failed in the process * @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> * @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 * 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 * <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 * 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> * 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> * {@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 * <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, * 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 * 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 * 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 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 * @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 * evaluate, now it's used to get the context
* @param contextType The {@link Context.Type} that the original function was called with * @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} * @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}. * {@code theLazyT}.
*/ */
default R checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type contextType) 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);
} }
} }