Merge branch 'master' into 1.15

# Conflicts:
#	src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java
#	src/main/java/carpet/script/CarpetExpression.java
This commit is contained in:
gnembon committed 2019-10-08 02:07:45 -03:00
commit dc9532cf05
24 files changed
+1695 -655

No files matched your search

@@ -1,9 +1,15 @@
package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import java.util.Iterator;
public abstract class AbstractListValue extends Value
{
public abstract Iterator<Value> iterator();
public void fatality() { }
public void append(Value v)
{
throw new InternalExpressionException("Cannot append a value to abstract list");
}
}
@@ -13,6 +13,7 @@ import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.GlobalPos;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
@@ -254,6 +255,14 @@ public class BlockValue extends Value
return new BlockValue(blockState, world, pos);
}
@Override
public int hashCode()
{
if (world != null && pos != null )
return GlobalPos.create(world.getDimension().getType(), pos).hashCode();
return ("b"+getString()).hashCode();
}
public BlockPos getPos()
{
return pos;
@@ -0,0 +1,13 @@
package carpet.script.value;
public interface ContainerValueInterface
{
public Value put(Value where, Value value);
default Value put(Value where, Value value, Value conditions)
{
return put(where, value);
}
public Value get(Value where);
public boolean has(Value where);
public Value delete(Value where);
}
@@ -101,13 +101,13 @@ public class EntityValue extends Value
}
@Override
public boolean equals(Value v)
public boolean equals(Object v)
{
if (v instanceof EntityValue)
{
return entity.getEntityId()==((EntityValue) v).entity.getEntityId();
}
return super.equals(v);
return super.equals((Value)v);
}
@Override
@@ -138,6 +138,13 @@ public class EntityValue extends Value
return "entity";
}
@Override
public int hashCode()
{
return entity.hashCode();
}
public static Pair<EntityType<?>, Predicate<? super Entity>> getPredicate(String who)
{
Pair<EntityType<?>, Predicate<? super Entity>> res = entityPredicates.get(who);
@@ -386,21 +393,11 @@ public class EntityValue extends Value
put("nbt",(e, a) -> {
CompoundTag nbttagcompound = e.toTag((new CompoundTag()));
if (a==null)
return new NBTSerializableValue(nbttagcompound);//StringValue(nbttagcompound.toString());
NbtPathArgumentType.NbtPath path = NBTSerializableValue.cachePath(a.getString());
try
{
List<Tag> tags = path.get(nbttagcompound);
if (tags.size()==0)
return Value.NULL;
if (tags.size()==1)
return NBTSerializableValue.decodeTag(tags.get(0));
return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag).collect(Collectors.toList()));
}
catch (CommandSyntaxException ignored) { }
return Value.NULL;
return new NBTSerializableValue(nbttagcompound);
return new NBTSerializableValue(nbttagcompound).get(a);
});
}};
private static <Req extends Entity> Req assertEntityArgType(Class<Req> klass, Value arg)
{
if (!(arg instanceof EntityValue))
@@ -728,6 +725,6 @@ public class EntityValue extends Value
put("on_death", (c, e, f, l) -> ((EntityInterface)e).setDeathCallback(c, f, l));
put("on_removed", (c, e, f, l) -> ((EntityInterface)e).setRemovedCallback(c, f, l));
put("on_tick", (c, e, f, l) -> ((EntityInterface)e).setTickCallback(c, f, l));
put("on_damage", (c, e, f, l) -> ((EntityInterface)e).setDamageCallback(c, f, l));
put("on_damaged", (c, e, f, l) -> ((EntityInterface)e).setDamageCallback(c, f, l));
}};
}
@@ -43,5 +43,11 @@ public class FunctionSignatureValue extends Value
}
public List<String> getGlobals() {return globals;}
@Override
public int hashCode()
{
throw new UnsupportedOperationException("function signature value cannot be used as map key");
}
}
@@ -19,4 +19,10 @@ public class GlobalValue extends Value
{
return false;
}
@Override
public int hashCode()
{
throw new UnsupportedOperationException("global value cannot be used as map key");
}
}
@@ -44,6 +44,12 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
{
return stepp > 0?(current < limit):(current > limit);
}
@Override
public String getString()
{
return String.format("[%d, %d, ..., %d]",start, start+stepp, limit);
}
};
}
@@ -115,16 +121,11 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
}
@Override
public boolean equals(final Value o)
public boolean equals(final Object o)
{
return false;
}
@Override
public Value getElementAt(Value v2)
{
throw new InternalExpressionException("get element can only be obtained for regular lists");
}
@Override
public String getTypeString()
{
@@ -145,4 +146,10 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
((LazyListValue)copy).reset();
return copy;
}
@Override
public int hashCode()
{
return ("i"+getString()).hashCode();
}
}
@@ -4,16 +4,13 @@ import carpet.script.exception.InternalExpressionException;
import net.minecraft.item.ItemStack;
import net.minecraft.util.registry.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static java.lang.Math.abs;
public class ListValue extends AbstractListValue
public class ListValue extends AbstractListValue implements ContainerValueInterface
{
protected List<Value> items;
@Override
@@ -102,6 +99,7 @@ public class ListValue extends AbstractListValue
}
return output;
}
@Override
public void append(Value v)
{
items.add(v);
@@ -215,18 +213,11 @@ public class ListValue extends AbstractListValue
}
@Override
public boolean equals(final Value o)
public boolean equals(final Object 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 false;
if (this_size == 0) return true;
for (int i = 0; i < this_size; i++)
if (!this.items.get(i).equals(ol.items.get(i))) return false;
return true;
return getItems().equals(((ListValue) o).getItems());
}
return false;
}
@@ -275,6 +266,8 @@ public class ListValue extends AbstractListValue
super(list);
}
}
@Override
public int length()
{
return items.size();
@@ -313,7 +306,69 @@ public class ListValue extends AbstractListValue
}
@Override
public Value getElementAt(Value value)
public Value put(Value where, Value value, Value conditionValue)
{
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, or replace");
}
@Override
public Value put(Value ind, Value value)
{
return put(ind, value, true, false);
}
private Value put(Value ind, Value value, boolean replace, boolean extend)
{
if (ind == Value.NULL)
{
if (extend && value instanceof AbstractListValue)
{
((AbstractListValue) value).iterator().forEachRemaining((v)-> items.add(v));
}
else
{
items.add(value);
}
return items.get(items.size()-1);
}
else
{
int numitems = items.size();
int index = (int) NumericValue.asNumber(ind).getLong();
if (index < 0)
{
long range = abs(index) / numitems;
index += (range + 2) * numitems;
index = index % numitems;
}
if (replace)
{
while (index >= items.size()) items.add(Value.NULL);
return items.set(index, value);
}
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 );
return items.get(index+appendix.size()-1);
}
items.add(index, value);
return value;
}
}
@Override
public Value get(Value value)
{
long index = NumericValue.asNumber(value).getLong();
int numitems = items.size();
@@ -322,9 +377,34 @@ public class ListValue extends AbstractListValue
index = index % numitems;
return items.get((int)index);
}
@Override
public boolean has(Value where)
{
long index = NumericValue.asNumber(where).getLong();
return index >= 0 && index < items.size();
}
@Override
public Value delete(Value where)
{
long index = NumericValue.asNumber(where).getLong();
int numitems = items.size();
long range = abs(index)/numitems;
index += (range+2)*numitems;
index = index % numitems;
return items.remove((int)index);
}
@Override
public String getTypeString()
{
return "list";
}
@Override
public int hashCode()
{
return items.hashCode();
}
}
@@ -0,0 +1,208 @@
package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class MapValue extends AbstractListValue implements ContainerValueInterface
{
private Map<Value, Value> map;
private MapValue()
{
map = new HashMap<>();
}
public MapValue(List<Value> kvPairs)
{
this();
for (Value v : kvPairs)
{
put(v);
}
}
@Override
public Iterator<Value> iterator()
{
return map.keySet().iterator();
}
@Override
public String getString()
{
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()+"}";
}
@Override
public boolean getBoolean()
{
return !map.isEmpty();
}
@Override
public Value clone()
{
return new MapValue(map);
}
public MapValue(Map<Value,Value> other)
{
map = new HashMap<>(other);
}
@Override
public Value add(Value o)
{
throw new InternalExpressionException("cannot add to a map value");
}
@Override
public Value subtract(Value v)
{
throw new InternalExpressionException("cannot subtract to a map value");
}
@Override
public Value multiply(Value v)
{
throw new InternalExpressionException("cannot multiply to a map value");
}
@Override
public Value divide(Value v)
{
throw new InternalExpressionException("cannot divide to a map value");
}
public void put(Value v)
{
if (!(v instanceof ListValue))
{
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 elements");
}
map.put(pair.getItems().get(0), pair.getItems().get(1));
}
@Override
public void append(Value v)
{
put(v);
}
@Override
public int compareTo(Value o)
{
throw new InternalExpressionException("cannot compare to a map value");
}
@Override
public boolean equals(final Object o)
{
if (o instanceof MapValue)
{
return map.equals(((MapValue) o).map);
}
return false;
}
public Map<Value, Value> getMap()
{
return map;
}
public void extend(List<Value> subList)
{
for (Value v: subList) put(v);
}
@Override
public int length()
{
return map.size();
}
@Override
public Value in(Value value1)
{
if (map.containsKey(value1)) return value1;
return Value.NULL;
}
@Override
public Value slice(long from, long to)
{
throw new InternalExpressionException("cannot slice a map value");
}
@Override
public double readNumber()
{
return (double)map.size();
}
@Override
public Value get(Value v2)
{
return map.getOrDefault(v2, Value.NULL);
}
@Override
public boolean has(Value where)
{
return map.containsKey(where);
}
@Override
public Value delete(Value where)
{
Value ret = map.remove(where);
if (ret == null)
return Value.NULL;
return ret;
}
@Override
public Value put(Value key, Value value)
{
Value ret = map.put(key, value);
if (ret == null)
return Value.NULL;
return ret;
}
@Override
public String getTypeString()
{
return "map";
}
@Override
public int hashCode()
{
return map.hashCode();
}
}
@@ -14,23 +14,28 @@ import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.AbstractListTag;
import net.minecraft.nbt.AbstractNumberTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringNbtReader;
import net.minecraft.nbt.Tag;
import net.minecraft.util.math.BlockPos;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class NBTSerializableValue extends Value
public class NBTSerializableValue extends Value implements ContainerValueInterface
{
private String nbtString = null;
private Tag nbtTag = null;
private Supplier<CompoundTag> nbtSupplier = null;
private Supplier<Tag> nbtSupplier = null;
public NBTSerializableValue(ItemStack stack)
{
@@ -43,7 +48,7 @@ public class NBTSerializableValue extends Value
{
try
{
return (new StringNbtReader(new StringReader(nbtString))).parseCompoundTag();
return (new StringNbtReader(new StringReader(nbtString))).parseTag();
}
catch (CommandSyntaxException e)
{
@@ -52,6 +57,26 @@ public class NBTSerializableValue extends Value
};
}
public static NBTSerializableValue parseString(String nbtString)
{
Tag tag;
try
{
tag = (new StringNbtReader(new StringReader(nbtString))).parseTag();
}
catch (CommandSyntaxException e)
{
return null;
}
NBTSerializableValue value = new NBTSerializableValue(tag);
value.nbtString = nbtString;
return value;
}
public Value clone()
{
return new NBTSerializableValue(getTag().copy());
}
public NBTSerializableValue(Tag tag)
{
nbtTag = tag;
@@ -156,7 +181,7 @@ public class NBTSerializableValue extends Value
return slot;
}
public static Value decodeTag(Tag t)
private static Value decodeTag(Tag t)
{
if (t instanceof CompoundTag)
return new NBTSerializableValue(t);
@@ -166,19 +191,26 @@ public class NBTSerializableValue extends Value
return new StringValue(t.asString());
}
public Tag getTag()
private Tag getTag()
{
if (nbtTag == null)
nbtTag = nbtSupplier.get();
return nbtTag;
}
private void replaceTag(Tag newTag)
{
nbtTag = newTag;
nbtString = null;
nbtSupplier = null; // just to be sure
}
@Override
public boolean equals(final Value o)
public boolean equals(final Object o)
{
if (o instanceof NBTSerializableValue)
return getTag().equals(((NBTSerializableValue) o).getTag());
return super.equals(o);
return super.equals((Value)o);
}
@Override
@@ -207,6 +239,188 @@ public class NBTSerializableValue extends Value
}
}
@Override
public Value put(Value where, Value value)
{
return put(where, value, new StringValue("replace"));
}
@Override
public Value put(Value where, Value value, Value conditions)
{
/// WIP
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
Tag tagToInsert = value instanceof NBTSerializableValue ?
((NBTSerializableValue) value).getTag() :
new NBTSerializableValue(value.getString()).getTag();
Tag modifiedTag;
if (conditions instanceof NumericValue)
{
modifiedTag = modify_insert((int)((NumericValue) conditions).getLong(), path, tagToInsert);
}
else
{
String ops = conditions.getString();
if (ops.equalsIgnoreCase("merge"))
{
modifiedTag = modify_merge(path, tagToInsert);
}
else if (ops.equalsIgnoreCase("replace"))
{
modifiedTag = modify_replace(path, tagToInsert);
}
else
{
return this;
}
}
if (modifiedTag != null)
{
replaceTag(modifiedTag);
}
return this;
}
private Tag modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement)
{
return modify_insert(index, nbtPath, newElement, this.getTag().copy());
}
private Tag modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement, Tag currentTag)
{
Collection<Tag> targets;
try
{
targets = nbtPath.putIfAbsent(currentTag, ListTag::new);
}
catch (CommandSyntaxException e)
{
return null;
}
boolean modified = false;
for (Tag target : targets)
{
if (!(target instanceof AbstractListTag))
{
continue;
}
try
{
AbstractListTag<?> targetList = (AbstractListTag) target;
if (!targetList.addTag(index < 0 ? targetList.size() + index + 1 : index, newElement.copy()))
return null;
modified = true;
}
catch (IndexOutOfBoundsException ignored)
{
}
}
return modified?currentTag:null;
}
private Tag modify_merge(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
{
if (!(replacement instanceof CompoundTag))
{
return getTag();
}
Tag originalTag = getTag().copy();
try
{
for (Tag target : nbtPath.putIfAbsent(originalTag, CompoundTag::new))
{
if (!(target instanceof CompoundTag))
{
continue;
}
((CompoundTag) target).copyFrom((CompoundTag) replacement);
}
}
catch (CommandSyntaxException ignored) { }
return originalTag;
}
private Tag modify_replace(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
{
Tag originalTag = getTag().copy();
String pathText = nbtPath.toString();
if (pathText.endsWith("]")) // workaround for array replacement or item in the array replacement
{
if (nbtPath.remove(originalTag)==0)
return null;
Pattern pattern = Pattern.compile("\\[[^\\[]*]$");
Matcher matcher = pattern.matcher(pathText);
if (!matcher.find()) // malformed path
{
return null;
}
String arrAccess = matcher.group();
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)
{
return null;
}
}
NbtPathArgumentType.NbtPath newPath = cachePath(pathText.substring(0, pathText.length()-arrAccess.length()));
return modify_insert(pos,newPath,replacement, originalTag);
}
try
{
nbtPath.put(originalTag, () -> replacement);
}
catch (CommandSyntaxException e)
{
return null;
}
return originalTag;
}
@Override
public Value get(Value value)
{
NbtPathArgumentType.NbtPath path = cachePath(value.getString());
try
{
List<Tag> tags = path.get(getTag());
if (tags.size()==0)
return Value.NULL;
if (tags.size()==1)
return NBTSerializableValue.decodeTag(tags.get(0));
return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag).collect(Collectors.toList()));
}
catch (CommandSyntaxException ignored) { }
return Value.NULL;
}
@Override
public boolean has(Value where)
{
return cachePath(where.getString()).count(getTag()) > 0;
}
@Override
public Value delete(Value where)
{
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
Tag tag = getTag().copy();
int removed = path.remove(tag);
if (removed > 0) replaceTag(tag);
return new NumericValue(removed);
}
public static class InventoryLocator
{
public Object owner;
@@ -223,7 +437,7 @@ public class NBTSerializableValue extends Value
}
private static Map<String, NbtPathArgumentType.NbtPath> pathCache = new HashMap<>();
public static NbtPathArgumentType.NbtPath cachePath(String arg)
private static NbtPathArgumentType.NbtPath cachePath(String arg)
{
NbtPathArgumentType.NbtPath res = pathCache.get(arg);
if (res != null)
@@ -242,23 +456,6 @@ public class NBTSerializableValue extends Value
return res;
}
@Override
public Value getElementAt(Value value)
{
NbtPathArgumentType.NbtPath path = cachePath(value.getString());
try
{
List<Tag> tags = path.get(getTag());
if (tags.size()==0)
return Value.NULL;
if (tags.size()==1)
return NBTSerializableValue.decodeTag(tags.get(0));
return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag).collect(Collectors.toList()));
}
catch (CommandSyntaxException ignored) { }
return Value.NULL;
}
@Override
public String getTypeString()
{
@@ -28,7 +28,7 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
public NullValue() {super(0.0D);}
@Override
public boolean equals(final Value o)
public boolean equals(final Object o)
{
return o instanceof NullValue;
}
@@ -44,4 +44,10 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
{
return "null";
}
@Override
public int hashCode()
{
return 0;
}
}
@@ -125,7 +125,7 @@ public class NumericValue extends Value
return getString().compareTo(o.getString());
}
@Override
public boolean equals(Value o)
public boolean equals(Object o)
{
if (o instanceof NullValue)
{
@@ -133,7 +133,7 @@ public class NumericValue extends Value
}
if (o instanceof NumericValue)
{
return !this.subtract(o).getBoolean();
return !this.subtract((Value) o).getBoolean();
}
return super.equals(o);
}
@@ -179,4 +179,13 @@ public class NumericValue extends Value
return "number";
}
@Override
public int hashCode()
{
if (Math.abs(Math.floor(value + 0.5D)-value) < epsilon) // is sufficiently close to the integer value
return Long.hashCode(getLong());
return Double.hashCode(value);
}
}
+18 -5
View File
@@ -115,6 +115,16 @@ public abstract class Value implements Comparable<Value>, Cloneable
}
return getString().compareTo(o.getString());
}
@Override // for hashmap key access
public boolean equals(final Object o)
{
if (o instanceof Value)
return this.compareTo((Value) o)==0;
return false;
}
// for general use
public boolean equals(final Value o)
{
return this.compareTo(o)==0;
@@ -173,13 +183,16 @@ public abstract class Value implements Comparable<Value>, Cloneable
return (long)readNumber();
}
public Value getElementAt(Value v2)
{
throw new InternalExpressionException("get element can only be obtained for lists and nbt values");
}
public String getTypeString()
{
throw new InternalExpressionException("How did you get here? Cannot get type of an intenal type.");
}
@Override
public int hashCode()
{
String stringVal = getString();
if (stringVal.isEmpty()) return 0;
return ("s"+stringVal).hashCode();
}
}