Merge branch 'master' into 1.17
# Conflicts: # src/main/java/carpet/script/api/Entities.java
This commit is contained in:
commit
02a25c0c99
16 files changed
+189
-33
No files matched your search
+32
-6
@@ -1757,7 +1757,8 @@ Here is the gist of the Minecraft related functions. Otherwise the CarpetScript
|
||||
## App structure
|
||||
|
||||
The main delivery method for scarpet programs into the game is in the form of apps in `*.sc` files located in the world `scripts`
|
||||
folder. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world.
|
||||
folder, flat. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world,
|
||||
and here you can actually organize them in folders.
|
||||
When loaded (via `/script load` command, etc.), the game will run the content of the app once, regardless of its scope
|
||||
(more about the app scopes below), without executing of any functions, unless called directly, and with the exception of the
|
||||
`__config()` function, if present, which will be executed once. Loading the app will also bind specific
|
||||
@@ -2919,7 +2920,9 @@ to the `regular` group.
|
||||
* `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
|
||||
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`,
|
||||
`chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`,
|
||||
`egg`, `elder_guardian`, `end_crystal`, `ender_dragon`, `ender_pearl`, `enderman`, `endermite`, `evoker`,
|
||||
@@ -3076,13 +3079,21 @@ List of entities riding the entity.
|
||||
|
||||
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')`
|
||||
|
||||
@@ -3744,6 +3755,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.
|
||||
|
||||
### 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)`
|
||||
|
||||
Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets),
|
||||
@@ -3940,6 +3959,13 @@ if it accepts required number of parameters.
|
||||
Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance
|
||||
is responsible independently from handling their events, so a global event may be executed multiple times for each player.
|
||||
|
||||
### `__on_server_starts()`
|
||||
Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`.
|
||||
|
||||
### `__on_server_shuts_down()`
|
||||
Event triggers when the server started the shutdown process, before `__on_close()` is executed. Unlike `__on_close()`, it doesn't
|
||||
trigger with `/reload`.
|
||||
|
||||
### `__on_tick()`
|
||||
Event triggers at the beginning of each tick, located in the overworld. You can use `in_dimension()`
|
||||
to access other dimensions from there.
|
||||
|
||||
@@ -52,7 +52,9 @@ to the `regular` group.
|
||||
* `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
|
||||
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`,
|
||||
`chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`,
|
||||
`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.
|
||||
|
||||
### `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')`
|
||||
|
||||
|
||||
@@ -32,6 +32,13 @@ if it accepts required number of parameters.
|
||||
Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance
|
||||
is responsible independently from handling their events, so a global event may be executed multiple times for each player.
|
||||
|
||||
### `__on_server_starts()`
|
||||
Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`.
|
||||
|
||||
### `__on_server_shuts_down()`
|
||||
Event triggers when the server started the shutdown process, before `__on_close()` is executed. Unlike `__on_close()`, it doesn't
|
||||
trigger with `/reload`.
|
||||
|
||||
### `__on_tick()`
|
||||
Event triggers at the beginning of each tick, located in the overworld. You can use `in_dimension()`
|
||||
to access other dimensions from there.
|
||||
|
||||
@@ -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.
|
||||
|
||||
### 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)`
|
||||
|
||||
Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets),
|
||||
|
||||
@@ -6,7 +6,8 @@ Here is the gist of the Minecraft related functions. Otherwise the CarpetScript
|
||||
## App structure
|
||||
|
||||
The main delivery method for scarpet programs into the game is in the form of apps in `*.sc` files located in the world `scripts`
|
||||
folder. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world.
|
||||
folder, flat. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world,
|
||||
and here you can actually organize them in folders.
|
||||
When loaded (via `/script load` command, etc.), the game will run the content of the app once, regardless of its scope
|
||||
(more about the app scopes below), without executing of any functions, unless called directly, and with the exception of the
|
||||
`__config()` function, if present, which will be executed once. Loading the app will also bind specific
|
||||
|
||||
@@ -52,6 +52,8 @@ inventory_remove
|
||||
inventory_set
|
||||
inventory_size
|
||||
item_category
|
||||
item_list
|
||||
item_tags
|
||||
last_tick_times
|
||||
light
|
||||
liquid
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -102,9 +102,9 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
|
||||
|
||||
public static void onServerLoadedWorlds(MinecraftServer minecraftServer)
|
||||
{
|
||||
HopperCounter.resetAll(minecraftServer);
|
||||
extensions.forEach(e -> e.onServerLoadedWorlds(minecraftServer));
|
||||
scriptServer.initializeForWorld();
|
||||
HopperCounter.resetAll(minecraftServer);
|
||||
}
|
||||
|
||||
public static void tick(MinecraftServer server)
|
||||
@@ -169,9 +169,9 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
|
||||
|
||||
public static void onServerClosed(MinecraftServer server)
|
||||
{
|
||||
if (scriptServer != null) scriptServer.onClose();
|
||||
ServerNetworkHandler.close();
|
||||
currentCommandDispatcher = null;
|
||||
if (scriptServer != null) scriptServer.onClose();
|
||||
|
||||
LoggerRegistry.stopLoggers();
|
||||
extensions.forEach(e -> e.onServerClosed(server));
|
||||
|
||||
@@ -431,7 +431,7 @@ public class CarpetSettings
|
||||
extra = "if /script is enabled",
|
||||
category = SCARPET
|
||||
)
|
||||
public static boolean scriptsAutoload = false;
|
||||
public static boolean scriptsAutoload = true;
|
||||
|
||||
@Rule(desc = "Enables /player command to control/spawn players", category = COMMAND)
|
||||
public static String commandPlayer = "ops";
|
||||
|
||||
@@ -309,6 +309,30 @@ public class CarpetEventServer
|
||||
return events;
|
||||
}
|
||||
|
||||
public static final Event START = new Event("server_starts", 0, true)
|
||||
{
|
||||
@Override
|
||||
public void onTick()
|
||||
{
|
||||
handler.call(Collections::emptyList, () ->
|
||||
CarpetServer.minecraft_server.getCommandSource().
|
||||
withWorld(CarpetServer.minecraft_server.getWorld(World.OVERWORLD))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
public static final Event SHUTDOWN = new Event("server_shuts_down", 0, true)
|
||||
{
|
||||
@Override
|
||||
public void onTick()
|
||||
{
|
||||
handler.call(Collections::emptyList, () ->
|
||||
CarpetServer.minecraft_server.getCommandSource().
|
||||
withWorld(CarpetServer.minecraft_server.getWorld(World.OVERWORLD))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
public static final Event TICK = new Event("tick", 0, true)
|
||||
{
|
||||
@Override
|
||||
|
||||
@@ -217,7 +217,7 @@ public class CarpetScriptHost extends ScriptHost
|
||||
if (!(ret instanceof MapValue)) return false;
|
||||
Map<Value, Value> config = ((MapValue) ret).getMap();
|
||||
setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player"));
|
||||
persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.FALSE).getBoolean();
|
||||
persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.TRUE).getBoolean();
|
||||
// read custom arguments
|
||||
Value arguments = config.get(StringValue.of("arguments"));
|
||||
if (arguments != null)
|
||||
|
||||
@@ -122,13 +122,12 @@ public class CarpetScriptServer
|
||||
});
|
||||
if (CarpetSettings.scriptsAutoload)
|
||||
{
|
||||
Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps");
|
||||
for (String moduleName: listAvailableModules(false))
|
||||
{
|
||||
addScriptHost(server.getCommandSource(), moduleName, null, true, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
CarpetEventServer.Event.START.onTick();
|
||||
}
|
||||
|
||||
public Module getModule(String name, boolean allowLibraries)
|
||||
@@ -149,7 +148,7 @@ public class CarpetScriptServer
|
||||
{
|
||||
Path globalFolder = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts");
|
||||
Files.createDirectories(globalFolder);
|
||||
scriptPath = Files.list(globalFolder)
|
||||
scriptPath = Files.walk(globalFolder)
|
||||
.filter(script -> script.getFileName().toString().equalsIgnoreCase(name + ".sc") ||
|
||||
(allowLibraries && script.getFileName().toString().equalsIgnoreCase(name + ".scl")))
|
||||
.findFirst();
|
||||
@@ -194,7 +193,7 @@ public class CarpetScriptServer
|
||||
try {
|
||||
Path worldScripts = server.getSavePath(WorldSavePath.ROOT).resolve("scripts");
|
||||
Files.createDirectories(worldScripts);
|
||||
Files.walk(worldScripts)
|
||||
Files.list(worldScripts)
|
||||
.filter(f -> f.toString().endsWith(".sc"))
|
||||
.forEach(f -> moduleNames.add(f.getFileName().toString().replaceFirst("\\.sc$","").toLowerCase(Locale.ROOT)));
|
||||
|
||||
@@ -490,6 +489,7 @@ public class CarpetScriptServer
|
||||
|
||||
public void onClose()
|
||||
{
|
||||
CarpetEventServer.Event.SHUTDOWN.onTick();
|
||||
for (ScriptHost host : modules.values())
|
||||
{
|
||||
host.onClose();
|
||||
|
||||
@@ -23,6 +23,7 @@ import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
@@ -34,6 +35,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -183,8 +185,9 @@ public class Entities {
|
||||
expression.addLazyFunction("entity_list", 1, (c, t, lv) ->
|
||||
{
|
||||
String who = lv.get(0).evalValue(c).getString();
|
||||
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who);
|
||||
List<? extends Entity> entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate);
|
||||
ServerCommandSource source = ((CarpetContext)c).s;
|
||||
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getMinecraftServer());
|
||||
List<? extends Entity> entityList = source.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate);
|
||||
Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList()));
|
||||
return (_c, _t ) -> retval;
|
||||
});
|
||||
@@ -212,8 +215,8 @@ public class Entities {
|
||||
throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument");
|
||||
Vec3d range = rangeLocator.vec;
|
||||
Box area = centerBox.expand(range.x, range.y, range.z);
|
||||
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who);
|
||||
List<? extends Entity> entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate);
|
||||
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.s.getMinecraftServer());
|
||||
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()));
|
||||
return (_c, _t ) -> retval;
|
||||
});
|
||||
@@ -238,7 +241,9 @@ public class Entities {
|
||||
Value v = lv.get(0).evalValue(c);
|
||||
if (!(v instanceof EntityValue))
|
||||
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;
|
||||
if (lv.size()==2)
|
||||
retval = ((EntityValue) v).get(what, null);
|
||||
@@ -269,11 +274,13 @@ public class Entities {
|
||||
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");
|
||||
String desc = (lv.size() == 1)?lv.get(0).getString():"*";
|
||||
return EntityValue.getEntityDescriptor(desc).listValue;
|
||||
String desc = (lv.size() == 1)?lv.get(0).evalValue(c).getString():"*";
|
||||
Value ret = EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue;
|
||||
return (_c, _t) -> ret;
|
||||
});
|
||||
|
||||
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())
|
||||
: Collections.singletonList(entityValue.getString());
|
||||
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);
|
||||
CarpetEventServer events = ((CarpetScriptHost)c.host).getScriptServer().events;
|
||||
if (funArg.function == null)
|
||||
|
||||
@@ -12,6 +12,7 @@ import carpet.script.value.NullValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.script.value.ValueConversions;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.command.argument.ItemStackArgument;
|
||||
@@ -32,6 +33,7 @@ import net.minecraft.recipe.ShapedRecipe;
|
||||
import net.minecraft.recipe.ShapelessRecipe;
|
||||
import net.minecraft.recipe.SpecialCraftingRecipe;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.tag.TagManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.InvalidIdentifierException;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -40,6 +42,7 @@ import net.minecraft.util.registry.Registry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Inventories {
|
||||
public static void apply(Expression expression)
|
||||
@@ -60,6 +63,43 @@ public class Inventories {
|
||||
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) ->
|
||||
{
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
|
||||
@@ -224,10 +224,28 @@ public class EntityValue extends Value
|
||||
return entity.hashCode();
|
||||
}
|
||||
|
||||
public static EntityClassDescriptor getEntityDescriptor(String who)
|
||||
public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server)
|
||||
{
|
||||
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;
|
||||
//TODO add more here like search by tags, or type
|
||||
//if (who.startsWith('tag:'))
|
||||
@@ -416,8 +434,21 @@ public class EntityValue extends Value
|
||||
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("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("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_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("head_yaw", (e, a)-> {
|
||||
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)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user