added item_list, item_tags to support item tags as well as options for entities to support entity type tags. fixes #382

This commit is contained in:
gnembon committed 2020-12-07 00:12:55 -04:00
1 parent ac6b3c7f48
commit a0067d0d61
8 files changed
+116 -18

No files matched your search

+15 -5
View File
@@ -52,7 +52,9 @@ to the `regular` group.
* `monster`, `creature`, `ambient`, `water_creature`, `water_ambient`, `misc` - another categorization of * `monster`, `creature`, `ambient`, `water_creature`, `water_ambient`, `misc` - another categorization of
living entities based on their spawn group. Negative descriptor resolves to all living types that don't belong to that living entities based on their spawn group. Negative descriptor resolves to all living types that don't belong to that
category. category.
* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command: * All entity tags including those provided with datapacks. Built-in entity tags include: `skeletons`, `raiders`,
`beehive_inhabitors` (bee, duh), `arrows` and `impact_projectiles`.
* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command:
`area_effect_cloud`, `armor_stand`, `arrow`, `bat`, `bee`, `blaze`, `boat`, `cat`, `cave_spider`, `chest_minecart`, `area_effect_cloud`, `armor_stand`, `arrow`, `bat`, `bee`, `blaze`, `boat`, `cat`, `cave_spider`, `chest_minecart`,
`chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`, `chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`,
`egg`, `elder_guardian`, `end_crystal`, `ender_dragon`, `ender_pearl`, `enderman`, `endermite`, `evoker`, `egg`, `elder_guardian`, `end_crystal`, `ender_dragon`, `ender_pearl`, `enderman`, `endermite`, `evoker`,
@@ -209,13 +211,21 @@ List of entities riding the entity.
Entity that `e` rides. Entity that `e` rides.
### `query(e, 'tags')` ### `query(e, 'scoreboard_tags')`, `query(e, 'tags')`(deprecated)
List of entity's tags. List of entity's scoreboard tags.
### `query(e, 'has_tag',tag)` ### `query(e, 'has_scoreboard_tag',tag)`, `query(e, 'has_tag',tag)`(deprecated)
Boolean, true if the entity is marked with `tag`. Boolean, true if the entity is marked with a `tag` scoreboad tag.
### `query(e, 'entity_tags')`
List of entity tags assigned to the type this entity represents.
### `query(e, 'has_entity_tag', tag)`
Returns `true` if the entity matches that entity tag, `false` if it doesn't, and `null` if the tag is not valid.
### `query(e, 'is_burning')` ### `query(e, 'is_burning')`
+8
View File
@@ -28,6 +28,14 @@ an inventory, all API functions typically do nothing and return null.
Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item.
### item_list(tag?)
With no arguments, returns a list of all items in the game. With an item tag provided, list items matching the tag, or `null` if tag is not valid.
### item_tags(item, tag?)
Returns list of tags the item belongs to, or, if tag is provided, `true` if an item maches the tag, `false` if it doesn't and `null` if that's not a valid tag
### `stack_limit(item)` ### `stack_limit(item)`
Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets), Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets),
@@ -52,6 +52,8 @@ inventory_remove
inventory_set inventory_set
inventory_size inventory_size
item_category item_category
item_list
item_tags
last_tick_times last_tick_times
light light
liquid liquid
@@ -68,7 +68,7 @@
player spawn entity_id entity_list entity_area entity_selector query modify entity_event entity_load_handler entity_types player spawn entity_id entity_list entity_area entity_selector query modify entity_event entity_load_handler entity_types
stack_limit item_category recipe_data crafting_remaining_item item_list item_tags stack_limit item_category recipe_data crafting_remaining_item
inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item
+16 -9
View File
@@ -23,6 +23,7 @@ import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@@ -34,6 +35,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -183,8 +185,9 @@ public class Entities {
expression.addLazyFunction("entity_list", 1, (c, t, lv) -> expression.addLazyFunction("entity_list", 1, (c, t, lv) ->
{ {
String who = lv.get(0).evalValue(c).getString(); String who = lv.get(0).evalValue(c).getString();
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who); ServerCommandSource source = ((CarpetContext)c).s;
List<Entity> entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate); EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getMinecraftServer());
List<Entity> entityList = source.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate);
Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList()));
return (_c, _t ) -> retval; return (_c, _t ) -> retval;
}); });
@@ -212,8 +215,8 @@ public class Entities {
throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument"); throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument");
Vec3d range = rangeLocator.vec; Vec3d range = rangeLocator.vec;
Box area = centerBox.expand(range.x, range.y, range.z); Box area = centerBox.expand(range.x, range.y, range.z);
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who); EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.s.getMinecraftServer());
List<? extends Entity> entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate); List<? extends Entity> entityList = cc.s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate);
Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList()));
return (_c, _t ) -> retval; return (_c, _t ) -> retval;
}); });
@@ -238,7 +241,9 @@ public class Entities {
Value v = lv.get(0).evalValue(c); Value v = lv.get(0).evalValue(c);
if (!(v instanceof EntityValue)) if (!(v instanceof EntityValue))
throw new InternalExpressionException("First argument to query should be an entity"); throw new InternalExpressionException("First argument to query should be an entity");
String what = lv.get(1).evalValue(c).getString(); String what = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
if (what.equals("tags"))
c.host.issueDeprecation("'tags' for entity querying");
Value retval; Value retval;
if (lv.size()==2) if (lv.size()==2)
retval = ((EntityValue) v).get(what, null); retval = ((EntityValue) v).get(what, null);
@@ -269,11 +274,13 @@ public class Entities {
return (cc, tt) -> v; return (cc, tt) -> v;
}); });
expression.addFunction("entity_types", (lv) -> expression.addLazyFunction("entity_types", -1, (c, t, lv) ->
{ {
if (lv.size() > 1) throw new InternalExpressionException("'entity_types' requires one or no arguments"); if (lv.size() > 1) throw new InternalExpressionException("'entity_types' requires one or no arguments");
String desc = (lv.size() == 1)?lv.get(0).getString():"*"; String desc = (lv.size() == 1)?lv.get(0).evalValue(c).getString():"*";
return EntityValue.getEntityDescriptor(desc).listValue; Value ret = EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue;
return (_c, _t) -> ret;
}); });
expression.addLazyFunction("entity_load_handler", -1, (c, t, lv) -> expression.addLazyFunction("entity_load_handler", -1, (c, t, lv) ->
@@ -285,7 +292,7 @@ public class Entities {
? ((ListValue) entityValue).getItems().stream().map(Value::getString).collect(Collectors.toList()) ? ((ListValue) entityValue).getItems().stream().map(Value::getString).collect(Collectors.toList())
: Collections.singletonList(entityValue.getString()); : Collections.singletonList(entityValue.getString());
Set<EntityType<? extends Entity>> types = new HashSet<>(); Set<EntityType<? extends Entity>> types = new HashSet<>();
descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s).typeList)); descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).s.getMinecraftServer()).typeList));
FunctionArgument<LazyValue> funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); FunctionArgument<LazyValue> funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false);
CarpetEventServer events = ((CarpetScriptHost)c.host).getScriptServer().events; CarpetEventServer events = ((CarpetScriptHost)c.host).getScriptServer().events;
if (funArg.function == null) if (funArg.function == null)
@@ -12,6 +12,7 @@ import carpet.script.value.NullValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.argument.ItemStackArgument; import net.minecraft.command.argument.ItemStackArgument;
@@ -32,6 +33,7 @@ import net.minecraft.recipe.ShapedRecipe;
import net.minecraft.recipe.ShapelessRecipe; import net.minecraft.recipe.ShapelessRecipe;
import net.minecraft.recipe.SpecialCraftingRecipe; import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.tag.TagManager;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.InvalidIdentifierException;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@@ -40,6 +42,7 @@ import net.minecraft.util.registry.Registry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class Inventories { public class Inventories {
public static void apply(Expression expression) public static void apply(Expression expression)
@@ -60,6 +63,43 @@ public class Inventories {
return (_c, _t) -> res; return (_c, _t) -> res;
}); });
expression.addLazyFunction("item_list", -1, (c, t, lv) ->
{
if (lv.size() == 0)
{
Value res = ListValue.wrap(Registry.ITEM.getIds().stream().map(ValueConversions::of).collect(Collectors.toList()));
return (cc, tt) -> res;
}
CarpetContext cc = (CarpetContext)c;
TagManager tagManager = cc.s.getMinecraftServer().getTagManager();
String tag = lv.get(0).evalValue(c).getString();
net.minecraft.tag.Tag<Item> itemTag = tagManager.getItems().getTag(new Identifier(tag));
if (itemTag == null) return LazyValue.NULL;
Value ret = ListValue.wrap(itemTag.values().stream().map(b -> ValueConversions.of(Registry.ITEM.getId(b))).collect(Collectors.toList()));
return (_c, _t) -> ret;
});
expression.addLazyFunction("item_tags", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
TagManager tagManager = cc.s.getMinecraftServer().getTagManager();
if (lv.size() == 0)
{
Value ret = ListValue.wrap(tagManager.getItems().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList()));
return (_c, _t) -> ret;
}
Item item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()).getItem();
if (lv.size() == 1)
{
Value ret = ListValue.wrap(tagManager.getItems().getTagsFor(item).stream().map(ValueConversions::of).collect(Collectors.toList()));
return (_c, _t) -> ret;
}
String tag = lv.get(1).evalValue(c).getString();
net.minecraft.tag.Tag<Item> itemTag = tagManager.getItems().getTag(new Identifier(tag));
if (itemTag == null) return LazyValue.NULL;
return item.isIn(itemTag)?LazyValue.TRUE:LazyValue.FALSE;
});
expression.addLazyFunction("recipe_data", -1, (c, t, lv) -> expression.addLazyFunction("recipe_data", -1, (c, t, lv) ->
{ {
CarpetContext cc = (CarpetContext)c; CarpetContext cc = (CarpetContext)c;
@@ -223,10 +223,28 @@ public class EntityValue extends Value
return entity.hashCode(); return entity.hashCode();
} }
public static EntityClassDescriptor getEntityDescriptor(String who) public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server)
{ {
EntityClassDescriptor eDesc = EntityClassDescriptor.byName.get(who); EntityClassDescriptor eDesc = EntityClassDescriptor.byName.get(who);
if (eDesc == null) throw new InternalExpressionException(who+" is not a valid entity descriptor"); if (eDesc == null)
{
boolean positive = true;
if (who.startsWith("!"))
{
positive = false;
who = who.substring(1);
}
net.minecraft.tag.Tag<EntityType<?>> eTag = server.getTagManager().getEntityTypes().getTag(new Identifier(who));
if (eTag == null) throw new InternalExpressionException(who+" is not a valid entity descriptor");
if (positive)
{
return new EntityClassDescriptor(null, e -> eTag.contains(e.getType()) && e.isAlive(), eTag.values().stream());
}
else
{
return new EntityClassDescriptor(null, e -> !eTag.contains(e.getType()) && e.isAlive(), Registry.ENTITY_TYPE.stream().filter(et -> !eTag.contains(et)));
}
}
return eDesc; return eDesc;
//TODO add more here like search by tags, or type //TODO add more here like search by tags, or type
//if (who.startsWith('tag:')) //if (who.startsWith('tag:'))
@@ -401,8 +419,21 @@ public class EntityValue extends Value
put("passengers", (e, a) -> ListValue.wrap(e.getPassengerList().stream().map(EntityValue::new).collect(Collectors.toList()))); 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("mount", (e, a) -> (e.getVehicle()!=null)?new EntityValue(e.getVehicle()):Value.NULL);
put("unmountable", (e, a) -> new NumericValue(((EntityInterface)e).isPermanentVehicle())); put("unmountable", (e, a) -> new NumericValue(((EntityInterface)e).isPermanentVehicle()));
// deprecated
put("tags", (e, a) -> ListValue.wrap(e.getScoreboardTags().stream().map(StringValue::new).collect(Collectors.toList()))); put("tags", (e, a) -> ListValue.wrap(e.getScoreboardTags().stream().map(StringValue::new).collect(Collectors.toList())));
put("scoreboard_tags", (e, a) -> ListValue.wrap(e.getScoreboardTags().stream().map(StringValue::new).collect(Collectors.toList())));
put("entity_tags", (e, a) -> ListValue.wrap(e.getServer().getTagManager().getEntityTypes().getTagsFor(e.getType()).stream().map(ValueConversions::of).collect(Collectors.toList())));
// deprecated
put("has_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString()))); put("has_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString())));
put("has_scoreboard_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString())));
put("has_entity_tag", (e, a) -> {
net.minecraft.tag.Tag<EntityType<?>> tag = e.getServer().getTagManager().getEntityTypes().getTag(new Identifier(a.getString()));
if (tag == null) return Value.NULL;
return new NumericValue(e.getType().isIn(tag));
});
put("yaw", (e, a)-> new NumericValue(e.yaw)); put("yaw", (e, a)-> new NumericValue(e.yaw));
put("head_yaw", (e, a)-> { put("head_yaw", (e, a)-> {
if (e instanceof LivingEntity) if (e instanceof LivingEntity)
@@ -267,7 +267,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
} }
} }
private static Map<String,ItemStackArgument> itemCache = new HashMap<>(); private static final Map<String,ItemStackArgument> itemCache = new HashMap<>();
public static ItemStackArgument parseItem(String itemString) public static ItemStackArgument parseItem(String itemString)
{ {