package com.laytonsmith.core.functions; import com.laytonsmith.PureUtilities.Common.StringUtils; import com.laytonsmith.PureUtilities.Vector3D; import com.laytonsmith.PureUtilities.Version; import com.laytonsmith.abstraction.MCAgeable; import com.laytonsmith.abstraction.MCArmorStand; import com.laytonsmith.abstraction.MCBlockCommandSender; import com.laytonsmith.abstraction.MCChunk; import com.laytonsmith.abstraction.MCCommandSender; import com.laytonsmith.abstraction.MCEnderCrystal; import com.laytonsmith.abstraction.MCEntity; import com.laytonsmith.abstraction.MCEntityEquipment; import com.laytonsmith.abstraction.MCExperienceOrb; import com.laytonsmith.abstraction.MCFireball; import com.laytonsmith.abstraction.MCHumanEntity; import com.laytonsmith.abstraction.MCItem; import com.laytonsmith.abstraction.MCItemStack; import com.laytonsmith.abstraction.MCLightningStrike; import com.laytonsmith.abstraction.MCLivingEntity; import com.laytonsmith.abstraction.MCLocation; import com.laytonsmith.abstraction.MCMaterialData; import com.laytonsmith.abstraction.MCPainting; import com.laytonsmith.abstraction.MCPlayer; import com.laytonsmith.abstraction.MCPotionData; import com.laytonsmith.abstraction.MCProjectile; import com.laytonsmith.abstraction.MCProjectileSource; import com.laytonsmith.abstraction.MCTNT; import com.laytonsmith.abstraction.MCWorld; import com.laytonsmith.abstraction.StaticLayer; import com.laytonsmith.abstraction.blocks.MCBlock; import com.laytonsmith.abstraction.blocks.MCBlockFace; import com.laytonsmith.abstraction.blocks.MCBlockProjectileSource; import com.laytonsmith.abstraction.blocks.MCShulkerBox; import com.laytonsmith.abstraction.entities.*; import com.laytonsmith.abstraction.entities.MCHorse.MCHorseColor; import com.laytonsmith.abstraction.entities.MCHorse.MCHorsePattern; import com.laytonsmith.abstraction.entities.MCHorse.MCHorseVariant; import com.laytonsmith.abstraction.entities.MCLlama.MCLlamaColor; import com.laytonsmith.abstraction.enums.MCArt; import com.laytonsmith.abstraction.enums.MCBodyPart; import com.laytonsmith.abstraction.enums.MCDyeColor; import com.laytonsmith.abstraction.enums.MCEnderDragonPhase; import com.laytonsmith.abstraction.enums.MCEntityEffect; import com.laytonsmith.abstraction.enums.MCEntityType; import com.laytonsmith.abstraction.enums.MCEquipmentSlot; import com.laytonsmith.abstraction.enums.MCOcelotType; import com.laytonsmith.abstraction.enums.MCParticle; import com.laytonsmith.abstraction.enums.MCProfession; import com.laytonsmith.abstraction.enums.MCProjectileType; import com.laytonsmith.abstraction.enums.MCRabbitType; import com.laytonsmith.abstraction.enums.MCRotation; import com.laytonsmith.abstraction.enums.MCSkeletonType; import com.laytonsmith.abstraction.enums.MCVersion; import com.laytonsmith.annotations.api; import com.laytonsmith.annotations.seealso; import com.laytonsmith.core.ArgumentValidation; import com.laytonsmith.core.CHVersion; import com.laytonsmith.core.ObjectGenerator; import com.laytonsmith.core.Static; import com.laytonsmith.core.constructs.CArray; import com.laytonsmith.core.constructs.CBoolean; import com.laytonsmith.core.constructs.CDouble; import com.laytonsmith.core.constructs.CInt; import com.laytonsmith.core.constructs.CNull; import com.laytonsmith.core.constructs.CString; import com.laytonsmith.core.constructs.CVoid; import com.laytonsmith.core.constructs.Construct; import com.laytonsmith.core.constructs.Target; import com.laytonsmith.core.environments.CommandHelperEnvironment; import com.laytonsmith.core.environments.Environment; import com.laytonsmith.core.exceptions.CRE.CREBadEntityException; import com.laytonsmith.core.exceptions.CRE.CREBadEntityTypeException; import com.laytonsmith.core.exceptions.CRE.CRECastException; import com.laytonsmith.core.exceptions.CRE.CREFormatException; import com.laytonsmith.core.exceptions.CRE.CREIndexOverflowException; import com.laytonsmith.core.exceptions.CRE.CREInvalidWorldException; import com.laytonsmith.core.exceptions.CRE.CRELengthException; import com.laytonsmith.core.exceptions.CRE.CRENotFoundException; import com.laytonsmith.core.exceptions.CRE.CREPlayerOfflineException; import com.laytonsmith.core.exceptions.CRE.CRERangeException; import com.laytonsmith.core.exceptions.CRE.CREThrowable; import com.laytonsmith.core.exceptions.CRE.CREUnageableMobException; import com.laytonsmith.core.exceptions.ConfigCompileException; import com.laytonsmith.core.exceptions.ConfigRuntimeException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; /** * * @author jb_aero */ public class EntityManagement { public static String docs(){ return "This class of functions allow entities to be managed."; } public static abstract class EntityFunction extends AbstractFunction { @Override public boolean isRestricted() { return true; } @Override public Boolean runAsync() { return false; } } public static abstract class EntityGetterFunction extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRELengthException.class, CREBadEntityException.class}; } @Override public Integer[] numArgs() { return new Integer[]{1}; } } public static abstract class EntitySetterFunction extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREFormatException.class, CRELengthException.class, CREBadEntityException.class}; } @Override public Integer[] numArgs() { return new Integer[]{2}; } } @api public static class all_entities extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREInvalidWorldException.class, CREFormatException.class, CRECastException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { CArray ret = new CArray(t); if (args.length == 0) { for (MCWorld w : Static.getServer().getWorlds()) { for (MCEntity e : w.getEntities()) { ret.push(new CString(e.getUniqueId().toString(), t), t); } } } else { MCWorld w; MCChunk c; if (args.length == 3) { w = Static.getServer().getWorld(args[0].val()); if (w == null) { throw new CREInvalidWorldException("Unknown world: " + args[0].val(), t); } try { int x = Static.getInt32(args[1], t); int z = Static.getInt32(args[2], t); c = w.getChunkAt(x, z); } catch (ConfigRuntimeException cre) { CArray l = CArray.GetAssociativeArray(t); l.set("x", args[1], t); l.set("z", args[2], t); c = w.getChunkAt(ObjectGenerator.GetGenerator().location(l, w, t)); } for (MCEntity e : c.getEntities()) { ret.push(new CString(e.getUniqueId().toString(), t), t); } } else { if (args[0] instanceof CArray) { c = ObjectGenerator.GetGenerator().location(args[0], null, t).getChunk(); for (MCEntity e : c.getEntities()) { ret.push(new CString(e.getUniqueId().toString(), t), t); } } else { w = Static.getServer().getWorld(args[0].val()); if (w == null) { throw new CREInvalidWorldException("Unknown world: " + args[0].val(), t); } for (MCEntity e : w.getEntities()) { ret.push(new CString(e.getUniqueId().toString(), t), t); } } } } return ret; } @Override public CHVersion since() { return CHVersion.V3_3_1; } @Override public String getName() { return "all_entities"; } @Override public Integer[] numArgs() { return new Integer[]{0, 1, 3}; } @Override public String docs() { return "array {[world, [x, z]] | [locationArray]} Returns an array of IDs for all entities in the given" + " scope. With no args, this will return all entities loaded on the entire server. If the first" + " argument is given and is a location, only entities in the chunk containin that location will" + " be returned, or if it is a world only entities in that world will be returned. If all three" + " arguments are given, only entities in the chunk with those coords will be returned. This can" + " take chunk coords (ints) or location coords (doubles)."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("Getting all entities in a world", "msg(all_entities(pworld()))", "Sends you an array of all entities in your world."), new ExampleScript("Getting entities in a chunk", "msg(all_entities(pworld(), 5, -3))", "Sends you an array of all entities in chunk (5,-3)."), new ExampleScript("Getting entities in your chunk", "msg(all_entities(ploc()))", "Sends you an array of all entities in the chunk you are in.") }; } } @api public static class entity_exists extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e; try { e = Static.getEntity(args[0], t); } catch (ConfigRuntimeException cre) { return CBoolean.FALSE; } return CBoolean.TRUE; } @Override public String getName() { return "entity_exists"; } @Override public String docs() { return "boolean {entityID} Returns true if entity exists, otherwise false."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class is_entity_living extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e; try { e = Static.getEntity(args[0], t); } catch (ConfigRuntimeException cre) { return CBoolean.FALSE; } return CBoolean.get(e instanceof MCLivingEntity); } @Override public String getName() { return "is_entity_living"; } @Override public String docs() { return "boolean {entityID} Returns true if entity is living, otherwise false."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_loc extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); return ObjectGenerator.GetGenerator().location(e.getLocation()); } @Override public String getName() { return "entity_loc"; } @Override public String docs() { return "locationArray {entityID} Returns the location array for this entity, if it exists." + " This array will be compatible with any function that expects a location."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("Sample output", "entity_loc(5048)", "{0: -3451.96, 1: 65.0, 2: 718.521, 3: world, 4: -170.9, 5: 35.5, pitch: 35.5," + " world: world, x: -3451.96, y: 65.0, yaw: -170.9, z: 718.521}") }; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_loc extends EntitySetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREBadEntityException.class, CREFormatException.class, CRECastException.class, CREInvalidWorldException.class, CRELengthException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); MCLocation l; if (args[1] instanceof CArray) { l = ObjectGenerator.GetGenerator().location((CArray) args[1], e.getWorld(), t); } else { throw new CREFormatException("An array was expected but recieved " + args[1], t); } return CBoolean.get(e.teleport(l)); } @Override public String getName() { return "set_entity_loc"; } @Override public String docs() { return "boolean {entityID, locationArray} Teleports the entity to the given location and returns whether" + " the action was successful. Note this can set both location and direction."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("Teleporting an entity to you", "set_entity_loc(386, ploc())", "The entity will teleport to the block you are standing on."), new ExampleScript("Teleporting an entity to another", "set_entity_loc(201, entity_location(10653))", "The entity will teleport to the other and face the same direction, if they both exist."), new ExampleScript("Setting location with a normal array", "set_entity_loc(465, array(214, 64, 1812, 'world', -170, 10))", "This set location and direction."), new ExampleScript("Setting location with an associative array", "set_entity_loc(852, array(x: 214, y: 64, z: 1812, world: 'world', yaw: -170, pitch: 10))", "This also sets location and direction") }; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_velocity extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); CArray va = ObjectGenerator.GetGenerator().vector(e.getVelocity(), t); va.set("magnitude", new CDouble(e.getVelocity().length(), t), t); return va; } @Override public String getName() { return "entity_velocity"; } @Override public String docs() { return "array {entityID} Returns an associative array indicating the x/y/z components of this entity's velocity." + " As a convenience, the magnitude is also included."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("A stationary entity", "msg(entity_velocity(235))", "{magnitude: 0.0, x: 0.0, y: 0.0, z: 0.0}") }; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_velocity extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); e.setVelocity(ObjectGenerator.GetGenerator().vector(args[1], t)); return CVoid.VOID; } @Override public String getName() { return "set_entity_velocity"; } @Override public String docs() { return "void {entityID, array} Sets the velocity of this entity according to the supplied xyz array. All 3" + " values default to 0, so an empty array will simply stop the entity's motion. Both normal and" + " associative arrays are accepted."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("Setting a bounce with a normal array", "set_entity_velocity(235, array(0, 0.5, 0))", "The entity just hopped, unless it was an item frame or painting."), new ExampleScript("Setting a bounce with an associative array", "set_entity_velocity(235, array(y: 0.5))", "The entity just hopped, unless it was an item frame or painting.") }; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_remove extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); if (ent == null) { return CVoid.VOID; } else if (ent instanceof MCHumanEntity) { throw new CREBadEntityException("Cannot remove human entity (" + ent.getUniqueId() + ")!", t); } else { ent.remove(); return CVoid.VOID; } } @Override public String getName() { return "entity_remove"; } @Override public String docs() { return "void {entityID} Removes the specified entity from the world, without any drops or animations. " + "Note: you can't remove players. As a safety measure for working with NPC plugins, it will " + "not work on anything human, even if it is not a player."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_type extends EntityGetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRECastException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent; try { ent = Static.getEntity(args[0], t); } catch (ConfigRuntimeException cre) { return CNull.NULL; } return new CString(ent.getType().name(), t); } @Override public String getName() { return "entity_type"; } @Override public String docs() { return "mixed {entityID} Returns the EntityType of the entity with the specified ID." + " Returns null if the entity does not exist."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_entity_breedable extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); if (ent instanceof MCAgeable){ return CBoolean.get(((MCAgeable)ent).getCanBreed()); } else { throw new CREBadEntityException("Entity ID must be from an ageable entity!", t); } } @Override public String getName() { return "get_entity_breedable"; } @Override public String docs() { return "boolean {entityID} Returns if an entity is set to be breedable."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_breedable extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { boolean breed = Static.getBoolean(args[1]); MCEntity ent = Static.getEntity(args[0], t); if (ent instanceof MCAgeable){ ((MCAgeable)ent).setCanBreed(breed); } else { throw new CREBadEntityException("Entity ID must be from an ageable entity!", t); } return CVoid.VOID; } @Override public String getName() { return "set_entity_breedable"; } @Override public String docs() { return "void {entityID, boolean} Set an entity to be breedable."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_entity_age extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); if (ent == null) { return CNull.NULL; } else { return new CInt(ent.getTicksLived(), t); } } @Override public String getName() { return "get_entity_age"; } @Override public String docs() { return "int {entityID} Returns the entity age as an integer, represented by server ticks."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_age extends EntitySetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRECastException.class, CREBadEntityException.class, CRERangeException.class, CRELengthException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { int age = Static.getInt32(args[1], t); if (age < 1) { throw new CRERangeException("Entity age can't be less than 1 server tick.", t); } MCEntity ent = Static.getEntity(args[0], t); if (ent == null) { return CNull.NULL; } else { ent.setTicksLived(age); return CVoid.VOID; } } @Override public String getName() { return "set_entity_age"; } @Override public String docs() { return "void {entityID, int} Sets the age of the entity to the specified int, represented by server ticks."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_mob_age extends EntityGetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREUnageableMobException.class, CRELengthException.class, CREBadEntityException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity ent = Static.getLivingEntity(args[0], t); if (ent == null) { return CNull.NULL; } else if (ent instanceof MCAgeable) { MCAgeable mob = ((MCAgeable) ent); return new CInt(mob.getAge(), t); } else { throw new CREUnageableMobException("The specified entity does not age", t); } } @Override public String getName() { return "get_mob_age"; } @Override public String docs() { return "int {entityID} Returns the mob's age as an integer. Zero represents the point of adulthood. Throws an" + " UnageableMobException if the mob is not a type that ages"; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_mob_age extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREUnageableMobException.class, CRECastException.class, CREBadEntityException.class, CRELengthException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { int age = Static.getInt32(args[1], t); boolean lock = false; if (args.length == 3) { lock = (boolean) Static.getBoolean(args[2]); } MCLivingEntity ent = Static.getLivingEntity(args[0], t); if (ent == null) { return CNull.NULL; } else if (ent instanceof MCAgeable) { MCAgeable mob = ((MCAgeable) ent); mob.setAge(age); mob.setAgeLock(lock); return CVoid.VOID; } else { throw new CREUnageableMobException("The specified entity does not age", t); } } @Override public String getName() { return "set_mob_age"; } @Override public Integer[] numArgs() { return new Integer[]{2, 3}; } @Override public String docs() { return "void {entityID, int[, lockAge]} sets the age of the mob to the specified int, and locks it at that age" + " if lockAge is true, but by default it will not. Throws a UnageableMobException if the mob does" + " not age naturally."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_mob_effects extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity mob = Static.getLivingEntity(args[0], t); return ObjectGenerator.GetGenerator().potions(mob.getEffects(), t); } @Override public String getName() { return "get_mob_effects"; } @Override public String docs() { return "array {entityID} Returns an array of potion arrays showing" + " the effects on this mob."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{new ExampleScript("Basic use", "msg(get_mob_effects(259))", "{{ambient: false, id: 1, seconds: 30, strength: 1}}")}; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_mob_effect extends EntityFunction { @Override public String getName() { return "set_mob_effect"; } @Override public Integer[] numArgs() { return new Integer[]{3, 4, 5, 6}; } @Override public String docs() { return "boolean {entityId, potionID, strength, [seconds], [ambient], [particles]} Effect is 1-23. Seconds" + " defaults to 30. If the potionID is out of range, a RangeException is thrown, because out of" + " range potion effects cause the client to crash, fairly hardcore. See" + " http://www.minecraftwiki.net/wiki/Potion_effects for a complete list of potions that can be" + " added. To remove an effect, set the seconds to 0. If seconds is less than 0 or greater than" + " 107374182 a RangeException is thrown. Strength is the number of levels to add to the" + " base power (effect level 1). Ambient takes a boolean of whether the particles should be less" + " noticeable. Particles takes a boolean of whether the particles should be visible at all. The" + " function returns true if the effect was added or removed as desired, and false if it wasn't" + " (however, this currently only will happen if an effect is attempted to be removed, yet isn't" + " already on the mob)."; } @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRELengthException.class, CREFormatException.class, CREBadEntityException.class, CRERangeException.class}; } @Override public Construct exec(Target t, Environment env, Construct... args) throws ConfigRuntimeException { MCLivingEntity mob = Static.getLivingEntity(args[0], t); int effect = Static.getInt32(args[1], t); int strength = Static.getInt32(args[2], t); int seconds = 30; boolean ambient = false; boolean particles = true; if (args.length >= 4) { seconds = Static.getInt32(args[3], t); if(seconds < 0) { throw new CRERangeException("Seconds cannot be less than 0", t); } else if(seconds > Integer.MAX_VALUE / 20) { throw new CRERangeException("Seconds cannot be greater than 107374182", t); } } if (args.length == 5) { ambient = Static.getBoolean(args[4]); } if (args.length == 6) { particles = Static.getBoolean(args[5]); } if (seconds == 0) { return CBoolean.get(mob.removeEffect(effect)); } else { mob.addEffect(effect, strength, seconds, ambient, particles, t); return CBoolean.TRUE; } } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api(environments={CommandHelperEnvironment.class}) public static class shoot_projectile extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREBadEntityException.class, CREBadEntityTypeException.class, CREFormatException.class, CREPlayerOfflineException.class}; } @Override public Construct exec(Target t, Environment env, Construct... args) throws ConfigRuntimeException { MCPlayer p = env.getEnv(CommandHelperEnvironment.class).GetPlayer(); MCLivingEntity shooter = null; MCLivingEntity target; UUID shooter_id = null; UUID target_id = null; MCLocation from = null; MCLocation to = null; MCLocation shifted_from; MCEntityType entity_shoot = null; MCProjectileType projectile_shoot = null; double speed = 0.0; if (args.length >= 1) { try { shooter_id = Static.GetPlayer(args[0], t).getUniqueId(); } catch (ConfigRuntimeException notPlayer) { try { shooter_id = Static.GetUUID(args[0], t); } catch (ConfigRuntimeException notEntIdEither) { } } if (shooter_id == null) { try { from = ObjectGenerator.GetGenerator().location(args[0], p != null ? p.getWorld() : null, t); } catch (ConfigRuntimeException badLocation) { } } if (shooter_id == null && from == null) { throw new CREFormatException("Could not find an entity or location matching " + args[0] + "!", t); } } else { Static.AssertPlayerNonNull(p, t); shooter_id = p.getUniqueId(); } if (args.length >= 3) { try { target_id = Static.GetPlayer(args[2], t).getUniqueId(); } catch (ConfigRuntimeException notPlayer) { try { target_id = Static.GetUUID(args[2], t); } catch (ConfigRuntimeException notEntIdEither) { } } if (target_id == null) { try { to = ObjectGenerator.GetGenerator().location(args[2], null, t); } catch (ConfigRuntimeException badLocation) { } } if (target_id == null && to == null) { throw new CREFormatException("Could not find an entity or location matching " + args[2] + " for target!", t); } } if (args.length == 4) { speed = Static.getDouble(args[3], t); } if (shooter_id != null) { shooter = Static.getLivingByUUID(shooter_id, t); from = shooter.getEyeLocation(); } if (target_id != null) { target = Static.getLivingByUUID(target_id, t); to = target.getEyeLocation(); } if (args.length >= 2) { if (shooter_id != null && to == null) { try { projectile_shoot = MCProjectileType.valueOf(args[1].val().toUpperCase()); } catch (IllegalArgumentException badEnum) { throw new CREFormatException(args[1] + " is not a valid Projectile", t); } } else { try { entity_shoot = MCEntityType.valueOf(args[1].val().toUpperCase()); } catch (IllegalArgumentException badEnum) { throw new CREBadEntityTypeException(args[1] + " is not a valid entity type", t); } } } else { if (shooter_id != null && to == null) { projectile_shoot = MCProjectileType.FIREBALL; } else { entity_shoot = MCEntityType.valueOfVanillaType(MCEntityType.MCVanillaEntityType.FIREBALL); } } if (args.length < 3 && shooter_id == null) { throw new CREFormatException("You must specify target location if you want shoot from location, not entity.", t); } if (shooter_id != null && to == null) { MCProjectile projectile = shooter.launchProjectile(projectile_shoot); return new CString(projectile.getUniqueId().toString(), t); } else { Vector3D velocity = to.toVector().subtract(from.toVector()).normalize(); if (shooter_id != null) { shifted_from = from.add(velocity); } else { shifted_from = from; } MCEntity entity = from.getWorld().spawn(shifted_from, entity_shoot); if (speed == 0.0) { entity.setVelocity(velocity); } else { entity.setVelocity(velocity.multiply(speed)); } return new CString(entity.getUniqueId().toString(), t); } } @Override public String getName() { return "shoot_projectile"; } @Override public Integer[] numArgs() { return new Integer[]{0, 1, 2, 3, 4}; } @Override public String docs() { return "int {[entity[, projectile]] | player, projectile, target[, speed]} shoots an entity from the" + " specified location (can be entityID, player name or location array), or the current player" + " if no arguments are passed. If no entity type is specified, it defaults to a fireball." + " If provide three arguments, with target (entityID, player name or location array), entity will" + " shoot to target location. Last, fourth argument, is double and specifies the speed" + " of projectile. Returns the EntityID of the entity. Valid projectile types: " + StringUtils.Join(MCProjectileType.values(), ", ", ", or ", " or "); } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api(environments = {CommandHelperEnvironment.class}) public static class entities_in_radius extends EntityFunction { @Override public String getName() { return "entities_in_radius"; } @Override public Integer[] numArgs() { return new Integer[]{2, 3}; } @Override public Construct exec(Target t, Environment env, Construct... args) throws ConfigRuntimeException { MCPlayer p = env.getEnv(CommandHelperEnvironment.class).GetPlayer(); MCLocation loc; int dist; List<String> types = new ArrayList<String>(); if (!(args[0] instanceof CArray)) { throw new CREBadEntityException("Expecting an array at parameter 1 of entities_in_radius", t); } loc = ObjectGenerator.GetGenerator().location(args[0], p != null ? p.getWorld() : null, t); dist = Static.getInt32(args[1], t); if (args.length == 3) { if (args[2] instanceof CArray) { CArray ta = (CArray) args[2]; for (int i = 0; i < ta.size(); i++) { types.add(ta.get(i, t).val()); } } else { types.add(args[2].val()); } types = prepareTypes(t, types); } // The idea and code comes from skore87 (http://forums.bukkit.org/members/skore87.105075/) // http://forums.bukkit.org/threads/getnearbyentities-of-a-location.101499/#post-1341141 int chunkRadius = dist < 16 ? 1 : (dist - (dist % 16)) / 16; Set<UUID> eSet = new HashSet<>(); for (int chX = 0 - chunkRadius; chX <= chunkRadius; chX++) { for (int chZ = 0 - chunkRadius; chZ <= chunkRadius; chZ++) { MCLocation nl = StaticLayer.GetLocation(loc.getWorld(), loc.getX()+(chX*16), loc.getY(), loc.getZ()+(chZ*16)); for (MCEntity e : nl.getChunk().getEntities()) { if (!e.getWorld().equals(loc.getWorld())) { // We can't measure entity distances that are in different worlds! continue; } if (e.getLocation().distance(loc) <= dist && e.getLocation().getBlock() != loc.getBlock()) { if (types.isEmpty() || types.contains(e.getType().name())) { eSet.add(e.getUniqueId()); } } } } } CArray entities = new CArray(t); for (UUID e : eSet) { entities.push(new CString(e.toString(), t), t); } return entities; } private List<String> prepareTypes(Target t, List<String> types) { List<String> newTypes = new ArrayList<String>(); MCEntityType entityType = null; for (String type : types) { try { entityType = MCEntityType.valueOf(type.toUpperCase()); } catch (IllegalArgumentException e) { throw new CREBadEntityException(String.format("Wrong entity type: %s", type), t); } newTypes.add(entityType.name()); } return newTypes; } @Override public String docs() { return "array {location array, distance, [type] | location array, distance, [arrayTypes]} Returns an array of" + " all entities within the given radius. Set type argument to filter entities to a specific type. You" + " can pass an array of types. Valid types (case doesn't matter): " + StringUtils.Join(MCEntityType.types(), ", ", ", or ", " or "); } @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRECastException.class, CREBadEntityException.class, CREFormatException.class}; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } //@api public static class get_mob_target extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); if (le.getTarget(t) == null) { return CNull.NULL; } else { return new CString(le.getTarget(t).getUniqueId().toString(), t); } } @Override public String getName() { return "get_mob_target"; } @Override public String docs() { return "entityID {entityID} Gets the mob's target if it has one, and returns the target's entityID." + " If there is no target, null is returned instead."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } //@api public static class set_mob_target extends EntitySetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREBadEntityException.class, CRELengthException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); MCLivingEntity target = null; if (!(args[1] instanceof CNull)) { target = Static.getLivingEntity(args[1], t); } le.setTarget(target, t); return CVoid.VOID; } @Override public String getName() { return "set_mob_target"; } @Override public String docs() { return "void {entityID, entityID} The first ID is the entity who is targetting, the second is the target." + " It can also be set to null to clear the current target."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_mob_equipment extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); MCEntityEquipment eq = le.getEquipment(); if (eq == null) { throw new CREBadEntityTypeException("Entities of type \"" + le.getType() + "\" do not have equipment.", t); } Map<MCEquipmentSlot, MCItemStack> eqmap = le.getEquipment().getAllEquipment(); CArray ret = CArray.GetAssociativeArray(t); for (MCEquipmentSlot key : eqmap.keySet()) { ret.set(key.name().toLowerCase(), ObjectGenerator.GetGenerator().item(eqmap.get(key), t), t); } return ret; } @Override public String getName() { return "get_mob_equipment"; } @Override public String docs() { return "equipmentArray {entityID} Returns an associative array showing the equipment this mob is wearing." + " This does not work on most \"dumb\" entities, only mobs (entities with AI)."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("Getting a mob's equipment", "get_mob_equipment(276)", "{boots: null," + " chestplate: null, helmet: {data: 0, enchants: {} meta: null, type: 91}, leggings: null," + " off_hand: null, weapon: {data: 5, enchants: {} meta: {display: Excalibur, lore: null}," + " type: 276}}") }; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_mob_equipment extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); MCEntityEquipment ee = le.getEquipment(); if (ee == null) { throw new CREBadEntityTypeException("Entities of type \"" + le.getType() + "\" do not have equipment.", t); } Map<MCEquipmentSlot, MCItemStack> eq = ee.getAllEquipment(); if (args[1] instanceof CNull) { ee.clearEquipment(); return CVoid.VOID; } else if (args[1] instanceof CArray) { CArray ea = (CArray) args[1]; for (String key : ea.stringKeySet()) { try { eq.put(MCEquipmentSlot.valueOf(key.toUpperCase()), ObjectGenerator.GetGenerator().item(ea.get(key, t), t)); } catch (IllegalArgumentException iae) { throw new CREFormatException("Not an equipment slot: " + key, t); } } } else { throw new CREFormatException("Expected argument 2 to be an array", t); } ee.setAllEquipment(eq); return CVoid.VOID; } @Override public String getName() { return "set_mob_equipment"; } @Override public String docs() { return "void {entityID, array} Takes an associative array with keys representing equipment slots and values" + " of itemArrays, the same used by set_pinv. This does not work on most \"dumb\" entities," + " only mobs (entities with AI). Unless a mod, plugin, or future update changes vanilla functionality," + " only humanoid mobs will render their equipment slots. The equipment slots are: " + StringUtils.Join(MCEquipmentSlot.values(), ", ", ", or ", " or "); } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{ new ExampleScript("Basic usage", "set_mob_equipment(spawn_mob('SKELETON')[0], array(WEAPON: array(type: 261)))", "Gives a bow to a skeleton") }; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_max_health extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); return new CDouble(le.getMaxHealth(), t); } @Override public String getName() { return "get_max_health"; } @Override public String docs() { return "double {entityID} Returns the maximum health of this living entity."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_max_health extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); le.setMaxHealth(Static.getDouble(args[1], t)); return CVoid.VOID; } @Override public String getName() { return "set_max_health"; } @Override public String docs() { return "void {entityID, double} Sets the max health of a living entity, players included." + " This value is persistent, and will not reset even after server restarts."; } @Override public ExampleScript[] examples() throws ConfigCompileException { return new ExampleScript[]{new ExampleScript("Basic use", "set_max_health(256, 10)", "The entity will now only have 5 hearts max.")}; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_onfire extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); return new CInt(ent.getFireTicks() / 20, t); } @Override public String getName() { return "entity_onfire"; } @Override public String docs() { return "int {entityID} Returns the number of seconds until this entity" + " stops being on fire, 0 if it already isn't."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_onfire extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); int seconds = Static.getInt32(args[1], t); if(seconds < 0) { throw new CRERangeException("Seconds cannot be less than 0", t); } else if(seconds > Integer.MAX_VALUE / 20) { throw new CRERangeException("Seconds cannot be greater than 107374182", t); } ent.setFireTicks(seconds * 20); return CVoid.VOID; } @Override public String getName() { return "set_entity_onfire"; } @Override public String docs() { return "void {entityID, seconds} Sets the entity on fire for the" + " given number of seconds. Throws a RangeException" + " if seconds is less than 0 or greater than 107374182."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class play_entity_effect extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); MCEntityEffect mee; try { mee = MCEntityEffect.valueOf(args[1].val().toUpperCase()); } catch (IllegalArgumentException iae) { throw new CREFormatException("Unknown effect at arg 2.", t); } ent.playEffect(mee); return CVoid.VOID; } @Override public String getName() { return "play_entity_effect"; } @Override public String docs() { return "void {entityID, effect} Plays the given visual effect on the" + " entity. Non-applicable effects simply won't happen. Note:" + " the death effect makes the mob invisible to players and" + " immune to melee attacks. When used on players, they are" + " shown the respawn menu, but because they are not actually" + " dead, they can only log out. Possible effects are: " + StringUtils.Join(MCEntityEffect.values(), ", ", ", or ", " or "); } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_mob_name extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity le = Static.getEntity(args[0], t); try { return new CString(le.getCustomName(), t); } catch (IllegalArgumentException e) { throw new CRECastException(e.getMessage(), t); } } @Override public String getName() { return "get_mob_name"; } @Override public String docs() { return "string {entityID} Returns the name of the given mob."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_mob_name extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity le = Static.getEntity(args[0], t); try { le.setCustomName(args[1].val()); } catch (IllegalArgumentException e) { throw new CRECastException(e.getMessage(), t); } return CVoid.VOID; } @Override public String getName() { return "set_mob_name"; } @Override public String docs() { return "void {entityID, name} Sets the name of the given mob. This" + " automatically truncates if it is more than 64 characters."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api(environments = {CommandHelperEnvironment.class}) public static class spawn_entity extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRECastException.class, CREFormatException.class, CREBadEntityException.class, CREInvalidWorldException.class, CREPlayerOfflineException.class, CRENotFoundException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCCommandSender cs = environment.getEnv(CommandHelperEnvironment.class).GetCommandSender(); int qty = 1; CArray ret = new CArray(t); MCEntityType entType; MCLocation l; MCEntity ent; if (args.length == 3) { l = ObjectGenerator.GetGenerator().location(args[2], null, t); } else { if (cs instanceof MCPlayer) { l = ((MCPlayer) cs).getLocation(); } else if (cs instanceof MCBlockCommandSender){ l = ((MCBlockCommandSender) cs).getBlock().getRelative(MCBlockFace.UP).getLocation(); } else { throw new CREPlayerOfflineException("A physical commandsender must exist or location must be explicit.", t); } } if (args.length >= 2) { qty = Static.getInt32(args[1], t); } try { entType = MCEntityType.valueOf(args[0].val().toUpperCase()); if (entType == null) { throw new CRENotFoundException( "Could not find the entity type internal object (are you running in cmdline mode?)", t); } if (!entType.isSpawnable()) { throw new CREFormatException("Unspawnable entitytype: " + args[0].val(), t); } } catch (IllegalArgumentException iae) { throw new CREFormatException("Unknown entitytype: " + args[0].val(), t); } for (int i = 0; i < qty; i++) { switch (entType.getAbstracted()) { case DROPPED_ITEM: CArray c = CArray.GetAssociativeArray(t); c.set("type", new CInt(1, t), t); c.set("qty", new CInt(qty, t), t); MCItemStack is = ObjectGenerator.GetGenerator().item(c, t); ent = l.getWorld().dropItem(l, is); qty = 0; break; case FALLING_BLOCK: ent = l.getWorld().spawnFallingBlock(l, 12, (byte) 0); break; case ITEM_FRAME: case LEASH_HITCH: case PAINTING: try { ent = l.getWorld().spawn(l.getBlock().getLocation(), entType); } catch(NullPointerException | IllegalArgumentException ex){ throw new CREFormatException("Unspawnable location for " + entType.getAbstracted().name(), t); } break; default: ent = l.getWorld().spawn(l, entType); } ret.push(new CString(ent.getUniqueId().toString(), t), t); } return ret; } @Override public String getName() { return "spawn_entity"; } @Override public Integer[] numArgs() { return new Integer[]{1, 2, 3}; } @Override public String docs() { List<String> spawnable = new ArrayList<String>(); for (MCEntityType type : MCEntityType.values()) { if (type.isSpawnable()) { spawnable.add(type.name()); } } return "array {entityType, [qty], [location]} Spawns the specified number of entities of the given type" + " at the given location. Returns an array of entityIDs of what is spawned. Qty defaults to 1" + " and location defaults to the location of the commandsender, if it is a block or player." + " If the commandsender is console, location must be supplied. ---- Entitytype can be one of " + StringUtils.Join(spawnable, ", ", " or ", ", or ") + ". Falling_blocks will be sand by default, and dropped_items will be stone," + " as these entities already have their own functions for spawning."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_rider extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity horse, rider; boolean success; if (args[0] instanceof CNull) { horse = null; } else { horse = Static.getEntity(args[0], t); } if (args[1] instanceof CNull) { rider = null; } else { rider = Static.getEntity(args[1], t); } if ((horse == null && rider == null) || horse == rider) { throw new CREFormatException("Horse and rider cannot be the same entity", t); } else if (horse == null) { success = rider.leaveVehicle(); } else if (rider == null) { success = horse.eject(); } else { try { success = horse.setPassenger(rider); } catch(IllegalStateException ex){ throw new CREFormatException("Circular entity riding!" + " One entity is already a passenger of the other.", t); } } return CBoolean.get(success); } @Override public String getName() { return "set_entity_rider"; } @Override public String docs() { return "boolean {horse, rider} Sets the way two entities are stacked. Horse and rider are entity ids." + " If rider is null, horse will eject its current rider, if it has one. If horse is null," + " rider will leave whatever it is riding. If horse and rider are both valid entities," + " rider will ride horse. The function returns the success of whatever operation is done." + " If horse and rider are both null, or otherwise the same, a FormatException is thrown."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_entity_rider extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); if (ent.getPassenger() != null) { return new CString(ent.getPassenger().getUniqueId().toString(), t); } return CNull.NULL; } @Override public String getName() { return "get_entity_rider"; } @Override public String docs() { return "mixed {entityID} Returns the ID of the given entity's rider, or null if it doesn't have one."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_entity_vehicle extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); if (ent.isInsideVehicle()) { return new CString(ent.getVehicle().getUniqueId().toString(), t); } return CNull.NULL; } @Override public String getName() { return "get_entity_vehicle"; } @Override public String docs() { return "mixed {entityID} Returns the ID of the given entity's vehicle, or null if it doesn't have one."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_entity_max_speed extends EntityGetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREBadEntityException.class, CREBadEntityTypeException.class, CRELengthException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); if (e instanceof MCBoat) { return new CDouble(((MCBoat) e).getMaxSpeed(), t); } else if(e instanceof MCMinecart) { return new CDouble(((MCMinecart) e).getMaxSpeed(), t); } throw new CREBadEntityTypeException("Given entity must be a boat or minecart.", t); } @Override public String getName() { return "get_entity_max_speed"; } @Override public String docs() { return "double {entityID} Returns a max speed for given entity. Make sure that the entity is a boat" + " or minecart."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_max_speed extends EntitySetterFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREBadEntityException.class, CREBadEntityTypeException.class, CRECastException.class, CRELengthException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); double speed = Static.getDouble(args[1], t); if (e instanceof MCBoat) { ((MCBoat) e).setMaxSpeed(speed); } else if(e instanceof MCMinecart) { ((MCMinecart) e).setMaxSpeed(speed); } else { throw new CREBadEntityTypeException("Given entity must be a boat or minecart.", t); } return CVoid.VOID; } @Override public String getName() { return "set_entity_max_speed"; } @Override public String docs() { return "void {entityID} Sets a max speed for given entity. Make sure that the entity is a boat" + " or minecart."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_equipment_droprates extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntityEquipment eq = Static.getLivingEntity(args[0], t).getEquipment(); if (eq.getHolder() instanceof MCPlayer) { throw new CREBadEntityException(getName() + " does not work on players.", t); } CArray ret = CArray.GetAssociativeArray(t); for (Map.Entry<MCEquipmentSlot, Float> ent : eq.getAllDropChances().entrySet()) { ret.set(ent.getKey().name(), new CDouble(ent.getValue(), t), t); } return ret; } @Override public String getName() { return "get_equipment_droprates"; } @Override public String docs() { return "array {entityID} Returns an associative array of the drop rate for each equipment slot." + " If the rate is 0, the equipment will not drop. If it is 1, it is guaranteed to drop."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_equipment_droprates extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntityEquipment ee = Static.getLivingEntity(args[0], t).getEquipment(); Map<MCEquipmentSlot, Float> eq = ee.getAllDropChances(); if (ee.getHolder() instanceof MCPlayer) { throw new CREBadEntityException(getName() + " does not work on players.", t); } if (args[1] instanceof CNull) { for (Map.Entry<MCEquipmentSlot, Float> ent : eq.entrySet()) { eq.put(ent.getKey(), 0F); } } else if (args[1] instanceof CArray) { CArray ea = (CArray) args[1]; for (String key : ea.stringKeySet()) { try { eq.put(MCEquipmentSlot.valueOf(key.toUpperCase()), Static.getDouble32(ea.get(key, t), t)); } catch (IllegalArgumentException iae) { throw new CREFormatException("Not an equipment slot: " + key, t); } } } else { throw new CREFormatException("Expected argument 2 to be an array", t); } ee.setAllDropChances(eq); return CVoid.VOID; } @Override public String getName() { return "set_equipment_droprates"; } @Override public String docs() { return "void {entityID, array} Sets the drop chances for each equipment slot on a mob," + " but does not work on players. Passing null instead of an array will automatically" + " set all rates to 0, which will cause nothing to drop. A rate of 1 will guarantee a drop."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_name_visible extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { try { return CBoolean.get(Static.getEntity(args[0], t).isCustomNameVisible()); } catch (IllegalArgumentException e) { throw new CRECastException(e.getMessage(), t); } } @Override public String getName() { return "get_name_visible"; } @Override public String docs() { return "boolean {entityID} Returns whether or not a mob's custom name is always visible." + " If this is true it will be as visible as player names, otherwise it will only be" + " visible when near the mob."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_name_visible extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { try { Static.getEntity(args[0], t).setCustomNameVisible(Static.getBoolean(args[1])); } catch (IllegalArgumentException e) { throw new CRECastException(e.getMessage(), t); } return CVoid.VOID; } @Override public String getName() { return "set_name_visible"; } @Override public String docs() { return "void {entityID, boolean} Sets the visibility of a mob's custom name." + " True means it will be visible from a distance, like a playername." + " False means it will only be visible when near the mob."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class can_pickup_items extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return CBoolean.get(Static.getLivingEntity(args[0], t).getCanPickupItems()); } @Override public String getName() { return "can_pickup_items"; } @Override public String docs() { return "boolean {entityID} Returns whether the specified living entity can pick up items."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_can_pickup_items extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { Static.getLivingEntity(args[0], t).setCanPickupItems(Static.getBoolean(args[1])); return CVoid.VOID; } @Override public String getName() { return "set_can_pickup_items"; } @Override public String docs() { return "void {entityID, boolean} Sets a living entity's ability to pick up items."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_entity_persistence extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return CBoolean.get(!Static.getLivingEntity(args[0], t).getRemoveWhenFarAway()); } @Override public String getName() { return "get_entity_persistence"; } @Override public String docs() { return "boolean {entityID} Returns whether the specified living entity will despawn. True means it will not."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_persistence extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { Static.getLivingEntity(args[0], t).setRemoveWhenFarAway(!Static.getBoolean(args[1])); return CVoid.VOID; } @Override public String getName() { return "set_entity_persistence"; } @Override public String docs() { return "void {entityID, boolean} Sets whether a living entity will despawn. True means it will not."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_art_at extends AbstractFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREBadEntityException.class, CREFormatException.class}; } @Override public boolean isRestricted() { return true; } @Override public Boolean runAsync() { return false; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCWorld w = null; if(environment.getEnv(CommandHelperEnvironment.class).GetPlayer() != null){ w = environment.getEnv(CommandHelperEnvironment.class).GetPlayer().getWorld(); } List<MCEntity> es = StaticLayer.GetConvertor().GetEntitiesAt(ObjectGenerator.GetGenerator().location(args[0], w, t), 1); for(MCEntity e : es){ if(e instanceof MCPainting){ return new CString(((MCPainting)e).getArt().name(), t); } } throw new CREBadEntityException("There is no painting at the specified location", t); } @Override public String getName() { return "get_art_at"; } @Override public Integer[] numArgs() { return new Integer[]{1}; } @Override public String docs() { return "string {locationArray} Gets the specified art at the given location. If the item" + " at the specified location isn't a painting, an ----" + " Will be one of the following: " + StringUtils.Join(MCArt.values(), ", ") + "."; } @Override public Version since() { return CHVersion.V3_3_1; } } @api public static class set_art_at extends AbstractFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CREFormatException.class}; } @Override public boolean isRestricted() { return true; } @Override public Boolean runAsync() { return false; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCWorld w = null; if(environment.getEnv(CommandHelperEnvironment.class).GetPlayer() != null){ w = environment.getEnv(CommandHelperEnvironment.class).GetPlayer().getWorld(); } MCLocation loc = ObjectGenerator.GetGenerator().location(args[0], w, t); MCArt art; try{ art = MCArt.valueOf(args[1].val()); } catch(IllegalArgumentException e){ throw new CREFormatException("Invalid type: " + args[1].val(), t); } //If there's already a painting there, just use that one. Otherwise, spawn a new one. MCPainting p = null; for(MCEntity e : StaticLayer.GetConvertor().GetEntitiesAt(loc, 1)){ if(e instanceof MCPainting){ p = (MCPainting)e; break; } } if(p == null){ p = (MCPainting) loc.getWorld().spawn(loc, MCEntityType.MCVanillaEntityType.PAINTING); } boolean worked = p.setArt(art); if(!worked){ p.remove(); } return CBoolean.get(worked); } @Override public String getName() { return "set_art_at"; } @Override public Integer[] numArgs() { return new Integer[]{2, 3}; } @Override public String docs() { return "boolean {locationArray, art} Sets the art at the specified location. If the art" + " doesn't fit, nothing happens, and false is returned. Otherwise, true is returned." + " ---- Art may be one of the following: " + StringUtils.Join(MCArt.values(), ", "); } @Override public Version since() { return CHVersion.V3_3_1; } } @api public static class get_leashholder extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); if (!le.isLeashed()) { return CNull.NULL; } return new CString(le.getLeashHolder().getUniqueId().toString(), t); } @Override public String getName() { return "get_leashholder"; } @Override public String docs() { return "int {entityID} Returns the entityID of the entity that is holding the given living entity's leash," + " or null if it isn't being held."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_leashholder extends EntitySetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity le = Static.getLivingEntity(args[0], t); MCEntity holder; if (args[1] instanceof CNull) { holder = null; } else { holder = Static.getEntity(args[1], t); } le.setLeashHolder(holder); return CVoid.VOID; } @Override public String getName() { return "set_leashholder"; } @Override public String docs() { return "void {entityID, entityID} The first entity is the entity to be held on a leash, and must be living." + " The second entity is the holder of the leash. This does not have to be living," + " but the only non-living entity that will persist as a holder across restarts is the leash hitch." + " Bats, enderdragons, players, and withers can not be held by leashes due to minecraft limitations."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_grounded extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return CBoolean.get(Static.getEntity(args[0], t).isOnGround()); } @Override public String getName() { return "entity_grounded"; } @Override public String docs() { return "boolean {entityID} returns whether the entity is touching the ground"; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_air extends EntityGetterFunction { @Override public String getName() { return "entity_air"; } @Override public String docs() { return "int {entityID} Returns the amount of air the specified living entity has remaining."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return new CInt(Static.getLivingEntity(args[0], t).getRemainingAir(), t); } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_air extends EntitySetterFunction { @Override public String getName() { return "set_entity_air"; } @Override public String docs() { return "void {entityID, int} Sets the amount of air the specified living entity has remaining."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { Static.getLivingEntity(args[0], t).setRemainingAir(Static.getInt32(args[1], t)); return CVoid.VOID; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_max_air extends EntityGetterFunction { @Override public String getName() { return "entity_max_air"; } @Override public String docs() { return "int {entityID} Returns the maximum amount of air the specified living entity can have."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return new CInt(Static.getLivingEntity(args[0], t).getMaximumAir(), t); } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_max_air extends EntitySetterFunction { @Override public String getName() { return "set_entity_max_air"; } @Override public String docs() { return "void {entityID, int} Sets the maximum amount of air the specified living entity can have."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { Static.getLivingEntity(args[0], t).setMaximumAir(Static.getInt32(args[1], t)); return CVoid.VOID; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_line_of_sight extends EntityFunction { @Override public String getName() { return "entity_line_of_sight"; } @Override public Integer[] numArgs() { return new Integer[]{1, 2, 3}; } @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRECastException.class, CRELengthException.class, CREBadEntityException.class}; } @Override public String docs() { return "array {entityID, [transparents, [maxDistance]]} Returns an array containing all blocks along the" + " living entity's line of sight. transparents is an array of block IDs, only air by default." + " maxDistance represents the maximum distance to scan. The server may cap the scan distance," + " but probably by not any less than 100 meters."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity entity = Static.getLivingEntity(args[0], t); HashSet<Byte> transparents = null; int maxDistance = 512; if (args.length >= 2) { CArray givenTransparents = Static.getArray(args[1], t); if (givenTransparents.inAssociativeMode()) { throw new CRECastException("The array must not be associative.", t); } transparents = new HashSet<Byte>(); for (Construct blockID : givenTransparents.asList()) { transparents.add((byte) Static.getInt16(blockID, t)); } } if (args.length == 3) { maxDistance = Static.getInt32(args[2], t); } CArray lineOfSight = new CArray(t); for (MCBlock block : entity.getLineOfSight(transparents, maxDistance)) { lineOfSight.push(ObjectGenerator.GetGenerator().location(block.getLocation(), false), t); } return lineOfSight; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_can_see extends EntityFunction { @Override public String getName() { return "entity_can_see"; } @Override public Integer[] numArgs() { return new Integer[]{2}; } @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRELengthException.class, CREBadEntityException.class}; } @Override public String docs() { return "boolean {entityID, otherEntityID} Returns if the entity can have the other entity in his line of sight." + " For instance for players this mean that it can have the other entity on its screen and that this one is not hidden by opaque blocks." + " This uses the same algorithm that hostile mobs use to find the closest player."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return CBoolean.get(Static.getLivingEntity(args[0], t).hasLineOfSight(Static.getEntity(args[1], t))); } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_id extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntityByUuid(Static.GetUUID(args[0], t), t); return new CString(entity.getUniqueId().toString(), t); } @Override public String getName() { return "entity_id"; } @Override public String docs() { return "string {entityUUID} returns the entity id for unique persistent UUID"; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_uuid extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); return new CString(entity.getUniqueId().toString(), t); } @Override public String getName() { return "entity_uuid"; } @Override public String docs() { return "string {entityID} returns the persistent unique id of the entity"; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api @seealso(set_entity_spec.class) public static class entity_spec extends EntityGetterFunction { @Override public String getName() { return "entity_spec"; } @Override public String docs() { String docs = getBundledDocs(); docs = docs.replace("%BODY_PART%", "pose" + StringUtils.Join(MCBodyPart.humanoidParts(), ", pose", ", or pose", " or pose")); docs = docs.replace("%HORSE_COLOR%", StringUtils.Join(MCHorseColor.values(), ", ", ", or ", " or ")); docs = docs.replace("%HORSE_STYLE%", StringUtils.Join(MCHorsePattern.values(), ", ", ", or ", " or ")); docs = docs.replace("%HORSE_VARIANT%", StringUtils.Join(MCHorseVariant.values(), ", ", ", or ", " or ")); docs = docs.replace("%LLAMA_COLOR%", StringUtils.Join(MCLlamaColor.values(), ", ", ", or ", " or ")); docs = docs.replace("%ROTATION%", StringUtils.Join(MCRotation.values(), ", ", ", or ", " or ")); docs = docs.replace("%OCELOT_TYPE%", StringUtils.Join(MCOcelotType.values(), ", ", ", or ", " or ")); docs = docs.replace("%ART%", StringUtils.Join(MCArt.values(), ", ", ", or ", " or ")); docs = docs.replace("%DYE_COLOR%", StringUtils.Join(MCDyeColor.values(), ", ", ", or ", " or ")); docs = docs.replace("%SKELETON_TYPE%", StringUtils.Join(MCSkeletonType.values(), ", ", ", or ", " or ")); docs = docs.replace("%PROFESSION%", StringUtils.Join(MCProfession.values(), ", ", ", or ", " or ")); docs = docs.replace("%RABBIT_TYPE%", StringUtils.Join(MCRabbitType.values(), ", ", ", or ", " or ")); docs = docs.replace("%PARTICLE%", StringUtils.Join(MCParticle.values(), ", ", ", or ", " or ")); docs = docs.replace("%ENDERDRAGON_PHASE%", StringUtils.Join(MCEnderDragonPhase.values(), ", ", ", or ", " or ")); for (Field field : entity_spec.class.getDeclaredFields()) { try { String name = field.getName(); if (name.startsWith("KEY_")) { docs = docs.replace("%" + name + "%", (String) field.get(null)); } } catch (IllegalArgumentException | IllegalAccessException ex) { ex.printStackTrace(); } } return docs; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); CArray specArray = CArray.GetAssociativeArray(t); switch (entity.getType().getAbstracted()) { case AREA_EFFECT_CLOUD: MCAreaEffectCloud cloud = (MCAreaEffectCloud) entity; specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_COLOR, ObjectGenerator.GetGenerator().color(cloud.getColor(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_DURATION, new CInt(cloud.getDuration(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_DURATIONONUSE, new CInt(cloud.getDurationOnUse(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_PARTICLE, new CString(cloud.getParticle().name(), t), t); CArray meta = CArray.GetAssociativeArray(t); CArray effects = ObjectGenerator.GetGenerator().potions(cloud.getCustomEffects(), t); meta.set("potions", effects, t); meta.set("base", ObjectGenerator.GetGenerator().potionData(cloud.getBasePotionData(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_POTIONMETA, meta, t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_RADIUS, new CDouble(cloud.getRadius(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_RADIUSONUSE, new CDouble(cloud.getRadiusOnUse(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_RADIUSPERTICK, new CDouble(cloud.getRadiusPerTick(), t), t); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_REAPPLICATIONDELAY, new CInt(cloud.getReapplicationDelay(), t), t); MCProjectileSource cloudSource = cloud.getSource(); if(cloudSource instanceof MCBlockProjectileSource){ MCLocation blockLocation = ((MCBlockProjectileSource) cloudSource).getBlock().getLocation(); CArray locationArray = ObjectGenerator.GetGenerator().location(blockLocation, false); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_SOURCE, locationArray, t); } else if (cloudSource instanceof MCEntity) { String entityUUID = ((MCEntity) cloudSource).getUniqueId().toString(); specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_SOURCE, new CString(entityUUID, t), t); } else { specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_SOURCE, CNull.NULL, t); } specArray.set(entity_spec.KEY_AREAEFFECTCLOUD_WAITTIME, new CInt(cloud.getWaitTime(), t), t); break; case ARROW: MCArrow arrow = (MCArrow) entity; specArray.set(entity_spec.KEY_ARROW_CRITICAL, CBoolean.get(arrow.isCritical()), t); specArray.set(entity_spec.KEY_ARROW_KNOCKBACK, new CInt(arrow.getKnockbackStrength(), t), t); break; case ARMOR_STAND: MCArmorStand stand = (MCArmorStand) entity; specArray.set(entity_spec.KEY_ARMORSTAND_ARMS, CBoolean.get(stand.hasArms()), t); specArray.set(entity_spec.KEY_ARMORSTAND_BASEPLATE, CBoolean.get(stand.hasBasePlate()), t); specArray.set(entity_spec.KEY_ARMORSTAND_GRAVITY, CBoolean.get(stand.hasGravity()), t); Boolean marker = stand.isMarker(); if(marker != null) { // unsupported before 1.8.7 specArray.set(entity_spec.KEY_ARMORSTAND_MARKER, CBoolean.get(marker), t); } specArray.set(entity_spec.KEY_ARMORSTAND_SMALLSIZE, CBoolean.get(stand.isSmall()), t); specArray.set(entity_spec.KEY_ARMORSTAND_VISIBLE, CBoolean.get(stand.isVisible()), t); CArray poses = CArray.GetAssociativeArray(t); Map<MCBodyPart, Vector3D> poseMap = stand.getAllPoses(); for (MCBodyPart key : poseMap.keySet()) { poses.set("pose" + key.name(), ObjectGenerator.GetGenerator().vector(poseMap.get(key), t), t); } specArray.set(entity_spec.KEY_ARMORSTAND_POSES, poses, t); break; case CREEPER: MCCreeper creeper = (MCCreeper) entity; specArray.set(entity_spec.KEY_CREEPER_POWERED, CBoolean.get(creeper.isPowered()), t); break; case DONKEY: case MULE: MCChestedHorse chestedhorse = (MCChestedHorse) entity; specArray.set(entity_spec.KEY_HORSE_CHEST, CBoolean.get(chestedhorse.hasChest()), t); specArray.set(entity_spec.KEY_HORSE_JUMP, new CDouble(chestedhorse.getJumpStrength(), t), t); specArray.set(entity_spec.KEY_HORSE_DOMESTICATION, new CInt(chestedhorse.getDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_MAXDOMESTICATION, new CInt(chestedhorse.getMaxDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_SADDLE, ObjectGenerator.GetGenerator().item(chestedhorse.getSaddle(), t), t); break; case DROPPED_ITEM: MCItem item = (MCItem) entity; specArray.set(entity_spec.KEY_DROPPED_ITEM_ITEMSTACK, ObjectGenerator.GetGenerator().item(item.getItemStack(), t), t); specArray.set(entity_spec.KEY_DROPPED_ITEM_PICKUPDELAY, new CInt(item.getPickupDelay(), t), t); break; case ENDER_CRYSTAL: MCEnderCrystal endercrystal = (MCEnderCrystal) entity; if(Static.getServer().getMinecraftVersion().gte(MCVersion.MC1_9)){ specArray.set(entity_spec.KEY_ENDERCRYSTAL_BASE, CBoolean.get(endercrystal.isShowingBottom()), t); MCLocation location = endercrystal.getBeamTarget(); if(location == null){ specArray.set(entity_spec.KEY_ENDERCRYSTAL_BEAMTARGET, CNull.NULL, t); } else { specArray.set(entity_spec.KEY_ENDERCRYSTAL_BEAMTARGET, ObjectGenerator.GetGenerator().location(location, false), t); } } break; case ENDER_DRAGON: MCEnderDragon enderdragon = (MCEnderDragon) entity; if(Static.getServer().getMinecraftVersion().gte(MCVersion.MC1_9_X)){ specArray.set(entity_spec.KEY_ENDERDRAGON_PHASE, new CString(enderdragon.getPhase().name(), t), t); } break; case ENDERMAN: MCEnderman enderman = (MCEnderman) entity; MCMaterialData carried = enderman.getCarriedMaterial(); if (carried != null) { specArray.set(entity_spec.KEY_ENDERMAN_CARRIED, new CString(carried.getMaterial().getName(), t), t); } else { specArray.set(entity_spec.KEY_ENDERMAN_CARRIED, CNull.NULL, t); } break; case EXPERIENCE_ORB: MCExperienceOrb orb = (MCExperienceOrb) entity; specArray.set(entity_spec.KEY_EXPERIENCE_ORB_AMOUNT, new CInt(orb.getExperience(), t), t); break; case FALLING_BLOCK: MCFallingBlock block = (MCFallingBlock) entity; specArray.set(entity_spec.KEY_FALLING_BLOCK_BLOCK, new CInt(block.getMaterial().getName(), t), t); specArray.set(entity_spec.KEY_FALLING_BLOCK_DROPITEM, CBoolean.get(block.getDropItem()), t); break; case FIREBALL: case SMALL_FIREBALL: MCFireball ball = (MCFireball) entity; specArray.set(entity_spec.KEY_FIREBALL_DIRECTION, ObjectGenerator.GetGenerator().vector(ball.getDirection(), t), t); break; case FISHING_HOOK: MCFishHook hook = (MCFishHook) entity; specArray.set(entity_spec.KEY_FISHING_HOOK_CHANCE, new CDouble(hook.getBiteChance(), t), t); break; case GUARDIAN: MCGuardian guardian = (MCGuardian) entity; specArray.set(entity_spec.KEY_GUARDIAN_ELDER, CBoolean.get(guardian.isElder()), t); break; case HORSE: MCHorse horse = (MCHorse) entity; specArray.set(entity_spec.KEY_HORSE_COLOR, new CString(horse.getColor().name(), t), t); specArray.set(entity_spec.KEY_HORSE_STYLE, new CString(horse.getPattern().name(), t), t); specArray.set(entity_spec.KEY_HORSE_VARIANT, new CString(horse.getVariant().name(), t), t); specArray.set(entity_spec.KEY_HORSE_CHEST, CBoolean.get(horse.hasChest()), t); specArray.set(entity_spec.KEY_HORSE_JUMP, new CDouble(horse.getJumpStrength(), t), t); specArray.set(entity_spec.KEY_HORSE_DOMESTICATION, new CInt(horse.getDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_MAXDOMESTICATION, new CInt(horse.getMaxDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_ARMOR, ObjectGenerator.GetGenerator().item(horse.getArmor(), t), t); specArray.set(entity_spec.KEY_HORSE_SADDLE, ObjectGenerator.GetGenerator().item(horse.getSaddle(), t), t); break; case HUSK: MCZombie husk = (MCZombie) entity; specArray.set(entity_spec.KEY_ZOMBIE_BABY, CBoolean.get(husk.isBaby()), t); break; case IRON_GOLEM: MCIronGolem golem = (MCIronGolem) entity; specArray.set(entity_spec.KEY_IRON_GOLEM_PLAYERCREATED, CBoolean.get(golem.isPlayerCreated()), t); break; case ITEM_FRAME: MCItemFrame frame = (MCItemFrame) entity; MCItemStack itemstack = frame.getItem(); if (itemstack != null) { specArray.set(entity_spec.KEY_ITEM_FRAME_ITEM, ObjectGenerator.GetGenerator().item(frame.getItem(), t), t); } else { specArray.set(entity_spec.KEY_ITEM_FRAME_ITEM, CNull.NULL, t); } specArray.set(entity_spec.KEY_ITEM_FRAME_ROTATION, new CString(frame.getRotation().name(), t), t); break; case LIGHTNING: MCLightningStrike lightning = (MCLightningStrike) entity; specArray.set(entity_spec.KEY_LIGHTNING_EFFECT, CBoolean.get(lightning.isEffect()), t); break; case LLAMA: MCLlama llama = (MCLlama) entity; specArray.set(entity_spec.KEY_HORSE_COLOR, new CString(llama.getLlamaColor().name(), t), t); specArray.set(entity_spec.KEY_HORSE_CHEST, CBoolean.get(llama.hasChest()), t); specArray.set(entity_spec.KEY_HORSE_DOMESTICATION, new CInt(llama.getDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_MAXDOMESTICATION, new CInt(llama.getMaxDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_SADDLE, ObjectGenerator.GetGenerator().item(llama.getSaddle(), t), t); break; case MAGMA_CUBE: case SLIME: MCSlime cube = (MCSlime) entity; specArray.set(entity_spec.KEY_SLIME_SIZE, new CInt(cube.getSize(), t), t); break; case MINECART: MCMinecart minecart = (MCMinecart) entity; specArray.set(entity_spec.KEY_MINECART_BLOCK, new CString(minecart.getDisplayBlock().getMaterial().getName(), t), t); specArray.set(entity_spec.KEY_MINECART_OFFSET, new CInt(minecart.getDisplayBlockOffset(), t), t); break; case MINECART_COMMAND: MCCommandMinecart commandminecart = (MCCommandMinecart) entity; specArray.set(entity_spec.KEY_MINECART_COMMAND_COMMAND, new CString(commandminecart.getCommand(), t), t); specArray.set(entity_spec.KEY_MINECART_COMMAND_CUSTOMNAME, new CString(commandminecart.getName(), t), t); break; case OCELOT: MCOcelot ocelot = (MCOcelot) entity; specArray.set(entity_spec.KEY_OCELOT_TYPE, new CString(ocelot.getCatType().name(), t), t); specArray.set(entity_spec.KEY_OCELOT_SITTING, CBoolean.get(ocelot.isSitting()), t); break; case PAINTING: MCPainting painting = (MCPainting) entity; specArray.set(entity_spec.KEY_PAINTING_ART, new CString(painting.getArt().name(), t), t); break; case PIG: MCPig pig = (MCPig) entity; specArray.set(entity_spec.KEY_PIG_SADDLED, CBoolean.get(pig.isSaddled()), t); break; case PIG_ZOMBIE: MCPigZombie pigZombie = (MCPigZombie) entity; specArray.set(entity_spec.KEY_PIG_ZOMBIE_ANGRY, CBoolean.get(pigZombie.isAngry()), t); specArray.set(entity_spec.KEY_PIG_ZOMBIE_ANGER, new CInt(pigZombie.getAnger(), t), t); specArray.set(entity_spec.KEY_ZOMBIE_BABY, CBoolean.get(pigZombie.isBaby()), t); break; case PRIMED_TNT: MCTNT tnt = (MCTNT) entity; specArray.set(entity_spec.KEY_PRIMED_TNT_FUSETICKS, new CInt(tnt.getFuseTicks(), t), t); MCEntity source = tnt.getSource(); if (source != null) { specArray.set(entity_spec.KEY_PRIMED_TNT_SOURCE, new CString(source.getUniqueId().toString(), t), t); } else { specArray.set(entity_spec.KEY_PRIMED_TNT_SOURCE, CNull.NULL, t); } break; case RABBIT: MCRabbit rabbit = (MCRabbit) entity; specArray.set(entity_spec.KEY_RABBIT_TYPE, new CString(rabbit.getRabbitType().name(), t), t); break; case SHEEP: MCSheep sheep = (MCSheep) entity; specArray.set(entity_spec.KEY_SHEEP_COLOR, new CString(sheep.getColor().name(), t), t); specArray.set(entity_spec.KEY_SHEEP_SHEARED, CBoolean.get(sheep.isSheared()), t); break; case SHULKER_BULLET: MCShulkerBullet bullet = (MCShulkerBullet) entity; MCEntity target = bullet.getTarget(); if(target == null) { specArray.set(entity_spec.KEY_SHULKERBULLET_TARGET, CNull.NULL, t); } else { specArray.set(entity_spec.KEY_SHULKERBULLET_TARGET, new CString(target.getUniqueId().toString(), t), t); } break; case SKELETON: case STRAY: case WITHER_SKELETON: MCSkeleton skeleton = (MCSkeleton) entity; specArray.set(entity_spec.KEY_SKELETON_TYPE, new CString(skeleton.getSkeletonType().name(), t), t); break; case SKELETON_HORSE: case ZOMBIE_HORSE: MCAbstractHorse undeadhorse = (MCAbstractHorse) entity; specArray.set(entity_spec.KEY_HORSE_JUMP, new CDouble(undeadhorse.getJumpStrength(), t), t); specArray.set(entity_spec.KEY_HORSE_DOMESTICATION, new CInt(undeadhorse.getDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_MAXDOMESTICATION, new CInt(undeadhorse.getMaxDomestication(), t), t); specArray.set(entity_spec.KEY_HORSE_SADDLE, ObjectGenerator.GetGenerator().item(undeadhorse.getSaddle(), t), t); break; case SNOWMAN: if (Static.getVersion().gte(MCVersion.MC1_9_4)) { MCSnowman snowman = (MCSnowman) entity; specArray.set(entity_spec.KEY_SNOWMAN_DERP, CBoolean.GenerateCBoolean(snowman.isDerp(), t), t); } break; case LINGERING_POTION: case SPLASH_POTION: MCThrownPotion potion = (MCThrownPotion) entity; specArray.set(entity_spec.KEY_SPLASH_POTION_ITEM, ObjectGenerator.GetGenerator().item(potion.getItem(), t), t); break; case TIPPED_ARROW: MCTippedArrow tippedarrow = (MCTippedArrow) entity; specArray.set(entity_spec.KEY_ARROW_CRITICAL, CBoolean.get(tippedarrow.isCritical()), t); specArray.set(entity_spec.KEY_ARROW_KNOCKBACK, new CInt(tippedarrow.getKnockbackStrength(), t), t); CArray tippedmeta = CArray.GetAssociativeArray(t); CArray tippedeffects = ObjectGenerator.GetGenerator().potions(tippedarrow.getCustomEffects(), t); tippedmeta.set("potions", tippedeffects, t); tippedmeta.set("base", ObjectGenerator.GetGenerator().potionData(tippedarrow.getBasePotionData(), t), t); specArray.set(entity_spec.KEY_TIPPEDARROW_POTIONMETA, tippedmeta, t); break; case VILLAGER: MCVillager villager = (MCVillager) entity; specArray.set(entity_spec.KEY_VILLAGER_PROFESSION, new CString(villager.getProfession().name(), t), t); break; case WITHER_SKULL: MCWitherSkull skull = (MCWitherSkull) entity; specArray.set(entity_spec.KEY_WITHER_SKULL_CHARGED, CBoolean.get(skull.isCharged()), t); specArray.set(entity_spec.KEY_FIREBALL_DIRECTION, ObjectGenerator.GetGenerator().vector(skull.getDirection(), t), t); break; case WOLF: MCWolf wolf = (MCWolf) entity; specArray.set(entity_spec.KEY_WOLF_ANGRY, CBoolean.get(wolf.isAngry()), t); specArray.set(entity_spec.KEY_WOLF_COLOR, new CString(wolf.getCollarColor().name(), t), t); specArray.set(entity_spec.KEY_WOLF_SITTING, CBoolean.get(wolf.isSitting()), t); break; case ZOMBIE: MCZombie zombie = (MCZombie) entity; specArray.set(entity_spec.KEY_ZOMBIE_BABY, CBoolean.get(zombie.isBaby()), t); specArray.set(entity_spec.KEY_ZOMBIE_VILLAGER, CBoolean.get(zombie.isVillager()), t); break; case ZOMBIE_VILLAGER: MCZombieVillager zombievillager = (MCZombieVillager) entity; specArray.set(entity_spec.KEY_ZOMBIE_BABY, CBoolean.get(zombievillager.isBaby()), t); specArray.set(entity_spec.KEY_VILLAGER_PROFESSION, new CString(zombievillager.getProfession().name(), t), t); break; } return specArray; } @Override public CHVersion since() { return CHVersion.V3_3_1; } //used to ensure that the indexes are the same in entity_spec(), set_entity_spec(), and in the documentation. private static final String KEY_AREAEFFECTCLOUD_COLOR = "color"; private static final String KEY_AREAEFFECTCLOUD_DURATION = "duration"; private static final String KEY_AREAEFFECTCLOUD_DURATIONONUSE = "durationonuse"; private static final String KEY_AREAEFFECTCLOUD_PARTICLE = "particle"; private static final String KEY_AREAEFFECTCLOUD_POTIONMETA = "potionmeta"; private static final String KEY_AREAEFFECTCLOUD_RADIUS = "radius"; private static final String KEY_AREAEFFECTCLOUD_RADIUSONUSE = "radiusonuse"; private static final String KEY_AREAEFFECTCLOUD_RADIUSPERTICK = "radiuspertick"; private static final String KEY_AREAEFFECTCLOUD_REAPPLICATIONDELAY = "reapplicationdelay"; private static final String KEY_AREAEFFECTCLOUD_SOURCE = "source"; private static final String KEY_AREAEFFECTCLOUD_WAITTIME = "waittime"; private static final String KEY_ARROW_CRITICAL = "critical"; private static final String KEY_ARROW_KNOCKBACK = "knockback"; private static final String KEY_ARMORSTAND_ARMS = "arms"; private static final String KEY_ARMORSTAND_BASEPLATE = "baseplate"; private static final String KEY_ARMORSTAND_GRAVITY = "gravity"; private static final String KEY_ARMORSTAND_MARKER = "marker"; private static final String KEY_ARMORSTAND_POSES = "poses"; private static final String KEY_ARMORSTAND_SMALLSIZE = "small"; private static final String KEY_ARMORSTAND_VISIBLE = "visible"; private static final String KEY_CREEPER_POWERED = "powered"; private static final String KEY_DROPPED_ITEM_ITEMSTACK = "itemstack"; private static final String KEY_DROPPED_ITEM_PICKUPDELAY = "pickupdelay"; private static final String KEY_ENDERCRYSTAL_BASE = "base"; private static final String KEY_ENDERCRYSTAL_BEAMTARGET = "beamtarget"; private static final String KEY_ENDERDRAGON_PHASE = "phase"; private static final String KEY_ENDERMAN_CARRIED = "carried"; private static final String KEY_EXPERIENCE_ORB_AMOUNT = "amount"; private static final String KEY_FALLING_BLOCK_BLOCK = "block"; private static final String KEY_FALLING_BLOCK_DROPITEM = "dropitem"; private static final String KEY_FIREBALL_DIRECTION = "direction"; private static final String KEY_FISHING_HOOK_CHANCE = "chance"; private static final String KEY_GUARDIAN_ELDER = "elder"; private static final String KEY_HORSE_COLOR = "color"; private static final String KEY_HORSE_STYLE = "style"; private static final String KEY_HORSE_VARIANT = "variant"; private static final String KEY_HORSE_CHEST = "chest"; private static final String KEY_HORSE_JUMP = "jump"; private static final String KEY_HORSE_DOMESTICATION = "domestication"; private static final String KEY_HORSE_MAXDOMESTICATION = "maxdomestication"; private static final String KEY_HORSE_ARMOR = "armor"; private static final String KEY_HORSE_SADDLE = "saddle"; private static final String KEY_IRON_GOLEM_PLAYERCREATED = "playercreated"; private static final String KEY_ITEM_FRAME_ITEM = "item"; private static final String KEY_ITEM_FRAME_ROTATION = "rotation"; private static final String KEY_LIGHTNING_EFFECT = "effect"; private static final String KEY_MINECART_BLOCK = "block"; private static final String KEY_MINECART_OFFSET = "offset"; private static final String KEY_MINECART_COMMAND_COMMAND = "command"; private static final String KEY_MINECART_COMMAND_CUSTOMNAME = "customname"; private static final String KEY_OCELOT_TYPE = "type"; private static final String KEY_OCELOT_SITTING = "sitting"; private static final String KEY_PAINTING_ART = "type"; private static final String KEY_PIG_SADDLED = "saddled"; private static final String KEY_PIG_ZOMBIE_ANGRY = "angry"; private static final String KEY_PIG_ZOMBIE_ANGER = "anger"; private static final String KEY_RABBIT_TYPE = "type"; private static final String KEY_PRIMED_TNT_FUSETICKS = "fuseticks"; private static final String KEY_PRIMED_TNT_SOURCE = "source"; private static final String KEY_SHEEP_COLOR = "color"; private static final String KEY_SHEEP_SHEARED = "sheared"; private static final String KEY_SHULKERBULLET_TARGET = "target"; private static final String KEY_SKELETON_TYPE = "type"; private static final String KEY_SLIME_SIZE = "size"; private static final String KEY_SNOWMAN_DERP = "derp"; private static final String KEY_SPLASH_POTION_ITEM = "item"; private static final String KEY_TIPPEDARROW_POTIONMETA = "potionmeta"; private static final String KEY_VILLAGER_PROFESSION = "profession"; private static final String KEY_WITHER_SKULL_CHARGED = "charged"; private static final String KEY_WOLF_ANGRY = "angry"; private static final String KEY_WOLF_COLOR = "color"; private static final String KEY_WOLF_SITTING = "sitting"; private static final String KEY_ZOMBIE_BABY = "baby"; private static final String KEY_ZOMBIE_VILLAGER = "villager"; } @api @seealso(entity_spec.class) public static class set_entity_spec extends EntitySetterFunction { @Override public String getName() { return "set_entity_spec"; } @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{ CRECastException.class, CREBadEntityException.class, CREIndexOverflowException.class, CREIndexOverflowException.class, CRERangeException.class, CREFormatException.class, CRELengthException.class }; } @Override public String docs() { return "void {entityID, specArray} Sets the data in the specArray to the given entity." + " The specArray must follow the same format as entity_spec()." + " See the documentation for that function for info on available options." + " All indices in the specArray are optional."; } private static void throwException(String index, Target t) throws ConfigRuntimeException { throw new CREIndexOverflowException("Unknown or uneditable specification: " + index, t); } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); CArray specArray = Static.getArray(args[1], t); switch (entity.getType().getAbstracted()) { case AREA_EFFECT_CLOUD: MCAreaEffectCloud cloud = (MCAreaEffectCloud) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_AREAEFFECTCLOUD_COLOR: if (specArray.get(index, t) instanceof CArray){ CArray color = (CArray) specArray.get(index, t); cloud.setColor(ObjectGenerator.GetGenerator().color(color, t)); } else { throw new CRECastException("AreaEffectCloud color must be an array", t); } break; case entity_spec.KEY_AREAEFFECTCLOUD_DURATION: cloud.setDuration(ArgumentValidation.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_AREAEFFECTCLOUD_DURATIONONUSE: cloud.setDurationOnUse(ArgumentValidation.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_AREAEFFECTCLOUD_PARTICLE: String particleName = specArray.get(index, t).val(); try { cloud.setParticle(MCParticle.valueOf(particleName)); } catch(IllegalArgumentException ex){ throw new CREFormatException("Invalid particle type: " + particleName, t); } break; case entity_spec.KEY_AREAEFFECTCLOUD_POTIONMETA: Construct c = specArray.get(index, t); if(c instanceof CArray){ CArray meta = (CArray) c; if(meta.containsKey("base")){ Construct base = meta.get("base", t); if(base instanceof CArray){ MCPotionData pd = ObjectGenerator.GetGenerator().potionData((CArray) base, t); cloud.setBasePotionData(pd); } } if(meta.containsKey("potions")){ cloud.clearCustomEffects(); Construct potions = meta.get("potions", t); if(potions instanceof CArray){ List<MCLivingEntity.MCEffect> list = ObjectGenerator.GetGenerator().potions((CArray) potions, t); for(MCLivingEntity.MCEffect effect : list) { cloud.addCustomEffect(effect); } } } } else { throw new CRECastException("AreaEffectCloud potion meta must be an array", t); } break; case entity_spec.KEY_AREAEFFECTCLOUD_RADIUS: cloud.setRadius(ArgumentValidation.getDouble32(specArray.get(index, t), t)); break; case entity_spec.KEY_AREAEFFECTCLOUD_RADIUSONUSE: cloud.setRadiusOnUse(ArgumentValidation.getDouble32(specArray.get(index, t), t)); break; case entity_spec.KEY_AREAEFFECTCLOUD_RADIUSPERTICK: cloud.setRadiusPerTick(ArgumentValidation.getDouble32(specArray.get(index, t), t)); break; case entity_spec.KEY_AREAEFFECTCLOUD_REAPPLICATIONDELAY: cloud.setReapplicationDelay(ArgumentValidation.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_AREAEFFECTCLOUD_SOURCE: Construct cloudSource = specArray.get(index, t); if(cloudSource instanceof CNull){ cloud.setSource(null); } else if(cloudSource instanceof CArray){ MCBlock b = ObjectGenerator.GetGenerator().location(cloudSource, cloud.getWorld(), t).getBlock(); if(b.isDispenser()){ cloud.setSource(b.getDispenser().getBlockProjectileSource()); } else { throw new CRECastException("AreaEffectCloud block source must be a dispenser", t); } } else { cloud.setSource(Static.getLivingEntity(cloudSource, t)); } break; case entity_spec.KEY_AREAEFFECTCLOUD_WAITTIME: cloud.setWaitTime(ArgumentValidation.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case ARROW: MCArrow arrow = (MCArrow) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ARROW_CRITICAL: arrow.setCritical(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARROW_KNOCKBACK: int k = Static.getInt32(specArray.get(index, t), t); if (k < 0) { throw new CRERangeException("Knockback can not be negative.", t); } else { arrow.setKnockbackStrength(k); } break; default: throwException(index, t); } } break; case ARMOR_STAND: MCArmorStand stand = (MCArmorStand) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ARMORSTAND_ARMS: stand.setHasArms(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARMORSTAND_BASEPLATE: stand.setHasBasePlate(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARMORSTAND_GRAVITY: stand.setHasGravity(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARMORSTAND_MARKER: stand.setMarker(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARMORSTAND_SMALLSIZE: stand.setSmall(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARMORSTAND_VISIBLE: stand.setVisible(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARMORSTAND_POSES: Map<MCBodyPart, Vector3D> poseMap = stand.getAllPoses(); if (specArray.get(index, t) instanceof CArray) { CArray poseArray = (CArray) specArray.get(index, t); for (MCBodyPart key : poseMap.keySet()) { try { poseMap.put(key, ObjectGenerator.GetGenerator().vector(poseMap.get(key), poseArray.get("pose" + key.name(), t), t)); } catch (ConfigRuntimeException cre) { // Ignore, this just means the user didn't modify a body part } } } if (specArray.get(index, t) instanceof CNull) { for (MCBodyPart key : poseMap.keySet()) { poseMap.put(key, Vector3D.ZERO); } } stand.setAllPoses(poseMap); break; } } break; case CREEPER: MCCreeper creeper = (MCCreeper) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_CREEPER_POWERED: creeper.setPowered(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case DONKEY: case MULE: MCChestedHorse chestedhorse = (MCChestedHorse) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_HORSE_CHEST: chestedhorse.setHasChest(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_HORSE_JUMP: try { chestedhorse.setJumpStrength(Static.getDouble(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The jump strength must be between 0.0 and 2.0", t); } break; case entity_spec.KEY_HORSE_DOMESTICATION: try { chestedhorse.setDomestication(Static.getInt32(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The domestication level can not be higher than the max domestication level.", t); } break; case entity_spec.KEY_HORSE_MAXDOMESTICATION: chestedhorse.setMaxDomestication(Static.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_HORSE_SADDLE: chestedhorse.setSaddle(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case DROPPED_ITEM: MCItem item = (MCItem) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_DROPPED_ITEM_ITEMSTACK: item.setItemStack(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); break; case entity_spec.KEY_DROPPED_ITEM_PICKUPDELAY: item.setPickupDelay(Static.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case ENDER_CRYSTAL: MCEnderCrystal endercrystal = (MCEnderCrystal) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ENDERCRYSTAL_BASE: endercrystal.setShowingBottom(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ENDERCRYSTAL_BEAMTARGET: Construct c = specArray.get(index, t); if(c instanceof CNull){ endercrystal.setBeamTarget(null); } else if(c instanceof CArray){ MCLocation l = ObjectGenerator.GetGenerator().location((CArray) c, endercrystal.getWorld(), t); endercrystal.setBeamTarget(l); } else { throw new CRECastException("EnderCrystal beam target must be an array or null", t); } break; default: throwException(index, t); } } break; case ENDER_DRAGON: MCEnderDragon enderdragon = (MCEnderDragon) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ENDERDRAGON_PHASE: enderdragon.setPhase(MCEnderDragonPhase.valueOf(specArray.get(index, t).val().toUpperCase())); break; default: throwException(index, t); } } break; case ENDERMAN: MCEnderman enderman = (MCEnderman) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ENDERMAN_CARRIED: enderman.setCarriedMaterial(ObjectGenerator.GetGenerator().material(specArray.get(index, t), t).getData()); break; default: throwException(index, t); } } break; case EXPERIENCE_ORB: MCExperienceOrb orb = (MCExperienceOrb) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_EXPERIENCE_ORB_AMOUNT: orb.setExperience(Static.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case FALLING_BLOCK: MCFallingBlock block = (MCFallingBlock) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_FALLING_BLOCK_DROPITEM: block.setDropItem(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case FIREBALL: case SMALL_FIREBALL: MCFireball ball = (MCFireball) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_FIREBALL_DIRECTION: ball.setDirection(ObjectGenerator.GetGenerator().vector(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case FISHING_HOOK: MCFishHook hook = (MCFishHook) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_FISHING_HOOK_CHANCE: try { hook.setBiteChance(Static.getDouble(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The chance must be between 0.0 and 1.0", t); } break; default: throwException(index, t); } } break; case GUARDIAN: MCGuardian guardian = (MCGuardian) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_GUARDIAN_ELDER: guardian.setElder(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case HORSE: MCHorse horse = (MCHorse) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_HORSE_COLOR: try { horse.setColor(MCHorseColor.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid horse color: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_HORSE_STYLE: try { horse.setPattern(MCHorsePattern.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid horse style: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_HORSE_VARIANT: try { horse.setVariant(MCHorseVariant.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid horse variant: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_HORSE_CHEST: horse.setHasChest(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_HORSE_JUMP: try { horse.setJumpStrength(Static.getDouble(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The jump strength must be between 0.0 and 2.0", t); } break; case entity_spec.KEY_HORSE_DOMESTICATION: try { horse.setDomestication(Static.getInt32(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The domestication level can not be higher than the max domestication level.", t); } break; case entity_spec.KEY_HORSE_MAXDOMESTICATION: horse.setMaxDomestication(Static.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_HORSE_SADDLE: horse.setSaddle(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); break; case entity_spec.KEY_HORSE_ARMOR: horse.setArmor(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case HUSK: MCZombie husk = (MCZombie) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ZOMBIE_BABY: husk.setBaby(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case IRON_GOLEM: MCIronGolem golem = (MCIronGolem) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_IRON_GOLEM_PLAYERCREATED: golem.setPlayerCreated(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case ITEM_FRAME: MCItemFrame frame = (MCItemFrame) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ITEM_FRAME_ITEM: frame.setItem(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); if (specArray.get(index, t) instanceof CNull) { frame.setItem(null); } else { frame.setItem(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); } break; case entity_spec.KEY_ITEM_FRAME_ROTATION: try { frame.setRotation(MCRotation.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid rotation type: " + specArray.get(index, t).val(), t); } break; default: throwException(index, t); } } break; case LLAMA: MCLlama llama = (MCLlama) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_HORSE_COLOR: try { llama.setLlamaColor(MCLlamaColor.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid llama color: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_HORSE_CHEST: llama.setHasChest(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_HORSE_DOMESTICATION: try { llama.setDomestication(Static.getInt32(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The domestication level can not be higher than the max domestication level.", t); } break; case entity_spec.KEY_HORSE_MAXDOMESTICATION: llama.setMaxDomestication(Static.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_HORSE_SADDLE: llama.setSaddle(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case MAGMA_CUBE: case SLIME: MCSlime cube = (MCSlime) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_SLIME_SIZE: cube.setSize(Static.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case MINECART: MCMinecart minecart = (MCMinecart) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_MINECART_BLOCK: minecart.setDisplayBlock(ObjectGenerator.GetGenerator().material(specArray.get(index, t), t).getData()); break; case entity_spec.KEY_MINECART_OFFSET: minecart.setDisplayBlockOffset(Static.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case MINECART_COMMAND: MCCommandMinecart commandminecart = (MCCommandMinecart) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_MINECART_COMMAND_CUSTOMNAME: if(specArray.get(index, t) instanceof CNull) { commandminecart.setName(null); } else { commandminecart.setName(specArray.get(index, t).val()); } break; case entity_spec.KEY_MINECART_COMMAND_COMMAND: if(specArray.get(index, t) instanceof CNull) { commandminecart.setCommand(null); } else { commandminecart.setCommand(specArray.get(index, t).val()); } break; default: throwException(index, t); } } break; case OCELOT: MCOcelot ocelot = (MCOcelot) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_OCELOT_TYPE: try { ocelot.setCatType(MCOcelotType.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid ocelot type: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_OCELOT_SITTING: ocelot.setSitting(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case PAINTING: MCPainting painting = (MCPainting) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_PAINTING_ART: try { painting.setArt(MCArt.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid art type: " + specArray.get(index, t).val(), t); } break; default: throwException(index, t); } } break; case PIG: MCPig pig = (MCPig) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_PIG_SADDLED: pig.setSaddled(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case PIG_ZOMBIE: MCPigZombie pigZombie = (MCPigZombie) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ZOMBIE_BABY: pigZombie.setBaby(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_PIG_ZOMBIE_ANGRY: pigZombie.setAngry(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_PIG_ZOMBIE_ANGER: pigZombie.setAnger(Static.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case PRIMED_TNT: MCTNT tnt = (MCTNT) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_PRIMED_TNT_FUSETICKS: tnt.setFuseTicks(Static.getInt32(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case RABBIT: MCRabbit rabbit = (MCRabbit) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_RABBIT_TYPE: try { rabbit.setRabbitType(MCRabbitType.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid rabbit type: " + specArray.get(index, t).val(), t); } break; default: throwException(index, t); } } break; case SHEEP: MCSheep sheep = (MCSheep) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_SHEEP_COLOR: try { sheep.setColor(MCDyeColor.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid sheep color: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_SHEEP_SHEARED: sheep.setSheared(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case SHULKER_BULLET: MCShulkerBullet bullet = (MCShulkerBullet) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_SHULKERBULLET_TARGET: Construct c = specArray.get(index, t); if(c instanceof CNull) { bullet.setTarget(null); } else { bullet.setTarget(Static.getEntity(c, t)); } break; default: throwException(index, t); } } break; case SKELETON: MCSkeleton skeleton = (MCSkeleton) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_SKELETON_TYPE: try { skeleton.setSkeletonType(MCSkeletonType.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid skeleton type: " + specArray.get(index, t).val(), t); } break; default: throwException(index, t); } } break; case SKELETON_HORSE: case ZOMBIE_HORSE: MCAbstractHorse undeadhorse = (MCAbstractHorse) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_HORSE_JUMP: try { undeadhorse.setJumpStrength(Static.getDouble(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The jump strength must be between 0.0 and 2.0", t); } break; case entity_spec.KEY_HORSE_DOMESTICATION: try { undeadhorse.setDomestication(Static.getInt32(specArray.get(index, t), t)); } catch (IllegalArgumentException exception) { throw new CRERangeException("The domestication level can not be higher than the max domestication level.", t); } break; case entity_spec.KEY_HORSE_MAXDOMESTICATION: undeadhorse.setMaxDomestication(Static.getInt32(specArray.get(index, t), t)); break; case entity_spec.KEY_HORSE_SADDLE: undeadhorse.setSaddle(ObjectGenerator.GetGenerator().item(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case SNOWMAN: if (Static.getVersion().gte(MCVersion.MC1_9_4)) { MCSnowman snowman = (MCSnowman) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_SNOWMAN_DERP: snowman.setDerp(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } } break; case LINGERING_POTION: case SPLASH_POTION: MCThrownPotion potion = (MCThrownPotion) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_SPLASH_POTION_ITEM: MCItemStack potionItem = ObjectGenerator.GetGenerator().item(specArray.get(index, t), t); try { potion.setItem(potionItem); } catch(IllegalArgumentException ex){ throw new CREFormatException("Invalid potion type: " + potionItem.getType().getName(), t); } break; default: throwException(index, t); } } break; case TIPPED_ARROW: MCTippedArrow tippedarrow = (MCTippedArrow) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ARROW_CRITICAL: tippedarrow.setCritical(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ARROW_KNOCKBACK: int k = Static.getInt32(specArray.get(index, t), t); if (k < 0) { throw new CRERangeException("Knockback can not be negative.", t); } else { tippedarrow.setKnockbackStrength(k); } break; case entity_spec.KEY_TIPPEDARROW_POTIONMETA: Construct c = specArray.get(index, t); if(c instanceof CArray){ CArray meta = (CArray) c; if(meta.containsKey("base")){ Construct base = meta.get("base", t); if(base instanceof CArray){ MCPotionData pd = ObjectGenerator.GetGenerator().potionData((CArray) base, t); tippedarrow.setBasePotionData(pd); } } if(meta.containsKey("potions")){ tippedarrow.clearCustomEffects(); Construct potions = meta.get("potions", t); if(potions instanceof CArray){ List<MCLivingEntity.MCEffect> list = ObjectGenerator.GetGenerator().potions((CArray) potions, t); for(MCLivingEntity.MCEffect effect : list) { tippedarrow.addCustomEffect(effect); } } } } else { throw new CRECastException("TippedArrow potion meta must be an array", t); } break; default: throwException(index, t); } } break; case VILLAGER: MCVillager villager = (MCVillager) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_VILLAGER_PROFESSION: try { villager.setProfession(MCProfession.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid profession: " + specArray.get(index, t).val(), t); } break; default: throwException(index, t); } } break; case WITHER_SKULL: MCWitherSkull skull = (MCWitherSkull) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_WITHER_SKULL_CHARGED: skull.setCharged(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_FIREBALL_DIRECTION: skull.setDirection(ObjectGenerator.GetGenerator().vector(specArray.get(index, t), t)); break; default: throwException(index, t); } } break; case WOLF: MCWolf wolf = (MCWolf) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_WOLF_ANGRY: wolf.setAngry(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_WOLF_COLOR: try { wolf.setCollarColor(MCDyeColor.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid collar color: " + specArray.get(index, t).val(), t); } break; case entity_spec.KEY_WOLF_SITTING: wolf.setSitting(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case ZOMBIE: MCZombie zombie = (MCZombie) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ZOMBIE_BABY: zombie.setBaby(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_ZOMBIE_VILLAGER: zombie.setVillager(Static.getBoolean(specArray.get(index, t))); break; default: throwException(index, t); } } break; case ZOMBIE_VILLAGER: MCZombieVillager zombievillager = (MCZombieVillager) entity; for (String index : specArray.stringKeySet()) { switch (index.toLowerCase()) { case entity_spec.KEY_ZOMBIE_BABY: zombievillager.setBaby(Static.getBoolean(specArray.get(index, t))); break; case entity_spec.KEY_VILLAGER_PROFESSION: try { zombievillager.setProfession(MCProfession.valueOf(specArray.get(index, t).val().toUpperCase())); } catch (IllegalArgumentException exception) { throw new CREFormatException("Invalid profession: " + specArray.get(index, t).val(), t); } break; default: throwException(index, t); } } break; default: for (String index : specArray.stringKeySet()) { throwException(index, t); } } return CVoid.VOID; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_projectile_shooter extends EntityGetterFunction { @Override public String getName() { return "get_projectile_shooter"; } @Override public String docs() { return "mixed {entityID} Returns the shooter of the given projectile, can be null." + " If the shooter is an entity, that entity's ID will be return, but if it is a block," + " that block's location will be returned."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); if (entity instanceof MCProjectile) { MCProjectileSource shooter = ((MCProjectile) entity).getShooter(); if (shooter instanceof MCBlockProjectileSource) { return ObjectGenerator.GetGenerator().location(((MCBlockProjectileSource) shooter).getBlock().getLocation(), false); } else if (shooter instanceof MCEntity) { return new CString(((MCEntity) shooter).getUniqueId().toString(), t); } else { return CNull.NULL; } } else { throw new CREBadEntityException("The given entity is not a projectile.", t); } } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_projectile_shooter extends EntitySetterFunction { @Override public String getName() { return "set_projectile_shooter"; } @Override public String docs() { return "void {entityID, shooterID} Sets the shooter of the given projectile. This can be entity UUID," + " dispenser location array (throws CastException if not a dispenser), or null."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); if (entity instanceof MCProjectile) { if (args[1] instanceof CNull) { ((MCProjectile) entity).setShooter(null); } else if (args[1] instanceof CArray) { MCBlock b = ObjectGenerator.GetGenerator().location(args[1], entity.getWorld(), t).getBlock(); if(b.isDispenser()){ ((MCProjectile) entity).setShooter(b.getDispenser().getBlockProjectileSource()); } else { throw new CRECastException("Given block location is not a dispenser.", t); } } else { ((MCProjectile) entity).setShooter(Static.getLivingEntity(args[1], t)); } } else { throw new CREBadEntityException("The given entity is not a projectile.", t); } return CVoid.VOID; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class get_projectile_bounce extends EntityGetterFunction { @Override public String getName() { return "get_projectile_bounce"; } @Override public String docs() { return "boolean {entityID} Returns whether or not the given projectile should bounce or not when it hits something."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); if (entity instanceof MCProjectile) { return CBoolean.get(((MCProjectile) entity).doesBounce()); } else { throw new CREBadEntityException("The given entity is not a projectile.", t); } } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_projectile_bounce extends EntitySetterFunction { @Override public String getName() { return "set_projectile_bounce"; } @Override public String docs() { return "void {entityID, boolean} Sets whether or not the given projectile should bounce or not when it hits something."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); if (entity instanceof MCProjectile) { ((MCProjectile) entity).setBounce(Static.getBoolean(args[1])); } else { throw new CREBadEntityException("The given entity is not a projectile.", t); } return CVoid.VOID; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class damage_entity extends EntityFunction { @Override public Class<? extends CREThrowable>[] thrown() { return new Class[]{CRECastException.class, CRELengthException.class, CREBadEntityTypeException.class, CREBadEntityException.class}; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity entity = Static.getEntity(args[0], t); if (!(entity instanceof MCLivingEntity)) { throw new CREBadEntityTypeException("The entity id provided doesn't" + " belong to a living entity", t); } MCLivingEntity living = (MCLivingEntity)entity; double damage = Static.getDouble(args[1], t); if (args.length == 3) { MCEntity source = Static.getEntity(args[2], t); living.damage(damage, source); } else { living.damage(damage); } return CVoid.VOID; } @Override public String getName() { return "damage_entity"; } @Override public Integer[] numArgs() { return new Integer[]{2, 3}; } @Override public String docs() { return "void {entityId, amount, [sourceEntityId]} Damage an entity. If given," + " the source entity will be attributed as the damager."; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class entity_fall_distance extends EntityGetterFunction { @Override public String getName() { return "entity_fall_distance"; } @Override public String docs() { return "double {entityID} Returns the distance the entity has fallen."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return new CDouble(Static.getEntity(args[0], t).getFallDistance(), t); } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_fall_distance extends EntitySetterFunction { @Override public String getName() { return "set_entity_fall_distance"; } @Override public String docs() { return "void {entityID, double} Sets the distance the entity has fallen."; } @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { Static.getEntity(args[0], t).setFallDistance(ArgumentValidation.getDouble32(args[1], t)); return CVoid.VOID; } @Override public CHVersion since() { return CHVersion.V3_3_1; } } @api public static class set_entity_glowing extends EntitySetterFunction { public String getName() { return "set_entity_glowing"; } public String docs() { return "void {Entity ID, boolean} If true, applies glowing effect to the entity"; } public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { Static.getEntity(args[0], t).setGlowing(Static.getBoolean(args[1])); return CVoid.VOID; } public Version since() { return CHVersion.V3_3_2; } } @api public static class get_entity_glowing extends EntityGetterFunction { public String getName() { return "get_entity_glowing"; } public String docs() { return "boolean {Entity} Returns true if the entity is glowing"; } public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity e = Static.getEntity(args[0], t); return CBoolean.GenerateCBoolean(e.isGlowing(), t); } public Version since() { return CHVersion.V3_3_2; } } @api public static class set_entity_gliding extends EntitySetterFunction { public String getName() { return "set_entity_gliding"; } public String docs() { return "void {Entity, boolean} If possible, makes the entity glide"; } public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity e = Static.getLivingEntity(args[0], t); boolean glide = Static.getBoolean(args[1]); e.setGliding(glide); return CVoid.VOID; } public Version since() { return CHVersion.V3_3_2; } } @api public static class get_entity_gliding extends EntityGetterFunction { public String getName() { return "get_entity_gliding"; } public String docs() { return "boolean {Entity} Returns true if the given entity is gliding"; } public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return CBoolean.GenerateCBoolean(Static.getLivingEntity(args[0], t).isGliding(), t); } public Version since() { return CHVersion.V3_3_2; } } @api public static class get_entity_ai extends EntityGetterFunction { public String getName() { return "get_entity_ai"; } public String docs() { return "boolean {Entity} Returns true if the given entity has AI"; } public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { return CBoolean.GenerateCBoolean(Static.getLivingEntity(args[0], t).hasAI(), t); } public Version since() { return CHVersion.V3_3_2; } } @api public static class set_entity_ai extends EntitySetterFunction { public String getName() { return "set_entity_ai"; } public String docs() { return "void {Entity, boolean} enables or disables the entity AI"; } public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCLivingEntity e = Static.getLivingEntity(args[0], t); boolean ai = Static.getBoolean(args[1]); e.setAI(ai); return CVoid.VOID; } public Version since() { return CHVersion.V3_3_2; } } }