diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 844eedd7..f6219452 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -74,10 +74,13 @@ belonging to that group. Returns entities of a specified type in an area centered on `center` and at most `distance` blocks away from -the center point. Uses the same `type` selectors as `entities_list`. +the center point/area. Uses the same `type` selectors as `entities_list`. `center` and `distance` can either be a triple of coordinates or three consecutive arguments for `entity_area`. `center` can -also be represented as a block, in this case the search box will be centered on the middle of the block. +also be represented as a block, in this case the search box will be centered on the middle of the block, or an entity - in this case +entire bounding box of the entity serves as a 'center' of search which is then expanded in all directions with the `'distance'` vector. + +In any case - returns all entities which bounding box collides with the bounding box defined by `'center'` and `'disteance'`. entity_area is simpler than `entity_selector` and runs about 20% faster, but is limited to predefined selectors and cuboid search area. diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 5f417d4c..227cc386 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -332,7 +332,7 @@ public class Auxiliary { { Value nameValue = lv.get(0).evalValue(c); name = nameValue instanceof NullValue ? "" : nameValue.getString(); - pointLocator = Vector3Argument.findIn(cc, lv, 1, true); + pointLocator = Vector3Argument.findIn(cc, lv, 1, true, false); if (lv.size()>pointLocator.offset) { BlockArgument blockLocator = BlockArgument.findIn(cc, lv, pointLocator.offset, true, true, false); diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index 7fac7ef1..c5a137a9 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -194,14 +194,24 @@ public class Entities { if (lv.size()<3) throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments"); String who = lv.get(0).evalValue(c).getString(); CarpetContext cc = (CarpetContext)c; - Vector3Argument centerLocator = Vector3Argument.findIn(cc, lv, 1); - Vec3d center = centerLocator.vec; - if (centerLocator.fromBlock) center.add(0.5, 0.5, 0.5); + Vector3Argument centerLocator = Vector3Argument.findIn(cc, lv, 1, false, true); + + Box centerBox; + if (centerLocator.entity != null) + { + centerBox = centerLocator.entity.getBoundingBox(); + } + else + { + Vec3d center = centerLocator.vec; + if (centerLocator.fromBlock) center.add(0.5, 0.5, 0.5); + centerBox = new Box(center, center); + } Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); if (rangeLocator.fromBlock) throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument"); Vec3d range = rangeLocator.vec; - Box area = new Box(center, center).expand(range.x, range.y, range.z); + Box area = centerBox.expand(range.x, range.y, range.z); EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who); List entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate); Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index 6c408089..003ffc4c 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -4,9 +4,11 @@ import carpet.script.CarpetContext; import carpet.script.LazyValue; import carpet.script.exception.InternalExpressionException; import carpet.script.value.BlockValue; +import carpet.script.value.EntityValue; import carpet.script.value.ListValue; import carpet.script.value.NumericValue; import carpet.script.value.Value; +import net.minecraft.entity.Entity; import net.minecraft.util.math.Vec3d; import java.util.List; @@ -16,7 +18,8 @@ public class Vector3Argument extends Argument public Vec3d vec; public final double yaw; public final double pitch; - public boolean fromBlock; + public boolean fromBlock = false; + public Entity entity = null; private Vector3Argument(Vec3d v, int o) { super(o); @@ -38,13 +41,19 @@ public class Vector3Argument extends Argument return this; } + private Vector3Argument withEntity(Entity e) + { + entity = e; + return this; + } + public static Vector3Argument findIn(CarpetContext c, List params, int offset) { - return findIn(c,params, offset, false); + return findIn(c,params, offset, false, false); } - public static Vector3Argument findIn(CarpetContext c, List params, int offset, boolean optionalDirection) + public static Vector3Argument findIn(CarpetContext c, List params, int offset, boolean optionalDirection, boolean optionalEntity) { try { @@ -54,6 +63,11 @@ public class Vector3Argument extends Argument // pos + 0.5v return (new Vector3Argument(Vec3d.ofCenter(((BlockValue) v1).getPos()), 1+offset)).fromBlock(); } + if (optionalEntity && v1 instanceof EntityValue) + { + Entity e = ((EntityValue) v1).getEntity(); + return new Vector3Argument(e.getPos(), 1+offset).withEntity(e); + } if (v1 instanceof ListValue) { List args = ((ListValue) v1).getItems(); diff --git a/src/main/resources/assets/carpet/scripts/ai_tracker.sc b/src/main/resources/assets/carpet/scripts/ai_tracker.sc index 4e7e9fd0..2e1977e3 100644 --- a/src/main/resources/assets/carpet/scripts/ai_tracker.sc +++ b/src/main/resources/assets/carpet/scripts/ai_tracker.sc @@ -145,9 +145,8 @@ global_functions = { [10+half_width,10+height,10+half_width], 0x65432100, 'buddy detection', false ); - [x,y,z] = pos(e); current_id = e~'id'; - buddies = entity_area('villager', x, y+height/2, z, 10+half_width, 10+height/2, 10+half_width); + buddies = entity_area('villager', e, 10, 10, 10); nb = length(buddies); for (filter(buddies, _~'id' != current_id), visuals+=['line', global_duration, 'from', pos(e), 'to', pos(_), 'color', 0xffff00ff]; @@ -518,9 +517,8 @@ __tick_tracker() -> return() ); p = player(); - [px, py, pz] = pos(p); in_dimension(p, - for (entity_area('valid', px, py, pz, global_range, global_range, global_range), + for (entity_area('valid', p, global_range, global_range, global_range), __handle_entity(_) ) );