semi-auto cleanup

This commit is contained in:
gnembon committed 2023-02-04 13:26:21 +01:00
1 parent cad80f82c6
commit 8f61271606
99 files changed
+11463 -8007

No files matched your search

@@ -8,21 +8,25 @@ import java.util.List;
public abstract class AbstractListValue extends Value implements Iterable<Value>
{
@Override public abstract Iterator<Value> iterator();
public List<Value> unpack()
{
List<Value> retVal = Lists.newArrayList(iterator());
final List<Value> retVal = Lists.newArrayList(iterator());
fatality();
return retVal;
}
public void fatality() { }
public void append(Value v)
public void fatality()
{
}
public void append(final Value v)
{
throw new InternalExpressionException("Cannot append a value to an abstract list");
}
@Override
public Value fromConstant() {
public Value fromConstant()
{
return this.deepcopy();
}
}
+102 -79
View File
@@ -7,12 +7,14 @@ import carpet.script.exception.Throwables;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -44,42 +46,51 @@ public class BlockValue extends Value
{
private BlockState blockState;
private final BlockPos pos;
@NotNull private final Level world;
@NotNull
private final Level world;
private CompoundTag data;
public static BlockValue fromCoords(CarpetContext c, int x, int y, int z)
public static BlockValue fromCoords(final CarpetContext c, final int x, final int y, final int z)
{
BlockPos pos = locateBlockPos(c, x,y,z);
final BlockPos pos = locateBlockPos(c, x, y, z);
return new BlockValue(null, c.level(), pos);
}
private static final Map<String, BlockValue> bvCache= new HashMap<>();
public static BlockValue fromString(String str, Level level)
private static final Map<String, BlockValue> bvCache = new HashMap<>();
public static BlockValue fromString(final String str, final Level level)
{
try
{
BlockValue bv = bvCache.get(str); // [SCARY SHIT] persistent caches over server reloads
if (bv != null) return bv;
BlockStateParser.BlockResult foo = BlockStateParser.parseForBlock(level.registryAccess().lookupOrThrow(Registries.BLOCK), new StringReader(str), true );
if (bv != null)
{
return bv;
}
final BlockStateParser.BlockResult foo = BlockStateParser.parseForBlock(level.registryAccess().lookupOrThrow(Registries.BLOCK), new StringReader(str), true);
if (foo.blockState() != null)
{
CompoundTag bd = foo.nbt();
if (bd == null)
{
bd = new CompoundTag();
bv = new BlockValue(foo.blockState(), level, null, bd );
if (bvCache.size()>10000)
}
bv = new BlockValue(foo.blockState(), level, null, bd);
if (bvCache.size() > 10000)
{
bvCache.clear();
}
bvCache.put(str, bv);
return bv;
}
}
catch (CommandSyntaxException ignored)
catch (final CommandSyntaxException ignored)
{
}
throw new ThrowStatement(str, Throwables.UNKNOWN_BLOCK);
}
public static BlockPos locateBlockPos(CarpetContext c, int xpos, int ypos, int zpos)
public static BlockPos locateBlockPos(final CarpetContext c, final int xpos, final int ypos, final int zpos)
{
final BlockPos pos = c.origin();
return new BlockPos(pos.getX() + xpos, pos.getY() + ypos, pos.getZ() + zpos);
@@ -99,13 +110,13 @@ public class BlockValue extends Value
throw new InternalExpressionException("Attempted to fetch block state without world or stored block state");
}
public static BlockEntity getBlockEntity(Level level, BlockPos pos)
public static BlockEntity getBlockEntity(final Level level, final BlockPos pos)
{
if (level instanceof ServerLevel serverLevel) {
if (serverLevel.getServer().isSameThread())
return serverLevel.getBlockEntity(pos);
else
return serverLevel.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE);
if (level instanceof final ServerLevel serverLevel)
{
return serverLevel.getServer().isSameThread()
? serverLevel.getBlockEntity(pos)
: serverLevel.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE);
}
return null;
}
@@ -115,13 +126,11 @@ public class BlockValue extends Value
{
if (data != null)
{
if (data.isEmpty())
return null;
return data;
return data.isEmpty() ? null : data;
}
if (pos != null)
{
BlockEntity be = getBlockEntity(world, pos);
final BlockEntity be = getBlockEntity(world, pos);
if (be == null)
{
data = new CompoundTag();
@@ -134,7 +143,7 @@ public class BlockValue extends Value
}
public BlockValue(BlockState state, @NotNull Level world, BlockPos position)
public BlockValue(final BlockState state, @NotNull final Level world, final BlockPos position)
{
this.world = world;
blockState = state;
@@ -142,7 +151,7 @@ public class BlockValue extends Value
data = null;
}
public BlockValue(BlockState state, @NotNull Level world, BlockPos position, CompoundTag nbt)
public BlockValue(final BlockState state, @NotNull final Level world, final BlockPos position, final CompoundTag nbt)
{
this.world = world;
blockState = state;
@@ -154,7 +163,7 @@ public class BlockValue extends Value
@Override
public String getString()
{
Registry<Block> blockRegistry = world.registryAccess().registryOrThrow(Registries.BLOCK);
final Registry<Block> blockRegistry = world.registryAccess().registryOrThrow(Registries.BLOCK);
return nameFromRegistryId(blockRegistry.getKey(getBlockState().getBlock()));
}
@@ -179,9 +188,9 @@ public class BlockValue extends Value
@Override
public int hashCode()
{
if (pos != null )
return GlobalPos.of(world.dimension() , pos).hashCode(); //getDimension().getType()
return ("b"+getString()).hashCode();
return pos != null
? GlobalPos.of(world.dimension(), pos).hashCode()
: ("b" + getString()).hashCode();
}
public BlockPos getPos()
@@ -189,29 +198,35 @@ public class BlockValue extends Value
return pos;
}
public Level getWorld() { return world;}
public Level getWorld()
{
return world;
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
// follows falling block convertion
CompoundTag tag = new CompoundTag();
CompoundTag state = new CompoundTag();
BlockState s = getBlockState();
final CompoundTag tag = new CompoundTag();
final CompoundTag state = new CompoundTag();
final BlockState s = getBlockState();
state.put("Name", StringTag.valueOf(world.registryAccess().registryOrThrow(Registries.BLOCK).getKey(s.getBlock()).toString()));
Collection<Property<?>> properties = s.getProperties();
final Collection<Property<?>> properties = s.getProperties();
if (!properties.isEmpty())
{
CompoundTag props = new CompoundTag();
for (Property<?> p: properties)
final CompoundTag props = new CompoundTag();
for (final Property<?> p : properties)
{
props.put(p.getName(), StringTag.valueOf(s.getValue(p).toString().toLowerCase(Locale.ROOT)));
}
state.put("Properties", props);
}
tag.put("BlockState", state);
CompoundTag dataTag = getData();
final CompoundTag dataTag = getData();
if (dataTag != null)
{
tag.put("TileEntityData", dataTag);
@@ -219,29 +234,30 @@ public class BlockValue extends Value
return tag;
}
public enum SpecificDirection {
UP("up",0.5, 0.0, 0.5, Direction.UP),
public enum SpecificDirection
{
UP("up", 0.5, 0.0, 0.5, Direction.UP),
UPNORTH ("up-north", 0.5, 0.0, 0.4, Direction.UP),
UPSOUTH ("up-south", 0.5, 0.0, 0.6, Direction.UP),
UPNORTH("up-north", 0.5, 0.0, 0.4, Direction.UP),
UPSOUTH("up-south", 0.5, 0.0, 0.6, Direction.UP),
UPEAST("up-east", 0.6, 0.0, 0.5, Direction.UP),
UPWEST("up-west", 0.4, 0.0, 0.5, Direction.UP),
DOWN("down", 0.5, 1.0, 0.5, Direction.DOWN),
DOWNNORTH ("down-north", 0.5, 1.0, 0.4, Direction.DOWN),
DOWNSOUTH ("down-south", 0.5, 1.0, 0.6, Direction.DOWN),
DOWNNORTH("down-north", 0.5, 1.0, 0.4, Direction.DOWN),
DOWNSOUTH("down-south", 0.5, 1.0, 0.6, Direction.DOWN),
DOWNEAST("down-east", 0.6, 1.0, 0.5, Direction.DOWN),
DOWNWEST("down-west", 0.4, 1.0, 0.5, Direction.DOWN),
NORTH ("north", 0.5, 0.4, 1.0, Direction.NORTH),
SOUTH ("south", 0.5, 0.4, 0.0, Direction.SOUTH),
NORTH("north", 0.5, 0.4, 1.0, Direction.NORTH),
SOUTH("south", 0.5, 0.4, 0.0, Direction.SOUTH),
EAST("east", 0.0, 0.4, 0.5, Direction.EAST),
WEST("west", 1.0, 0.4, 0.5, Direction.WEST),
NORTHUP ("north-up", 0.5, 0.6, 1.0, Direction.NORTH),
SOUTHUP ("south-up", 0.5, 0.6, 0.0, Direction.SOUTH),
NORTHUP("north-up", 0.5, 0.6, 1.0, Direction.NORTH),
SOUTHUP("south-up", 0.5, 0.6, 0.0, Direction.SOUTH),
EASTUP("east-up", 0.0, 0.6, 0.5, Direction.EAST),
WESTUP("west-up", 1.0, 0.6, 0.5, Direction.WEST);
@@ -252,87 +268,94 @@ public class BlockValue extends Value
private static final Map<String, SpecificDirection> DIRECTION_MAP = Arrays.stream(values()).collect(Collectors.toMap(SpecificDirection::getName, d -> d));
SpecificDirection(String name, double hitx, double hity, double hitz, Direction blockFacing)
SpecificDirection(final String name, final double hitx, final double hity, final double hitz, final Direction blockFacing)
{
this.name = name;
this.hitOffset = new Vec3(hitx, hity, hitz);
this.facing = blockFacing;
}
private String getName()
{
return name;
}
}
public static class PlacementContext extends BlockPlaceContext {
public static class PlacementContext extends BlockPlaceContext
{
private final Direction facing;
private final boolean sneakPlace;
public static PlacementContext from(Level world, BlockPos pos, String direction, boolean sneakPlace, ItemStack itemStack)
public static PlacementContext from(final Level world, final BlockPos pos, final String direction, final boolean sneakPlace, final ItemStack itemStack)
{
SpecificDirection dir = SpecificDirection.DIRECTION_MAP.get(direction);
final SpecificDirection dir = SpecificDirection.DIRECTION_MAP.get(direction);
if (dir == null)
throw new InternalExpressionException("unknown block placement direction: "+direction);
BlockHitResult hitres = new BlockHitResult(Vec3.atLowerCornerOf(pos).add(dir.hitOffset), dir.facing, pos, false);
{
throw new InternalExpressionException("unknown block placement direction: " + direction);
}
final BlockHitResult hitres = new BlockHitResult(Vec3.atLowerCornerOf(pos).add(dir.hitOffset), dir.facing, pos, false);
return new PlacementContext(world, dir.facing, sneakPlace, itemStack, hitres);
}
private PlacementContext(Level world_1, Direction direction_1, boolean sneakPlace, ItemStack itemStack_1, BlockHitResult hitres) {
private PlacementContext(final Level world_1, final Direction direction_1, final boolean sneakPlace, final ItemStack itemStack_1, final BlockHitResult hitres)
{
super(world_1, null, InteractionHand.MAIN_HAND, itemStack_1, hitres);
this.facing = direction_1;
this.sneakPlace = sneakPlace;
}
@Override
public BlockPos getClickedPos() {
boolean prevcanReplaceExisting = replaceClicked;
public BlockPos getClickedPos()
{
final boolean prevcanReplaceExisting = replaceClicked;
replaceClicked = true;
BlockPos ret = super.getClickedPos();
final BlockPos ret = super.getClickedPos();
replaceClicked = prevcanReplaceExisting;
return ret;
}
@Override
public Direction getNearestLookingDirection() {
public Direction getNearestLookingDirection()
{
return facing.getOpposite();
}
@Override
public Direction[] getNearestLookingDirections() {
switch(this.facing) {
case DOWN:
default:
return new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP};
case UP:
return new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
case NORTH:
return new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.SOUTH};
case SOUTH:
return new Direction[]{Direction.DOWN, Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.NORTH};
case WEST:
return new Direction[]{Direction.DOWN, Direction.WEST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.EAST};
case EAST:
return new Direction[]{Direction.DOWN, Direction.EAST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.WEST};
}
public Direction[] getNearestLookingDirections()
{
return switch (this.facing)
{
case DOWN -> new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP};
case UP -> new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
case NORTH -> new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.SOUTH};
case SOUTH -> new Direction[]{Direction.DOWN, Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.NORTH};
case WEST -> new Direction[]{Direction.DOWN, Direction.WEST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.EAST};
case EAST -> new Direction[]{Direction.DOWN, Direction.EAST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.WEST};
};
}
@Override
public Direction getHorizontalDirection() {
public Direction getHorizontalDirection()
{
return this.facing.getAxis() == Direction.Axis.Y ? Direction.NORTH : this.facing;
}
@Override
public Direction getNearestLookingVerticalDirection() {
public Direction getNearestLookingVerticalDirection()
{
return facing.getAxis() == Axis.Y ? facing : Direction.UP;
}
@Override
public boolean isSecondaryUseActive() {
public boolean isSecondaryUseActive()
{
return sneakPlace;
}
@Override
public float getRotation() {
return (float)(this.facing.get2DDataValue() * 90);
public float getRotation()
{
return (float) (this.facing.get2DDataValue() * 90);
}
}
}
@@ -11,53 +11,63 @@ public class BooleanValue extends NumericValue
public static final BooleanValue TRUE = new BooleanValue(true);
boolean boolValue;
private BooleanValue(boolean boolval) {
private BooleanValue(final boolean boolval)
{
super(boolval ? 1L : 0L);
boolValue = boolval;
}
public static BooleanValue of(boolean value)
public static BooleanValue of(final boolean value)
{
return value ? TRUE : FALSE;
}
@Override
public String getString() {
return boolValue?"true":"false";
public String getString()
{
return boolValue ? "true" : "false";
}
@Override
public String getPrettyString() {
public String getPrettyString()
{
return getString();
}
@Override
public String getTypeString() {
public String getTypeString()
{
return "bool";
}
@Override
public Value clone() {
public Value clone()
{
return new BooleanValue(boolValue);
}
@Override
public int hashCode() {
public int hashCode()
{
return Boolean.hashCode(boolValue);
}
@Override
public Tag toTag(boolean force) {
public Tag toTag(final boolean force)
{
return ByteTag.valueOf(boolValue);
}
@Override
public JsonElement toJson() {
public JsonElement toJson()
{
return new JsonPrimitive(boolValue);
}
@Override
public boolean isInteger() {
public boolean isInteger()
{
return true;
}
}
@@ -3,11 +3,15 @@ package carpet.script.value;
public interface ContainerValueInterface
{
boolean put(Value where, Value value);
default boolean put(Value where, Value value, Value conditions)
default boolean put(final Value where, final Value value, final Value conditions)
{
return put(where, value);
}
Value get(Value where);
boolean has(Value where);
boolean delete(Value where);
}
File diff suppressed because it is too large. Load diff
@@ -9,51 +9,56 @@ import net.minecraft.network.chat.MutableComponent;
public class FormattedTextValue extends StringValue
{
Component text;
public FormattedTextValue(Component text)
public FormattedTextValue(final Component text)
{
super(null);
this.text = text;
}
public static Value combine(Value left, Value right) {
MutableComponent text;
if (left instanceof FormattedTextValue)
public static Value combine(final Value left, final Value right)
{
final MutableComponent text;
if (left instanceof final FormattedTextValue ftv)
{
text = ((FormattedTextValue) left).getText().copy();
text = ftv.getText().copy();
}
else
{
if (left.isNull())
{
return right;
}
text = Component.literal(left.getString());
}
if (right instanceof FormattedTextValue)
{
text.append(((FormattedTextValue) right).getText().copy());
return new FormattedTextValue(text);
}
else
{
if (right.isNull())
return left;
text.append(right.getString());
return new FormattedTextValue(text);
}
}
public static Value of(Component text) {
if (text == null) return Value.NULL;
if (right instanceof final FormattedTextValue ftv)
{
text.append(ftv.getText().copy());
return new FormattedTextValue(text);
}
if (right.isNull())
{
return left;
}
text.append(right.getString());
return new FormattedTextValue(text);
}
public static Value of(final Component text)
{
return text == null ? Value.NULL : new FormattedTextValue(text);
}
@Override
public String getString() {
public String getString()
{
return text.getString();
}
@Override
public boolean getBoolean() {
public boolean getBoolean()
{
return !text.getString().isEmpty();
}
@@ -75,19 +80,24 @@ public class FormattedTextValue extends StringValue
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return StringTag.valueOf(Component.Serializer.toJson(text));
}
@Override
public JsonElement toJson() {
public JsonElement toJson()
{
return Component.Serializer.toJsonTree(text);
}
@Override
public Value add(Value o) {
public Value add(final Value o)
{
return combine(this, o);
}
@@ -96,13 +106,14 @@ public class FormattedTextValue extends StringValue
return Component.Serializer.toJson(text);
}
public static FormattedTextValue deserialize(String serialized)
public static FormattedTextValue deserialize(final String serialized)
{
return new FormattedTextValue(Component.Serializer.fromJson(serialized));
}
public static Component getTextByValue(Value value) {
return (value instanceof FormattedTextValue) ? ((FormattedTextValue) value).getText() : Component.literal(value.getString());
public static Component getTextByValue(final Value value)
{
return (value instanceof final FormattedTextValue ftv) ? ftv.getText() : Component.literal(value.getString());
}
}
@@ -29,7 +29,7 @@ public abstract class FrameworkValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
throw new UnsupportedOperationException("Scarpet language component cannot be serialized to the tag");
}
@@ -9,11 +9,15 @@ public class FunctionAnnotationValue extends Value
{
GLOBAL, VARARG
}
public Type type;
public FunctionAnnotationValue(Value variable, Type type)
public FunctionAnnotationValue(final Value variable, final Type type)
{
if (variable.boundVariable == null)
{
throw new InternalExpressionException("You can only borrow variables from the outer scope");
}
this.boundVariable = variable.boundVariable;
this.type = type;
}
@@ -37,7 +41,7 @@ public class FunctionAnnotationValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
throw new UnsupportedOperationException("Global value cannot be serialized to the tag");
}
@@ -9,23 +9,21 @@ public class FunctionSignatureValue extends FrameworkValue
private List<String> globals;
private String varArgs;
public FunctionSignatureValue(String name, List<String> args, String varArgs, List<String> globals)
public FunctionSignatureValue(final String name, final List<String> args, final String varArgs, final List<String> globals)
{
this.identifier = name;
this.arguments = args;
this.varArgs = varArgs;
this.globals = globals;
}
public String getName()
public String identifier()
{
return identifier;
}
public List<String> getArgs()
public List<String> arguments()
{
return arguments;
}
public List<String> getGlobals() {return globals;}
public String getVarArgs() { return varArgs;}
public List<String> globals() {return globals;}
public String varArgs() { return varArgs;}
}
@@ -4,7 +4,8 @@ import java.util.List;
public class FunctionUnpackedArgumentsValue extends ListValue
{
public FunctionUnpackedArgumentsValue(List<Value> list) {
public FunctionUnpackedArgumentsValue(final List<Value> list)
{
super(list);
}
@@ -17,7 +18,6 @@ public class FunctionUnpackedArgumentsValue extends ListValue
@Override
public Value deepcopy()
{
ListValue copy = (ListValue)super.deepcopy();
return new FunctionUnpackedArgumentsValue(copy.items);
return new FunctionUnpackedArgumentsValue(((ListValue) super.deepcopy()).items);
}
}
@@ -12,12 +12,14 @@ import carpet.script.exception.ContinueStatement;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ReturnStatement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
@@ -33,7 +35,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
private static long variantCounter = 1;
private long variant;
private FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List<String> args, String varArgs)
private FunctionValue(final Expression expression, final Tokenizer.Token token, final String name, final LazyValue body, final List<String> args, final String varArgs)
{
this.expression = expression;
this.token = token;
@@ -45,7 +47,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
variant = 0L;
}
public FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List<String> args, String varArgs, Map<String, LazyValue> outerState)
public FunctionValue(final Expression expression, final Tokenizer.Token token, final String name, final LazyValue body, final List<String> args, final String varArgs, final Map<String, LazyValue> outerState)
{
this.expression = expression;
this.token = token;
@@ -63,19 +65,27 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
return name;
}
public Module getModule() {return expression.module;}
public Module getModule()
{
return expression.module;
}
@Override
public String getPrettyString()
{
List<String> stringArgs= new ArrayList<>(args);
final List<String> stringArgs = new ArrayList<>(args);
if (outerState != null)
{
stringArgs.addAll(outerState.entrySet().stream().map(e ->
"outer("+e.getKey()+") = "+e.getValue().evalValue(null).getPrettyString()).collect(Collectors.toList()));
return (name.equals("_")?"<lambda>":name) +"("+String.join(", ",stringArgs)+")";
"outer(" + e.getKey() + ") = " + e.getValue().evalValue(null).getPrettyString()).toList());
}
return (name.equals("_") ? "<lambda>" : name) + "(" + String.join(", ", stringArgs) + ")";
}
public String fullName() {return (name.equals("_")?"<lambda>":name)+(expression.module == null?"":"["+expression.module.name()+"]");}
public String fullName()
{
return (name.equals("_") ? "<lambda>" : name) + (expression.module == null ? "" : "[" + expression.module.name() + "]");
}
@Override
public boolean getBoolean()
@@ -86,7 +96,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
@Override
protected Value clone()
{
FunctionValue ret = new FunctionValue(expression, token, name, body, args, varArgs);
final FunctionValue ret = new FunctionValue(expression, token, name, body, args, varArgs);
ret.outerState = this.outerState;
ret.variant = this.variant;
return ret;
@@ -95,26 +105,22 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
@Override
public int hashCode()
{
return name.hashCode()+(int)variant;
return name.hashCode() + (int) variant;
}
@Override
public boolean equals(Object o)
public boolean equals(final Object o)
{
if (o instanceof FunctionValue)
return name.equals(((FunctionValue) o).name) && variant == ((FunctionValue) o).variant;
return false;
return o instanceof final FunctionValue fv && name.equals(fv.name) && variant == fv.variant;
}
@Override
public int compareTo(final Value o)
{
if (o instanceof FunctionValue)
if (o instanceof final FunctionValue fv)
{
int nameSame = this.name.compareTo(((FunctionValue) o).name);
if (nameSame != 0)
return nameSame;
return (int) (variant-((FunctionValue) o).variant);
final int nameSame = this.name.compareTo(fv.name);
return nameSame != 0 ? nameSame : (int) (variant - fv.variant);
}
return getString().compareTo(o.getString());
}
@@ -132,7 +138,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
}
@Override
public Value slice(long from, Long to)
public Value slice(final long from, final Long to)
{
throw new InternalExpressionException("Cannot slice a function");
}
@@ -149,46 +155,49 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
return varArgs != null;
}
public LazyValue callInContext(Context c, Context.Type type, List<Value> params)
public LazyValue callInContext(final Context c, final Context.Type type, final List<Value> params)
{
try
{
return execute(c, type, expression, token, params);
}
catch (ExpressionException exc)
catch (final ExpressionException exc)
{
exc.stack.add(this);
throw exc;
}
catch (InternalExpressionException exc)
catch (final InternalExpressionException exc)
{
exc.stack.add(this);
throw new ExpressionException(c, expression, token, exc.getMessage(), exc.stack);
}
catch (ArithmeticException exc)
catch (final ArithmeticException exc)
{
throw new ExpressionException(c, expression, token, "Your math is wrong, "+exc.getMessage(), Collections.singletonList(this));
throw new ExpressionException(c, expression, token, "Your math is wrong, " + exc.getMessage(), Collections.singletonList(this));
}
}
public void checkArgs(int candidates)
public void checkArgs(final int candidates)
{
int actual = getArguments().size();
final int actual = getArguments().size();
if (candidates < actual)
{
throw new InternalExpressionException("Function " + getPrettyString() + " requires at least " + actual + " arguments");
}
if (candidates > actual && getVarArgs() == null)
{
throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments");
}
}
public static List<Value> unpackArgs(List<LazyValue> lazyParams, Context c)
public static List<Value> unpackArgs(final List<LazyValue> lazyParams, final Context c)
{
// TODO we shoudn't need that if all fuctions are not lazy really
List<Value> params = new ArrayList<>();
for (LazyValue lv : lazyParams)
final List<Value> params = new ArrayList<>();
for (final LazyValue lv : lazyParams)
{
Value param = lv.evalValue(c, Context.NONE);
final Value param = lv.evalValue(c, Context.NONE);
if (param instanceof FunctionUnpackedArgumentsValue)
{
CarpetSettings.LOG.error("How did we get here?");
@@ -203,48 +212,51 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
}
@Override
public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams) {
List<Value> resolvedParams = unpackArgs(lazyParams, c);
public LazyValue lazyEval(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final List<LazyValue> lazyParams)
{
final List<Value> resolvedParams = unpackArgs(lazyParams, c);
return execute(c, type, e, t, resolvedParams);
}
public LazyValue execute(Context c, Context.Type type, Expression e, Tokenizer.Token t, List<Value> params)
public LazyValue execute(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final List<Value> params)
{
assertArgsOk(params, (fixedArgs) ->{
assertArgsOk(params, fixedArgs -> {
if (fixedArgs) // wrong number of args for fixed args
{
throw new ExpressionException(c, e, t,
"Incorrect number of arguments for function "+name+
". Should be "+args.size()+", not "+params.size()+" like "+args
"Incorrect number of arguments for function " + name +
". Should be " + args.size() + ", not " + params.size() + " like " + args
);
}
else // too few args for varargs
{
List<String> argList = new ArrayList<>(args);
argList.add("... "+varArgs);
throw new ExpressionException(c, e, t,
"Incorrect number of arguments for function "+name+
". Should be at least "+args.size()+", not "+params.size()+" like "+argList
);
}
});
Context newFrame = c.recreate();
// too few args for varargs
if (outerState != null) outerState.forEach(newFrame::setVariable);
for (int i=0; i<args.size(); i++)
final List<String> argList = new ArrayList<>(args);
argList.add("... " + varArgs);
throw new ExpressionException(c, e, t,
"Incorrect number of arguments for function " + name +
". Should be at least " + args.size() + ", not " + params.size() + " like " + argList
);
});
final Context newFrame = c.recreate();
if (outerState != null)
{
String arg = args.get(i);
Value val = params.get(i).reboundedTo(arg); // todo check if we need to copy that
outerState.forEach(newFrame::setVariable);
}
for (int i = 0; i < args.size(); i++)
{
final String arg = args.get(i);
final Value val = params.get(i).reboundedTo(arg); // todo check if we need to copy that
newFrame.setVariable(arg, (cc, tt) -> val);
}
if (varArgs != null)
{
List<Value> extraParams = new ArrayList<>();
final List<Value> extraParams = new ArrayList<>();
for (int i = args.size(), mx = params.size(); i < mx; i++)
{
extraParams.add(params.get(i).reboundedTo(null)); // copy by value I guess
}
Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that?
final Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that?
newFrame.setVariable(varArgs, (cc, tt) -> rest);
}
@@ -253,15 +265,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
{
retVal = body.evalValue(newFrame, type); // todo not sure if we need to propagete type / consider boolean context in defined functions - answer seems ye
}
catch (BreakStatement | ContinueStatement exc)
catch (final BreakStatement | ContinueStatement exc)
{
throw new ExpressionException(c, e, t, "'continue' and 'break' can only be called inside loop function bodies");
}
catch (ReturnStatement returnStatement)
catch (final ReturnStatement returnStatement)
{
retVal = returnStatement.retval;
}
Value otherRetVal = retVal;
final Value otherRetVal = retVal;
return (cc, tt) -> otherRetVal;
}
@@ -269,30 +281,38 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
{
return expression;
}
public Tokenizer.Token getToken()
{
return token;
}
public List<String> getArguments()
{
return args;
}
public String getVarArgs() {return varArgs; }
public String getVarArgs()
{
return varArgs;
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return StringTag.valueOf(getString());
}
public void assertArgsOk(List<?> list, Consumer<Boolean> feedback)
public void assertArgsOk(final List<?> list, final Consumer<Boolean> feedback)
{
int size = list.size();
final int size = list.size();
if (varArgs == null && args.size() != size) // wrong number of args for fixed args
{
feedback.accept(true);
}
else if (varArgs != null && args.size() > size) // too few args for varargs
{
@@ -301,12 +321,14 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
}
@Override
public boolean pure() {
public boolean pure()
{
return false;
}
@Override
public boolean transitive() {
public boolean transitive()
{
return false;
}
}
@@ -2,16 +2,23 @@ package carpet.script.value;
public class LContainerValue extends FrameworkValue
{
private ContainerValueInterface container;
private Value address;
private final ContainerValueInterface container;
private final Value address;
public static final LContainerValue NULL_CONTAINER = new LContainerValue(null, null);
public LContainerValue(ContainerValueInterface c, Value v)
public LContainerValue(final ContainerValueInterface c, final Value v)
{
container = c;
address = v;
}
public ContainerValueInterface getContainer() {return container; }
public Value getAddress() {return address; }
public ContainerValueInterface container()
{
return container;
}
public Value address()
{
return address;
}
}
@@ -1,35 +1,41 @@
package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
public abstract class LazyListValue extends AbstractListValue implements Iterator<Value>
{
public static LazyListValue rangeDouble(double from, double to, double step)
public static LazyListValue rangeDouble(final double from, final double to, final double step)
{
return new LazyListValue()
{
{
if (step == 0)
{
throw new InternalExpressionException("Range will never end with a zero step");
}
this.start = from;
this.current = this.start;
this.limit = to;
this.stepp = step;
}
private final double start;
private double current;
private final double limit;
private final double stepp;
@Override
public Value next()
{
Value val = new NumericValue(current);
final Value val = new NumericValue(current);
current += stepp;
return val;
}
@@ -43,36 +49,41 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
@Override
public boolean hasNext()
{
return stepp > 0?(current < limit):(current > limit);
return stepp > 0 ? (current < limit) : (current > limit);
}
@Override
public String getString()
{
return String.format(Locale.ROOT, "[%s, %s, ..., %s)",NumericValue.of(start).getString(), NumericValue.of(start+stepp).getString(), NumericValue.of( limit).getString());
return String.format(Locale.ROOT, "[%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString());
}
};
}
public static LazyListValue rangeLong(long from, long to, long step)
public static LazyListValue rangeLong(final long from, final long to, final long step)
{
return new LazyListValue()
{
{
if (step == 0)
{
throw new InternalExpressionException("Range will never end with a zero step");
}
this.start = from;
this.current = this.start;
this.limit = to;
this.stepp = step;
}
private final long start;
private long current;
private final long limit;
private final long stepp;
@Override
public Value next()
{
Value val = new NumericValue(current);
final Value val = new NumericValue(current);
current += stepp;
return val;
}
@@ -86,13 +97,13 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
@Override
public boolean hasNext()
{
return stepp > 0?(current < limit):(current > limit);
return stepp > 0 ? (current < limit) : (current > limit);
}
@Override
public String getString()
{
return String.format(Locale.ROOT, "[%s, %s, ..., %s)",NumericValue.of(start).getString(), NumericValue.of(start+stepp).getString(), NumericValue.of( limit).getString());
return String.format(Locale.ROOT, "[%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString());
}
};
}
@@ -108,20 +119,24 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
{
return hasNext();
}
@Override public abstract boolean hasNext();
@Override public abstract Value next();
@Override
public void fatality() {reset();}
public void fatality()
{
reset();
}
public abstract void reset();
@Override
public Iterator<Value> iterator() {return this;}
public Iterator<Value> iterator()
{
return this;
}
public List<Value> unroll()
{
List<Value> result = new ArrayList<>();
final List<Value> result = new ArrayList<>();
this.forEachRemaining(result::add);
fatality();
return result;
@@ -130,26 +145,38 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
@Override
public Value slice(long from, Long to)
{
if (to == null || to < 0) to = (long) Integer.MAX_VALUE;
if (from < 0) from = 0;
if (to == null || to < 0)
{
to = (long) Integer.MAX_VALUE;
}
if (from < 0)
{
from = 0;
}
if (from > to)
{
return ListValue.of();
List<Value> result = new ArrayList<>();
}
final List<Value> result = new ArrayList<>();
int i;
for (i = 0; i < from; i++)
{
if (hasNext())
{
next();
}
else
{
fatality();
return ListValue.wrap(result);
}
}
for (i = (int)from; i < to; i++)
for (i = (int) from; i < to; i++)
{
if (hasNext())
{
result.add(next());
}
else
{
fatality();
@@ -158,8 +185,9 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
}
return ListValue.wrap(result);
}
@Override
public Value add(Value other)
public Value add(final Value other)
{
throw new InternalExpressionException("Cannot add to iterators");
}
@@ -175,37 +203,42 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
{
return "iterator";
}
@Override
public Object clone()
{
Object copy;
final Object copy;
try
{
copy = super.clone();
}
catch (CloneNotSupportedException e)
catch (final CloneNotSupportedException e)
{
throw new InternalExpressionException("Cannot copy iterators");
}
((LazyListValue)copy).reset();
((LazyListValue) copy).reset();
return copy;
}
@Override
public Value fromConstant() {
return (Value)clone();
public Value fromConstant()
{
return (Value) clone();
}
@Override
public int hashCode()
{
return ("i"+getString()).hashCode();
return ("i" + getString()).hashCode();
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return StringTag.valueOf(getString());
}
}
+198 -135
View File
@@ -4,6 +4,7 @@ import carpet.script.LazyValue;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -14,6 +15,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.IntTag;
@@ -28,23 +30,24 @@ import static java.lang.Math.abs;
public class ListValue extends AbstractListValue implements ContainerValueInterface
{
protected final List<Value> items;
@Override
public String getString()
{
return "["+items.stream().map(Value::getString).collect(Collectors.joining(", "))+"]";
return "[" + items.stream().map(Value::getString).collect(Collectors.joining(", ")) + "]";
}
@Override
public String getPrettyString()
{
if (items.size()<8)
return "["+items.stream().map(Value::getPrettyString).collect(Collectors.joining(", "))+"]";
return "["+items.get(0).getPrettyString()+", "+items.get(1).getPrettyString()+", ..., "+
items.get(items.size()-2).getPrettyString()+", "+items.get(items.size()-1).getPrettyString()+"]";
return items.size() < 8
? "[" + items.stream().map(Value::getPrettyString).collect(Collectors.joining(", ")) + "]"
: "[" + items.get(0).getPrettyString() + ", " + items.get(1).getPrettyString() + ", ..., " + items.get(items.size() - 2).getPrettyString() + ", " + items.get(items.size() - 1).getPrettyString() + "]";
}
@Override
public boolean getBoolean() {
public boolean getBoolean()
{
return !items.isEmpty();
}
@@ -57,56 +60,63 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
@Override
public Value deepcopy()
{
List<Value> copyItems = new ArrayList<>(items.size());
for (Value entry: items) copyItems.add(entry.deepcopy());
final List<Value> copyItems = new ArrayList<>(items.size());
for (final Value entry : items)
{
copyItems.add(entry.deepcopy());
}
return new ListValue(copyItems);
}
public ListValue(Collection<? extends Value> list)
public ListValue(final Collection<? extends Value> list)
{
items = new ArrayList<>(list);
}
protected ListValue(List<Value> list)
protected ListValue(final List<Value> list)
{
items = list;
}
public static Value fromTriple(double a, double b, double c)
public static Value fromTriple(final double a, final double b, final double c)
{
return ListValue.of(new NumericValue(a), new NumericValue(b), new NumericValue(c));
}
public static Value fromTriple(int a, int b, int c)
public static Value fromTriple(final int a, final int b, final int c)
{
return fromTriple((double) a, b, c);
}
public static ListValue wrap(Stream<Value> stream)
public static ListValue wrap(final Stream<Value> stream)
{
return wrap(stream.collect(Collectors.toList()));
}
public static ListValue wrap(List<Value> list)
public static ListValue wrap(final List<Value> list)
{
return new ListValue(list);
}
public static ListValue of(Value ... list)
public static ListValue of(final Value... list)
{
return new ListValue(new ArrayList<>(Arrays.asList(list)));
}
public static ListValue ofNums(Number ... list)
public static ListValue ofNums(final Number... list)
{
List<Value> valList = new ArrayList<>();
for (Number i : list)
final List<Value> valList = new ArrayList<>();
for (final Number i : list)
{
valList.add(new NumericValue(i.doubleValue()));
}
return new ListValue(valList);
}
public static LazyValue lazyEmpty()
{
Value ret = new ListValue();
final Value ret = new ListValue();
return (c, t) -> ret;
}
@@ -116,16 +126,17 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public Value add(Value other) {
ListValue output = new ListValue();
if (other instanceof ListValue)
public Value add(final Value other)
{
final ListValue output = new ListValue();
if (other instanceof final ListValue list)
{
List<Value> other_list = ((ListValue) other).items;
if (other_list.size() == items.size())
final List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
{
for(int i = 0, size = items.size(); i < size; i++)
for (int i = 0, size = items.size(); i < size; i++)
{
output.items.add(items.get(i).add(other_list.get(i)));
output.items.add(items.get(i).add(otherItems.get(i)));
}
}
else
@@ -135,31 +146,32 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
else
{
for (Value v : items)
for (final Value v : items)
{
output.items.add(v.add(other));
}
}
return output;
}
@Override
public void append(Value v)
public void append(final Value v)
{
items.add(v);
}
@Override
public Value subtract(Value other)
public Value subtract(final Value other)
{
ListValue output = new ListValue();
if (other instanceof ListValue)
final ListValue output = new ListValue();
if (other instanceof final ListValue list)
{
List<Value> other_list = ((ListValue) other).items;
if (other_list.size() == items.size())
final List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
{
for(int i = 0, size = items.size(); i < size; i++)
for (int i = 0, size = items.size(); i < size; i++)
{
output.items.add(items.get(i).subtract(other_list.get(i)));
output.items.add(items.get(i).subtract(otherItems.get(i)));
}
}
else
@@ -169,31 +181,32 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
else
{
for (Value v : items)
for (final Value v : items)
{
output.items.add(v.subtract(other));
}
}
return output;
}
public void subtractFrom(Value v) // if I ever do -= then it wouod remove items
public void subtractFrom(final Value v) // if I ever do -= then it wouod remove items
{
throw new UnsupportedOperationException(); // TODO
}
@Override
public Value multiply(Value other)
public Value multiply(final Value other)
{
ListValue output = new ListValue();
if (other instanceof ListValue)
final ListValue output = new ListValue();
if (other instanceof final ListValue list)
{
List<Value> other_list = ((ListValue) other).items;
if (other_list.size() == items.size())
final List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
{
for(int i = 0, size = items.size(); i < size; i++)
for (int i = 0, size = items.size(); i < size; i++)
{
output.items.add(items.get(i).multiply(other_list.get(i)));
output.items.add(items.get(i).multiply(otherItems.get(i)));
}
}
else
@@ -203,7 +216,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
else
{
for (Value v : items)
for (final Value v : items)
{
output.items.add(v.multiply(other));
}
@@ -212,17 +225,17 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public Value divide(Value other)
public Value divide(final Value other)
{
ListValue output = new ListValue();
if (other instanceof ListValue)
final ListValue output = new ListValue();
if (other instanceof final ListValue list)
{
List<Value> other_list = ((ListValue) other).items;
if (other_list.size() == items.size())
final List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
{
for(int i = 0, size = items.size(); i < size; i++)
for (int i = 0, size = items.size(); i < size; i++)
{
output.items.add(items.get(i).divide(other_list.get(i)));
output.items.add(items.get(i).divide(otherItems.get(i)));
}
}
else
@@ -232,7 +245,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
else
{
for (Value v : items)
for (final Value v : items)
{
output.items.add(v.divide(other));
}
@@ -241,19 +254,27 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public int compareTo(Value o)
public int compareTo(final Value o)
{
if (o instanceof ListValue)
if (o instanceof final ListValue ol)
{
ListValue ol = (ListValue)o;
int this_size = this.getItems().size();
int o_size = ol.getItems().size();
if (this_size != o_size) return this_size - o_size;
if (this_size == 0) return 0;
for (int i = 0; i < this_size; i++)
final int size = this.getItems().size();
final int otherSize = ol.getItems().size();
if (size != otherSize)
{
int res = this.items.get(i).compareTo(ol.items.get(i));
if (res != 0) return res;
return size - otherSize;
}
if (size == 0)
{
return 0;
}
for (int i = 0; i < size; i++)
{
final int res = this.items.get(i).compareTo(ol.items.get(i));
if (res != 0)
{
return res;
}
}
return 0;
}
@@ -263,11 +284,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
@Override
public boolean equals(final Object o)
{
if (o instanceof ListValue)
{
return getItems().equals(((ListValue) o).getItems());
}
return false;
return o instanceof final ListValue list && getItems().equals(list.getItems());
}
public List<Value> getItems()
@@ -276,7 +293,10 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public Iterator<Value> iterator() { return new ArrayList<>(items).iterator(); } // should be thread safe
public Iterator<Value> iterator()
{
return new ArrayList<>(items).iterator();
} // should be thread safe
@Override
public List<Value> unpack()
@@ -284,7 +304,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
return new ArrayList<>(items);
}
public void extend(List<Value> subList)
public void extend(final List<Value> subList)
{
items.addAll(subList);
}
@@ -296,18 +316,21 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
* @param len
* @return
*/
public static int normalizeIndex(long idx, int len)
public static int normalizeIndex(long idx, final int len)
{
if (idx >=0 && idx < len) return (int)idx;
long range = abs(idx)/len;
idx += (range+2)*len;
if (idx >= 0 && idx < len)
{
return (int) idx;
}
final long range = abs(idx) / len;
idx += (range + 2) * len;
idx = idx % len;
return (int)idx;
return (int) idx;
}
public static class ListConstructorValue extends ListValue
{
public ListConstructorValue(Collection<? extends Value> list)
public ListConstructorValue(final Collection<? extends Value> list)
{
super(list);
}
@@ -320,11 +343,11 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public Value in(Value value1)
public Value in(final Value value1)
{
for (int i = 0; i < items.size(); i++)
{
Value v = items.get(i);
final Value v = items.get(i);
if (v.equals(value1))
{
return new NumericValue(i);
@@ -334,22 +357,27 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public Value slice(long fromDesc, Long toDesc)
public Value slice(final long fromDesc, final Long toDesc)
{
List<Value> items = getItems();
int size = items.size();
int from = normalizeIndex(fromDesc, size);
final List<Value> items = getItems();
final int size = items.size();
final int from = normalizeIndex(fromDesc, size);
if (toDesc == null)
{
return new ListValue(new ArrayList<>(getItems().subList(from, size)));
int to = normalizeIndex(toDesc, size+1);
}
final int to = normalizeIndex(toDesc, size + 1);
if (from > to)
{
return ListValue.of();
}
return new ListValue(new ArrayList<>(getItems().subList(from, to)));
}
@Override
public Value split(Value delimiter) {
ListValue result = new ListValue();
public Value split(final Value delimiter)
{
final ListValue result = new ListValue();
if (delimiter == null)
{
this.forEach(item -> result.items.add(of(item)));
@@ -357,12 +385,12 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
int startIndex = 0;
int index = 0;
for (Value val : this.items)
for (final Value val : this.items)
{
index++;
if (val.equals(delimiter))
{
result.items.add(new ListValue(new ArrayList<>(this.items.subList(startIndex, index-1))));
result.items.add(new ListValue(new ArrayList<>(this.items.subList(startIndex, index - 1))));
startIndex = index;
}
}
@@ -373,35 +401,41 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
@Override
public double readDoubleNumber()
{
return (double)items.size();
return items.size();
}
@Override
public boolean put(Value where, Value value, Value conditionValue)
public boolean put(final Value where, final Value value, final Value conditionValue)
{
String condition = conditionValue.getString();
final String condition = conditionValue.getString();
if (condition.equalsIgnoreCase("insert"))
{
return put(where, value, false, false);
}
if (condition.equalsIgnoreCase("extend"))
{
return put(where, value, false, true);
}
if (condition.equalsIgnoreCase("replace"))
{
return put(where, value, true, false);
throw new InternalExpressionException("List 'put' modifier could be either 'insert', 'replace', or extend");
}
throw new InternalExpressionException("List 'put' modifier could be either 'insert', 'replace', or extend");
}
@Override
public boolean put(Value ind, Value value)
public boolean put(final Value ind, final Value value)
{
return put(ind, value, true, false);
}
private boolean put(Value ind, Value value, boolean replace, boolean extend)
private boolean put(final Value ind, final Value value, final boolean replace, final boolean extend)
{
if (ind.isNull())
{
if (extend && value instanceof AbstractListValue)
{
((AbstractListValue) value).iterator().forEachRemaining((v)-> items.add(v));
((AbstractListValue) value).iterator().forEachRemaining(items::add);
}
else
{
@@ -410,27 +444,35 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
else
{
int numitems = items.size();
final int numitems = items.size();
if (!(ind instanceof NumericValue))
{
return false;
int index = (int)((NumericValue) ind).getLong();
}
int index = (int) ((NumericValue) ind).getLong();
if (index < 0)
{// only for values < 0
index = normalizeIndex(index, numitems);
}
if (replace)
{
while (index >= items.size()) items.add(Value.NULL);
while (index >= items.size())
{
items.add(Value.NULL);
}
items.set(index, value);
return true;
}
while (index > items.size()) items.add(Value.NULL);
while (index > items.size())
{
items.add(Value.NULL);
}
if (extend && value instanceof AbstractListValue)
{
Iterable<Value> iterable = ((AbstractListValue) value)::iterator;
List<Value> appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList());
items.addAll(index, appendix );
final Iterable<Value> iterable = ((AbstractListValue) value)::iterator;
final List<Value> appendix = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
items.addAll(index, appendix);
return true;
}
items.add(index, value);
@@ -439,25 +481,27 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
}
@Override
public Value get(Value value)
public Value get(final Value value)
{
int size = items.size();
if (size == 0) return Value.NULL;
return items.get(normalizeIndex(NumericValue.asNumber(value, "'address' to a list index").getLong(), size));
final int size = items.size();
return size == 0 ? Value.NULL : items.get(normalizeIndex(NumericValue.asNumber(value, "'address' to a list index").getLong(), size));
}
@Override
public boolean has(Value where)
public boolean has(final Value where)
{
long index = NumericValue.asNumber(where, "'address' to a list index").getLong();
final long index = NumericValue.asNumber(where, "'address' to a list index").getLong();
return index >= 0 && index < items.size();
}
@Override
public boolean delete(Value where)
public boolean delete(final Value where)
{
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
long index = ((NumericValue) where).getLong();
if (!(where instanceof NumericValue) || items.isEmpty())
{
return false;
}
final long index = ((NumericValue) where).getLong();
items.remove(normalizeIndex(index, items.size()));
return true;
}
@@ -482,35 +526,54 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
LIST,
MAP,
STRING;
private static TagTypeCompat getType(Tag tag)
private static TagTypeCompat getType(final Tag tag)
{
if (tag instanceof IntTag) return INT;
if (tag instanceof LongTag) return LONG;
if (tag instanceof DoubleTag) return DBL;
if (tag instanceof ListTag) return LIST;
if (tag instanceof CompoundTag) return MAP;
if (tag instanceof IntTag)
{
return INT;
}
if (tag instanceof LongTag)
{
return LONG;
}
if (tag instanceof DoubleTag)
{
return DBL;
}
if (tag instanceof ListTag)
{
return LIST;
}
if (tag instanceof CompoundTag)
{
return MAP;
}
return STRING;
}
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
int argSize = items.size();
if (argSize == 0) return new ListTag();
ListTag tag = new ListTag();
if (argSize ==1)
final int argSize = items.size();
if (argSize == 0)
{
return new ListTag();
}
final ListTag tag = new ListTag();
if (argSize == 1)
{
tag.add(items.get(0).toTag(force));
return tag;
}
// figuring out the types
List<Tag> tags= new ArrayList<>();
final List<Tag> tags = new ArrayList<>();
items.forEach(v -> tags.add(v.toTag(force)));
Set<TagTypeCompat> cases = EnumSet.noneOf(TagTypeCompat.class);
final Set<TagTypeCompat> cases = EnumSet.noneOf(TagTypeCompat.class);
tags.forEach(t -> cases.add(TagTypeCompat.getType(t)));
if (cases.size()==1) // well, one type of items
if (cases.size() == 1) // well, one type of items
{
tag.addAll(tags);
return tag;
@@ -519,28 +582,28 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|| cases.contains(TagTypeCompat.MAP)
|| cases.contains(TagTypeCompat.STRING)) // incompatible types
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
tags.forEach(t -> tag.add(StringTag.valueOf(t.getAsString())));
return tag;
}
// only numbers / mixed types
if (cases.contains(TagTypeCompat.DBL))
{
tags.forEach(t -> tag.add(DoubleTag.valueOf(((NumericTag)t).getAsDouble())));
}
else
{
tags.forEach(t -> tag.add(LongTag.valueOf(((NumericTag)t).getAsLong())));
}
tags.forEach(cases.contains(TagTypeCompat.DBL)
? (t -> tag.add(DoubleTag.valueOf(((NumericTag) t).getAsDouble())))
: (t -> tag.add(LongTag.valueOf(((NumericTag) t).getAsLong()))));
return tag;
}
@Override
public JsonElement toJson()
{
JsonArray array = new JsonArray();
for (Value el: items)
final JsonArray array = new JsonArray();
for (final Value el : items)
{
array.add(el.toJson());
}
return array;
}
}
+60 -67
View File
@@ -3,6 +3,7 @@ package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -11,6 +12,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
@@ -23,22 +25,16 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
map = new HashMap<>();
}
public MapValue(List<Value> kvPairs)
public MapValue(final List<Value> kvPairs)
{
this();
for (Value v : kvPairs)
{
put(v);
}
kvPairs.forEach(this::put);
}
public MapValue(Set<Value> keySet)
public MapValue(final Set<Value> keySet)
{
this();
for (Value v : keySet)
{
map.put(v, Value.NULL);
}
keySet.forEach(v -> map.put(v, Value.NULL));
}
@Override
@@ -56,20 +52,22 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
@Override
public String getString()
{
return "{"+map.entrySet().stream().map((p) -> p.getKey().getString()+": "+p.getValue().getString()).collect(Collectors.joining(", "))+"}";
return "{" + map.entrySet().stream().map(p -> p.getKey().getString() + ": " + p.getValue().getString()).collect(Collectors.joining(", ")) + "}";
}
@Override
public String getPrettyString()
{
if (map.size()<6)
return "{"+map.entrySet().stream().map((p) -> p.getKey().getPrettyString()+": "+p.getValue().getPrettyString()).collect(Collectors.joining(", "))+"}";
List<Value> keys = new ArrayList<>(map.keySet());
int max = keys.size();
return "{"+keys.get(0).getPrettyString()+": "+map.get(keys.get(0)).getPrettyString()+", "+
keys.get(1).getPrettyString()+": "+map.get(keys.get(1)).getPrettyString()+", ..., "+
keys.get(max-2).getPrettyString()+": "+map.get(keys.get(max-2)).getPrettyString()+", "+
keys.get(max-1).getPrettyString()+": "+map.get(keys.get(max-1)).getPrettyString()+"}";
if (map.size() < 6)
{
return "{" + map.entrySet().stream().map(p -> p.getKey().getPrettyString() + ": " + p.getValue().getPrettyString()).collect(Collectors.joining(", ")) + "}";
}
final List<Value> keys = new ArrayList<>(map.keySet());
final int max = keys.size();
return "{" + keys.get(0).getPrettyString() + ": " + map.get(keys.get(0)).getPrettyString() + ", " +
keys.get(1).getPrettyString() + ": " + map.get(keys.get(1)).getPrettyString() + ", ..., " +
keys.get(max - 2).getPrettyString() + ": " + map.get(keys.get(max - 2)).getPrettyString() + ", " +
keys.get(max - 1).getPrettyString() + ": " + map.get(keys.get(max - 1)).getPrettyString() + "}";
}
@Override
@@ -87,35 +85,34 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
@Override
public Value deepcopy()
{
Map<Value, Value> copyMap = new HashMap<>();
final Map<Value, Value> copyMap = new HashMap<>();
map.forEach((key, value) -> copyMap.put(key.deepcopy(), value.deepcopy()));
return new MapValue(copyMap);
}
private MapValue(Map<Value,Value> other)
private MapValue(final Map<Value, Value> other)
{
map = other;
}
public static MapValue wrap(Map<Value,Value> other)
public static MapValue wrap(final Map<Value, Value> other)
{
return new MapValue(other);
}
@Override
public Value add(Value o)
public Value add(final Value o)
{
Map<Value, Value> newItems = new HashMap<>(map);
if (o instanceof MapValue)
final Map<Value, Value> newItems = new HashMap<>(map);
if (o instanceof final MapValue mapValue)
{
newItems.putAll(((MapValue) o).map);
newItems.putAll(mapValue.map);
}
else if (o instanceof AbstractListValue)
else if (o instanceof final AbstractListValue alv)
{
Iterator<Value> it = ((AbstractListValue) o).iterator();
while (it.hasNext())
for (final Value value : alv)
{
newItems.put(it.next(), Value.NULL);
newItems.put(value, Value.NULL);
}
}
else
@@ -126,31 +123,30 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
}
@Override
public Value subtract(Value v)
public Value subtract(final Value v)
{
throw new InternalExpressionException("Cannot subtract from a map value");
}
@Override
public Value multiply(Value v)
public Value multiply(final Value v)
{
throw new InternalExpressionException("Cannot multiply with a map value");
}
@Override
public Value divide(Value v)
public Value divide(final Value v)
{
throw new InternalExpressionException("Cannot divide a map value");
}
public void put(Value v)
public void put(final Value v)
{
if (!(v instanceof ListValue))
if (!(v instanceof final ListValue pair))
{
map.put(v, Value.NULL);
return;
}
ListValue pair = (ListValue)v;
if (pair.getItems().size() != 2)
{
throw new InternalExpressionException("Map constructor requires elements that have two items");
@@ -159,13 +155,13 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
}
@Override
public void append(Value v)
public void append(final Value v)
{
map.put(v, Value.NULL);
}
@Override
public int compareTo(Value o)
public int compareTo(final Value o)
{
throw new InternalExpressionException("Cannot compare with a map value");
}
@@ -173,11 +169,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
@Override
public boolean equals(final Object o)
{
if (o instanceof MapValue)
{
return map.equals(((MapValue) o).map);
}
return false;
return o instanceof final MapValue mapValue && map.equals(mapValue.map);
}
public Map<Value, Value> getMap()
@@ -185,9 +177,9 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
return map;
}
public void extend(List<Value> subList)
public void extend(final List<Value> subList)
{
for (Value v: subList) put(v);
subList.forEach(this::put);
}
@Override
@@ -197,53 +189,51 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
}
@Override
public Value in(Value value1)
public Value in(final Value value)
{
if (map.containsKey(value1)) return value1;
return Value.NULL;
return map.containsKey(value) ? value : Value.NULL;
}
@Override
public Value slice(long from, Long to)
public Value slice(final long from, final Long to)
{
throw new InternalExpressionException("Cannot slice a map value");
}
@Override
public Value split(Value delimiter) {
throw new InternalExpressionException("Cannot split a map value");
public Value split(final Value delimiter)
{
throw new InternalExpressionException("Cannot split a map value");
}
@Override
public double readDoubleNumber()
{
return (double)map.size();
return map.size();
}
@Override
public Value get(Value v2)
public Value get(final Value v2)
{
return map.getOrDefault(v2, Value.NULL);
}
@Override
public boolean has(Value where)
public boolean has(final Value where)
{
return map.containsKey(where);
}
@Override
public boolean delete(Value where)
public boolean delete(final Value where)
{
Value ret = map.remove(where);
return ret != null;
return map.remove(where) != null;
}
@Override
public boolean put(Value key, Value value)
public boolean put(final Value key, final Value value)
{
Value ret = map.put(key, value);
return ret != null;
return map.put(key, value) != null;
}
@Override
@@ -259,12 +249,15 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
CompoundTag tag = new CompoundTag() ;
map.forEach( (k, v) ->
final CompoundTag tag = new CompoundTag();
map.forEach((k, v) ->
{
if (!force && !(k instanceof StringValue)) throw new NBTSerializableValue.IncompatibleTypeException(k);
if (!force && !(k instanceof StringValue))
{
throw new NBTSerializableValue.IncompatibleTypeException(k);
}
tag.put(k.getString(), v.toTag(force));
});
return tag;
@@ -273,10 +266,10 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
@Override
public JsonElement toJson()
{
JsonObject jsonMap = new JsonObject();
List<Value> keys = new ArrayList<>(map.keySet());
final JsonObject jsonMap = new JsonObject();
final List<Value> keys = new ArrayList<>(map.keySet());
Collections.sort(keys);
keys.forEach( k -> jsonMap.add(k.getString(), map.get(k).toJson()));
keys.forEach(k -> jsonMap.add(k.getString(), map.get(k).toJson()));
return jsonMap;
}
}
@@ -8,6 +8,7 @@ import carpet.script.exception.Throwables;
import carpet.script.utils.EquipmentInventory;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -17,6 +18,7 @@ import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.minecraft.commands.arguments.NbtPathArgument;
import net.minecraft.commands.arguments.item.ItemInput;
import net.minecraft.commands.arguments.item.ItemParser;
@@ -59,9 +61,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
private Supplier<Tag> nbtSupplier = null;
private boolean owned = false;
private NBTSerializableValue() {}
private NBTSerializableValue()
{
}
public NBTSerializableValue(String nbtString)
public NBTSerializableValue(final String nbtString)
{
nbtSupplier = () ->
{
@@ -69,64 +73,70 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
{
return (new TagParser(new StringReader(nbtString))).readValue();
}
catch (CommandSyntaxException e)
catch (final CommandSyntaxException e)
{
throw new InternalExpressionException("Incorrect NBT data: "+nbtString);
throw new InternalExpressionException("Incorrect NBT data: " + nbtString);
}
};
owned = true;
}
public NBTSerializableValue(Tag tag)
public NBTSerializableValue(final Tag tag)
{
nbtTag = tag;
owned = true;
}
public static Value of(Tag tag)
public static Value of(final Tag tag)
{
if (tag == null) return Value.NULL;
if (tag == null)
{
return Value.NULL;
}
return new NBTSerializableValue(tag);
}
public NBTSerializableValue(Supplier<Tag> tagSupplier)
public NBTSerializableValue(final Supplier<Tag> tagSupplier)
{
nbtSupplier = tagSupplier;
}
public static Value fromStack(ItemStack stack)
public static Value fromStack(final ItemStack stack)
{
if (stack.hasTag())
{
NBTSerializableValue value = new NBTSerializableValue();
final NBTSerializableValue value = new NBTSerializableValue();
value.nbtSupplier = stack::getTag;
return value;
}
return Value.NULL;
}
public static String nameFromRegistryId(ResourceLocation id)
public static String nameFromRegistryId(final ResourceLocation id)
{
if (id == null) // should be Value.NULL
{
return "";
if (id.getNamespace().equals("minecraft"))
return id.getPath();
return id.toString();
}
return id.getNamespace().equals("minecraft") ? id.getPath() : id.toString();
}
public static NBTSerializableValue parseString(String nbtString, boolean fail)
public static NBTSerializableValue parseString(final String nbtString, final boolean fail)
{
Tag tag;
final Tag tag;
try
{
tag = (new TagParser(new StringReader(nbtString))).readValue();
}
catch (CommandSyntaxException e)
catch (final CommandSyntaxException e)
{
if (fail) throw new InternalExpressionException("Incorrect NBT tag: "+ nbtString);
if (fail)
{
throw new InternalExpressionException("Incorrect NBT tag: " + nbtString);
}
return null;
}
NBTSerializableValue value = new NBTSerializableValue(tag);
final NBTSerializableValue value = new NBTSerializableValue(tag);
value.nbtString = null;
return value;
}
@@ -136,7 +146,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
public Value clone()
{
// sets only nbttag, even if emtpy;
NBTSerializableValue copy = new NBTSerializableValue(nbtTag);
final NBTSerializableValue copy = new NBTSerializableValue(nbtTag);
copy.nbtSupplier = this.nbtSupplier;
copy.nbtString = this.nbtString;
copy.owned = this.owned;
@@ -146,59 +156,67 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
@Override
public Value deepcopy()
{
NBTSerializableValue copy = (NBTSerializableValue) clone();
final NBTSerializableValue copy = (NBTSerializableValue) clone();
copy.owned = false;
ensureOwnership();
return copy;
}
@Override
public Value fromConstant() {
public Value fromConstant()
{
return deepcopy();
}
// stolen from HopperBlockEntity, adjusted for threaded operation
public static Container getInventoryAt(ServerLevel world, BlockPos blockPos)
public static Container getInventoryAt(final ServerLevel world, final BlockPos blockPos)
{
Container inventory = null;
BlockState blockState = world.getBlockState(blockPos);
Block block = blockState.getBlock();
if (block instanceof WorldlyContainerHolder) {
inventory = ((WorldlyContainerHolder)block).getContainer(blockState, world, blockPos);
} else if (blockState.hasBlockEntity()) {
BlockEntity blockEntity = BlockValue.getBlockEntity(world, blockPos);
if (blockEntity instanceof Container) {
inventory = (Container)blockEntity;
if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) {
inventory = ChestBlock.getContainer((ChestBlock)block, blockState, world, blockPos, true);
final BlockState blockState = world.getBlockState(blockPos);
final Block block = blockState.getBlock();
if (block instanceof final WorldlyContainerHolder containerHolder)
{
inventory = containerHolder.getContainer(blockState, world, blockPos);
}
else if (blockState.hasBlockEntity())
{
final BlockEntity blockEntity = BlockValue.getBlockEntity(world, blockPos);
if (blockEntity instanceof final Container inventoryHolder)
{
inventory = inventoryHolder;
if (inventory instanceof ChestBlockEntity && block instanceof final ChestBlock chestBlock)
{
inventory = ChestBlock.getContainer(chestBlock, blockState, world, blockPos, true);
}
}
}
if (inventory == null) {
List<Entity> list = world.getEntities(
(Entity)null, //TODO check this matches the correct method
if (inventory == null)
{
final List<Entity> list = world.getEntities(
(Entity) null, //TODO check this matches the correct method
new AABB(
blockPos.getX() - 0.5D, blockPos.getY() - 0.5D, blockPos.getZ() - 0.5D,
blockPos.getX() + 0.5D, blockPos.getY() + 0.5D, blockPos.getZ() + 0.5D),
EntitySelector.CONTAINER_ENTITY_SELECTOR
);
if (!list.isEmpty()) {
inventory = (Container)list.get(world.random.nextInt(list.size()));
if (!list.isEmpty())
{
inventory = (Container) list.get(world.random.nextInt(list.size()));
}
}
return inventory;
}
public static InventoryLocator locateInventory(CarpetContext c, List<Value> params, int offset)
public static InventoryLocator locateInventory(final CarpetContext c, final List<Value> params, int offset)
{
try
{
Value v1 = params.get(offset);
if (v1.isNull())
{
offset ++;
offset++;
v1 = params.get(offset);
}
else if (v1 instanceof StringValue)
@@ -206,23 +224,38 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
String strVal = v1.getString().toLowerCase(Locale.ROOT);
if (strVal.equals("enderchest"))
{
Value v2 = params.get(1 + offset);
ServerPlayer player = EntityValue.getPlayerByValue(c.server(), v2);
if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument");
final Value v2 = params.get(1 + offset);
final ServerPlayer player = EntityValue.getPlayerByValue(c.server(), v2);
if (player == null)
{
throw new InternalExpressionException("enderchest inventory requires player argument");
}
return new InventoryLocator(player, player.blockPosition(), player.getEnderChestInventory(), offset + 2, true);
}
if (strVal.equals("equipment"))
{
Value v2 = params.get(1 + offset);
if (!(v2 instanceof EntityValue)) throw new InternalExpressionException("Equipment inventory requires a living entity argument");
Entity e = ((EntityValue) v2).getEntity();
if (!(e instanceof LivingEntity)) throw new InternalExpressionException("Equipment inventory requires a living entity argument");
return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory((LivingEntity) e), offset + 2);
final Value v2 = params.get(1 + offset);
if (!(v2 instanceof final EntityValue ev))
{
throw new InternalExpressionException("Equipment inventory requires a living entity argument");
}
final Entity e = ev.getEntity();
if (!(e instanceof final LivingEntity le))
{
throw new InternalExpressionException("Equipment inventory requires a living entity argument");
}
return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory(le), offset + 2);
}
final boolean isEnder = strVal.startsWith("enderchest_");
if (isEnder)
{
strVal = strVal.substring(11); // len("enderchest_")
}
final ServerPlayer player = c.server().getPlayerList().getPlayerByName(strVal);
if (player == null)
{
throw new InternalExpressionException("String description of an inventory should either denote a player or player's enderchest");
}
boolean isEnder = strVal.startsWith("enderchest_");
if (isEnder) strVal = strVal.substring(11); // len("enderchest_")
ServerPlayer player = c.server().getPlayerList().getPlayerByName(strVal);
if (player == null) throw new InternalExpressionException("String description of an inventory should either denote a player or player's enderchest");
return new InventoryLocator(
player,
player.blockPosition(),
@@ -231,149 +264,150 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
isEnder
);
}
if (v1 instanceof EntityValue)
if (v1 instanceof final EntityValue ev)
{
Container inv = null;
Entity e = ((EntityValue) v1).getEntity();
if (e instanceof Player pe) inv = pe.getInventory();
else if (e instanceof Container) inv = (Container) e;
else if (e instanceof InventoryCarrier io) inv = io.getInventory();
else if (e instanceof InventoryBearerInterface ibi) inv = ibi.getCMInventory(); // horse only
else if (e instanceof LivingEntity le) return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory(le), offset+1);
if (inv == null)
return null;
final Entity e = ev.getEntity();
if (e instanceof final Player pe)
{
inv = pe.getInventory();
}
else if (e instanceof final Container container)
{
inv = container;
}
else if (e instanceof final InventoryCarrier io)
{
inv = io.getInventory();
}
else if (e instanceof final InventoryBearerInterface ibi)
{
inv = ibi.getCMInventory(); // horse only
}
else if (e instanceof final LivingEntity le)
{
return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory(le), offset + 1);
}
return inv == null ? null : new InventoryLocator(e, e.blockPosition(), inv, offset + 1);
return new InventoryLocator(e, e.blockPosition(), inv, offset+1);
}
if (v1 instanceof BlockValue)
if (v1 instanceof final BlockValue bv)
{
BlockPos pos = ((BlockValue) v1).getPos();
final BlockPos pos = bv.getPos();
if (pos == null)
{
throw new InternalExpressionException("Block to access inventory needs to be positioned in the world");
Container inv = getInventoryAt(c.level(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset+1);
}
final Container inv = getInventoryAt(c.level(), pos);
return inv == null ? null : new InventoryLocator(pos, pos, inv, offset + 1);
}
if (v1 instanceof ListValue)
if (v1 instanceof final ListValue lv)
{
List<Value> args = ((ListValue) v1).getItems();
BlockPos pos = new BlockPos(
final List<Value> args = lv.getItems();
final BlockPos pos = new BlockPos(
NumericValue.asNumber(args.get(0)).getDouble(),
NumericValue.asNumber(args.get(1)).getDouble(),
NumericValue.asNumber(args.get(2)).getDouble());
Container inv = getInventoryAt(c.level(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset+1);
final Container inv = getInventoryAt(c.level(), pos);
return inv == null ? null : new InventoryLocator(pos, pos, inv, offset + 1);
}
if (v1 instanceof ScreenValue screenValue)
if (v1 instanceof final ScreenValue screenValue)
{
if(!screenValue.isOpen()) return null;
return new InventoryLocator(screenValue.getPlayer(), screenValue.getPlayer().blockPosition(), screenValue.getInventory(), offset+1);
return !screenValue.isOpen() ? null : new InventoryLocator(screenValue.getPlayer(), screenValue.getPlayer().blockPosition(), screenValue.getInventory(), offset + 1);
}
BlockPos pos = new BlockPos(
final BlockPos pos = new BlockPos(
NumericValue.asNumber(v1).getDouble(),
NumericValue.asNumber(params.get(1 + offset)).getDouble(),
NumericValue.asNumber(params.get(2 + offset)).getDouble());
Container inv = getInventoryAt(c.level(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset + 3);
final Container inv = getInventoryAt(c.level(), pos);
return inv == null ? null : new InventoryLocator(pos, pos, inv, offset + 3);
}
catch (IndexOutOfBoundsException e)
catch (final IndexOutOfBoundsException e)
{
throw new InternalExpressionException("Inventory should be defined either by three coordinates, a block value, an entity, or a screen");
}
}
private static final Map<String,ItemInput> itemCache = new HashMap<>();
private static final Map<String, ItemInput> itemCache = new HashMap<>();
public static ItemInput parseItem(String itemString, RegistryAccess regs)
public static ItemInput parseItem(final String itemString, final RegistryAccess regs)
{
return parseItem(itemString, null, regs);
}
public static ItemInput parseItem(String itemString, CompoundTag customTag, RegistryAccess regs)
public static ItemInput parseItem(final String itemString, final CompoundTag customTag, final RegistryAccess regs)
{
try
{
ItemInput res = itemCache.get(itemString); // [SCARY SHIT] persistent caches over server reloads
if (res != null)
if (customTag == null)
return res;
else
return new ItemInput(Holder.direct(res.getItem()), customTag);
ItemParser.ItemResult parser = ItemParser.parseForItem(regs.lookupOrThrow(Registries.ITEM), new StringReader(itemString));
{
return customTag == null ? res : new ItemInput(Holder.direct(res.getItem()), customTag);
}
final ItemParser.ItemResult parser = ItemParser.parseForItem(regs.lookupOrThrow(Registries.ITEM), new StringReader(itemString));
res = new ItemInput(parser.item(), parser.nbt());
itemCache.put(itemString, res);
if (itemCache.size()>64000)
if (itemCache.size() > 64000)
{
itemCache.clear();
if (customTag == null)
return res;
else
return new ItemInput(Holder.direct(res.getItem()), customTag);
}
return customTag == null ? res : new ItemInput(Holder.direct(res.getItem()), customTag);
}
catch (CommandSyntaxException e)
catch (final CommandSyntaxException e)
{
throw new ThrowStatement(itemString, Throwables.UNKNOWN_ITEM);
}
}
public static int validateSlot(int slot, Container inv)
public static int validateSlot(int slot, final Container inv)
{
int invSize = inv.getContainerSize();
final int invSize = inv.getContainerSize();
if (slot < 0)
{
slot = invSize + slot;
if (slot < 0 || slot >= invSize)
return inv.getContainerSize(); // outside of inventory
return slot;
}
return slot < 0 || slot >= invSize ? inv.getContainerSize() : slot; // outside of inventory
}
private static Value decodeSimpleTag(Tag t)
private static Value decodeSimpleTag(final Tag t)
{
if (t instanceof NumericTag)
if (t instanceof final NumericTag number)
{
if (t instanceof LongTag || t instanceof IntTag) // short and byte will never exceed float's precision, even int won't
{
return NumericValue.of(((NumericTag) t).getAsLong());
}
return NumericValue.of(((NumericTag) t).getAsNumber());
// short and byte will never exceed float's precision, even int won't
return t instanceof LongTag || t instanceof IntTag ? NumericValue.of(number.getAsLong()) : NumericValue.of(number.getAsNumber());
}
if (t instanceof StringTag)
return StringValue.of(t.getAsString());
if (t instanceof EndTag)
return Value.NULL;
throw new InternalExpressionException("How did we get here: Unknown nbt element class: "+t.getType().getName());
}
private static Value decodeTag(Tag t)
{
if (t instanceof CompoundTag || t instanceof CollectionTag)
return new NBTSerializableValue(() -> t);
return decodeSimpleTag(t);
}
private static Value decodeTagDeep(Tag t)
{
if (t instanceof CompoundTag)
{
Map<Value, Value> pairs = new HashMap<>();
CompoundTag ctag = (CompoundTag)t;
for (String key: ctag.getAllKeys())
return StringValue.of(t.getAsString());
}
if (t instanceof EndTag)
{
return Value.NULL;
}
throw new InternalExpressionException("How did we get here: Unknown nbt element class: " + t.getType().getName());
}
private static Value decodeTag(final Tag t)
{
return t instanceof CompoundTag || t instanceof CollectionTag ? new NBTSerializableValue(() -> t) : decodeSimpleTag(t);
}
private static Value decodeTagDeep(final Tag t)
{
if (t instanceof final CompoundTag ctag)
{
final Map<Value, Value> pairs = new HashMap<>();
for (final String key : ctag.getAllKeys())
{
pairs.put(new StringValue(key), decodeTagDeep(ctag.get(key)));
}
return MapValue.wrap(pairs);
}
if (t instanceof CollectionTag)
if (t instanceof final CollectionTag<?> ltag)
{
List<Value> elems = new ArrayList<>();
CollectionTag<?> ltag = (CollectionTag<?>)t;
for (Tag elem: ltag)
final List<Value> elems = new ArrayList<>();
for (final Tag elem : ltag)
{
elems.add(decodeTagDeep(elem));
}
@@ -387,50 +421,64 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return decodeTagDeep(this.getTag());
}
public static Value fromValue(Value v)
public static Value fromValue(final Value v)
{
if (v instanceof NBTSerializableValue)
{
return v;
}
if (v.isNull())
{
return Value.NULL;
}
return NBTSerializableValue.parseString(v.getString(), true);
}
public Tag getTag()
{
if (nbtTag == null)
{
nbtTag = nbtSupplier.get();
}
return nbtTag;
}
@Override
public boolean equals(final Object o)
{
if (o instanceof NBTSerializableValue)
return getTag().equals(((NBTSerializableValue) o).getTag());
return super.equals(o);
return o instanceof final NBTSerializableValue nbtsv ? getTag().equals(nbtsv.getTag()) : super.equals(o);
}
@Override
public String getString()
{
if (nbtString == null)
{
nbtString = getTag().toString();
}
return nbtString;
}
@Override
public boolean getBoolean()
{
Tag tag = getTag();
if (tag instanceof CompoundTag)
return !((CompoundTag) tag).isEmpty();
if (tag instanceof CollectionTag)
return !((CollectionTag<?>) tag).isEmpty();
if (tag instanceof NumericTag)
return ((NumericTag) tag).getAsDouble()!=0.0;
final Tag tag = getTag();
if (tag instanceof final CompoundTag ctag)
{
return !(ctag).isEmpty();
}
if (tag instanceof final CollectionTag<?> ltag)
{
return !(ltag).isEmpty();
}
if (tag instanceof final NumericTag number)
{
return number.getAsDouble() != 0.0;
}
if (tag instanceof StringTag)
{
return !tag.getAsString().isEmpty();
}
return true;
}
@@ -441,86 +489,89 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
ensureOwnership();
return (CompoundTag) getTag();
}
catch (ClassCastException e)
catch (final ClassCastException e)
{
throw new InternalExpressionException(getString()+" is not a valid compound tag");
throw new InternalExpressionException(getString() + " is not a valid compound tag");
}
}
@Override
public boolean put(Value where, Value value)
public boolean put(final Value where, final Value value)
{
return put(where, value, new StringValue("replace"));
}
@Override
public boolean put(Value where, Value value, Value conditions)
public boolean put(final Value where, final Value value, final Value conditions)
{
/// WIP
ensureOwnership();
NbtPathArgument.NbtPath path = cachePath(where.getString());
Tag tagToInsert = value instanceof NBTSerializableValue ?
((NBTSerializableValue) value).getTag() :
new NBTSerializableValue(value.getString()).getTag();
boolean modifiedTag;
if (conditions instanceof NumericValue)
final NbtPathArgument.NbtPath path = cachePath(where.getString());
final Tag tagToInsert = value instanceof final NBTSerializableValue nbtsv
? nbtsv.getTag()
: new NBTSerializableValue(value.getString()).getTag();
final boolean modifiedTag;
if (conditions instanceof final NumericValue number)
{
modifiedTag = modify_insert((int)((NumericValue) conditions).getLong(), path, tagToInsert);
modifiedTag = modifyInsert((int) number.getLong(), path, tagToInsert);
}
else
{
String ops = conditions.getString();
final String ops = conditions.getString();
if (ops.equalsIgnoreCase("merge"))
{
modifiedTag = modify_merge(path, tagToInsert);
modifiedTag = modifyMerge(path, tagToInsert);
}
else if (ops.equalsIgnoreCase("replace"))
{
modifiedTag = modify_replace(path, tagToInsert);
modifiedTag = modifyReplace(path, tagToInsert);
}
else
{
return false;
}
}
if (modifiedTag) dirty();
if (modifiedTag)
{
dirty();
}
return modifiedTag;
}
private boolean modify_insert(int index, NbtPathArgument.NbtPath nbtPath, Tag newElement)
private boolean modifyInsert(final int index, final NbtPathArgument.NbtPath nbtPath, final Tag newElement)
{
return modify_insert(index, nbtPath, newElement, this.getTag());
return modifyInsert(index, nbtPath, newElement, this.getTag());
}
private boolean modify_insert(int index, NbtPathArgument.NbtPath nbtPath, Tag newElement, Tag currentTag)
private boolean modifyInsert(final int index, final NbtPathArgument.NbtPath nbtPath, final Tag newElement, final Tag currentTag)
{
Collection<Tag> targets;
final Collection<Tag> targets;
try
{
targets = nbtPath.getOrCreate(currentTag, ListTag::new);
}
catch (CommandSyntaxException e)
catch (final CommandSyntaxException e)
{
return false;
}
boolean modified = false;
for (Tag target : targets)
for (final Tag target : targets)
{
if (!(target instanceof CollectionTag))
if (!(target instanceof final CollectionTag<?> targetList))
{
continue;
}
try
{
CollectionTag<?> targetList = (CollectionTag<?>) target;
if (!targetList.addTag(index < 0 ? targetList.size() + index + 1 : index, newElement.copy()))
{
return false;
}
modified = true;
}
catch (IndexOutOfBoundsException ignored)
catch (final IndexOutOfBoundsException ignored)
{
}
}
@@ -528,68 +579,72 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
}
private boolean modify_merge(NbtPathArgument.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
private boolean modifyMerge(final NbtPathArgument.NbtPath nbtPath, final Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
{
if (!(replacement instanceof CompoundTag))
if (!(replacement instanceof final CompoundTag replacementCompound))
{
return false;
}
Tag ownTag = getTag();
final Tag ownTag = getTag();
try
{
for (Tag target : nbtPath.getOrCreate(ownTag, CompoundTag::new))
for (final Tag target : nbtPath.getOrCreate(ownTag, CompoundTag::new))
{
if (!(target instanceof CompoundTag))
if (!(target instanceof final CompoundTag targetCompound))
{
continue;
}
((CompoundTag) target).merge((CompoundTag) replacement);
targetCompound.merge(replacementCompound);
}
}
catch (CommandSyntaxException ignored)
catch (final CommandSyntaxException ignored)
{
return false;
}
return true;
}
private boolean modify_replace(NbtPathArgument.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
private boolean modifyReplace(final NbtPathArgument.NbtPath nbtPath, final Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
{
Tag tag = getTag();
String pathText = nbtPath.toString();
final Tag tag = getTag();
final String pathText = nbtPath.toString();
if (pathText.endsWith("]")) // workaround for array replacement or item in the array replacement
{
if (nbtPath.remove(tag)==0)
if (nbtPath.remove(tag) == 0)
{
return false;
Pattern pattern = Pattern.compile("\\[[^\\[]*]$");
Matcher matcher = pattern.matcher(pathText);
}
final Pattern pattern = Pattern.compile("\\[[^\\[]*]$");
final Matcher matcher = pattern.matcher(pathText);
if (!matcher.find()) // malformed path
{
return false;
}
String arrAccess = matcher.group();
int pos;
if (arrAccess.length()==2) // we just removed entire array
final String arrAccess = matcher.group();
final int pos;
if (arrAccess.length() == 2) // we just removed entire array
{
pos = 0;
}
else
{
try
{
pos = Integer.parseInt(arrAccess.substring(1, arrAccess.length() - 1));
}
catch (NumberFormatException e)
catch (final NumberFormatException e)
{
return false;
}
}
NbtPathArgument.NbtPath newPath = cachePath(pathText.substring(0, pathText.length()-arrAccess.length()));
return modify_insert(pos,newPath,replacement, tag);
final NbtPathArgument.NbtPath newPath = cachePath(pathText.substring(0, pathText.length() - arrAccess.length()));
return modifyInsert(pos, newPath, replacement, tag);
}
try
{
nbtPath.set(tag, replacement);
}
catch (CommandSyntaxException e)
catch (final CommandSyntaxException e)
{
return false;
}
@@ -597,25 +652,31 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
}
@Override
public Value get(Value value)
public Value get(final Value value)
{
String valString = value.getString();
NbtPathArgument.NbtPath path = cachePath(valString);
final String valString = value.getString();
final NbtPathArgument.NbtPath path = cachePath(valString);
try
{
List<Tag> tags = path.get(getTag());
if (tags.size()==0)
final List<Tag> tags = path.get(getTag());
if (tags.isEmpty())
{
return Value.NULL;
if (tags.size()==1 && !valString.endsWith("[]"))
}
if (tags.size() == 1 && !valString.endsWith("[]"))
{
return NBTSerializableValue.decodeTag(tags.get(0));
}
return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag));
}
catch (CommandSyntaxException ignored) { }
catch (final CommandSyntaxException ignored)
{
}
return Value.NULL;
}
@Override
public boolean has(Value where)
public boolean has(final Value where)
{
return cachePath(where.getString()).countMatching(getTag()) > 0;
}
@@ -637,11 +698,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
}
@Override
public boolean delete(Value where)
public boolean delete(final Value where)
{
NbtPathArgument.NbtPath path = cachePath(where.getString());
final NbtPathArgument.NbtPath path = cachePath(where.getString());
ensureOwnership();
int removed = path.remove(getTag());
final int removed = path.remove(getTag());
if (removed > 0)
{
dirty();
@@ -650,30 +711,36 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return false;
}
public static record InventoryLocator(Object owner, BlockPos position, Container inventory, int offset, boolean isEnder)
public record InventoryLocator(Object owner, BlockPos position, Container inventory, int offset,
boolean isEnder)
{
InventoryLocator(Object owner, BlockPos pos, Container i, int o)
InventoryLocator(final Object owner, final BlockPos pos, final Container i, final int o)
{
this(owner, pos, i, o, false);
}
}
private static Map<String, NbtPathArgument.NbtPath> pathCache = new HashMap<>();
private static NbtPathArgument.NbtPath cachePath(String arg)
private static final Map<String, NbtPathArgument.NbtPath> pathCache = new HashMap<>();
private static NbtPathArgument.NbtPath cachePath(final String arg)
{
NbtPathArgument.NbtPath res = pathCache.get(arg);
if (res != null)
{
return res;
}
try
{
res = NbtPathArgument.nbtPath().parse(new StringReader(arg));
}
catch (CommandSyntaxException exc)
catch (final CommandSyntaxException exc)
{
throw new InternalExpressionException("Incorrect nbt path: "+arg);
throw new InternalExpressionException("Incorrect nbt path: " + arg);
}
if (pathCache.size() > 1024)
{
pathCache.clear();
}
pathCache.put(arg, res);
return res;
}
@@ -686,9 +753,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
ensureOwnership();
return getTag();
}
@@ -696,9 +766,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
public static class IncompatibleTypeException extends RuntimeException
{
public final Value val;
public IncompatibleTypeException(Value val)
public IncompatibleTypeException(final Value val)
{
this.val = val;
}
};
}
}
@@ -1,6 +1,7 @@
package carpet.script.value;
import java.util.ArrayList;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import com.google.gson.JsonElement;
@@ -9,6 +10,7 @@ import com.google.gson.JsonNull;
public class NullValue extends NumericValue // TODO check nonsingleton code
{
public static final NullValue NULL = new NullValue();
@Override
public String getString()
{
@@ -32,41 +34,45 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
{
return new NullValue();
}
protected NullValue() {super(0);}
protected NullValue()
{
super(0);
}
@Override
public boolean equals(final Object o)
{
if (o instanceof Value value)
{
return value.isNull();
}
return false;
return o instanceof Value value && value.isNull();
}
@Override
public Value slice(long fromDesc, Long toDesc) {
public Value slice(final long fromDesc, final Long toDesc)
{
return Value.NULL;
}
@Override
public NumericValue opposite() {
public NumericValue opposite()
{
return Value.NULL;
}
@Override
public int length() {
public int length()
{
return 0;
}
@Override
public int compareTo(Value o)
public int compareTo(final Value o)
{
return o.isNull() ? 0 : -1;
return o.isNull() ? 0 : -1;
}
@Override
public Value in(Value value) {
public Value in(final Value value)
{
return Value.NULL;
}
@@ -83,15 +89,19 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return StringTag.valueOf("null");
}
@Override
public Value split(Value delimiter) {
return ListValue.wrap(new ArrayList<Value>());
public Value split(final Value delimiter)
{
return ListValue.wrap(new ArrayList<>());
}
@Override
@@ -101,7 +111,8 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
}
@Override
public boolean isNull() {
public boolean isNull()
{
return true;
}
}
@@ -9,6 +9,7 @@ import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Locale;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.LongTag;
@@ -21,28 +22,41 @@ public class NumericValue extends Value
{
private final double value;
private Long longValue;
private final static double epsilon = abs(32*((7*0.1)*10-7));
private final static MathContext displayRounding = new MathContext(12, RoundingMode.HALF_EVEN);
private static final double epsilon = abs(32 * ((7 * 0.1) * 10 - 7));
private static final MathContext displayRounding = new MathContext(12, RoundingMode.HALF_EVEN);
public static NumericValue asNumber(Value v1, String id)
public static NumericValue asNumber(final Value v1, final String id)
{
if (!(v1 instanceof NumericValue))
throw new InternalExpressionException("Argument "+id+" has to be of a numeric type");
return ((NumericValue) v1);
if (v1 instanceof final NumericValue nv)
{
return nv;
}
throw new InternalExpressionException("Argument " + id + " has to be of a numeric type");
}
public static NumericValue asNumber(Value v1)
public static NumericValue asNumber(final Value v1)
{
if (!(v1 instanceof NumericValue))
throw new InternalExpressionException("Operand has to be of a numeric type");
return ((NumericValue) v1);
if (v1 instanceof final NumericValue nv)
{
return nv;
}
throw new InternalExpressionException("Operand has to be of a numeric type");
}
public static <T extends Number> Value of(T value)
public static <T extends Number> Value of(final T value)
{
if (value == null) return Value.NULL;
if (value.doubleValue() == value.longValue()) return new NumericValue(value.longValue());
if (value instanceof Float) return new NumericValue(0.000_001D * Math.round(1_000_000.0D*value.doubleValue()));
if (value == null)
{
return Value.NULL;
}
if (value.doubleValue() == value.longValue())
{
return new NumericValue(value.longValue());
}
if (value instanceof Float)
{
return new NumericValue(0.000_001D * Math.round(1_000_000.0D * value.doubleValue()));
}
return new NumericValue(value.doubleValue());
}
@@ -56,30 +70,33 @@ public class NumericValue extends Value
}
try
{
if (Double.isInfinite(value)) return (value>0)?"INFINITY":"-INFINITY";
if (Double.isNaN(value)) return "NaN";
if (abs(value) < epsilon) return (signum(value) < 0)?"-0":"0"; //zero rounding fails with big decimals
if (Double.isInfinite(value))
{
return (value > 0) ? "INFINITY" : "-INFINITY";
}
if (Double.isNaN(value))
{
return "NaN";
}
if (abs(value) < epsilon)
{
return (signum(value) < 0) ? "-0" : "0"; //zero rounding fails with big decimals
}
// dobules have 16 point precision, 12 is plenty to display
return BigDecimal.valueOf(value).round(displayRounding).stripTrailingZeros().toPlainString();
}
catch (NumberFormatException exc)
catch (final NumberFormatException exc)
{
throw new InternalExpressionException("Incorrect number format for "+value);
throw new InternalExpressionException("Incorrect number format for " + value);
}
}
@Override
public String getPrettyString()
{
if (longValue!= null || getDouble() == (double)getLong())
{
return Long.toString(getLong());
}
else
{
return String.format(Locale.ROOT, "%.1f..", getDouble());
}
return longValue != null || getDouble() == getLong()
? Long.toString(getLong())
: String.format(Locale.ROOT, "%.1f..", getDouble());
}
@Override
@@ -87,80 +104,62 @@ public class NumericValue extends Value
{
return abs(value) > epsilon;
}
public double getDouble()
{
return value;
}
public float getFloat()
{
return (float) value;
}
private static long floor(double double_1) {
long int_1 = (long)double_1;
return double_1 < (double)int_1 ? int_1 - 1 : int_1;
private static long floor(final double v)
{
final long invValue = (long) v;
return v < invValue ? invValue - 1 : invValue;
}
public long getLong()
{
if (longValue != null) return longValue;
return floor((value+epsilon));
return longValue != null ? longValue : Long.valueOf(floor((value + epsilon)));
}
@Override
public Value add(Value v)
public Value add(final Value v)
{ // TODO test if definintn add(NumericVlaue) woud solve the casting
if (v instanceof NumericValue nv)
if (v instanceof final NumericValue nv)
{
if (longValue != null && nv.longValue != null)
{
return new NumericValue(longValue+nv.longValue);
}
return new NumericValue(value + nv.value);
return new NumericValue(longValue != null && nv.longValue != null ? (longValue + nv.longValue) : (value + nv.value));
}
return super.add(v);
}
@Override
public Value subtract(Value v) { // TODO test if definintn add(NumericVlaue) woud solve the casting
if (v instanceof NumericValue nv)
public Value subtract(final Value v)
{ // TODO test if definintn add(NumericVlaue) woud solve the casting
if (v instanceof final NumericValue nv)
{
if (longValue != null && nv.longValue != null)
{
return new NumericValue(longValue-nv.longValue);
}
return new NumericValue(value - nv.value);
return new NumericValue(longValue != null && nv.longValue != null ? (longValue - nv.longValue) : (value - nv.value));
}
return super.subtract(v);
}
@Override
public Value multiply(Value v)
public Value multiply(final Value v)
{
if (v instanceof NumericValue nv)
if (v instanceof final NumericValue nv)
{
if (longValue != null && nv.longValue != null)
{
return new NumericValue(longValue*nv.longValue);
}
return new NumericValue(value * nv.value);
return new NumericValue(longValue != null && nv.longValue != null ? (longValue * nv.longValue) : (value * nv.value));
}
if (v instanceof ListValue)
{
return v.multiply(this);
}
return new StringValue(StringUtils.repeat(v.getString(), (int) getLong()));
return v instanceof ListValue ? v.multiply(this) : new StringValue(StringUtils.repeat(v.getString(), (int) getLong()));
}
@Override
public Value divide(Value v)
public Value divide(final Value v)
{
//if (1+2==3) throw new ArithmeticException("Booyah");
if (v instanceof NumericValue)
{
return new NumericValue(getDouble() / ((NumericValue) v).getDouble() );
}
return super.divide(v);
return v instanceof final NumericValue nv ? new NumericValue(getDouble() / nv.getDouble()) : super.divide(v);
}
@Override
@@ -170,64 +169,68 @@ public class NumericValue extends Value
}
@Override
public int compareTo(Value o)
public int compareTo(final Value o)
{
if (o.isNull())
{
return -o.compareTo(this);
}
if (o instanceof NumericValue no)
if (o instanceof final NumericValue no)
{
if (longValue != null && no.longValue != null)
return longValue.compareTo(no.longValue);
return Double.compare(value, no.value);
return longValue != null && no.longValue != null ? longValue.compareTo(no.longValue) : Double.compare(value, no.value);
}
return getString().compareTo(o.getString());
}
@Override
public boolean equals(Object o)
public boolean equals(final Object o)
{
if (o instanceof Value value) {
if (value.isNull()) {
if (o instanceof final Value otherValue)
{
if (otherValue.isNull())
{
return o.equals(this);
}
if (o instanceof NumericValue no) {
if (longValue != null && no.longValue != null)
return longValue.equals(no.longValue);
return !this.subtract(no).getBoolean();
if (o instanceof final NumericValue no)
{
return longValue != null && no.longValue != null ? longValue.equals(no.longValue) : !this.subtract(no).getBoolean();
}
return super.equals(o);
}
return false;
}
public NumericValue(double value)
public NumericValue(final double value)
{
this.value = value;
}
private NumericValue(double value, Long longValue)
private NumericValue(final double value, final Long longValue)
{
this.value = value;
this.longValue = longValue;
}
public NumericValue(String value)
public NumericValue(final String value)
{
BigDecimal decimal = new BigDecimal(value);
final BigDecimal decimal = new BigDecimal(value);
if (decimal.stripTrailingZeros().scale() <= 0)
{
try
{
longValue = decimal.longValueExact();
}
catch (ArithmeticException ignored) {}
catch (final ArithmeticException ignored)
{
}
}
this.value = decimal.doubleValue();
}
public NumericValue(long value)
public NumericValue(final long value)
{
this.longValue = value;
this.value = (double)value;
this.value = (double) value;
}
@Override
@@ -257,31 +260,34 @@ public class NumericValue extends Value
@Override
public int hashCode()
{
if (longValue!= null || Math.abs(Math.floor(value + 0.5D)-value) < epsilon) // is sufficiently close to the integer value
return Long.hashCode(getLong());
return Double.hashCode(value);
// is sufficiently close to the integer value
return longValue != null || Math.abs(Math.floor(value + 0.5D) - value) < epsilon ? Long.hashCode(getLong()) : Double.hashCode(value);
}
public int getInt()
{
return (int)getLong();
return (int) getLong();
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (longValue != null)
{
if (abs(longValue) < Integer.MAX_VALUE-2)
return IntTag.valueOf((int)(long)longValue);
if (abs(longValue) < Integer.MAX_VALUE - 2)
{
return IntTag.valueOf((int) (long) longValue);
}
return LongTag.valueOf(longValue);
}
long lv = getLong();
if (value == (double)lv)
final long lv = getLong();
if (value == (double) lv)
{
if (abs(value) < Integer.MAX_VALUE-2)
return IntTag.valueOf((int)lv);
if (abs(value) < Integer.MAX_VALUE - 2)
{
return IntTag.valueOf((int) lv);
}
return LongTag.valueOf(getLong());
}
else
@@ -294,35 +300,35 @@ public class NumericValue extends Value
public JsonElement toJson()
{
if (longValue != null)
{
return new JsonPrimitive(longValue);
long lv = getLong();
if (value == (double)lv)
{
return new JsonPrimitive(getLong());
}
else
{
return new JsonPrimitive(value);
}
final long lv = getLong();
return new JsonPrimitive(value == lv ? getLong() : value);
}
public NumericValue opposite() {
if (longValue != null) return new NumericValue(-longValue);
return new NumericValue(-value);
public NumericValue opposite()
{
return new NumericValue(longValue != null ? -longValue : -value);
}
public boolean isInteger()
{
return longValue!= null || getDouble() == (double)getLong();
return longValue != null || getDouble() == getLong();
}
public Value mod(NumericValue n2)
public Value mod(final NumericValue n2)
{
if (this.longValue != null && n2.longValue != null)
{
return new NumericValue(Math.floorMod(longValue, n2.longValue));
double x = value;
double y = n2.value;
if (y == 0) throw new ArithmeticException("Division by zero");
return new NumericValue( x - Math.floor(x / y) * y);
}
final double x = value;
final double y = n2.value;
if (y == 0)
{
throw new ArithmeticException("Division by zero");
}
return new NumericValue(x - Math.floor(x / y) * y);
}
}
+244 -176
View File
@@ -12,11 +12,13 @@ import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.InvalidCallbackException;
import carpet.script.exception.ThrowStatement;
import carpet.script.exception.Throwables;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
@@ -29,37 +31,14 @@ import net.minecraft.world.SimpleContainer;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.AbstractFurnaceMenu;
import net.minecraft.world.inventory.AnvilMenu;
import net.minecraft.world.inventory.BeaconMenu;
import net.minecraft.world.inventory.BlastFurnaceMenu;
import net.minecraft.world.inventory.BrewingStandMenu;
import net.minecraft.world.inventory.CartographyTableMenu;
import net.minecraft.world.inventory.ChestMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.ContainerListener;
import net.minecraft.world.inventory.CraftingMenu;
import net.minecraft.world.inventory.DataSlot;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.inventory.FurnaceMenu;
import net.minecraft.world.inventory.GrindstoneMenu;
import net.minecraft.world.inventory.HopperMenu;
import net.minecraft.world.inventory.LecternMenu;
import net.minecraft.world.inventory.LoomMenu;
import net.minecraft.world.inventory.MerchantMenu;
import net.minecraft.world.inventory.ShulkerBoxMenu;
import net.minecraft.world.inventory.SimpleContainerData;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.inventory.SmithingMenu;
import net.minecraft.world.inventory.SmokerMenu;
import net.minecraft.world.inventory.StonecutterMenu;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import static net.minecraft.world.inventory.MenuType.*;
public class ScreenValue extends Value {
public class ScreenValue extends Value
{
private AbstractContainerMenu screenHandler;
private ScreenHandlerInventory inventory;
@@ -69,83 +48,96 @@ public class ScreenValue extends Value {
private final String hostname;
private final ServerPlayer player;
public static Map<String,ScarpetScreenHandlerFactory> screenHandlerFactories;
public static Map<String, ScarpetScreenHandlerFactory> screenHandlerFactories;
static
{
screenHandlerFactories = new HashMap<>();
screenHandlerFactories.put("anvil",(syncId, playerInventory) -> new AnvilMenu(syncId,playerInventory));
screenHandlerFactories.put("beacon",(syncId, playerInventory) -> new BeaconMenu(syncId,playerInventory));
screenHandlerFactories.put("blast_furnace",(syncId, playerInventory) -> new BlastFurnaceMenu(syncId,playerInventory));
screenHandlerFactories.put("brewing_stand",(syncId, playerInventory) -> new BrewingStandMenu(syncId,playerInventory,new SimpleContainer(5),new SimpleContainerData(2)));
screenHandlerFactories.put("cartography_table",(syncId, playerInventory) -> new CartographyTableMenu(syncId,playerInventory));
screenHandlerFactories.put("crafting",(syncId, playerInventory) -> new CraftingMenu(syncId,playerInventory));
screenHandlerFactories.put("enchantment",(syncId, playerInventory) -> new EnchantmentMenu(syncId,playerInventory));
screenHandlerFactories.put("furnace",(syncId, playerInventory) -> new FurnaceMenu(syncId,playerInventory));
screenHandlerFactories.put("generic_3x3",((syncId, playerInventory) -> new ChestMenu(GENERIC_3x3,syncId,playerInventory,new SimpleContainer(9),1)));
screenHandlerFactories.put("generic_9x1",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x1,syncId,playerInventory,new SimpleContainer(9),1)));
screenHandlerFactories.put("generic_9x2",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x2,syncId,playerInventory,new SimpleContainer(9*2),2)));
screenHandlerFactories.put("generic_9x3",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x3,syncId,playerInventory,new SimpleContainer(9*3),3)));
screenHandlerFactories.put("generic_9x4",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x4,syncId,playerInventory,new SimpleContainer(9*4),4)));
screenHandlerFactories.put("generic_9x5",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x5,syncId,playerInventory,new SimpleContainer(9*5),5)));
screenHandlerFactories.put("generic_9x6",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x6,syncId,playerInventory,new SimpleContainer(9*6),6)));
screenHandlerFactories.put("grindstone",(syncId, playerInventory) -> new GrindstoneMenu(syncId,playerInventory));
screenHandlerFactories.put("hopper",(syncId, playerInventory) -> new HopperMenu(syncId,playerInventory));
screenHandlerFactories.put("lectern",(syncId, playerInventory) -> new LecternMenu(syncId,new SimpleContainer(1),new SimpleContainerData(1)));
screenHandlerFactories.put("loom",(syncId, playerInventory) -> new LoomMenu(syncId,playerInventory));
screenHandlerFactories.put("merchant",(syncId, playerInventory) -> new MerchantMenu(syncId,playerInventory));
screenHandlerFactories.put("shulker_box",(syncId, playerInventory) -> new ShulkerBoxMenu(syncId,playerInventory,new SimpleContainer(9*3)));
screenHandlerFactories.put("smithing",(syncId, playerInventory) -> new SmithingMenu(syncId,playerInventory));
screenHandlerFactories.put("smoker",(syncId, playerInventory) -> new SmokerMenu(syncId,playerInventory));
screenHandlerFactories.put("stonecutter",(syncId, playerInventory) -> new StonecutterMenu(syncId,playerInventory));
screenHandlerFactories.put("anvil", AnvilMenu::new);
screenHandlerFactories.put("beacon", BeaconMenu::new);
screenHandlerFactories.put("blast_furnace", BlastFurnaceMenu::new);
screenHandlerFactories.put("brewing_stand", (syncId, playerInventory) -> new BrewingStandMenu(syncId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)));
screenHandlerFactories.put("cartography_table", CartographyTableMenu::new);
screenHandlerFactories.put("crafting", CraftingMenu::new);
screenHandlerFactories.put("enchantment", EnchantmentMenu::new);
screenHandlerFactories.put("furnace", FurnaceMenu::new);
screenHandlerFactories.put("generic_3x3", ((syncId, playerInventory) -> new ChestMenu(GENERIC_3x3, syncId, playerInventory, new SimpleContainer(9), 1)));
screenHandlerFactories.put("generic_9x1", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x1, syncId, playerInventory, new SimpleContainer(9), 1)));
screenHandlerFactories.put("generic_9x2", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x2, syncId, playerInventory, new SimpleContainer(9 * 2), 2)));
screenHandlerFactories.put("generic_9x3", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x3, syncId, playerInventory, new SimpleContainer(9 * 3), 3)));
screenHandlerFactories.put("generic_9x4", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x4, syncId, playerInventory, new SimpleContainer(9 * 4), 4)));
screenHandlerFactories.put("generic_9x5", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x5, syncId, playerInventory, new SimpleContainer(9 * 5), 5)));
screenHandlerFactories.put("generic_9x6", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x6, syncId, playerInventory, new SimpleContainer(9 * 6), 6)));
screenHandlerFactories.put("grindstone", GrindstoneMenu::new);
screenHandlerFactories.put("hopper", HopperMenu::new);
screenHandlerFactories.put("lectern", (syncId, playerInventory) -> new LecternMenu(syncId, new SimpleContainer(1), new SimpleContainerData(1)));
screenHandlerFactories.put("loom", LoomMenu::new);
screenHandlerFactories.put("merchant", MerchantMenu::new);
screenHandlerFactories.put("shulker_box", (syncId, playerInventory) -> new ShulkerBoxMenu(syncId, playerInventory, new SimpleContainer(9 * 3)));
screenHandlerFactories.put("smithing_legacy", LegacySmithingMenu::new);
screenHandlerFactories.put("smithing", SmithingMenu::new);
screenHandlerFactories.put("smoker", SmokerMenu::new);
screenHandlerFactories.put("stonecutter", StonecutterMenu::new);
}
protected interface ScarpetScreenHandlerFactory {
protected interface ScarpetScreenHandlerFactory
{
AbstractContainerMenu create(int syncId, Inventory playerInventory);
}
public ScreenValue(ServerPlayer player, String type, Component name, FunctionValue callback, Context c) {
public ScreenValue(final ServerPlayer player, final String type, final Component name, final FunctionValue callback, final Context c)
{
this.name = name;
this.typestring = type.toLowerCase();
if(callback != null) callback.checkArgs(4);
if (callback != null)
{
callback.checkArgs(4);
}
this.callback = callback;
this.hostname = c.host.getName();
this.player = player;
MenuProvider factory = this.createScreenHandlerFactory();
if(factory == null) throw new ThrowStatement(type, Throwables.UNKNOWN_SCREEN);
final MenuProvider factory = this.createScreenHandlerFactory();
if (factory == null)
{
throw new ThrowStatement(type, Throwables.UNKNOWN_SCREEN);
}
this.openScreen(factory);
this.inventory = new ScreenHandlerInventory(this.screenHandler);
}
private MenuProvider createScreenHandlerFactory() {
if(!screenHandlerFactories.containsKey(this.typestring)) {
private MenuProvider createScreenHandlerFactory()
{
if (!screenHandlerFactories.containsKey(this.typestring))
{
return null;
}
return new SimpleMenuProvider((i, playerInventory, playerEntity) -> {
AbstractContainerMenu screen = screenHandlerFactories.get(ScreenValue.this.typestring).create(i,playerInventory);
final AbstractContainerMenu screen = screenHandlerFactories.get(ScreenValue.this.typestring).create(i, playerInventory);
ScreenValue.this.addListenerCallback(screen);
ScreenValue.this.screenHandler = screen;
return screen;
}, this.name);
}
private void openScreen(MenuProvider factory) {
if(this.player == null) return;
OptionalInt optionalSyncId = this.player.openMenu(factory);
if(optionalSyncId.isPresent() && this.player.containerMenu.containerId == optionalSyncId.getAsInt()) {
private void openScreen(final MenuProvider factory)
{
if (this.player == null)
{
return;
}
final OptionalInt optionalSyncId = this.player.openMenu(factory);
if (optionalSyncId.isPresent() && this.player.containerMenu.containerId == optionalSyncId.getAsInt())
{
this.screenHandler = this.player.containerMenu;
}
}
public void close() {
if(this.player.containerMenu != this.player.inventoryMenu) {
public void close()
{
if (this.player.containerMenu != this.player.inventoryMenu)
{
//prevent recursion when closing screen in closing screen callback by doing this before triggering event
this.inventory = null;
this.player.containerMenu = this.player.inventoryMenu;
@@ -154,11 +146,14 @@ public class ScreenValue extends Value {
}
}
public boolean isOpen() {
if(this.screenHandler == null) {
public boolean isOpen()
{
if (this.screenHandler == null)
{
return false;
}
if(this.player.containerMenu.containerId == this.screenHandler.containerId) {
if (this.player.containerMenu.containerId == this.screenHandler.containerId)
{
return true;
}
this.screenHandler = null;
@@ -166,104 +161,124 @@ public class ScreenValue extends Value {
}
private boolean callListener(ServerPlayer player, String action, Map<Value,Value> data) {
Value playerValue = EntityValue.of(player);
Value actionValue = StringValue.of(action);
Value dataValue = MapValue.wrap(data);
List<Value> args = Arrays.asList(this,playerValue,actionValue,dataValue);
CarpetScriptHost appHost = CarpetServer.scriptServer.getAppHostByName(this.hostname);
if(appHost == null) {
private boolean callListener(final ServerPlayer player, final String action, final Map<Value, Value> data)
{
final Value playerValue = EntityValue.of(player);
final Value actionValue = StringValue.of(action);
final Value dataValue = MapValue.wrap(data);
final List<Value> args = Arrays.asList(this, playerValue, actionValue, dataValue);
final CarpetScriptHost appHost = CarpetServer.scriptServer.getAppHostByName(this.hostname);
if (appHost == null)
{
this.close();
this.screenHandler = null;
return false;
}
CommandSourceStack source = player.createCommandSourceStack().withPermission(CarpetSettings.runPermissionLevel);
CarpetScriptHost executingHost = appHost.retrieveForExecution(source,player);
final CommandSourceStack source = player.createCommandSourceStack().withPermission(CarpetSettings.runPermissionLevel);
final CarpetScriptHost executingHost = appHost.retrieveForExecution(source, player);
try
{
Value cancelValue = executingHost.callUDF(source.withPermission(CarpetSettings.runPermissionLevel), callback, args);
final Value cancelValue = executingHost.callUDF(source.withPermission(CarpetSettings.runPermissionLevel), callback, args);
return cancelValue.getString().equals("cancel");
}
catch (NullPointerException | InvalidCallbackException | IntegrityException error)
catch (final NullPointerException | InvalidCallbackException | IntegrityException error)
{
CarpetScriptServer.LOG.error("Got exception when running screen event call ", error);
return false;
}
}
private void addListenerCallback(AbstractContainerMenu screenHandler) {
if(this.callback == null) return;
private void addListenerCallback(final AbstractContainerMenu screenHandler)
{
if (this.callback == null)
{
return;
}
screenHandler.addSlotListener(new ScarpetScreenHandlerListener() {
screenHandler.addSlotListener(new ScarpetScreenHandlerListener()
{
@Override
public boolean onSlotClick(ServerPlayer player, ClickType actionType, int slot, int button) {
Map<Value,Value> data = new HashMap<>();
data.put(StringValue.of("slot"),slot == AbstractContainerMenu.SLOT_CLICKED_OUTSIDE ? Value.NULL : NumericValue.of(slot));
if(actionType == ClickType.QUICK_CRAFT) {
data.put(StringValue.of("quick_craft_stage"),NumericValue.of(AbstractContainerMenu.getQuickcraftHeader(button)));
public boolean onSlotClick(final ServerPlayer player, final ClickType actionType, final int slot, int button)
{
final Map<Value, Value> data = new HashMap<>();
data.put(StringValue.of("slot"), slot == AbstractContainerMenu.SLOT_CLICKED_OUTSIDE ? Value.NULL : NumericValue.of(slot));
if (actionType == ClickType.QUICK_CRAFT)
{
data.put(StringValue.of("quick_craft_stage"), NumericValue.of(AbstractContainerMenu.getQuickcraftHeader(button)));
button = AbstractContainerMenu.getQuickcraftType(button);
}
data.put(StringValue.of("button"),NumericValue.of(button));
return ScreenValue.this.callListener(player,actionTypeToString(actionType),data);
data.put(StringValue.of("button"), NumericValue.of(button));
return ScreenValue.this.callListener(player, actionTypeToString(actionType), data);
}
@Override
public boolean onButtonClick(ServerPlayer player, int button) {
Map<Value,Value> data = new HashMap<>();
data.put(StringValue.of("button"),NumericValue.of(button));
return ScreenValue.this.callListener(player,"button",data);
public boolean onButtonClick(final ServerPlayer player, final int button)
{
final Map<Value, Value> data = new HashMap<>();
data.put(StringValue.of("button"), NumericValue.of(button));
return ScreenValue.this.callListener(player, "button", data);
}
@Override
public void onClose(ServerPlayer player) {
Map<Value,Value> data = new HashMap<>();
ScreenValue.this.callListener(player,"close",data);
public void onClose(final ServerPlayer player)
{
final Map<Value, Value> data = new HashMap<>();
ScreenValue.this.callListener(player, "close", data);
}
@Override
public boolean onSelectRecipe(ServerPlayer player, Recipe<?> recipe, boolean craftAll) {
Map<Value,Value> data = new HashMap<>();
data.put(StringValue.of("recipe"),StringValue.of(recipe.getId().toString()));
data.put(StringValue.of("craft_all"),BooleanValue.of(craftAll));
return ScreenValue.this.callListener(player,"select_recipe",data);
public boolean onSelectRecipe(final ServerPlayer player, final Recipe<?> recipe, final boolean craftAll)
{
final Map<Value, Value> data = new HashMap<>();
data.put(StringValue.of("recipe"), StringValue.of(recipe.getId().toString()));
data.put(StringValue.of("craft_all"), BooleanValue.of(craftAll));
return ScreenValue.this.callListener(player, "select_recipe", data);
}
@Override
public void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack stack) {
Map<Value,Value> data = new HashMap<>();
data.put(StringValue.of("slot"),NumericValue.of(slotId));
data.put(StringValue.of("stack"),ValueConversions.of(stack, player.level.registryAccess()));
ScreenValue.this.callListener(ScreenValue.this.player,"slot_update",data);
public void slotChanged(final AbstractContainerMenu handler, final int slotId, final ItemStack stack)
{
final Map<Value, Value> data = new HashMap<>();
data.put(StringValue.of("slot"), NumericValue.of(slotId));
data.put(StringValue.of("stack"), ValueConversions.of(stack, player.level.registryAccess()));
ScreenValue.this.callListener(ScreenValue.this.player, "slot_update", data);
}
@Override
public void dataChanged(AbstractContainerMenu handler, int property, int value) {}
public void dataChanged(final AbstractContainerMenu handler, final int property, final int value)
{
}
});
}
private DataSlot getPropertyForType(Class<? extends AbstractContainerMenu> screenHandlerClass, String requiredType, int propertyIndex, String propertyName) {
if(screenHandlerClass.isInstance(this.screenHandler)) {
private DataSlot getPropertyForType(final Class<? extends AbstractContainerMenu> screenHandlerClass, final String requiredType, final int propertyIndex, final String propertyName)
{
if (screenHandlerClass.isInstance(this.screenHandler))
{
return ((ScreenHandlerInterface) this.screenHandler).getProperty(propertyIndex);
}
if(!this.isOpen()) {
if (!this.isOpen())
{
throw new InternalExpressionException("Screen property cannot be accessed, because the screen is already closed");
}
throw new InternalExpressionException("Screen property " + propertyName + " expected a " + requiredType + " screen.");
}
private DataSlot getProperty(String propertyName) {
return switch (propertyName) {
private DataSlot getProperty(final String propertyName)
{
return switch (propertyName)
{
case "fuel_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 0, propertyName);
case "max_fuel_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 1, propertyName);
case "cook_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 2, propertyName);
case "max_cook_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 3, propertyName);
case "level_cost" -> getPropertyForType(AnvilMenu.class, "anvil", 0, propertyName);
case "page" -> getPropertyForType(LecternMenu.class, "lectern", 0, propertyName);
case "beacon_level" -> getPropertyForType(BeaconMenu.class, "beacon", 0, propertyName);
case "primary_effect" -> getPropertyForType(BeaconMenu.class, "beacon", 1, propertyName);
case "secondary_effect" -> getPropertyForType(BeaconMenu.class, "beacon", 2, propertyName);
case "brew_time" -> getPropertyForType(BrewingStandMenu.class, "brewing_stand", 0, propertyName);
case "brewing_fuel" -> getPropertyForType(BrewingStandMenu.class, "brewing_stand", 1, propertyName);
case "enchantment_power_1" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 0, propertyName);
case "enchantment_power_2" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 1, propertyName);
case "enchantment_power_3" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 2, propertyName);
@@ -274,50 +289,55 @@ public class ScreenValue extends Value {
case "enchantment_level_1" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 7, propertyName);
case "enchantment_level_2" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 8, propertyName);
case "enchantment_level_3" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 9, propertyName);
case "banner_pattern" -> getPropertyForType(LoomMenu.class, "loom", 0, propertyName);
case "stonecutter_recipe" -> getPropertyForType(StonecutterMenu.class, "stonecutter", 0, propertyName);
default -> throw new InternalExpressionException("Invalid screen property: " + propertyName);
};
}
public Value queryProperty(String propertyName) {
if(propertyName.equals("name")) return FormattedTextValue.of(this.name);
if(propertyName.equals("open")) return BooleanValue.of(this.isOpen());
DataSlot property = getProperty(propertyName);
public Value queryProperty(final String propertyName)
{
if (propertyName.equals("name"))
{
return FormattedTextValue.of(this.name);
}
if (propertyName.equals("open"))
{
return BooleanValue.of(this.isOpen());
}
final DataSlot property = getProperty(propertyName);
return NumericValue.of(property.get());
}
public Value modifyProperty(String propertyName, List<Value> lv) {
DataSlot property = getProperty(propertyName);
int intValue = NumericValue.asNumber(lv.get(0)).getInt();
public Value modifyProperty(final String propertyName, final List<Value> lv)
{
final DataSlot property = getProperty(propertyName);
final int intValue = NumericValue.asNumber(lv.get(0)).getInt();
property.set(intValue);
this.screenHandler.sendAllDataToRemote();
return Value.TRUE;
}
public AbstractContainerMenu getScreenHandler() {
return this.screenHandler;
}
public ServerPlayer getPlayer() {
public ServerPlayer getPlayer()
{
return this.player;
}
public Container getInventory() {
public Container getInventory()
{
return this.inventory;
}
@Override
public String getString() {
public String getString()
{
return this.typestring + "_screen";
}
@Override
public boolean getBoolean() {
public boolean getBoolean()
{
return this.isOpen();
}
@@ -328,92 +348,134 @@ public class ScreenValue extends Value {
}
@Override
public Tag toTag(boolean force) {
if(this.screenHandler == null) {
public Tag toTag(final boolean force)
{
if (this.screenHandler == null)
{
return Value.NULL.toTag(true);
}
ListTag nbtList = new ListTag();
for(int i = 0; i < this.screenHandler.slots.size(); i++) {
ItemStack itemStack = this.screenHandler.getSlot(i).getItem();
final ListTag nbtList = new ListTag();
for (int i = 0; i < this.screenHandler.slots.size(); i++)
{
final ItemStack itemStack = this.screenHandler.getSlot(i).getItem();
nbtList.add(itemStack.save(new CompoundTag()));
}
return nbtList;
}
public interface ScarpetScreenHandlerListener extends ContainerListener {
public interface ScarpetScreenHandlerListener extends ContainerListener
{
boolean onSlotClick(ServerPlayer player, ClickType actionType, int slot, int button);
boolean onButtonClick(ServerPlayer player, int button);
void onClose(ServerPlayer player);
boolean onSelectRecipe(ServerPlayer player, Recipe<?> recipe, boolean craftAll);
}
public static class ScreenHandlerInventory implements Container {
public static class ScreenHandlerInventory implements Container
{
protected AbstractContainerMenu screenHandler;
public ScreenHandlerInventory(AbstractContainerMenu screenHandler) {
public ScreenHandlerInventory(final AbstractContainerMenu screenHandler)
{
this.screenHandler = screenHandler;
}
@Override
public int getContainerSize() {
public int getContainerSize()
{
return this.screenHandler.slots.size() + 1;
}
@Override
public boolean isEmpty() {
for(Slot slot : this.screenHandler.slots) {
if(slot.hasItem() && !slot.getItem().isEmpty()) return false;
public boolean isEmpty()
{
for (final Slot slot : this.screenHandler.slots)
{
if (slot.hasItem() && !slot.getItem().isEmpty())
{
return false;
}
}
return this.screenHandler.getCarried().isEmpty();
}
@Override
public ItemStack getItem(int slot) {
if(slot == this.getContainerSize()-1) return this.screenHandler.getCarried();
public ItemStack getItem(final int slot)
{
if (slot == this.getContainerSize() - 1)
{
return this.screenHandler.getCarried();
}
return slot >= -1 && slot < this.getContainerSize() ? this.screenHandler.slots.get(slot).getItem() : ItemStack.EMPTY;
}
@Override
public ItemStack removeItem(int slot, int amount) {
ItemStack itemStack;
if(slot == this.getContainerSize()-1)
public ItemStack removeItem(final int slot, final int amount)
{
final ItemStack itemStack;
if (slot == this.getContainerSize() - 1)
{
itemStack = this.screenHandler.getCarried().split(amount);
}
else
{
itemStack = ScreenHandlerInventory.splitStack(this.screenHandler.slots, slot, amount);
if (!itemStack.isEmpty()) {
}
if (!itemStack.isEmpty())
{
this.setChanged();
}
return itemStack;
}
@Override
public ItemStack removeItemNoUpdate(int slot) {
ItemStack itemStack;
if(slot == this.getContainerSize()-1)
public ItemStack removeItemNoUpdate(final int slot)
{
final ItemStack itemStack;
if (slot == this.getContainerSize() - 1)
{
itemStack = this.screenHandler.getCarried();
}
else
{
itemStack = this.screenHandler.slots.get(slot).getItem();
if (itemStack.isEmpty()) {
}
if (itemStack.isEmpty())
{
return ItemStack.EMPTY;
} else {
if(slot == this.getContainerSize()-1)
}
else
{
if (slot == this.getContainerSize() - 1)
{
this.screenHandler.setCarried(ItemStack.EMPTY);
}
else
{
this.screenHandler.slots.get(slot).set(ItemStack.EMPTY);
}
return itemStack;
}
}
@Override
public void setItem(int slot, ItemStack stack) {
if(slot == this.getContainerSize()-1)
public void setItem(final int slot, final ItemStack stack)
{
if (slot == this.getContainerSize() - 1)
{
this.screenHandler.setCarried(stack);
}
else
{
this.screenHandler.slots.get(slot).set(stack);
if (!stack.isEmpty() && stack.getCount() > this.getMaxStackSize()) {
}
if (!stack.isEmpty() && stack.getCount() > this.getMaxStackSize())
{
stack.setCount(this.getMaxStackSize());
}
@@ -421,18 +483,21 @@ public class ScreenValue extends Value {
}
@Override
public void setChanged() {
public void setChanged()
{
}
@Override
public boolean stillValid(Player player) {
public boolean stillValid(final Player player)
{
return true;
}
@Override
public void clearContent() {
for(Slot slot : this.screenHandler.slots) {
public void clearContent()
{
for (final Slot slot : this.screenHandler.slots)
{
slot.set(ItemStack.EMPTY);
}
this.screenHandler.setCarried(ItemStack.EMPTY);
@@ -440,13 +505,16 @@ public class ScreenValue extends Value {
}
public static ItemStack splitStack(List<Slot> slots, int slot, int amount) {
public static ItemStack splitStack(final List<Slot> slots, final int slot, final int amount)
{
return slot >= 0 && slot < slots.size() && !slots.get(slot).getItem().isEmpty() && amount > 0 ? slots.get(slot).getItem().split(amount) : ItemStack.EMPTY;
}
}
private static String actionTypeToString(ClickType actionType) {
return switch (actionType) {
private static String actionTypeToString(final ClickType actionType)
{
return switch (actionType)
{
case PICKUP -> "pickup";
case QUICK_MOVE -> "quick_move";
case SWAP -> "swap";
@@ -7,15 +7,17 @@ public class StringValue extends Value
{
public static Value EMPTY = StringValue.of("");
private String str;
private final String str;
@Override
public String getString() {
public String getString()
{
return str;
}
@Override
public boolean getBoolean() {
public boolean getBoolean()
{
return str != null && !str.isEmpty();
}
@@ -25,15 +27,14 @@ public class StringValue extends Value
return new StringValue(str);
}
public StringValue(String str)
public StringValue(final String str)
{
this.str = str;
}
public static Value of(String value)
public static Value of(final String value)
{
if (value == null) return Value.NULL;
return new StringValue(value);
return value == null ? Value.NULL : new StringValue(value);
}
@Override
@@ -43,7 +44,7 @@ public class StringValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
return StringTag.valueOf(str);
}
@@ -6,10 +6,12 @@ import carpet.script.Tokenizer;
import carpet.script.exception.ExitStatement;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import net.minecraft.nbt.Tag;
public class ThreadValue extends Value
@@ -18,21 +20,21 @@ public class ThreadValue extends Value
private final long id;
private static long sequence = 0L;
public ThreadValue(CompletableFuture<Value> taskFuture)
public ThreadValue(final CompletableFuture<Value> taskFuture)
{
this.taskFuture = taskFuture;
this.id = sequence++;
}
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
public ThreadValue(final Value pool, final FunctionValue function, final Expression expr, final Tokenizer.Token token, final Context ctx, final List<Value> args)
{
this(getCompletableFutureFromFunction(pool, function, expr, token, ctx, args));
Thread.yield();
}
public static CompletableFuture<Value> getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
public static CompletableFuture<Value> getCompletableFutureFromFunction(final Value pool, final FunctionValue function, final Expression expr, final Tokenizer.Token token, final Context ctx, final List<Value> args)
{
ExecutorService executor = ctx.host.getExecutor(pool);
final ExecutorService executor = ctx.host.getExecutor(pool);
if (executor == null)
{
// app is shutting down - no more threads can be spawned.
@@ -40,27 +42,22 @@ public class ThreadValue extends Value
}
else
{
return CompletableFuture.supplyAsync(
() ->
{
try
{
return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx);
}
catch (ExitStatement exit)
{
// app stopped
return exit.retval;
}
catch (ExpressionException exc)
{
ctx.host.handleExpressionException("Thread failed\n", exc);
return Value.NULL;
}
},
ctx.host.getExecutor(pool)
);
return CompletableFuture.supplyAsync(() -> {
try
{
return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx);
}
catch (final ExitStatement exit)
{
// app stopped
return exit.retval;
}
catch (final ExpressionException exc)
{
ctx.host.handleExpressionException("Thread failed\n", exc);
return Value.NULL;
}
}, ctx.host.getExecutor(pool));
}
}
@@ -87,12 +84,12 @@ public class ThreadValue extends Value
{
return taskFuture.get();
}
catch (ExitStatement exit)
catch (final ExitStatement exit)
{
taskFuture.complete(exit.retval);
return exit.retval;
}
catch (InterruptedException | ExecutionException e)
catch (final InterruptedException | ExecutionException e)
{
return Value.NULL;
}
@@ -104,19 +101,19 @@ public class ThreadValue extends Value
}
@Override
public boolean equals(Object o)
public boolean equals(final Object o)
{
if (!(o instanceof ThreadValue))
return false;
return ((ThreadValue) o).id == this.id;
return o instanceof final ThreadValue tv && tv.id == this.id;
}
@Override
public int compareTo(Value o)
public int compareTo(final Value o)
{
if (!(o instanceof ThreadValue))
if (!(o instanceof final ThreadValue tv))
{
throw new InternalExpressionException("Cannot compare tasks to other types");
return (int) (this.id - ((ThreadValue) o).id);
}
return (int) (this.id - tv.id);
}
@Override
@@ -126,9 +123,12 @@ public class ThreadValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return getValue().toTag(true);
}
@@ -4,14 +4,15 @@ import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import net.minecraft.nbt.Tag;
public class UndefValue extends NullValue {
public class UndefValue extends NullValue
{
public static final UndefValue UNDEF = new UndefValue();
private RuntimeException getError() {
return new InternalExpressionException("variable "+boundVariable+" was used before initialization under 'strict' app config");
private RuntimeException getError()
{
return new InternalExpressionException("variable " + boundVariable + " was used before initialization under 'strict' app config");
}
@Override
public String getString()
{
@@ -43,28 +44,32 @@ public class UndefValue extends NullValue {
}
@Override
public Value slice(long fromDesc, Long toDesc) {
throw getError();
}
@Override
public NumericValue opposite() {
throw getError();
}
@Override
public int length() {
throw getError();
}
@Override
public int compareTo(Value o)
public Value slice(final long fromDesc, final Long toDesc)
{
throw getError();
}
@Override
public Value in(Value value) {
public NumericValue opposite()
{
throw getError();
}
@Override
public int length()
{
throw getError();
}
@Override
public int compareTo(final Value o)
{
throw getError();
}
@Override
public Value in(final Value value)
{
throw getError();
}
@@ -81,13 +86,14 @@ public class UndefValue extends NullValue {
}
@Override
public Tag toTag(boolean force)
public Tag toTag(final boolean force)
{
throw getError();
}
@Override
public Value split(Value delimiter) {
public Value split(final Value delimiter)
{
throw getError();
}
@@ -98,29 +104,31 @@ public class UndefValue extends NullValue {
}
@Override
public boolean isNull() {
throw getError();
}
@Override
public Value add(Value v) {
throw getError();
}
@Override
public Value subtract(Value v)
public boolean isNull()
{
throw getError();
}
@Override
public Value multiply(Value v)
public Value add(final Value v)
{
throw getError();
}
@Override
public Value divide(Value v)
public Value subtract(final Value v)
{
throw getError();
}
@Override
public Value multiply(final Value v)
{
throw getError();
}
@Override
public Value divide(final Value v)
{
throw getError();
}
+96 -69
View File
@@ -4,23 +4,25 @@ import carpet.CarpetSettings;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import net.minecraft.nbt.Tag;
public abstract class Value implements Comparable<Value>, Cloneable
{
public static NumericValue FALSE = BooleanValue.FALSE;
public static NumericValue TRUE = BooleanValue.TRUE;
public static NumericValue ZERO = new NumericValue(0);
public static NumericValue ONE = new NumericValue(1);
public static final NumericValue FALSE = BooleanValue.FALSE;
public static final NumericValue TRUE = BooleanValue.TRUE;
public static final NumericValue ZERO = new NumericValue(0);
public static final NumericValue ONE = new NumericValue(1);
public static NullValue NULL = NullValue.NULL;
public static UndefValue UNDEF = UndefValue.UNDEF;
public static final NullValue NULL = NullValue.NULL;
public static final UndefValue UNDEF = UndefValue.UNDEF;
public String boundVariable;
@@ -28,29 +30,32 @@ public abstract class Value implements Comparable<Value>, Cloneable
{
return boundVariable != null;
}
public String getVariable()
{
return boundVariable;
}
public Value reboundedTo(String var)
public Value reboundedTo(final String value)
{
Value copy;
final Value copy;
try
{
copy = (Value)clone();
copy = (Value) clone();
}
catch (CloneNotSupportedException e)
catch (final CloneNotSupportedException e)
{
// should not happen
CarpetSettings.LOG.error("Failed to clone variable", e);
throw new InternalExpressionException("Variable of type "+getTypeString()+" is not cloneable. Tell gnembon about it, this shoudn't happen");
throw new InternalExpressionException("Variable of type " + getTypeString() + " is not cloneable. Tell gnembon about it, this shoudn't happen");
}
copy.boundVariable = var;
copy.boundVariable = value;
return copy;
}
public Value bindTo(String var)
public Value bindTo(final String value)
{
this.boundVariable = var;
this.boundVariable = value;
return this;
}
@@ -64,35 +69,37 @@ public abstract class Value implements Comparable<Value>, Cloneable
public abstract boolean getBoolean();
public Value add(Value o) {
public Value add(final Value o)
{
if (o instanceof FormattedTextValue)
{
return FormattedTextValue.combine(this, o);
}
String leftStr = this.getString();
String rightStr = o.getString();
final String leftStr = this.getString();
final String rightStr = o.getString();
return new StringValue(leftStr + rightStr);
}
public Value subtract(Value v)
public Value subtract(final Value v)
{
return new StringValue(this.getString().replace(v.getString(),""));
return new StringValue(this.getString().replace(v.getString(), ""));
}
public Value multiply(Value v)
public Value multiply(final Value v)
{
if (v instanceof NumericValue || v instanceof ListValue)
{
return v.multiply(this);
}
return new StringValue(this.getString()+"."+v.getString());
return v instanceof NumericValue || v instanceof ListValue
? v.multiply(this)
: new StringValue(this.getString() + "." + v.getString());
}
public Value divide(Value v)
public Value divide(final Value v)
{
if (v instanceof NumericValue)
if (v instanceof final NumericValue number)
{
String lstr = getString();
return new StringValue(lstr.substring(0, (int)(lstr.length()/ ((NumericValue) v).getDouble())));
final String lstr = getString();
return new StringValue(lstr.substring(0, (int) (lstr.length() / number.getDouble())));
}
return new StringValue(getString()+"/"+v.getString());
return new StringValue(getString() + "/" + v.getString());
}
public Value()
@@ -103,18 +110,18 @@ public abstract class Value implements Comparable<Value>, Cloneable
@Override
public int compareTo(final Value o)
{
if (o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue)
{
return -o.compareTo(this);
}
return getString().compareTo(o.getString());
return o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue
? -o.compareTo(this)
: getString().compareTo(o.getString());
}
@Override // for hashmap key access, and == operator
public boolean equals(final Object o)
{
if (o instanceof Value)
return this.compareTo((Value) o)==0;
if (o instanceof final Value v)
{
return this.compareTo(v) == 0;
}
return false;
}
@@ -126,50 +133,65 @@ public abstract class Value implements Comparable<Value>, Cloneable
{
throw new InternalExpressionException(boundVariable+ " cannot be assigned a new value");
}*/
throw new InternalExpressionException(getString()+ " is not a variable");
throw new InternalExpressionException(getString() + " is not a variable");
}
}
public Value in(Value value1)
public Value in(final Value value1)
{
final Pattern p;
try
{
p = Pattern.compile(value1.getString());
}
catch (PatternSyntaxException pse)
catch (final PatternSyntaxException pse)
{
throw new InternalExpressionException("Incorrect matching pattern: "+pse.getMessage());
throw new InternalExpressionException("Incorrect matching pattern: " + pse.getMessage());
}
final Matcher m = p.matcher(this.getString());
if (!m.find()) return Value.NULL;
int gc = m.groupCount();
if (gc == 0) return new StringValue(m.group());
if (gc == 1) return StringValue.of(m.group(1));
List<Value> groups = new ArrayList<>(gc);
if (!m.find())
{
return Value.NULL;
}
final int gc = m.groupCount();
if (gc == 0)
{
return new StringValue(m.group());
}
if (gc == 1)
{
return StringValue.of(m.group(1));
}
final List<Value> groups = new ArrayList<>(gc);
for (int i = 1; i <= gc; i++)
{
groups.add(StringValue.of(m.group(i)));
}
return ListValue.wrap(groups);
}
public int length()
{
return getString().length();
}
public Value slice(long fromDesc, Long toDesc)
public Value slice(final long fromDesc, final Long toDesc)
{
String value = this.getString();
int size = value.length();
int from = ListValue.normalizeIndex(fromDesc, size);
if (toDesc == null) return new StringValue(value.substring(from));
int to = ListValue.normalizeIndex(toDesc, size+1);
if (from > to) return StringValue.EMPTY;
final String value = this.getString();
final int size = value.length();
final int from = ListValue.normalizeIndex(fromDesc, size);
if (toDesc == null)
{
return new StringValue(value.substring(from));
}
final int to = ListValue.normalizeIndex(toDesc, size + 1);
if (from > to)
{
return StringValue.EMPTY;
}
return new StringValue(value.substring(from, to));
}
public Value split(Value delimiter)
{
if (delimiter == null)
@@ -180,20 +202,20 @@ public abstract class Value implements Comparable<Value>, Cloneable
{
return ListValue.wrap(Arrays.stream(getString().split(delimiter.getString())).map(StringValue::new));
}
catch (PatternSyntaxException pse)
catch (final PatternSyntaxException pse)
{
throw new InternalExpressionException("Incorrect pattern for 'split': "+pse.getMessage());
throw new InternalExpressionException("Incorrect pattern for 'split': " + pse.getMessage());
}
}
public double readDoubleNumber()
{
String s = getString();
final String s = getString();
try
{
return Double.valueOf(s);
return Double.parseDouble(s);
}
catch (NumberFormatException e)
catch (final NumberFormatException e)
{
return Double.NaN;
}
@@ -212,21 +234,20 @@ public abstract class Value implements Comparable<Value>, Cloneable
@Override
public int hashCode()
{
String stringVal = getString();
if (stringVal.isEmpty()) return 0;
return ("s"+stringVal).hashCode();
final String stringVal = getString();
return stringVal.isEmpty() ? 0 : ("s" + stringVal).hashCode();
}
public Value deepcopy()
{
try
{
return (Value)this.clone();
return (Value) this.clone();
}
catch (CloneNotSupportedException e)
catch (final CloneNotSupportedException e)
{
// should never happen
throw new InternalExpressionException("Cannot make a copy of value: "+this);
throw new InternalExpressionException("Cannot make a copy of value: " + this);
}
}
@@ -237,12 +258,18 @@ public abstract class Value implements Comparable<Value>, Cloneable
return new JsonPrimitive(getString());
}
public boolean isNull() { return false; }
public boolean isNull()
{
return false;
}
/**
* @return retrieves useful in-run value of an optimized code-base value.
* For immutable values (most of them) it can return itself,
* but for mutables, it needs to be its copy or deep copy.
*/
public Value fromConstant() { return this; }
public Value fromConstant()
{
return this;
}
}
@@ -46,6 +46,7 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -60,58 +61,65 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
public class ValueConversions
{
public static Value of(BlockPos pos)
public static Value of(final BlockPos pos)
{
return ListValue.of(new NumericValue(pos.getX()), new NumericValue(pos.getY()), new NumericValue(pos.getZ()));
}
public static Value of(Vec3 vec)
public static Value of(final Vec3 vec)
{
return ListValue.of(new NumericValue(vec.x), new NumericValue(vec.y), new NumericValue(vec.z));
}
public static Value of(ColumnPos cpos) { return ListValue.of(new NumericValue(cpos.x()), new NumericValue(cpos.z()));}
public static Value of(final ColumnPos cpos)
{
return ListValue.of(new NumericValue(cpos.x()), new NumericValue(cpos.z()));
}
public static Value of(ServerLevel world)
public static Value of(final ServerLevel world)
{
return of(world.dimension().location());
}
public static Value of(MaterialColor color) {return ListValue.of(StringValue.of(BlockInfo.mapColourName.get(color)), ofRGB(color.col));}
public static Value of(final MaterialColor color)
{
return ListValue.of(StringValue.of(BlockInfo.mapColourName.get(color)), ofRGB(color.col));
}
public static <T extends Number> Value of(MinMaxBounds<T> range) { return ListValue.of(NumericValue.of(range.getMin()), NumericValue.of(range.getMax()));}
public static <T extends Number> Value of(final MinMaxBounds<T> range)
{
return ListValue.of(NumericValue.of(range.getMin()), NumericValue.of(range.getMax()));
}
@Deprecated
public static Value of(ItemStack stack)
public static Value of(final ItemStack stack)
{
if (stack == null || stack.isEmpty())
return Value.NULL;
return ListValue.of(
return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of(
of(BuiltInRegistries.ITEM.getKey(stack.getItem())),
new NumericValue(stack.getCount()),
NBTSerializableValue.fromStack(stack)
);
}
public static Value of(ItemStack stack, RegistryAccess regs) {
if (stack == null || stack.isEmpty())
return Value.NULL;
return ListValue.of(
public static Value of(final ItemStack stack, final RegistryAccess regs)
{
return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of(
of(regs.registryOrThrow(Registries.ITEM).getKey(stack.getItem())),
new NumericValue(stack.getCount()),
NBTSerializableValue.fromStack(stack)
);
}
public static Value of(Objective objective)
public static Value of(final Objective objective)
{
return ListValue.of(
StringValue.of(objective.getName()),
StringValue.of(objective.getCriteria().getName())
);
);
}
public static Value of(ObjectiveCriteria criteria)
public static Value of(final ObjectiveCriteria criteria)
{
return ListValue.of(
StringValue.of(criteria.getName()),
@@ -120,20 +128,22 @@ public class ValueConversions
}
public static Value of(ParticleOptions particle)
public static Value of(final ParticleOptions particle)
{
String repr = particle.writeToString();
if (repr.startsWith("minecraft:")) return StringValue.of(repr.substring(10));
return StringValue.of(repr);
final String repr = particle.writeToString();
return StringValue.of(repr.startsWith("minecraft:") ? repr.substring(10) : repr);
}
public static Value ofRGB(int value) {return new NumericValue(value*256+255 );}
public static Value ofRGB(final int value)
{
return new NumericValue(value * 256 + 255);
}
public static Level dimFromValue(Value dimensionValue, MinecraftServer server)
public static Level dimFromValue(final Value dimensionValue, final MinecraftServer server)
{
if (dimensionValue instanceof EntityValue)
{
return ((EntityValue)dimensionValue).getEntity().getCommandSenderWorld();
return ((EntityValue) dimensionValue).getEntity().getCommandSenderWorld();
}
else if (dimensionValue instanceof BlockValue bv)
{
@@ -148,23 +158,16 @@ public class ValueConversions
}
else
{
String dimString = dimensionValue.getString().toLowerCase(Locale.ROOT);
switch (dimString)
{
case "nether":
case "the_nether":
return server.getLevel(Level.NETHER);
case "end":
case "the_end":
return server.getLevel(Level.END);
case "overworld":
case "over_world":
return server.getLevel(Level.OVERWORLD);
default:
final String dimString = dimensionValue.getString().toLowerCase(Locale.ROOT);
return switch (dimString) {
case "nether", "the_nether" -> server.getLevel(Level.NETHER);
case "end", "the_end" -> server.getLevel(Level.END);
case "overworld", "over_world" -> server.getLevel(Level.OVERWORLD);
default -> {
ResourceKey<Level> dim = null;
ResourceLocation id = new ResourceLocation(dimString);
final ResourceLocation id = new ResourceLocation(dimString);
// not using RegistryKey.of since that one creates on check
for (ResourceKey<Level> world : (server.levelKeys()))
for (final ResourceKey<Level> world : (server.levelKeys()))
{
if (id.equals(world.location()))
{
@@ -173,36 +176,48 @@ public class ValueConversions
}
}
if (dim == null)
{
throw new ThrowStatement(dimString, Throwables.UNKNOWN_DIMENSION);
return server.getLevel(dim);
}
}
yield server.getLevel(dim);
}
};
}
}
public static Value of(ResourceKey<?> dim)
public static Value of(final ResourceKey<?> dim)
{
return of(dim.location());
}
public static Value of(TagKey<?> tagKey) { return of(tagKey.location()); }
public static Value of(final TagKey<?> tagKey)
{
return of(tagKey.location());
}
public static Value of(ResourceLocation id)
public static Value of(final ResourceLocation id)
{
if (id == null) // should be Value.NULL
{
return Value.NULL;
}
return new StringValue(simplify(id));
}
public static String simplify(ResourceLocation id)
public static String simplify(final ResourceLocation id)
{
if (id == null) // should be Value.NULL
{
return "";
}
if (id.getNamespace().equals("minecraft"))
{
return id.getPath();
}
return id.toString();
}
public static Value of(GlobalPos pos)
public static Value of(final GlobalPos pos)
{
return ListValue.of(
ValueConversions.of(pos.dimension()),
@@ -210,14 +225,13 @@ public class ValueConversions
);
}
public static Value fromPath(ServerLevel world, Path path)
public static Value fromPath(final ServerLevel world, final Path path)
{
List<Value> nodes = new ArrayList<>();
//for (PathNode node: path.getNodes())
final List<Value> nodes = new ArrayList<>();
for (int i = 0, len = path.getNodeCount(); i < len; i++)
{
Node node = path.getNode(i);
nodes.add( ListValue.of(
final Node node = path.getNode(i);
nodes.add(ListValue.of(
new BlockValue(null, world, node.asBlockPos()),
new StringValue(node.type.name().toLowerCase(Locale.ROOT)),
new NumericValue(node.costMalus),
@@ -227,101 +241,106 @@ public class ValueConversions
return ListValue.wrap(nodes);
}
public static Value fromTimedMemory(Entity e, long expiry, Object v)
public static Value fromTimedMemory(final Entity e, final long expiry, final Object v)
{
Value ret = fromEntityMemory(e, v);
if (ret.isNull() || expiry == Long.MAX_VALUE) return ret;
return ListValue.of(ret, new NumericValue(expiry));
final Value ret = fromEntityMemory(e, v);
return ret.isNull() || expiry == Long.MAX_VALUE ? ret : ListValue.of(ret, new NumericValue(expiry));
}
private static Value fromEntityMemory(Entity e, Object v)
private static Value fromEntityMemory(final Entity e, Object v)
{
if (v instanceof GlobalPos pos)
{
return of(pos);
}
if (v instanceof Entity)
if (v instanceof final Entity entity)
{
return new EntityValue((Entity)v);
return new EntityValue(entity);
}
if (v instanceof BlockPos)
if (v instanceof final BlockPos pos)
{
return new BlockValue(null, (ServerLevel) e.getCommandSenderWorld(), (BlockPos) v);
return new BlockValue(null, e.getCommandSenderWorld(), pos);
}
if (v instanceof Number)
if (v instanceof final Number number)
{
return new NumericValue(((Number) v).doubleValue());
return new NumericValue(number.doubleValue());
}
if (v instanceof Boolean)
if (v instanceof final Boolean bool)
{
return BooleanValue.of((Boolean) v);
return BooleanValue.of(bool);
}
if (v instanceof UUID)
if (v instanceof final UUID uuid)
{
return ofUUID( (ServerLevel) e.getCommandSenderWorld(), (UUID)v);
return ofUUID((ServerLevel) e.getCommandSenderWorld(), uuid);
}
if (v instanceof DamageSource source)
if (v instanceof final DamageSource source)
{
return ListValue.of(
new StringValue(source.getMsgId()),
source.getEntity()==null?Value.NULL:new EntityValue(source.getEntity())
source.getEntity() == null ? Value.NULL : new EntityValue(source.getEntity())
);
}
if (v instanceof Path)
if (v instanceof final Path path)
{
return fromPath((ServerLevel)e.getCommandSenderWorld(), (Path)v);
return fromPath((ServerLevel) e.getCommandSenderWorld(), path);
}
if (v instanceof PositionTracker)
if (v instanceof final PositionTracker tracker)
{
return new BlockValue(null, e.getCommandSenderWorld(), ((PositionTracker)v).currentBlockPosition());
return new BlockValue(null, e.getCommandSenderWorld(), tracker.currentBlockPosition());
}
if (v instanceof WalkTarget)
if (v instanceof final WalkTarget target)
{
return ListValue.of(
new BlockValue(null, e.getCommandSenderWorld(), ((WalkTarget)v).getTarget().currentBlockPosition()),
new NumericValue(((WalkTarget) v).getSpeedModifier()),
new NumericValue(((WalkTarget) v).getCloseEnoughDist())
new BlockValue(null, e.getCommandSenderWorld(), target.getTarget().currentBlockPosition()),
new NumericValue(target.getSpeedModifier()),
new NumericValue(target.getCloseEnoughDist())
);
}
if (v instanceof NearestVisibleLivingEntities nvle) {
if (v instanceof final NearestVisibleLivingEntities nvle)
{
v = StreamSupport.stream(nvle.findAll(entity -> true).spliterator(), false).toList();
}
if (v instanceof Set)
if (v instanceof final Set<?> set)
{
v = new ArrayList<>(((Set<?>) v));
v = new ArrayList<>(set);
}
if (v instanceof List<?> l)
if (v instanceof final List<?> l)
{
if (l.isEmpty()) return ListValue.of();
Object el = l.get(0);
if (el instanceof Entity)
if (l.isEmpty())
{
return ListValue.wrap(l.stream().map(o -> new EntityValue((Entity)o)));
return ListValue.of();
}
if (el instanceof GlobalPos)
final Object el = l.get(0);
if (el instanceof final Entity entity)
{
return ListValue.wrap(l.stream().map(o -> of((GlobalPos) o)));
return ListValue.wrap(l.stream().map(o -> new EntityValue(entity)));
}
if (el instanceof final GlobalPos pos)
{
return ListValue.wrap(l.stream().map(o -> of(pos)));
}
}
return Value.NULL;
}
private static Value ofUUID(ServerLevel entityWorld, UUID uuid)
private static Value ofUUID(final ServerLevel entityWorld, final UUID uuid)
{
Entity current = entityWorld.getEntity(uuid);
final Entity current = entityWorld.getEntity(uuid);
return ListValue.of(
current == null?Value.NULL:new EntityValue(current),
current == null ? Value.NULL : new EntityValue(current),
new StringValue(uuid.toString())
);
}
public static Value of(AABB box)
public static Value of(final AABB box)
{
return ListValue.of(
ListValue.fromTriple(box.minX, box.minY, box.minZ),
ListValue.fromTriple(box.maxX, box.maxY, box.maxZ)
);
}
public static Value of(BoundingBox box)
public static Value of(final BoundingBox box)
{
return ListValue.of(
ListValue.fromTriple(box.minX(), box.minY(), box.minZ()),
@@ -329,17 +348,23 @@ public class ValueConversions
);
}
public static Value of(StructureStart structure, final RegistryAccess regs)
public static Value of(final StructureStart structure, final RegistryAccess regs)
{
if (structure == null || structure == StructureStart.INVALID_START) return Value.NULL;
BoundingBox boundingBox = structure.getBoundingBox();
if (boundingBox.maxX() < boundingBox.minX() || boundingBox.maxY() < boundingBox.minY() || boundingBox.maxZ() < boundingBox.minZ()) return Value.NULL;
Map<Value, Value> ret = new HashMap<>();
ret.put(new StringValue("box"), of(boundingBox));
List<Value> pieces = new ArrayList<>();
for (StructurePiece piece : structure.getPieces())
if (structure == null || structure == StructureStart.INVALID_START)
{
BoundingBox box = piece.getBoundingBox();
return Value.NULL;
}
final BoundingBox boundingBox = structure.getBoundingBox();
if (boundingBox.maxX() < boundingBox.minX() || boundingBox.maxY() < boundingBox.minY() || boundingBox.maxZ() < boundingBox.minZ())
{
return Value.NULL;
}
final Map<Value, Value> ret = new HashMap<>();
ret.put(new StringValue("box"), of(boundingBox));
final List<Value> pieces = new ArrayList<>();
for (final StructurePiece piece : structure.getPieces())
{
final BoundingBox box = piece.getBoundingBox();
if (box.maxX() >= box.minX() && box.maxY() >= box.minY() && box.maxZ() >= box.minZ())
{
pieces.add(ListValue.of(
@@ -354,41 +379,51 @@ public class ValueConversions
return MapValue.wrap(ret);
}
public static Value fromProperty(BlockState state, Property<?> p)
public static Value fromProperty(final BlockState state, final Property<?> p)
{
Comparable<?> object = state.getValue(p);
if (object instanceof Boolean || object instanceof Number) return StringValue.of(object.toString());
if (object instanceof StringRepresentable)
final Comparable<?> object = state.getValue(p);
if (object instanceof Boolean || object instanceof Number)
{
return StringValue.of(((StringRepresentable) object).getSerializedName());
return StringValue.of(object.toString());
}
throw new InternalExpressionException("Unknown property type: "+p.getName());
if (object instanceof final StringRepresentable stringRepresentable)
{
return StringValue.of(stringRepresentable.getSerializedName());
}
throw new InternalExpressionException("Unknown property type: " + p.getName());
}
record SlotParam(/* Nullable */ String type, int id) {
public ListValue build() {
record SlotParam(/* Nullable */ String type, int id)
{
public ListValue build()
{
return ListValue.of(StringValue.of(type), new NumericValue(id));
}
}
private static final Int2ObjectMap<SlotParam> slotIdsToSlotParams = new Int2ObjectOpenHashMap<>() {{
private static final Int2ObjectMap<SlotParam> slotIdsToSlotParams = new Int2ObjectOpenHashMap<>()
{{
int n;
//covers blocks, player hotbar and inventory, and all default inventories
for(n = 0; n < 54; ++n) {
for (n = 0; n < 54; ++n)
{
put(n, new SlotParam(null, n));
}
for(n = 0; n < 27; ++n) {
for (n = 0; n < 27; ++n)
{
put(200 + n, new SlotParam("enderchest", n));
}
// villager
for(n = 0; n < 8; ++n) {
for (n = 0; n < 8; ++n)
{
put(300 + n, new SlotParam(null, n));
}
// horse, llamas, donkeys, etc.
// two first slots are for saddle and armour
for(n = 0; n < 15; ++n) {
for (n = 0; n < 15; ++n)
{
put(500 + n, new SlotParam(null, n + 2));
}
// weapon main hand
@@ -396,7 +431,8 @@ public class ValueConversions
// offhand
put(99, new SlotParam("equipment", 5));
// feet, legs, chest, head
for(n = 0; n < 4; ++n) {
for (n = 0; n < 4; ++n)
{
put(100 + n, new SlotParam("equipment", n + 1));
}
//horse defaults saddle
@@ -407,26 +443,25 @@ public class ValueConversions
//hashMap.put("horse.chest", 499);
}};
public static Value ofVanillaSlotResult(int itemSlot)
public static Value ofVanillaSlotResult(final int itemSlot)
{
SlotParam ret = slotIdsToSlotParams.get(itemSlot);
if (ret == null) return ListValue.of(Value.NULL, new NumericValue(itemSlot));
return ret.build();
final SlotParam ret = slotIdsToSlotParams.get(itemSlot);
return ret == null ? ListValue.of(Value.NULL, new NumericValue(itemSlot)) : ret.build();
}
public static Value ofBlockPredicate(RegistryAccess registryAccess, Predicate<BlockInWorld> blockPredicate)
public static Value ofBlockPredicate(final RegistryAccess registryAccess, final Predicate<BlockInWorld> blockPredicate)
{
BlockPredicateInterface predicateData = (BlockPredicateInterface) blockPredicate;
final BlockPredicateInterface predicateData = (BlockPredicateInterface) blockPredicate;
final Registry<Block> blocks = registryAccess.registryOrThrow(Registries.BLOCK);
return ListValue.of(
predicateData.getCMBlockState()==null?Value.NULL:of(blocks.getKey(predicateData.getCMBlockState().getBlock())),
predicateData.getCMBlockTagKey()==null?Value.NULL:of(blocks.getTag(predicateData.getCMBlockTagKey()).get().key()),
predicateData.getCMBlockState() == null ? Value.NULL : of(blocks.getKey(predicateData.getCMBlockState().getBlock())),
predicateData.getCMBlockTagKey() == null ? Value.NULL : of(blocks.getTag(predicateData.getCMBlockTagKey()).get().key()),
MapValue.wrap(predicateData.getCMProperties()),
predicateData.getCMDataTag() == null?Value.NULL:new NBTSerializableValue(predicateData.getCMDataTag())
predicateData.getCMDataTag() == null ? Value.NULL : new NBTSerializableValue(predicateData.getCMDataTag())
);
}
public static ItemStack getItemStackFromValue(Value value, boolean withCount, RegistryAccess regs)
public static ItemStack getItemStackFromValue(final Value value, final boolean withCount, final RegistryAccess regs)
{
if (value.isNull())
{
@@ -439,7 +474,7 @@ public class ValueConversions
{
if (list.length() != 3)
{
throw new ThrowStatement("item definition from list of size "+list.length(), Throwables.UNKNOWN_ITEM);
throw new ThrowStatement("item definition from list of size " + list.length(), Throwables.UNKNOWN_ITEM);
}
final List<Value> items = list.getItems();
name = items.get(0).getString();
@@ -447,7 +482,7 @@ public class ValueConversions
{
count = NumericValue.asNumber(items.get(1)).getInt();
}
Value nbtValue = items.get(2);
final Value nbtValue = items.get(2);
if (!nbtValue.isNull())
{
nbtTag = ((NBTSerializableValue) NBTSerializableValue.fromValue(nbtValue)).getCompoundTag();
@@ -457,12 +492,12 @@ public class ValueConversions
{
name = value.getString();
}
ItemInput itemInput = NBTSerializableValue.parseItem(name, nbtTag, regs);
final ItemInput itemInput = NBTSerializableValue.parseItem(name, nbtTag, regs);
try
{
return itemInput.createItemStack(count,false);
return itemInput.createItemStack(count, false);
}
catch (CommandSyntaxException cse)
catch (final CommandSyntaxException cse)
{
if (!withCount)
{
@@ -475,31 +510,56 @@ public class ValueConversions
}
}
public static Value guess(ServerLevel serverWorld, Object o) {
public static Value guess(final ServerLevel serverWorld, final Object o)
{
if (o == null)
{
return Value.NULL;
if (o instanceof List)
return ListValue.wrap(((List<?>) o).stream().map(oo -> guess(serverWorld, oo)));
if (o instanceof BlockPos)
return new BlockValue(null, serverWorld, (BlockPos)o);
if (o instanceof Entity)
return EntityValue.of((Entity) o);
if (o instanceof Vec3)
return of((Vec3)o);
if (o instanceof Vec3i)
return of(new BlockPos((Vec3i)o));
if (o instanceof AABB)
return of((AABB)o);
if (o instanceof BoundingBox)
return of((BoundingBox) o);
if (o instanceof ItemStack)
return of((ItemStack)o, serverWorld.registryAccess());
if (o instanceof Boolean)
return BooleanValue.of((Boolean) o);
if (o instanceof Number)
return NumericValue.of((Number) o);
if (o instanceof ResourceLocation)
return of((ResourceLocation)o);
}
if (o instanceof final List<?> list)
{
return ListValue.wrap(list.stream().map(oo -> guess(serverWorld, oo)));
}
if (o instanceof final BlockPos pos)
{
return new BlockValue(null, serverWorld, pos);
}
if (o instanceof final Entity e)
{
return EntityValue.of(e);
}
if (o instanceof final Vec3 vec3)
{
return of(vec3);
}
if (o instanceof final Vec3i vec3i)
{
return of(new BlockPos(vec3i));
}
if (o instanceof final AABB aabb)
{
return of(aabb);
}
if (o instanceof final BoundingBox bb)
{
return of(bb);
}
if (o instanceof final ItemStack itemStack)
{
return of(itemStack, serverWorld.registryAccess());
}
if (o instanceof final Boolean bool)
{
return BooleanValue.of(bool);
}
if (o instanceof final Number number)
{
return NumericValue.of(number);
}
if (o instanceof final ResourceLocation resourceLocation)
{
return of(resourceLocation);
}
return StringValue.of(o.toString());
}
}