scarpet v1.2
This commit is contained in:
1 parent
723f863d98
commit
885f579d6c
34 files changed
+8786
-18
No files matched your search
@@ -0,0 +1,220 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.CarpetContext;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.command.arguments.BlockArgumentParser;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockValue extends Value
|
||||
{
|
||||
public static final BlockValue AIR = new BlockValue(Blocks.AIR.getDefaultState(), null, BlockPos.ORIGIN);
|
||||
public static final BlockValue NULL = new BlockValue(null, null, null);
|
||||
private BlockState blockState;
|
||||
private BlockPos pos;
|
||||
private World world;
|
||||
|
||||
public static BlockValue fromCoords(CarpetContext c, int x, int y, int z)
|
||||
{
|
||||
BlockPos pos = locateBlockPos(c, x,y,z);
|
||||
return new BlockValue(null, c.s.getWorld(), pos);
|
||||
}
|
||||
|
||||
public static BlockValue fromString(String str)
|
||||
{
|
||||
try
|
||||
{
|
||||
Identifier blockId = Identifier.fromCommandInput(new StringReader(str));
|
||||
if (Registry.BLOCK.containsId(blockId))
|
||||
{
|
||||
|
||||
Block block = Registry.BLOCK.get(blockId);
|
||||
return new BlockValue(block.getDefaultState(), null, null);
|
||||
}
|
||||
}
|
||||
catch (CommandSyntaxException ignored)
|
||||
{
|
||||
}
|
||||
throw new InternalExpressionException("Unknown block: "+str);
|
||||
}
|
||||
|
||||
private static Map<String, BlockValue> bvCache= new HashMap<>();
|
||||
public static BlockValue fromCommandExpression(String str)
|
||||
{
|
||||
try
|
||||
{
|
||||
BlockValue bv = bvCache.get(str);
|
||||
if (bv != null) return bv;
|
||||
BlockArgumentParser blockstateparser = (new BlockArgumentParser(new StringReader(str), false)).parse(true);
|
||||
if (blockstateparser.getBlockState() != null)
|
||||
{
|
||||
bv = new BlockValue(blockstateparser.getBlockState(), null, null);
|
||||
bvCache.put(str, bv);
|
||||
return bv;
|
||||
}
|
||||
}
|
||||
catch (CommandSyntaxException ignored)
|
||||
{
|
||||
}
|
||||
throw new InternalExpressionException("Cannot parse block: "+str);
|
||||
}
|
||||
|
||||
public static VectorLocator locateVec(CarpetContext c, List<LazyValue> params, int offset)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value v1 = params.get(0 + offset).evalValue(c);
|
||||
if (v1 instanceof BlockValue)
|
||||
{
|
||||
return new VectorLocator(new Vec3d(((BlockValue) v1).getPos()).add(0.5,0.5,0.5), 1+offset);
|
||||
}
|
||||
if (v1 instanceof ListValue)
|
||||
{
|
||||
List<Value> args = ((ListValue) v1).getItems();
|
||||
return new VectorLocator( new Vec3d(
|
||||
NumericValue.asNumber(args.get(0)).getDouble(),
|
||||
NumericValue.asNumber(args.get(1)).getDouble(),
|
||||
NumericValue.asNumber(args.get(2)).getDouble()),
|
||||
offset+1
|
||||
);
|
||||
}
|
||||
return new VectorLocator( new Vec3d(
|
||||
NumericValue.asNumber(v1).getDouble(),
|
||||
NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(),
|
||||
NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()),
|
||||
offset+3
|
||||
);
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value");
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockPos locateBlockPos(CarpetContext c, int xpos, int ypos, int zpos)
|
||||
{
|
||||
return new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos);
|
||||
}
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value v1 = params.get(0 + offset).evalValue(c);
|
||||
if (v1 instanceof BlockValue)
|
||||
{
|
||||
return new LocatorResult(((BlockValue) v1), 1+offset);
|
||||
}
|
||||
if (v1 instanceof ListValue)
|
||||
{
|
||||
List<Value> args = ((ListValue) v1).getItems();
|
||||
int xpos = (int) NumericValue.asNumber(args.get(0)).getLong();
|
||||
int ypos = (int) NumericValue.asNumber(args.get(1)).getLong();
|
||||
int zpos = (int) NumericValue.asNumber(args.get(2)).getLong();
|
||||
return new LocatorResult(
|
||||
new BlockValue(
|
||||
null,
|
||||
c.s.getWorld(),
|
||||
new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos)
|
||||
),
|
||||
1+offset);
|
||||
}
|
||||
int xpos = (int) NumericValue.asNumber(v1).getLong();
|
||||
int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong();
|
||||
int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong();
|
||||
return new LocatorResult(
|
||||
new BlockValue(
|
||||
null,
|
||||
c.s.getWorld(),
|
||||
new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos)
|
||||
),
|
||||
3+offset
|
||||
);
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value");
|
||||
}
|
||||
}
|
||||
|
||||
public BlockState getBlockState()
|
||||
{
|
||||
if (blockState != null)
|
||||
{
|
||||
return blockState;
|
||||
}
|
||||
if (world != null && pos != null)
|
||||
{
|
||||
blockState = world.getBlockState(pos);
|
||||
return blockState;
|
||||
}
|
||||
throw new InternalExpressionException("Attemted to fetch blockstate without world or stored blockstate");
|
||||
}
|
||||
|
||||
public BlockValue(BlockState state, World world, BlockPos position)
|
||||
{
|
||||
this.world = world;
|
||||
blockState = state;
|
||||
pos = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return Registry.BLOCK.getId(getBlockState().getBlock()).getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return this != NULL && !getBlockState().isAir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
return new BlockValue(blockState, world, pos);
|
||||
}
|
||||
|
||||
public BlockPos getPos()
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
public static class LocatorResult
|
||||
{
|
||||
public BlockValue block;
|
||||
public int offset;
|
||||
LocatorResult(BlockValue b, int o)
|
||||
{
|
||||
block = b;
|
||||
offset = o;
|
||||
}
|
||||
}
|
||||
|
||||
public static class VectorLocator
|
||||
{
|
||||
public Vec3d vec;
|
||||
public int offset;
|
||||
VectorLocator(Vec3d v, int o)
|
||||
{
|
||||
vec = v;
|
||||
offset = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.command.EntitySelector;
|
||||
import net.minecraft.command.EntitySelectorReader;
|
||||
import net.minecraft.command.arguments.NbtPathArgumentType;
|
||||
import net.minecraft.entity.mob.MobEntityWithAi; // EntityCreature;
|
||||
import net.minecraft.entity.mob.MobEntity; //LivingEntity;
|
||||
import net.minecraft.entity.ai.goal.Goal;
|
||||
import net.minecraft.entity.ai.goal.GoToWalkTargetGoal;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.client.network.packet.EntityVelocityUpdateS2CPacket;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class EntityValue extends Value
|
||||
{
|
||||
private Entity entity;
|
||||
|
||||
public EntityValue(Entity e)
|
||||
{
|
||||
entity = e;
|
||||
}
|
||||
|
||||
private static Map<String, EntitySelector> selectorCache = new HashMap<>();
|
||||
public static Collection<? extends Entity > getEntitiesFromSelector(ServerCommandSource source, String selector)
|
||||
{
|
||||
try
|
||||
{
|
||||
EntitySelector entitySelector = selectorCache.get(selector);
|
||||
if (entitySelector != null)
|
||||
{
|
||||
return entitySelector.getEntities(source);
|
||||
}
|
||||
entitySelector = new EntitySelectorReader(new StringReader(selector), true).build();
|
||||
selectorCache.put(selector, entitySelector);
|
||||
return entitySelector.getEntities(source);
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
throw new InternalExpressionException("Cannot select entities from "+selector);
|
||||
}
|
||||
}
|
||||
|
||||
public Entity getEntity()
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return entity.getDisplayName().getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Value v)
|
||||
{
|
||||
if (v instanceof EntityValue)
|
||||
{
|
||||
return entity.getEntityId()==((EntityValue) v).entity.getEntityId();
|
||||
}
|
||||
return super.equals(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value in(Value v)
|
||||
{
|
||||
String what = v.getString();
|
||||
return this.get(what, null);
|
||||
}
|
||||
|
||||
public static Pair<EntityType<?>, Predicate<? super Entity>> getPredicate(String who)
|
||||
{
|
||||
Pair<EntityType<?>, Predicate<? super Entity>> res = entityPredicates.get(who);
|
||||
if (res != null) return res;
|
||||
return res; //TODO add more here like search by tags, or type
|
||||
//if (who.startsWith('tag:'))
|
||||
}
|
||||
private static Map<String, Pair<EntityType<?>, Predicate<? super Entity>>> entityPredicates =
|
||||
new HashMap<String, Pair<EntityType<?>, Predicate<? super Entity>>>()
|
||||
{{
|
||||
put("*", Pair.of(null, EntityPredicates.VALID_ENTITY));
|
||||
put("living", Pair.of(null, (e) -> e instanceof LivingEntity && e.isAlive()));
|
||||
put("items", Pair.of(EntityType.ITEM, EntityPredicates.VALID_ENTITY));
|
||||
put("players", Pair.of(EntityType.PLAYER, EntityPredicates.VALID_ENTITY));
|
||||
put("!players", Pair.of(null, (e) -> !(e instanceof PlayerEntity) ));
|
||||
}};
|
||||
public Value get(String what, Value arg)
|
||||
{
|
||||
if (!(featureAccessors.containsKey(what)))
|
||||
throw new InternalExpressionException("unknown feature of entity: "+what);
|
||||
return featureAccessors.get(what).apply(entity, arg);
|
||||
}
|
||||
private static Map<String, EquipmentSlot> inventorySlots = new HashMap<String, EquipmentSlot>(){{
|
||||
put("main", EquipmentSlot.MAINHAND);
|
||||
put("offhand", EquipmentSlot.OFFHAND);
|
||||
put("head", EquipmentSlot.HEAD);
|
||||
put("chest", EquipmentSlot.CHEST);
|
||||
put("legs", EquipmentSlot.LEGS);
|
||||
put("feet", EquipmentSlot.FEET);
|
||||
}};
|
||||
private static Map<String, BiFunction<Entity, Value, Value>> featureAccessors = new HashMap<String, BiFunction<Entity, Value, Value>>() {{
|
||||
put("removed", (entity, arg) -> new NumericValue(entity.removed));
|
||||
put("uuid",(e, a) -> new StringValue(e.getUuidAsString()));
|
||||
put("id",(e, a) -> new NumericValue(e.getEntityId()));
|
||||
put("pos", (e, a) -> ListValue.of(new NumericValue(e.x), new NumericValue(e.y), new NumericValue(e.z)));
|
||||
put("x", (e, a) -> new NumericValue(e.x));
|
||||
put("y", (e, a) -> new NumericValue(e.y));
|
||||
put("z", (e, a) -> new NumericValue(e.z));
|
||||
put("motion", (e, a) ->
|
||||
{
|
||||
Vec3d velocity = e.getVelocity();
|
||||
return ListValue.of(new NumericValue(velocity.x), new NumericValue(velocity.y), new NumericValue(velocity.z));
|
||||
});
|
||||
put("motion_x", (e, a) -> new NumericValue(e.getVelocity().x));
|
||||
put("motion_y", (e, a) -> new NumericValue(e.getVelocity().y));
|
||||
put("motion_z", (e, a) -> new NumericValue(e.getVelocity().z));
|
||||
put("name", (e, a) -> new StringValue(e.getDisplayName().getString()));
|
||||
put("custom_name", (e, a) -> e.hasCustomName()?new StringValue(e.getCustomName().getString()):Value.NULL);
|
||||
put("type", (e, a) -> new StringValue(Registry.ENTITY_TYPE.getId(e.getType()).toString().replaceFirst("minecraft:","")));
|
||||
put("is_riding", (e, a) -> new NumericValue(e.hasVehicle()));
|
||||
put("is_ridden", (e, a) -> new NumericValue(e.hasPassengers()));
|
||||
put("passengers", (e, a) -> ListValue.wrap(e.getPassengerList().stream().map(EntityValue::new).collect(Collectors.toList())));
|
||||
put("mount", (e, a) -> (e.getVehicle()!=null)?new EntityValue(e.getVehicle()):Value.NULL);
|
||||
put("tags", (e, a) -> ListValue.wrap(e.getScoreboardTags().stream().map(StringValue::new).collect(Collectors.toList())));
|
||||
put("has_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString())));
|
||||
put("yaw", (e, a)-> new NumericValue(e.yaw));
|
||||
put("pitch", (e, a)-> new NumericValue(e.pitch));
|
||||
put("is_burning", (e, a) -> new NumericValue(e.isOnFire()));
|
||||
//put("fire", (e, a) -> new NumericValue(e.getFire())); needs mixing
|
||||
put("silent", (e, a)-> new NumericValue(e.isSilent()));
|
||||
put("gravity", (e, a) -> new NumericValue(!e.hasNoGravity()));
|
||||
put("immune_to_fire", (e, a) -> new NumericValue(e.isFireImmune()));
|
||||
|
||||
put("invulnerable", (e, a) -> new NumericValue(e.isInvulnerable()));
|
||||
put("dimension", (e, a) -> new StringValue(e.dimension.toString().replaceFirst("minecraft:","")));
|
||||
put("height", (e, a) -> new NumericValue(e.getSize(EntityPose.STANDING).height));
|
||||
put("width", (e, a) -> new NumericValue(e.getSize(EntityPose.STANDING).width));
|
||||
put("eye_height", (e, a) -> new NumericValue(e.getEyeHeight(EntityPose.STANDING)));
|
||||
put("age", (e, a) -> new NumericValue(e.age));
|
||||
put("item", (e, a) -> (e instanceof ItemEntity)?new StringValue(((ItemEntity) e).getStack().getDisplayName().getString()):Value.NULL);
|
||||
put("count", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntity) e).getStack().getAmount()):Value.NULL);
|
||||
// ItemEntity -> despawn timer via ssGetAge
|
||||
put("is_baby", (e, a) -> (e instanceof LivingEntity)?new NumericValue(((LivingEntity) e).isBaby()):Value.NULL);
|
||||
put("target", (e, a) -> {
|
||||
if (e instanceof MobEntity)
|
||||
{
|
||||
LivingEntity target = ((MobEntity) e).getTarget(); // there is also getAttacking in living....
|
||||
if (target != null)
|
||||
{
|
||||
return new EntityValue(target);
|
||||
}
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
/*put("home", (e, a) -> {
|
||||
if (e instanceof MobEntityWithAi)
|
||||
{
|
||||
return ((MobEntityWithAi) e).has hasHome()?new BlockValue(null, e.getEntityWorld(), ((MobEntityWithAi) e).getHomePosition()):Value.FALSE;
|
||||
}
|
||||
return Value.NULL;
|
||||
});*/
|
||||
put("sneaking", (e, a) -> e.isSneaking()?Value.TRUE:Value.FALSE);
|
||||
put("sprinting", (e, a) -> e.isSprinting()?Value.TRUE:Value.FALSE);
|
||||
put("swimming", (e, a) -> e.isSwimming()?Value.TRUE:Value.FALSE);
|
||||
/*put("jumping", (e, a) -> {
|
||||
if (e instanceof LivingEntity)
|
||||
{
|
||||
return ((LivingEntity) e).getJumping()?Value.TRUE:Value.FALSE;
|
||||
}
|
||||
return Value.NULL;
|
||||
});*/ //needs mixing
|
||||
put("gamemode", (e, a) -> {
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
{
|
||||
return new StringValue(((ServerPlayerEntity) e).interactionManager.getGameMode().getName());
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
put("gamemode_id", (e, a) -> {
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
{
|
||||
return new NumericValue(((ServerPlayerEntity) e).interactionManager.getGameMode().getId());
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
//spectating_entity
|
||||
// isGlowing
|
||||
put("effect", (e, a) ->
|
||||
{
|
||||
if (!(e instanceof LivingEntity))
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
if (a == null)
|
||||
{
|
||||
List<Value> effects = new ArrayList<>();
|
||||
for (StatusEffectInstance p : ((LivingEntity) e).getStatusEffects())
|
||||
{
|
||||
effects.add(ListValue.of(
|
||||
new StringValue(p.getTranslationKey().replaceFirst("^effect\\.minecraft\\.", "")),
|
||||
new NumericValue(p.getAmplifier()),
|
||||
new NumericValue(p.getDuration())
|
||||
));
|
||||
}
|
||||
return ListValue.wrap(effects);
|
||||
}
|
||||
String effectName = a.getString();
|
||||
StatusEffect potion = Registry.STATUS_EFFECT.get(new Identifier(effectName));
|
||||
if (potion == null)
|
||||
throw new InternalExpressionException("No such an effect: "+effectName);
|
||||
if (!((LivingEntity) e).hasStatusEffect(potion))
|
||||
return Value.NULL;
|
||||
StatusEffectInstance pe = ((LivingEntity) e).getStatusEffect(potion);
|
||||
return ListValue.of( new NumericValue(pe.getAmplifier()), new NumericValue(pe.getDuration()) );
|
||||
});
|
||||
put("health", (e, a) ->
|
||||
{
|
||||
if (e instanceof LivingEntity)
|
||||
{
|
||||
return new NumericValue(((LivingEntity) e).getHealth());
|
||||
}
|
||||
//if (e instanceof ItemEntity)
|
||||
//{
|
||||
// e.h consider making item health public
|
||||
//}
|
||||
return Value.NULL;
|
||||
});
|
||||
put("holds", (e, a) -> {
|
||||
EquipmentSlot where = EquipmentSlot.MAINHAND;
|
||||
if (a != null)
|
||||
where = inventorySlots.get(a.getString());
|
||||
if (where == null)
|
||||
throw new InternalExpressionException("Unknown inventory slot: "+a.getString());
|
||||
if (e instanceof LivingEntity)
|
||||
{
|
||||
ItemStack itemstack = ((LivingEntity)e).getEquippedStack(where);
|
||||
if (!itemstack.isEmpty())
|
||||
{
|
||||
return ListValue.of(
|
||||
new StringValue(Registry.ITEM.getId(itemstack.getItem()).getPath()),
|
||||
new NumericValue(itemstack.getAmount()),
|
||||
new StringValue(itemstack.toTag(new CompoundTag()).toString())
|
||||
);
|
||||
}
|
||||
}
|
||||
return Value.NULL;
|
||||
|
||||
});
|
||||
|
||||
put("nbt",(e, a) -> {
|
||||
CompoundTag nbttagcompound = e.toTag((new CompoundTag()));
|
||||
if (a==null)
|
||||
return new StringValue(nbttagcompound.toString());
|
||||
NbtPathArgumentType.NbtPath path;
|
||||
try
|
||||
{
|
||||
path = NbtPathArgumentType.create().method_9362(new StringReader(a.getString()));
|
||||
}
|
||||
catch (CommandSyntaxException exc)
|
||||
{
|
||||
throw new InternalExpressionException("Incorrect path: "+a.getString());
|
||||
}
|
||||
String res = null;
|
||||
try
|
||||
{
|
||||
List<Tag> tags = path.get(nbttagcompound);
|
||||
if (tags.size()==0)
|
||||
return Value.NULL;
|
||||
if (tags.size()==1)
|
||||
return new StringValue(tags.get(0).toTextComponent().getString());
|
||||
return ListValue.wrap(tags.stream().map((t) -> new StringValue(t.toTextComponent().getString())).collect(Collectors.toList()));
|
||||
}
|
||||
catch (CommandSyntaxException ignored) { }
|
||||
return new StringValue(res);
|
||||
});
|
||||
}};
|
||||
private static <Req extends Entity> Req assertEntityArgType(Class<Req> klass, Value arg)
|
||||
{
|
||||
if (!(arg instanceof EntityValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Entity e = ((EntityValue) arg).getEntity();
|
||||
if (!(klass.isAssignableFrom(e.getClass())))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return (Req)e;
|
||||
}
|
||||
|
||||
public void set(String what, Value toWhat)
|
||||
{
|
||||
if (!(featureModifiers.containsKey(what)))
|
||||
throw new InternalExpressionException("unknown action on entity: " + what);
|
||||
featureModifiers.get(what).accept(entity, toWhat);
|
||||
}
|
||||
|
||||
private static Map<String, BiConsumer<Entity, Value>> featureModifiers = new HashMap<String, BiConsumer<Entity, Value>>() {{
|
||||
put("remove", (entity, value) -> entity.remove());
|
||||
put("health", (e, v) -> { if (e instanceof LivingEntity) ((LivingEntity) e).setHealth((float) NumericValue.asNumber(v).getDouble()); });
|
||||
put("kill", (e, v) -> e.kill());
|
||||
put("pos", (e, v) ->
|
||||
{
|
||||
if (!(v instanceof ListValue))
|
||||
{
|
||||
throw new InternalExpressionException("expected a list of 3 parameters as second argument");
|
||||
}
|
||||
List<Value> coords = ((ListValue) v).getItems();
|
||||
e.x = NumericValue.asNumber(coords.get(0)).getDouble();
|
||||
e.y = NumericValue.asNumber(coords.get(1)).getDouble();
|
||||
e.z = NumericValue.asNumber(coords.get(2)).getDouble();
|
||||
e.setPosition(e.x, e.y, e.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
put("x", (e, v) ->
|
||||
{
|
||||
e.x = NumericValue.asNumber(v).getDouble();
|
||||
e.setPosition(e.x, e.y, e.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
put("y", (e, v) ->
|
||||
{
|
||||
e.y = NumericValue.asNumber(v).getDouble();
|
||||
e.setPosition(e.x, e.y, e.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
put("z", (e, v) ->
|
||||
{
|
||||
e.z = NumericValue.asNumber(v).getDouble();
|
||||
e.setPosition(e.x, e.y, e.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
put("pitch", (e, v) ->
|
||||
{
|
||||
e.pitch = (float) NumericValue.asNumber(v).getDouble();
|
||||
e.prevPitch = e.pitch;
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
put("yaw", (e, v) ->
|
||||
{
|
||||
e.yaw = (float) NumericValue.asNumber(v).getDouble();
|
||||
e.prevYaw = e.yaw;
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
//"look"
|
||||
//"turn"
|
||||
//"nod"
|
||||
|
||||
put("move", (e, v) ->
|
||||
{
|
||||
if (!(v instanceof ListValue))
|
||||
{
|
||||
throw new InternalExpressionException("expected a list of 3 parameters as second argument");
|
||||
}
|
||||
List<Value> coords = ((ListValue) v).getItems();
|
||||
e.x += NumericValue.asNumber(coords.get(0)).getDouble();
|
||||
e.y += NumericValue.asNumber(coords.get(1)).getDouble();
|
||||
e.z += NumericValue.asNumber(coords.get(2)).getDouble();
|
||||
e.setPosition(e.x, e.y, e.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.requestTeleport(e.y, e.y, e.z, e.yaw, e.pitch);
|
||||
});
|
||||
|
||||
put("motion", (e, v) ->
|
||||
{
|
||||
if (!(v instanceof ListValue))
|
||||
{
|
||||
throw new InternalExpressionException("expected a list of 3 parameters as second argument");
|
||||
}
|
||||
List<Value> coords = ((ListValue) v).getItems();
|
||||
e.setVelocity(
|
||||
NumericValue.asNumber(coords.get(0)).getDouble(),
|
||||
NumericValue.asNumber(coords.get(1)).getDouble(),
|
||||
NumericValue.asNumber(coords.get(2)).getDouble()
|
||||
);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(e));
|
||||
});
|
||||
put("motion_x", (e, v) ->
|
||||
{
|
||||
Vec3d velocity = e.getVelocity();
|
||||
e.setVelocity(NumericValue.asNumber(v).getDouble(), velocity.y, velocity.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(e));
|
||||
});
|
||||
put("motion_y", (e, v) ->
|
||||
{
|
||||
Vec3d velocity = e.getVelocity();
|
||||
e.setVelocity(velocity.x, NumericValue.asNumber(v).getDouble(), velocity.z);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(e));
|
||||
});
|
||||
put("motion_z", (e, v) ->
|
||||
{
|
||||
Vec3d velocity = e.getVelocity();
|
||||
e.setVelocity(velocity.x, velocity.y, NumericValue.asNumber(v).getDouble());
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(e));
|
||||
});
|
||||
|
||||
put("accelerate", (e, v) ->
|
||||
{
|
||||
if (!(v instanceof ListValue))
|
||||
{
|
||||
throw new InternalExpressionException("expected a list of 3 parameters as second argument");
|
||||
}
|
||||
List<Value> coords = ((ListValue) v).getItems();
|
||||
e.addVelocity(
|
||||
NumericValue.asNumber(coords.get(0)).getDouble(),
|
||||
NumericValue.asNumber(coords.get(1)).getDouble(),
|
||||
NumericValue.asNumber(coords.get(2)).getDouble()
|
||||
);
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
((ServerPlayerEntity)e).networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(e));
|
||||
|
||||
});
|
||||
put("custom_name", (e, v) -> {
|
||||
String name = v.getString();
|
||||
if (name.isEmpty())
|
||||
e.setCustomName(null);
|
||||
e.setCustomName(new TextComponent(v.getString()));
|
||||
});
|
||||
put("dismount", (e, v) -> e.stopRiding() );
|
||||
put("mount", (e, v) -> {
|
||||
if (v instanceof EntityValue)
|
||||
{
|
||||
e.startRiding(((EntityValue) v).getEntity(),true);
|
||||
}
|
||||
});
|
||||
put("drop_passengers", (e, v) -> e.removeAllPassengers());
|
||||
put("mount_passengers", (e, v) -> {
|
||||
if (v==null)
|
||||
throw new InternalExpressionException("mount_passengers needs entities to ride");
|
||||
if (v instanceof EntityValue)
|
||||
((EntityValue) v).getEntity().startRiding(e);
|
||||
else if (v instanceof ListValue)
|
||||
for (Value element : ((ListValue) v).getItems())
|
||||
if (element instanceof EntityValue)
|
||||
((EntityValue) element).getEntity().startRiding(e);
|
||||
});
|
||||
put("tag", (e, v) -> {
|
||||
if (v==null)
|
||||
throw new InternalExpressionException("tag requires parameters");
|
||||
if (v instanceof ListValue)
|
||||
for (Value element : ((ListValue) v).getItems()) e.addScoreboardTag(element.getString());
|
||||
else
|
||||
e.addScoreboardTag(v.getString());
|
||||
});
|
||||
put("clear_tag", (e, v) -> {
|
||||
if (v==null)
|
||||
throw new InternalExpressionException("clear_tag requires parameters");
|
||||
if (v instanceof ListValue)
|
||||
for (Value element : ((ListValue) v).getItems()) e.removeScoreboardTag(element.getString());
|
||||
else
|
||||
e.removeScoreboardTag(v.getString());
|
||||
});
|
||||
//put("target", (e, v) -> {
|
||||
// // attacks indefinitely - might need to do it through tasks
|
||||
// if (e instanceof MobEntity)
|
||||
// {
|
||||
// LivingEntity elb = assertEntityArgType(LivingEntity.class, v);
|
||||
// ((MobEntity) e).setAttackTarget(elb);
|
||||
// }
|
||||
//});
|
||||
put("talk", (e, v) -> {
|
||||
// attacks indefinitely
|
||||
if (e instanceof MobEntity)
|
||||
{
|
||||
((MobEntity) e).playAmbientSound();
|
||||
}
|
||||
});
|
||||
/*
|
||||
put("home", (e, v) -> {
|
||||
if (!(e instanceof MobEntityWithAi))
|
||||
return;
|
||||
MobEntityWithAi ec = (MobEntityWithAi)e;
|
||||
if (v == null)
|
||||
throw new InternalExpressionException("home requires at least one position argument, and optional distance, or null to cancel");
|
||||
if (v instanceof NullValue)
|
||||
{
|
||||
ec.detachHome();
|
||||
ec.getAI(false).removeTask(ec.temporaryTasks.get("home"));
|
||||
ec.temporaryTasks.remove("home");
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos;
|
||||
int distance = 16;
|
||||
|
||||
if (v instanceof BlockValue)
|
||||
{
|
||||
pos = ((BlockValue) v).getPos();
|
||||
if (pos == null) throw new InternalExpressionException("block is not positioned in the world");
|
||||
}
|
||||
else if (v instanceof ListValue)
|
||||
{
|
||||
List<Value> lv = ((ListValue) v).getItems();
|
||||
if (lv.get(0) instanceof BlockValue)
|
||||
{
|
||||
pos = ((BlockValue) lv.get(0)).getPos();
|
||||
if (lv.size()>1)
|
||||
{
|
||||
distance = (int) NumericValue.asNumber(lv.get(1)).getLong();
|
||||
}
|
||||
}
|
||||
else if (lv.size()>=3)
|
||||
{
|
||||
pos = new BlockPos(NumericValue.asNumber(lv.get(0)).getLong(),
|
||||
NumericValue.asNumber(lv.get(1)).getLong(),
|
||||
NumericValue.asNumber(lv.get(2)).getLong());
|
||||
if (lv.size()>3)
|
||||
{
|
||||
distance = (int) NumericValue.asNumber(lv.get(4)).getLong();
|
||||
}
|
||||
}
|
||||
else throw new InternalExpressionException("home requires at least one position argument, and optional distance");
|
||||
|
||||
}
|
||||
else throw new InternalExpressionException("home requires at least one position argument, and optional distance");
|
||||
|
||||
ec.setHomePosAndDistance(pos, distance);
|
||||
if (!ec.temporaryTasks.containsKey("home"))
|
||||
{
|
||||
Goal task = new GoToWalkTargetGoal(ec, 1.0D);
|
||||
ec.temporaryTasks.put("home", task);
|
||||
ec.getAI(false).addTask(10, task);
|
||||
}
|
||||
});*/ //requires mixing
|
||||
|
||||
// gamemode
|
||||
// spectate
|
||||
// "fire"
|
||||
// "extinguish"
|
||||
// "silent"
|
||||
// "gravity"
|
||||
// "invulnerable"
|
||||
// "dimension"
|
||||
// "item"
|
||||
// "count",
|
||||
// "age",
|
||||
// "effect_"name
|
||||
// "hold"
|
||||
// "hold_offhand"
|
||||
// "jump"
|
||||
// "nbt" <-big one, for now use run('data merge entity ...
|
||||
}};
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.value.Value;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FunctionSignatureValue extends Value
|
||||
{
|
||||
private String identifier;
|
||||
private List<String> arguments;
|
||||
private List<String> globals;
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
throw new ExpressionException("Function "+identifier+" is not defined yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
throw new ExpressionException("Function "+identifier+" is not defined yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
throw new ExpressionException("Function "+identifier+" is not defined yet");
|
||||
}
|
||||
public FunctionSignatureValue(String name, List<String> args, List<String> globals)
|
||||
{
|
||||
this.identifier = name;
|
||||
this.arguments = args;
|
||||
this.globals = globals;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
public List<String> getArgs()
|
||||
{
|
||||
return arguments;
|
||||
}
|
||||
public List<String> getGlobals() {return globals;}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.value.Value;
|
||||
|
||||
public class GlobalValue extends Value
|
||||
{
|
||||
public GlobalValue(Value variable)
|
||||
{
|
||||
variable.assertAssignable();
|
||||
this.boundVariable = variable.boundVariable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return boundVariable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class LazyListValue extends ListValue implements Iterator<Value>
|
||||
{
|
||||
public static LazyListValue range(long from, long to, long step)
|
||||
{
|
||||
return new LazyListValue()
|
||||
{
|
||||
{
|
||||
if (step == 0)
|
||||
throw new InternalExpressionException("range will never end with zero step");
|
||||
this.current = from;
|
||||
this.limit = to;
|
||||
this.stepp = step;
|
||||
}
|
||||
private long current;
|
||||
private long limit;
|
||||
private long stepp;
|
||||
@Override
|
||||
public Value next()
|
||||
{
|
||||
Value val = new NumericValue(current);
|
||||
current += stepp;
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return stepp > 0?(current < limit):(current > limit);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public LazyListValue()
|
||||
{
|
||||
super(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return "[...]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return hasNext();
|
||||
}
|
||||
public abstract boolean hasNext();
|
||||
|
||||
public abstract Value next();
|
||||
|
||||
@Override
|
||||
public Iterator<Value> iterator() {return this;}
|
||||
|
||||
public List<Value> unroll()
|
||||
{
|
||||
List<Value> result = new ArrayList<>();
|
||||
this.forEachRemaining(result::add);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value slice(long from, long to)
|
||||
{
|
||||
if (to < 0) to = Integer.MAX_VALUE;
|
||||
if (from < 0) from = 0;
|
||||
if (from > to)
|
||||
return ListValue.of();
|
||||
List<Value> result = new ArrayList<>();
|
||||
int i;
|
||||
for (i = 0; i < from; i++)
|
||||
{
|
||||
if (hasNext())
|
||||
next();
|
||||
else
|
||||
return ListValue.wrap(result);
|
||||
}
|
||||
for (i = (int)from; i < to; i++)
|
||||
{
|
||||
if (hasNext())
|
||||
result.add(next());
|
||||
else
|
||||
return ListValue.wrap(result);
|
||||
}
|
||||
return ListValue.wrap(result);
|
||||
}
|
||||
@Override
|
||||
public Value add(Value other)
|
||||
{
|
||||
throw new InternalExpressionException("Cannot add to iterators");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
public class ListValue extends Value
|
||||
{
|
||||
protected List<Value> items;
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
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()+"]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean() {
|
||||
return !items.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
return new ListValue(items);
|
||||
}
|
||||
public ListValue(Collection<? extends Value> list)
|
||||
{
|
||||
items = new ArrayList<>();
|
||||
items.addAll(list);
|
||||
}
|
||||
public static ListValue wrap(List<Value> list)
|
||||
{
|
||||
ListValue created = new ListValue();
|
||||
created.items = list;
|
||||
return created;
|
||||
}
|
||||
public static ListValue of(Value ... list)
|
||||
{
|
||||
return ListValue.wrap(Arrays.asList(list));
|
||||
}
|
||||
|
||||
private ListValue()
|
||||
{
|
||||
items = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value add(Value other) {
|
||||
ListValue output = new ListValue();
|
||||
if (other instanceof ListValue)
|
||||
{
|
||||
List<Value> other_list = ((ListValue) other).items;
|
||||
if (other_list.size() == items.size())
|
||||
{
|
||||
for(int i = 0, size = items.size(); i < size; i++)
|
||||
{
|
||||
output.items.add(items.get(i).add(other_list.get(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalExpressionException("Cannot subtract two lists of uneven sizes");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Value v : items)
|
||||
{
|
||||
output.items.add(v.add(other));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
public void append(Value v)
|
||||
{
|
||||
items.add(v);
|
||||
}
|
||||
public Value subtract(Value other)
|
||||
{
|
||||
ListValue output = new ListValue();
|
||||
if (other instanceof ListValue)
|
||||
{
|
||||
List<Value> other_list = ((ListValue) other).items;
|
||||
if (other_list.size() == items.size())
|
||||
{
|
||||
for(int i = 0, size = items.size(); i < size; i++)
|
||||
{
|
||||
output.items.add(items.get(i).subtract(other_list.get(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalExpressionException("Cannot subtract two lists of uneven sizes");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (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
|
||||
{
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
|
||||
public Value multiply(Value other)
|
||||
{
|
||||
ListValue output = new ListValue();
|
||||
if (other instanceof ListValue)
|
||||
{
|
||||
List<Value> other_list = ((ListValue) other).items;
|
||||
if (other_list.size() == items.size())
|
||||
{
|
||||
for(int i = 0, size = items.size(); i < size; i++)
|
||||
{
|
||||
output.items.add(items.get(i).multiply(other_list.get(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalExpressionException("Cannot subtract two lists of uneven sizes");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Value v : items)
|
||||
{
|
||||
output.items.add(v.multiply(other));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
public Value divide(Value other)
|
||||
{
|
||||
ListValue output = new ListValue();
|
||||
if (other instanceof ListValue)
|
||||
{
|
||||
List<Value> other_list = ((ListValue) other).items;
|
||||
if (other_list.size() == items.size())
|
||||
{
|
||||
for(int i = 0, size = items.size(); i < size; i++)
|
||||
{
|
||||
output.items.add(items.get(i).divide(other_list.get(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalExpressionException("Cannot subtract two lists of uneven sizes");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Value v : items)
|
||||
{
|
||||
output.items.add(v.divide(other));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Value o)
|
||||
{
|
||||
if (o instanceof ListValue)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
int res = this.items.get(i).compareTo(ol.items.get(i));
|
||||
if (res != 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return super.compareTo(o);
|
||||
}
|
||||
|
||||
public List<Value> getItems()
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
public Iterator<Value> iterator()
|
||||
{
|
||||
return items.iterator();
|
||||
}
|
||||
public void fatality()
|
||||
{
|
||||
}
|
||||
|
||||
public void extend(List<Value> subList)
|
||||
{
|
||||
for (Value v: subList)
|
||||
items.add(v);
|
||||
}
|
||||
|
||||
public void addAtIndex(int index, List<Value> subList)
|
||||
{
|
||||
int numitems = items.size();
|
||||
long range = abs(index)/numitems;
|
||||
index += (range+2)*numitems;
|
||||
index = index % numitems;
|
||||
for (Value v: subList)
|
||||
{
|
||||
if (index < numitems)
|
||||
{
|
||||
items.set(index, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
items.add(v);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ListConstructorValue extends ListValue
|
||||
{
|
||||
public ListConstructorValue(Collection<? extends Value> list)
|
||||
{
|
||||
super(list);
|
||||
}
|
||||
}
|
||||
public int length()
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value in(Value value1)
|
||||
{
|
||||
for (int i = 0; i < items.size(); i++)
|
||||
{
|
||||
Value v = items.get(i);
|
||||
if (v.equals(value1))
|
||||
{
|
||||
return new NumericValue(i);
|
||||
}
|
||||
}
|
||||
return Value.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value slice(long from, long to)
|
||||
{
|
||||
List<Value> items = getItems();
|
||||
int size = items.size();
|
||||
if (to < 0 || to > size) to = size;
|
||||
if (from < 0 || from > size) from = size;
|
||||
if (from > to)
|
||||
return ListValue.of();
|
||||
return new ListValue(getItems().subList((int)from, (int) to));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readNumber()
|
||||
{
|
||||
return (double)items.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package carpet.script.value;
|
||||
|
||||
public class NullValue extends NumericValue // TODO check nonsingleton code
|
||||
{
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrettyString()
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
return new NullValue();
|
||||
}
|
||||
public NullValue() {super(0.0D);}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Value o)
|
||||
{
|
||||
return o instanceof NullValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Value o)
|
||||
{
|
||||
return o instanceof NullValue ? 0 : -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
public class NumericValue extends Value
|
||||
{
|
||||
private Double value;
|
||||
final static double epsilon = 1024*Double.MIN_VALUE;
|
||||
|
||||
public static NumericValue asNumber(Value v1)
|
||||
{
|
||||
if (!(v1 instanceof NumericValue))
|
||||
throw new InternalExpressionException("Operand has to be of a numeric type");
|
||||
return ((NumericValue) v1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
try
|
||||
{
|
||||
return BigDecimal.valueOf(value).stripTrailingZeros().toPlainString();
|
||||
}
|
||||
catch (NumberFormatException exc)
|
||||
{
|
||||
throw new ArithmeticException("Incorrect number format for "+value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrettyString()
|
||||
{
|
||||
if (getDouble() == (double)getLong())
|
||||
{
|
||||
return Long.toString(getLong());
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.format("%.3f..", getDouble());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return value != null && abs(value) > epsilon;
|
||||
}
|
||||
public double getDouble()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
public long getLong()
|
||||
{
|
||||
return (long)(value+epsilon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value add(Value v)
|
||||
{ // TODO test if definintn add(NumericVlaue) woud solve the casting
|
||||
if (v instanceof NumericValue)
|
||||
{
|
||||
return new NumericValue(getDouble() + ((NumericValue) v).getDouble() );
|
||||
}
|
||||
return super.add(v);
|
||||
}
|
||||
public Value subtract(Value v) { // TODO test if definintn add(NumericVlaue) woud solve the casting
|
||||
if (v instanceof NumericValue)
|
||||
{
|
||||
return new NumericValue(getDouble() - (((NumericValue) v).getDouble()));
|
||||
}
|
||||
return super.subtract(v);
|
||||
}
|
||||
public Value multiply(Value v)
|
||||
{
|
||||
if (v instanceof NumericValue)
|
||||
{
|
||||
return new NumericValue(getDouble() * ((NumericValue) v).getDouble() );
|
||||
}
|
||||
if (v instanceof ListValue)
|
||||
{
|
||||
return v.multiply(this);
|
||||
}
|
||||
return new StringValue(StringUtils.repeat(v.getString(), (int) getLong()));
|
||||
}
|
||||
public Value divide(Value v)
|
||||
{
|
||||
if (v instanceof NumericValue)
|
||||
{
|
||||
return new NumericValue(getDouble() / ((NumericValue) v).getDouble() );
|
||||
}
|
||||
return super.divide(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
return new NumericValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Value o)
|
||||
{
|
||||
if (o instanceof NullValue)
|
||||
{
|
||||
return -o.compareTo(this);
|
||||
}
|
||||
if (o instanceof NumericValue)
|
||||
{
|
||||
return value.compareTo(((NumericValue) o).getDouble());
|
||||
}
|
||||
return super.compareTo(o);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Value o)
|
||||
{
|
||||
if (o instanceof NullValue)
|
||||
{
|
||||
return o.equals(this);
|
||||
}
|
||||
if (o instanceof NumericValue)
|
||||
{
|
||||
return !this.subtract(o).getBoolean();
|
||||
}
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
public NumericValue(double value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
public NumericValue(String value)
|
||||
{
|
||||
this(new BigDecimal(value).doubleValue());
|
||||
}
|
||||
public NumericValue(long value)
|
||||
{
|
||||
this.value = (double)value;
|
||||
}
|
||||
public NumericValue(boolean boolval)
|
||||
{
|
||||
this(boolval?1.0D:0.0D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length()
|
||||
{
|
||||
return Integer.toString(value.intValue()).length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readNumber()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readInteger()
|
||||
{
|
||||
return getLong();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package carpet.script.value;
|
||||
|
||||
public class StringValue extends Value
|
||||
{
|
||||
private String str;
|
||||
|
||||
@Override
|
||||
public String getString() {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean() {
|
||||
return str != null && !str.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
return new StringValue(str);
|
||||
}
|
||||
|
||||
public StringValue(String str)
|
||||
{
|
||||
this.str = str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public abstract class Value implements Comparable<Value>, Cloneable
|
||||
{
|
||||
public static Value FALSE = new NumericValue(0);
|
||||
public static Value TRUE = new NumericValue(1);
|
||||
public static Value ZERO = FALSE;
|
||||
public static Value NULL = new NullValue();
|
||||
|
||||
public String boundVariable;
|
||||
|
||||
public static <T> T assertNotNull(T t)
|
||||
{
|
||||
if (t == null)
|
||||
throw new InternalExpressionException("Operand may not be null");
|
||||
return t;
|
||||
}
|
||||
|
||||
public static <T> void assertNotNull(T t1, T t2)
|
||||
{
|
||||
if (t1 == null)
|
||||
throw new InternalExpressionException("First operand may not be null");
|
||||
if (t2 == null)
|
||||
throw new InternalExpressionException("Second operand may not be null");
|
||||
}
|
||||
|
||||
public boolean isBound()
|
||||
{
|
||||
return boundVariable != null;
|
||||
}
|
||||
public String getVariable()
|
||||
{
|
||||
return boundVariable;
|
||||
}
|
||||
public Value reboundedTo(String var)
|
||||
{
|
||||
Value copy = null;
|
||||
try
|
||||
{
|
||||
copy = (Value)clone();
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
// should not happen
|
||||
e.printStackTrace();
|
||||
}
|
||||
copy.boundVariable = var;
|
||||
return copy;
|
||||
}
|
||||
public Value bindTo(String var)
|
||||
{
|
||||
this.boundVariable = var;
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract String getString();
|
||||
|
||||
public String getPrettyString()
|
||||
{
|
||||
return getString();
|
||||
}
|
||||
|
||||
|
||||
public abstract boolean getBoolean();
|
||||
|
||||
public Value add(Value o) {
|
||||
String lstr = this.getString();
|
||||
if (lstr == null) // null
|
||||
return new StringValue(o.getString());
|
||||
String rstr = o.getString();
|
||||
if (rstr == null)
|
||||
{
|
||||
return new StringValue(lstr);
|
||||
}
|
||||
return new StringValue(lstr+rstr);
|
||||
}
|
||||
public Value subtract(Value v)
|
||||
{
|
||||
return new StringValue(this.getString().replace(v.getString(),""));
|
||||
}
|
||||
public Value multiply(Value v)
|
||||
{
|
||||
if (v instanceof NumericValue || v instanceof ListValue)
|
||||
{
|
||||
return v.multiply(this);
|
||||
}
|
||||
return new StringValue(this.getString()+"."+v.getString());
|
||||
}
|
||||
public Value divide(Value v)
|
||||
{
|
||||
if (v instanceof NumericValue)
|
||||
{
|
||||
String lstr = getString();
|
||||
return new StringValue(lstr.substring(0, (int)(lstr.length()/ ((NumericValue) v).getDouble())));
|
||||
}
|
||||
return new StringValue(getString()+"/"+v.getString());
|
||||
}
|
||||
|
||||
public Value()
|
||||
{
|
||||
this.boundVariable = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Value o)
|
||||
{
|
||||
if (o instanceof NumericValue || o instanceof ListValue)
|
||||
{
|
||||
return -o.compareTo(this);
|
||||
}
|
||||
return getString().compareTo(o.getString());
|
||||
}
|
||||
public boolean equals(final Value o)
|
||||
{
|
||||
return this.compareTo(o)==0;
|
||||
}
|
||||
|
||||
public void assertAssignable()
|
||||
{
|
||||
if (boundVariable == null || boundVariable.startsWith("_"))
|
||||
{
|
||||
if (boundVariable != null)
|
||||
{
|
||||
throw new InternalExpressionException(boundVariable+ " cannot be assigned a new value");
|
||||
}
|
||||
throw new InternalExpressionException(getString()+ " is not a variable");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Value in(Value value1)
|
||||
{
|
||||
final Pattern p = Pattern.compile(value1.getString());
|
||||
final Matcher m = p.matcher(this.getString());
|
||||
return m.find()?new StringValue(m.group()):Value.NULL;
|
||||
}
|
||||
public int length()
|
||||
{
|
||||
return getString().length();
|
||||
}
|
||||
|
||||
public Value slice(long from, long to)
|
||||
{
|
||||
String value = this.getString();
|
||||
int size = value.length();
|
||||
if (to > size) to = -1;
|
||||
if (from < 0) from = 0;
|
||||
if (from > size) from = size;
|
||||
if (to>=0)
|
||||
return new StringValue(value.substring((int)from, (int)to));
|
||||
return new StringValue(value.substring((int)from));
|
||||
}
|
||||
public double readNumber()
|
||||
{
|
||||
String s = getString();
|
||||
try
|
||||
{
|
||||
return Double.valueOf(s);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
public long readInteger()
|
||||
{
|
||||
return (long)readNumber();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user