diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 20ffa81d..21efb79a 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -519,6 +519,12 @@ Regardless of the options selected, the result could be: - block value if block is in reach, or - a coordinate triple if `'exact'` option was used and hit was successful. +### `query(e, 'attribute')` `query(e, 'attribute', name)` + +returns the value of an attribute of the living entity. If the name is not provided, +returns a map of all attributes and values of this entity. If an attribute doesn't apply to the entity, +or the entity is not a living entity, `null` is returned. + ### `query(e, 'brain', memory)` Retrieves brain memory for entity. Possible memory units highly depend on the game version. Brain is availalble diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 18bd5df0..4534d667 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -1048,6 +1048,37 @@ public class CarpetEventServer public void onWorldEvent(ServerWorld world, BlockPos pos) { } public void onWorldEventFlag(ServerWorld world, BlockPos pos, int flag) { } public void onCarpetRuleChanges(ParsedRule rule, ServerCommandSource source) { } + public void onCustomPlayerEvent(ServerPlayerEntity player, Object ... args) + { + if (handler.reqArgs != (args.length+1)) + throw new InternalExpressionException("Expected "+handler.reqArgs+" arguments for "+name+", got "+(args.length+1)); + handler.call( + () -> { + List valArgs = new ArrayList<>(); + valArgs.add(EntityValue.of(player)); + for (Object o: args) + { + valArgs.add(ValueConversions.guess(player.getServerWorld(), o)); + } + return valArgs; + }, player::getCommandSource + ); + } + public void onCustomWorldEvent(ServerWorld world, Object ... args) + { + if (handler.reqArgs != args.length) + throw new InternalExpressionException("Expected "+handler.reqArgs+" arguments for "+name+", got "+args.length); + handler.call( + () -> { + List valArgs = new ArrayList<>(); + for (Object o: args) + { + valArgs.add(ValueConversions.guess(world, o)); + } + return valArgs; + }, () -> CarpetServer.minecraft_server.getCommandSource().withWorld(world) + ); + } } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 52bb189f..e8c3e9c6 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -25,6 +25,8 @@ import net.minecraft.entity.ai.brain.Memory; import net.minecraft.entity.EntityGroup; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.ai.pathing.Path; +import net.minecraft.entity.attribute.AttributeContainer; +import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.entity.vehicle.AbstractMinecartEntity; import net.minecraft.nbt.NbtString; @@ -848,6 +850,22 @@ public class EntityValue extends Value return Value.NULL; }); + put("attribute", (e, a) ->{ + if (!(e instanceof LivingEntity)) return Value.NULL; + LivingEntity el = (LivingEntity)e; + if (a == null) + { + AttributeContainer container = el.getAttributes(); + return MapValue.wrap(Registry.ATTRIBUTE.stream().filter(container::hasAttribute).collect(Collectors.toMap(aa -> ValueConversions.of(Registry.ATTRIBUTE.getId(aa)), aa -> NumericValue.of(container.getValue(aa))))); + } + Identifier id = new Identifier(a.getString()); + EntityAttribute attrib = Registry.ATTRIBUTE.getOrEmpty(id).orElseThrow( + () -> new InternalExpressionException("Unknown attribute: "+a.getString()) + ); + if (!el.getAttributes().hasAttribute(attrib)) return Value.NULL; + return NumericValue.of(el.getAttributeValue(attrib)); + }); + put("nbt",(e, a) -> { NbtCompound nbttagcompound = e.writeNbt((new NbtCompound())); if (a==null) diff --git a/src/main/java/carpet/script/value/ValueConversions.java b/src/main/java/carpet/script/value/ValueConversions.java index d0c92ecf..3cf8c8e8 100644 --- a/src/main/java/carpet/script/value/ValueConversions.java +++ b/src/main/java/carpet/script/value/ValueConversions.java @@ -34,6 +34,7 @@ import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ColumnPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; @@ -401,4 +402,26 @@ public class ValueConversions predicateData.getCMDataTag() == null?Value.NULL:new NBTSerializableValue(predicateData.getCMDataTag()) ); } + + public static Value guess(ServerWorld serverWorld, Object o) { + if (o instanceof List) + return ListValue.wrap(((List) o).stream().map(oo -> guess(serverWorld, oo)).collect(Collectors.toList())); + if (o instanceof BlockPos) + return new BlockValue(null, serverWorld, (BlockPos)o); + if (o instanceof Entity) + return EntityValue.of((Entity) o); + if (o instanceof Vec3d) + return of((Vec3d)o); + if (o instanceof Vec3i) + return of(new BlockPos((Vec3i)o)); + if (o instanceof ItemStack) + return of((ItemStack)o); + if (o instanceof Boolean) + return BooleanValue.of((Boolean) o); + if (o instanceof Number) + return NumericValue.of((Number) o); + if (o instanceof Identifier) + return of((Identifier)o); + return StringValue.of(o.toString()); + } }