Re-implement /remove and /butcher with the new entity API.

This commit is contained in:
sk89q 2014-07-15 19:47:47 -07:00
parent 9dbc53476e
commit 3e34d5ca52
31 changed files with 1110 additions and 604 deletions

View File

@ -23,10 +23,13 @@ import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.entity.metadata.Tameable;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@ -94,4 +97,14 @@ class BukkitEntity implements Entity {
return entity.isDead();
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
if (EntityType.class.isAssignableFrom(cls)) {
return (T) new BukkitEntityType(entity);
} else {
return null;
}
}
}

View File

@ -0,0 +1,140 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.util.Enums;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Golem;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Villager;
import static com.google.common.base.Preconditions.checkNotNull;
class BukkitEntityType implements EntityType {
private static final org.bukkit.entity.EntityType tntMinecartType =
Enums.findByValue(org.bukkit.entity.EntityType.class, "MINECART_TNT");
private final Entity entity;
BukkitEntityType(Entity entity) {
checkNotNull(entity);
this.entity = entity;
}
@Override
public boolean isPlayerDerived() {
return entity instanceof HumanEntity;
}
@Override
public boolean isProjectile() {
return entity instanceof Projectile;
}
@Override
public boolean isItem() {
return entity instanceof Item;
}
@Override
public boolean isFallingBlock() {
return entity instanceof FallingBlock;
}
@Override
public boolean isPainting() {
return entity instanceof Painting;
}
@Override
public boolean isItemFrame() {
return entity instanceof ItemFrame;
}
@Override
public boolean isBoat() {
return entity instanceof Boat;
}
@Override
public boolean isMinecart() {
return entity instanceof Minecart;
}
@Override
public boolean isTNT() {
return entity instanceof TNTPrimed || entity.getType() == tntMinecartType;
}
@Override
public boolean isExperienceOrb() {
return entity instanceof ExperienceOrb;
}
@Override
public boolean isLiving() {
return entity instanceof LivingEntity;
}
@Override
public boolean isAnimal() {
return entity instanceof Animals;
}
@Override
public boolean isAmbient() {
return entity instanceof Ambient;
}
@Override
public boolean isNPC() {
return entity instanceof Villager;
}
@Override
public boolean isGolem() {
return entity instanceof Golem;
}
@Override
public boolean isTamed() {
return entity instanceof Tameable && ((Tameable) entity).isTamed();
}
@Override
public boolean isTagged() {
return entity instanceof LivingEntity && ((LivingEntity) entity).getCustomName() != null;
}
}

View File

@ -35,6 +35,8 @@ import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
public class BukkitPlayer extends LocalPlayer {
private Player player;
private WorldEditPlugin plugin;
@ -184,4 +186,10 @@ public class BukkitPlayer extends LocalPlayer {
(float) Math.toRadians(nativeLocation.getYaw()),
(float) Math.toRadians(nativeLocation.getPitch()));
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
}
}

View File

@ -22,8 +22,6 @@ package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
@ -35,12 +33,10 @@ import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Enums;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.registry.LegacyWorldData;
import com.sk89q.worldedit.world.registry.WorldData;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.TreeType;
import org.bukkit.World;
@ -48,24 +44,7 @@ import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Chest;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Golem;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.DoubleChestInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -75,11 +54,8 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -88,8 +64,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class BukkitWorld extends LocalWorld {
private static final Logger logger = WorldEdit.logger;
private static final org.bukkit.entity.EntityType tntMinecartType =
Enums.findByValue(org.bukkit.entity.EntityType.class, "MINECART_TNT");
private static final Map<Integer, Effect> effects = new HashMap<Integer, Effect>();
static {
@ -377,168 +351,6 @@ public class BukkitWorld extends LocalWorld {
world.dropItemNaturally(BukkitUtil.toLocation(world, pt), bukkitItem);
}
@Override
public int killMobs(Vector origin, double radius, int flags) {
World world = getWorld();
boolean killPets = (flags & KillFlags.PETS) != 0;
boolean killNPCs = (flags & KillFlags.NPCS) != 0;
boolean killAnimals = (flags & KillFlags.ANIMALS) != 0;
boolean withLightning = (flags & KillFlags.WITH_LIGHTNING) != 0;
boolean killGolems = (flags & KillFlags.GOLEMS) != 0;
boolean killAmbient = (flags & KillFlags.AMBIENT) != 0;
boolean killTagged = (flags & KillFlags.TAGGED) != 0;
int num = 0;
double radiusSq = radius * radius;
Location bukkitOrigin = BukkitUtil.toLocation(world, origin);
for (LivingEntity ent : world.getLivingEntities()) {
if (ent instanceof HumanEntity) {
continue;
}
if (!killAnimals && ent instanceof Animals) {
continue;
}
if (!killPets && ent instanceof Tameable && ((Tameable) ent).isTamed()) {
continue; // tamed pet
}
if (!killGolems && ent instanceof Golem) {
continue;
}
if (!killNPCs && ent instanceof Villager) {
continue;
}
if (!killAmbient && ent instanceof Ambient) {
continue;
}
if (!killTagged && isTagged(ent)) {
continue;
}
if (radius < 0 || bukkitOrigin.distanceSquared(ent.getLocation()) <= radiusSq) {
if (withLightning) {
world.strikeLightningEffect(ent.getLocation());
}
ent.remove();
++num;
}
}
return num;
}
private static boolean isTagged(LivingEntity ent) {
return ent.getCustomName() != null;
}
/**
* Remove entities in an area.
*
* @param origin
* @param radius
* @return
*/
@Override
public int removeEntities(EntityType type, Vector origin, int radius) {
World world = getWorld();
int num = 0;
double radiusSq = Math.pow(radius, 2);
for (Entity ent : world.getEntities()) {
if (radius != -1
&& origin.distanceSq(BukkitUtil.toVector(ent.getLocation())) > radiusSq) {
continue;
}
switch (type) {
case ALL:
if (ent instanceof Projectile || ent instanceof Boat || ent instanceof Item
|| ent instanceof FallingBlock || ent instanceof Minecart || ent instanceof Hanging
|| ent instanceof TNTPrimed || ent instanceof ExperienceOrb) {
ent.remove();
num++;
}
break;
case PROJECTILES:
case ARROWS:
if (ent instanceof Projectile) {
// covers: arrow, egg, enderpearl, fireball, fish, snowball, throwpotion, thrownexpbottle
ent.remove();
++num;
}
break;
case BOATS:
if (ent instanceof Boat) {
ent.remove();
++num;
}
break;
case ITEMS:
if (ent instanceof Item) {
ent.remove();
++num;
}
break;
case FALLING_BLOCKS:
if (ent instanceof FallingBlock) {
ent.remove();
++num;
}
break;
case MINECARTS:
if (ent instanceof Minecart) {
ent.remove();
++num;
}
break;
case PAINTINGS:
if (ent instanceof Painting) {
ent.remove();
++num;
}
break;
case ITEM_FRAMES:
if (ent instanceof ItemFrame) {
ent.remove();
++num;
}
break;
case TNT:
if (ent instanceof TNTPrimed || ent.getType() == tntMinecartType) {
ent.remove();
++num;
}
break;
case XP_ORBS:
if (ent instanceof ExperienceOrb) {
ent.remove();
++num;
}
break;
}
}
return num;
}
@SuppressWarnings("deprecation")
@Override
public boolean isValidBlockType(int type) {
@ -609,24 +421,6 @@ public class BukkitWorld extends LocalWorld {
getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally();
}
@Override
public int killEntities(LocalEntity... entities) {
World world = getWorld();
int amount = 0;
Set<UUID> toKill = new HashSet<UUID>();
for (LocalEntity entity : entities) {
toKill.add(((com.sk89q.worldedit.bukkit.entity.BukkitEntity) entity).getEntityId());
}
for (Entity entity : world.getEntities()) {
if (toKill.contains(entity.getUniqueId())) {
entity.remove();
++amount;
}
}
return amount;
}
@Override
public BaseBlock getBlock(Vector position) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();

View File

@ -22,14 +22,14 @@ package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.helper.MCDirections;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import net.minecraft.entity.EntityHanging;
import net.minecraft.entity.EntityList;
import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
class ForgeEntity implements Entity {
@ -41,6 +41,15 @@ class ForgeEntity implements Entity {
this.entity = entity;
}
/**
* Return the underlying entity.
*
* @return the underlying entity
*/
net.minecraft.entity.Entity getEntity() {
return entity;
}
@Override
public BaseEntity getState() {
String id = EntityList.getEntityString(entity);
@ -73,4 +82,14 @@ class ForgeEntity implements Entity {
return true;
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
if (EntityType.class.isAssignableFrom(cls)) {
return (T) new ForgeEntityType(entity);
} else {
return null;
}
}
}

View File

@ -0,0 +1,138 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.entity.metadata.EntityType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IMerchant;
import net.minecraft.entity.INpc;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityEnderEye;
import net.minecraft.entity.item.EntityFallingSand;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityPainting;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.monster.EntityGolem;
import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.passive.IAnimals;
import net.minecraft.entity.player.EntityPlayer;
import static com.google.common.base.Preconditions.checkNotNull;
public class ForgeEntityType implements EntityType {
private final Entity entity;
public ForgeEntityType(Entity entity) {
checkNotNull(entity);
this.entity = entity;
}
@Override
public boolean isPlayerDerived() {
return entity instanceof EntityPlayer;
}
@Override
public boolean isProjectile() {
return entity instanceof EntityEnderEye || entity instanceof IProjectile;
}
@Override
public boolean isItem() {
return entity instanceof EntityItem;
}
@Override
public boolean isFallingBlock() {
return entity instanceof EntityFallingSand;
}
@Override
public boolean isPainting() {
return entity instanceof EntityPainting;
}
@Override
public boolean isItemFrame() {
return entity instanceof EntityItemFrame;
}
@Override
public boolean isBoat() {
return entity instanceof EntityBoat;
}
@Override
public boolean isMinecart() {
return entity instanceof EntityMinecart;
}
@Override
public boolean isTNT() {
return entity instanceof EntityTNTPrimed;
}
@Override
public boolean isExperienceOrb() {
return entity instanceof EntityXPOrb;
}
@Override
public boolean isLiving() {
return entity instanceof EntityLiving;
}
@Override
public boolean isAnimal() {
return entity instanceof IAnimals;
}
@Override
public boolean isAmbient() {
return entity instanceof EntityAmbientCreature;
}
@Override
public boolean isNPC() {
return entity instanceof INpc || entity instanceof IMerchant;
}
@Override
public boolean isGolem() {
return entity instanceof EntityGolem;
}
@Override
public boolean isTamed() {
return entity instanceof EntityTameable && ((EntityTameable) entity).isTamed();
}
@Override
public boolean isTagged() {
return entity instanceof EntityLiving && ((EntityLiving) entity).hasCustomNameTag();
}
}

View File

@ -20,10 +20,10 @@
package com.sk89q.worldedit.forge;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.internal.cui.CUIEvent;
@ -33,7 +33,10 @@ import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.Packet250CustomPayload;
import net.minecraft.util.ChatMessageComponent;
public class ForgePlayer extends LocalPlayer {
import javax.annotation.Nullable;
public class ForgePlayer extends AbstractPlayerActor {
private EntityPlayerMP player;
protected ForgePlayer(EntityPlayerMP player) {
@ -133,4 +136,11 @@ public class ForgePlayer extends LocalPlayer {
public boolean hasPermission(String perm) {
return ForgeUtil.hasPermission(this.player, perm);
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
}
}

View File

@ -22,7 +22,6 @@ package com.sk89q.worldedit.forge;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
@ -33,34 +32,15 @@ import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.helper.MCDirections;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Direction.Flag;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.registry.LegacyWorldData;
import com.sk89q.worldedit.world.registry.WorldData;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityHanging;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityEnderEye;
import net.minecraft.entity.item.EntityFallingSand;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityPainting;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.monster.EntityGolem;
import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
@ -224,7 +204,7 @@ public class ForgeWorld extends AbstractWorld {
checkNotNull(position);
checkNotNull(item);
if ((item == null) || (item.getType() == 0)) {
if (item.getType() == 0) {
return;
}
@ -233,121 +213,6 @@ public class ForgeWorld extends AbstractWorld {
getWorld().spawnEntityInWorld(entity);
}
@Override
@SuppressWarnings({"unchecked", "ConstantConditions"})
public int killMobs(Vector origin, double radius, int flags) {
boolean killPets = (flags & 0x1) != 0;
boolean killNPCs = (flags & 0x2) != 0;
boolean killAnimals = (flags & 0x4) != 0;
boolean killGolems = (flags & 0x8) != 0;
boolean killAmbient = (flags & 0x10) != 0;
int num = 0;
double radiusSq = radius * radius;
for (net.minecraft.entity.Entity obj : (Iterable<net.minecraft.entity.Entity>) getWorld().loadedEntityList) {
if ((obj instanceof EntityLiving)) {
EntityLiving ent = (EntityLiving) obj;
if (!killAnimals && ent instanceof EntityAnimal) {
continue;
}
if (!killPets && ent instanceof EntityTameable && ((EntityTameable) ent).isTamed()) {
continue; // tamed pet
}
if (!killGolems && ent instanceof EntityGolem) {
continue;
}
if (!killNPCs && ent instanceof EntityVillager) {
continue;
}
if (!killAmbient && ent instanceof EntityAmbientCreature) {
continue;
}
if ((radius < 0.0D) || (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) <= radiusSq)) {
ent.isDead = true;
num++;
}
}
}
return num;
}
@Override
@SuppressWarnings("unchecked")
public int removeEntities(EntityType type, Vector origin, int radius) {
checkNotNull(type);
checkNotNull(origin);
int num = 0;
double radiusSq = Math.pow(radius, 2.0D);
for (net.minecraft.entity.Entity ent : (Iterable<net.minecraft.entity.Entity>) getWorld().loadedEntityList) {
if ((radius != -1) && (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) > radiusSq)) {
continue;
}
if (type == EntityType.ALL) {
if (((ent instanceof EntityBoat)) || ((ent instanceof EntityItem)) || ((ent instanceof EntityFallingSand)) || ((ent instanceof EntityMinecart)) || ((ent instanceof EntityHanging)) || ((ent instanceof EntityTNTPrimed)) || ((ent instanceof EntityXPOrb)) || ((ent instanceof EntityEnderEye)) || ((ent instanceof IProjectile))) {
ent.isDead = true;
num++;
}
} else if ((type == EntityType.PROJECTILES) || (type == EntityType.ARROWS)) {
if (((ent instanceof EntityEnderEye)) || ((ent instanceof IProjectile))) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.BOATS) {
if ((ent instanceof EntityBoat)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.ITEMS) {
if ((ent instanceof EntityItem)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.FALLING_BLOCKS) {
if ((ent instanceof EntityFallingSand)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.MINECARTS) {
if ((ent instanceof EntityMinecart)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.PAINTINGS) {
if ((ent instanceof EntityPainting)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.ITEM_FRAMES) {
if ((ent instanceof EntityItemFrame)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.TNT) {
if ((ent instanceof EntityTNTPrimed)) {
ent.isDead = true;
num++;
}
} else if ((type == EntityType.XP_ORBS) && ((ent instanceof EntityXPOrb))) {
ent.isDead = true;
num++;
}
}
return num;
}
@Override
public boolean regenerate(Region region, EditSession editSession) {
BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)];

View File

@ -33,24 +33,6 @@ import com.sk89q.worldedit.world.World;
@Deprecated
public abstract class LocalWorld extends AbstractWorld {
/**
* Named flags to use as parameters to {@link LocalWorld#killMobs(Vector, double, int)}
*/
@SuppressWarnings("PointlessBitwiseExpression")
public final class KillFlags {
public static final int PETS = 1 << 0;
public static final int NPCS = 1 << 1;
public static final int ANIMALS = 1 << 2;
public static final int GOLEMS = 1 << 3;
public static final int AMBIENT = 1 << 4;
public static final int TAGGED = 1 << 5;
public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED;
public static final int WITH_LIGHTNING = 1 << 20;
private KillFlags() {
}
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return getBlock(position);

View File

@ -25,13 +25,11 @@ import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.command.UtilityCommands.FlagContainer;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
@ -41,6 +39,7 @@ import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush;
import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush;
import com.sk89q.worldedit.command.tool.brush.SmoothBrush;
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
import com.sk89q.worldedit.command.util.CreatureButcher;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.BlockMask;
@ -229,13 +228,21 @@ public class BrushCommands {
@Command(
aliases = { "butcher", "kill" },
usage = "[radius] [command flags]",
usage = "[radius]",
flags = "plangbtf",
desc = "Butcher brush",
help = "Kills nearby mobs within the specified radius.\n" +
"Any number of 'flags' that the //butcher command uses\n" +
"may be specified as an argument",
"Flags:" +
" -p also kills pets.\n" +
" -n also kills NPCs.\n" +
" -g also kills Golems.\n" +
" -a also kills animals.\n" +
" -b also kills ambient mobs.\n" +
" -t also kills mobs with name tags.\n" +
" -f compounds all previous flags.\n" +
" -l currently does nothing.",
min = 0,
max = 2
max = 1
)
@CommandPermissions("worldedit.brush.butcher")
public void butcherBrush(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
@ -254,24 +261,13 @@ public class BrushCommands {
return;
}
FlagContainer flags = new FlagContainer(player);
if (args.argsLength() == 2) {
String flagString = args.getString(1);
// straight from the command, using contains instead of hasflag
flags.or(KillFlags.FRIENDLY , flagString.contains("f")); // No permission check here. Flags will instead be filtered by the subsequent calls.
flags.or(KillFlags.PETS , flagString.contains("p"), "worldedit.butcher.pets");
flags.or(KillFlags.NPCS , flagString.contains("n"), "worldedit.butcher.npcs");
flags.or(KillFlags.GOLEMS , flagString.contains("g"), "worldedit.butcher.golems");
flags.or(KillFlags.ANIMALS , flagString.contains("a"), "worldedit.butcher.animals");
flags.or(KillFlags.AMBIENT , flagString.contains("b"), "worldedit.butcher.ambient");
flags.or(KillFlags.TAGGED , flagString.contains("t"), "worldedit.butcher.tagged");
flags.or(KillFlags.WITH_LIGHTNING, flagString.contains("l"), "worldedit.butcher.lightning");
}
CreatureButcher flags = new CreatureButcher(player);
flags.fromCommand(args);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new ButcherBrush(flags.flags), "worldedit.brush.butcher");
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");
player.print(String.format("Butcher brush equipped (%.0f).",
radius));
player.print(String.format("Butcher brush equipped (%.0f).", radius));
}
}

View File

@ -26,30 +26,35 @@ import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.util.CreatureButcher;
import com.sk89q.worldedit.command.util.EntityRemover;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.EntityVisitor;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
import com.sk89q.worldedit.util.formatting.Style;
import com.sk89q.worldedit.util.formatting.StyledFragment;
@ -374,7 +379,7 @@ public class UtilityCommands {
" -b also kills ambient mobs.\n" +
" -t also kills mobs with name tags.\n" +
" -f compounds all previous flags.\n" +
" -l strikes lightning on each killed mob.",
" -l currently does nothing.",
min = 0,
max = 1
)
@ -399,26 +404,37 @@ public class UtilityCommands {
}
}
FlagContainer flags = new FlagContainer(actor);
flags.or(KillFlags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls.
flags.or(KillFlags.PETS , args.hasFlag('p'), "worldedit.butcher.pets");
flags.or(KillFlags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs");
flags.or(KillFlags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems");
flags.or(KillFlags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals");
flags.or(KillFlags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient");
flags.or(KillFlags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged");
flags.or(KillFlags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning");
// If you add flags here, please add them to com.sk89q.worldedit.commands.BrushCommands.butcherBrush() as well
CreatureButcher flags = new CreatureButcher(actor);
flags.fromCommand(args);
List<EntityVisitor> visitors = new ArrayList<EntityVisitor>();
LocalSession session = null;
EditSession editSession = null;
int killed;
if (player != null) {
LocalSession session = we.getSessionManager().get(player);
killed = player.getWorld().killMobs(session.getPlacementPosition(player), radius, flags.flags);
} else {
killed = 0;
for (World world : we.getServer().getWorlds()) {
killed += world.killMobs(new Vector(), radius, flags.flags);
session = we.getSessionManager().get(player);
Vector center = session.getPlacementPosition(player);
editSession = session.createEditSession(player);
List<? extends Entity> entities;
if (radius >= 0) {
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
entities = editSession.getEntities(region);
} else {
entities = editSession.getEntities();
}
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
} else {
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
for (World world : platform.getWorlds()) {
List<? extends Entity> entities = world.getEntities();
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction(world.getWorldData().getEntityRegistry())));
}
}
int killed = 0;
for (EntityVisitor visitor : visitors) {
Operations.completeLegacy(visitor);
killed += visitor.getAffected();
}
if (radius < 0) {
@ -426,25 +442,10 @@ public class UtilityCommands {
} else {
actor.print("Killed " + killed + " mobs in a radius of " + radius + ".");
}
}
public static class FlagContainer {
private final Actor player;
public int flags = 0;
public FlagContainer(Actor player) {
this.player = player;
}
public void or(int flag, boolean on) {
if (on) flags |= flag;
}
public void or(int flag, boolean on, String permission) {
or(flag, on);
if ((flags & flag) != 0 && !player.hasPermission(permission)) {
flags &= ~flag;
}
if (editSession != null) {
session.remember(editSession);
editSession.flushQueue();
}
}
@ -457,56 +458,55 @@ public class UtilityCommands {
)
@CommandPermissions("worldedit.remove")
@Logging(PLACEMENT)
public void remove(Actor actor, @Optional Player player, @Optional LocalSession session, CommandContext args) throws WorldEditException {
public void remove(Actor actor, CommandContext args) throws WorldEditException, CommandException {
String typeStr = args.getString(0);
int radius = args.getInteger(1);
Player player = actor instanceof Player ? (Player) actor : null;
if (radius < -1) {
actor.printError("Use -1 to remove all entities in loaded chunks");
return;
}
EntityType type = null;
EntityRemover remover = new EntityRemover();
remover.fromString(typeStr);
if (typeStr.matches("all")) {
type = EntityType.ALL;
} else if (typeStr.matches("projectiles?|arrows?")) {
type = EntityType.PROJECTILES;
} else if (typeStr.matches("items?")
|| typeStr.matches("drops?")) {
type = EntityType.ITEMS;
} else if (typeStr.matches("falling(blocks?|sand|gravel)")) {
type = EntityType.FALLING_BLOCKS;
} else if (typeStr.matches("paintings?")
|| typeStr.matches("art")) {
type = EntityType.PAINTINGS;
} else if (typeStr.matches("(item)frames?")) {
type = EntityType.ITEM_FRAMES;
} else if (typeStr.matches("boats?")) {
type = EntityType.BOATS;
} else if (typeStr.matches("minecarts?")
|| typeStr.matches("carts?")) {
type = EntityType.MINECARTS;
} else if (typeStr.matches("tnt")) {
type = EntityType.TNT;
} else if (typeStr.matches("xp")) {
type = EntityType.XP_ORBS;
List<EntityVisitor> visitors = new ArrayList<EntityVisitor>();
LocalSession session = null;
EditSession editSession = null;
if (player != null) {
session = we.getSessionManager().get(player);
Vector center = session.getPlacementPosition(player);
editSession = session.createEditSession(player);
List<? extends Entity> entities;
if (radius >= 0) {
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
entities = editSession.getEntities(region);
} else {
entities = editSession.getEntities();
}
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
} else {
actor.printError("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
return;
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
for (World world : platform.getWorlds()) {
List<? extends Entity> entities = world.getEntities();
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction(world.getWorldData().getEntityRegistry())));
}
}
int removed = 0;
if (player != null) {
Vector origin = session.getPlacementPosition(player);
removed = player.getWorld().removeEntities(type, origin, radius);
} else {
for (World world : we.getServer().getWorlds()) {
removed += world.removeEntities(type, new Vector(), radius);
}
for (EntityVisitor visitor : visitors) {
Operations.completeLegacy(visitor);
removed += visitor.getAffected();
}
actor.print("Marked " + (removed != 1 ? "entities" : "entity") + " for removal.");
if (editSession != null) {
session.remember(editSession);
editSession.flushQueue();
}
player.print("Marked " + removed + " entit(ies) for removal.");
}
@Command(

View File

@ -22,19 +22,28 @@ package com.sk89q.worldedit.command.tool.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.util.CreatureButcher;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.EntityVisitor;
import com.sk89q.worldedit.regions.CylinderRegion;
import java.util.List;
public class ButcherBrush implements Brush {
private int flags;
private CreatureButcher flags;
public ButcherBrush(int flags) {
public ButcherBrush(CreatureButcher flags) {
this.flags = flags;
}
@Override
public void build(EditSession editSession, Vector pos, Pattern mat, double size) throws MaxChangedBlocksException {
editSession.getWorld().killMobs(pos, size, flags);
CylinderRegion region = CylinderRegion.createRadius(editSession, pos, size);
List<? extends Entity> entities = editSession.getEntities(region);
Operations.completeLegacy(new EntityVisitor(entities.iterator(), flags.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
}
}

View File

@ -0,0 +1,135 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.util;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.EntityFunction;
import com.sk89q.worldedit.world.registry.EntityRegistry;
/**
* The implementation of /butcher.
*/
public class CreatureButcher {
final class Flags {
@SuppressWarnings("PointlessBitwiseExpression")
public static final int PETS = 1 << 0;
public static final int NPCS = 1 << 1;
public static final int ANIMALS = 1 << 2;
public static final int GOLEMS = 1 << 3;
public static final int AMBIENT = 1 << 4;
public static final int TAGGED = 1 << 5;
public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED;
public static final int WITH_LIGHTNING = 1 << 20;
private Flags() {
}
}
private final Actor player;
public int flags = 0;
public CreatureButcher(Actor player) {
this.player = player;
}
public void or(int flag, boolean on) {
if (on) flags |= flag;
}
public void or(int flag, boolean on, String permission) {
or(flag, on);
if ((flags & flag) != 0 && !player.hasPermission(permission)) {
flags &= ~flag;
}
}
public void fromCommand(CommandContext args) {
or(Flags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls.
or(Flags.PETS , args.hasFlag('p'), "worldedit.butcher.pets");
or(Flags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs");
or(Flags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems");
or(Flags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals");
or(Flags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient");
or(Flags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged");
or(Flags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning");
}
public EntityFunction createFunction(final EntityRegistry entityRegistry) {
return new EntityFunction() {
@Override
public boolean apply(Entity entity) throws WorldEditException {
boolean killPets = (flags & Flags.PETS) != 0;
boolean killNPCs = (flags & Flags.NPCS) != 0;
boolean killAnimals = (flags & Flags.ANIMALS) != 0;
boolean killGolems = (flags & Flags.GOLEMS) != 0;
boolean killAmbient = (flags & Flags.AMBIENT) != 0;
boolean killTagged = (flags & Flags.TAGGED) != 0;
EntityType type = entity.getFacet(EntityType.class);
if (type == null) {
return false;
}
if (type.isPlayerDerived()) {
return false;
}
if (!type.isLiving()) {
return false;
}
if (!killAnimals && type.isAnimal()) {
return false;
}
if (!killPets && type.isTamed()) {
return false;
}
if (!killGolems && type.isGolem()) {
return false;
}
if (!killNPCs && type.isNPC()) {
return false;
}
if (!killAmbient && type.isAmbient()) {
return false;
}
if (!killTagged && type.isTagged()) {
return false;
}
entity.remove();
return true;
}
};
}
}

View File

@ -0,0 +1,160 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.util;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.function.EntityFunction;
import com.sk89q.worldedit.world.registry.EntityRegistry;
import javax.annotation.Nullable;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The implementation of /remove.
*/
public class EntityRemover {
public enum Type {
ALL("all") {
@Override
boolean matches(EntityType type) {
for (Type value : values()) {
if (value != this && value.matches(type)) {
return true;
}
}
return false;
}
},
PROJECTILES("projectiles?|arrows?") {
@Override
boolean matches(EntityType type) {
return type.isProjectile();
}
},
ITEMS("items?|drops?") {
@Override
boolean matches(EntityType type) {
return type.isItem();
}
},
FALLING_BLOCKS("falling(blocks?|sand|gravel)") {
@Override
boolean matches(EntityType type) {
return type.isFallingBlock();
}
},
PAINTINGS("paintings?|art") {
@Override
boolean matches(EntityType type) {
return type.isPainting();
}
},
ITEM_FRAMES("(item)frames?") {
@Override
boolean matches(EntityType type) {
return type.isItemFrame();
}
},
BOATS("boats?") {
@Override
boolean matches(EntityType type) {
return type.isBoat();
}
},
MINECARTS("(mine)?carts?") {
@Override
boolean matches(EntityType type) {
return type.isMinecart();
}
},
TNT("tnt") {
@Override
boolean matches(EntityType type) {
return type.isTNT();
}
},
XP_ORBS("xp") {
@Override
boolean matches(EntityType type) {
return type.isExperienceOrb();
}
};
private final Pattern pattern;
Type(String pattern) {
this.pattern = Pattern.compile(pattern);
}
public boolean matches(String str) {
return pattern.matcher(str).matches();
}
abstract boolean matches(EntityType type);
@Nullable
public static Type findByPattern(String str) {
for (Type type : values()) {
if (type.matches(str)) {
return type;
}
}
return null;
}
}
private Type type;
public void fromString(String str) throws CommandException {
Type type = Type.findByPattern(str);
if (type != null) {
this.type = type;
} else {
throw new CommandException("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
}
}
public EntityFunction createFunction(final EntityRegistry entityRegistry) {
final Type type = this.type;
checkNotNull("type can't be null", type);
return new EntityFunction() {
@Override
public boolean apply(Entity entity) throws WorldEditException {
EntityType registryType = entity.getFacet(EntityType.class);
if (registryType != null) {
if (type.matches(registryType)) {
entity.remove();
return true;
}
}
return false;
}
};
}
}

View File

@ -43,6 +43,15 @@ public class BaseEntity implements NbtValued {
setNbtData(nbtData);
}
/**
* Create a new base entity with no NBT data.
*
* @param id the entity type ID
*/
public BaseEntity(String id) {
setTypeId(id);
}
/**
* Make a clone of a {@link BaseEntity}.
*

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Faceted;
import com.sk89q.worldedit.util.Location;
import javax.annotation.Nullable;
@ -34,7 +35,7 @@ import javax.annotation.Nullable;
* can then be used to spawn new instances of that particular entity
* description.
*/
public interface Entity {
public interface Entity extends Faceted {
/**
* Get a copy of the entity's state.

View File

@ -0,0 +1,151 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.entity.metadata;
/**
* Describes various classes of entities.
*/
public interface EntityType {
/**
* Test whether the entity is a player-derived entity.
*
* @return true if a player derived entity
*/
boolean isPlayerDerived();
/**
* Test whether the entity is a projectile.
*
* @return true if a projectile
*/
boolean isProjectile();
/**
* Test whether the entity is an item.
*
* @return true if an item
*/
boolean isItem();
/**
* Test whether the entity is a falling block.
*
* @return true if a falling block
*/
boolean isFallingBlock();
/**
* Test whether the entity is a painting.
*
* @return true if a painting
*/
boolean isPainting();
/**
* Test whether the entity is an item frame.
*
* @return true if an item frame
*/
boolean isItemFrame();
/**
* Test whether the entity is a boat.
*
* @return true if a boat
*/
boolean isBoat();
/**
* Test whether the entity is a minecart.
*
* @return true if a minecart
*/
boolean isMinecart();
/**
* Test whether the entity is a primed TNT block.
*
* @return true if TNT
*/
boolean isTNT();
/**
* Test whether the entity is an experience orb.
*
* @return true if an experience orb
*/
boolean isExperienceOrb();
/**
* Test whether the entity is a living entity.
*
* <p>A "living entity" is the superclass of many living entity classes
* in Minecraft.</p>
*
* @return true if a living entity
*/
boolean isLiving();
/**
* Test whether the entity is an animal.
*
* @return true if an animal
*/
boolean isAnimal();
/**
* Test whether the entity is an ambient creature, which includes
* the bat.
*
* @return true if an ambient creature
*/
boolean isAmbient();
/**
* Test whether the entity is a non-player controlled character, which
* includes villagers, NPCs from mods, and so on.
*
* @return true if an NPC
*/
boolean isNPC();
/**
* Test whether the entity is the iron golem from Minecraft.
*
* @return true if an iron golem
*/
boolean isGolem();
/**
* Test whether the entity is tameable and is tamed.
*
* @return true if tamed
*/
boolean isTamed();
/**
* Test whether the entity has been named (tagged).
*
* @return true if named
*/
boolean isTagged();
}

View File

@ -28,6 +28,8 @@ import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
class PlayerProxy extends AbstractPlayerActor {
@ -137,4 +139,10 @@ class PlayerProxy extends AbstractPlayerActor {
public void dispatchCUIEvent(CUIEvent event) {
cuiActor.dispatchCUIEvent(event);
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return basePlayer.getFacet(cls);
}
}

View File

@ -124,5 +124,11 @@ public class ChangeSetExtent extends AbstractDelegateExtent {
}
return success;
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return entity.getFacet(cls);
}
}
}

View File

@ -164,6 +164,12 @@ public class BlockArrayClipboard implements Clipboard {
public boolean remove() {
return entities.remove(this);
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
}
}
}

View File

@ -22,8 +22,6 @@ package com.sk89q.worldedit.internal;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
@ -135,33 +133,6 @@ public class LocalWorldAdapter extends LocalWorld {
world.simulateBlockMine(position);
}
@Override
public int killEntities(LocalEntity... entity) {
return world.killEntities(entity);
}
@Override
@Deprecated
public int killMobs(Vector origin, int radius) {
return world.killMobs(origin, radius);
}
@Override
@Deprecated
public int killMobs(Vector origin, int radius, boolean killPets) {
return world.killMobs(origin, radius, killPets);
}
@Override
public int killMobs(Vector origin, double radius, int flags) {
return world.killMobs(origin, radius, flags);
}
@Override
public int removeEntities(EntityType type, Vector origin, int radius) {
return world.removeEntities(type, origin, radius);
}
@Override
public boolean regenerate(Region region, EditSession editSession) {
return world.regenerate(region, editSession);

View File

@ -19,7 +19,12 @@
package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.geom.Polygons;
import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
@ -28,6 +33,8 @@ import com.sk89q.worldedit.world.World;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a cylindrical region.
*
@ -84,6 +91,23 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
hasY = true;
}
/**
* Construct the region.
*
* @param center the center position
* @param radius the radius along the X and Z axes
* @param minY the minimum Y, inclusive
* @param maxY the maximum Y, inclusive
*/
public CylinderRegion(Vector center, Vector2D radius, int minY, int maxY) {
super(null);
setCenter(center.toVector2D());
setRadius(radius);
this.minY = minY;
this.maxY = maxY;
hasY = true;
}
public CylinderRegion(CylinderRegion region) {
this(region.world, region.getCenter(), region.getRadius(), region.minY, region.maxY);
hasY = region.hasY;
@ -377,4 +401,24 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
public List<BlockVector2D> polygonize(int maxPoints) {
return Polygons.polygonizeCylinder(center, radius, maxPoints);
}
/**
* Return a new instance with the given center and radius in the X and Z
* axes with a Y that extends from the bottom of the extent to the top
* of the extent.
*
* @param extent the extent
* @param center the center position
* @param radius the radius in the X and Z axes
* @return a region
*/
public static CylinderRegion createRadius(Extent extent, Vector center, double radius) {
checkNotNull(extent);
checkNotNull(center);
Vector2D radiusVec = new Vector2D(radius, radius);
int minY = extent.getMinimumPoint().getBlockY();
int maxY = extent.getMaximumPoint().getBlockY();
return new CylinderRegion(center, radiusVec, minY, maxY);
}
}

View File

@ -0,0 +1,52 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util;
import com.sk89q.worldedit.entity.Entity;
import javax.annotation.Nullable;
/**
* Indicates that an object can provide various "facets," which are
* specific distinct interfaces that can represent a portion of the object.
*
* <p>For example, an instance of an {@link Entity} may have a facet
* for accessing its inventory (if it contains an inventory) or a facet
* for accessing its health (if it has health).</p>
*
* <p>Facets are referred to by their interface or abstract class and
* it is dependent on the implementation of the object specifying this
* interface to return the most applicable implementation. However, in
* many cases, such an implementation may not apply or it has not been
* implemented so a request for a facet may return {@code null}.</p>
*/
public interface Faceted {
/**
* Get the facet corresponding to the given class or interface.
*
* @param cls the class or interface
* @param <T> the type
* @return an implementation of the facet or {@code null} if one is unavailable
*/
@Nullable
<T> T getFacet(Class<? extends T> cls);
}

View File

@ -104,7 +104,11 @@ public class FastListIterator<E> implements Iterator<E> {
* @return an iterator
*/
public static <E> Iterator<E> reverseIterator(List<E> list) {
return new FastListIterator<E>(list, list.size() - 1, list.size(), -1);
if (!list.isEmpty()) {
return new FastListIterator<E>(list, list.size() - 1, list.size(), -1);
} else {
return new FastListIterator<E>(list, 0, 0, -1);
}
}
}

View File

@ -21,8 +21,6 @@ package com.sk89q.worldedit.world;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -141,21 +139,6 @@ public abstract class AbstractWorld implements World {
}
}
@Override
public int killEntities(LocalEntity... entities) {
return 0;
}
@Override
public int killMobs(Vector origin, int radius) {
return killMobs(origin, radius, false);
}
@Override
public int killMobs(Vector origin, int radius, boolean killPets) {
return killMobs(origin, radius, killPets ? KillFlags.PETS : 0);
}
@Override
public boolean generateTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return generateTree(TreeType.TREE, editSession, pt);

View File

@ -74,16 +74,6 @@ public class NullWorld extends AbstractWorld {
public void dropItem(Vector position, BaseItemStack item) {
}
@Override
public int killMobs(Vector origin, double radius, int flags) {
return 0;
}
@Override
public int removeEntities(EntityType type, Vector origin, int radius) {
return 0;
}
@Override
public boolean regenerate(Region region, EditSession editSession) {
return false;

View File

@ -22,9 +22,6 @@ package com.sk89q.worldedit.world;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
@ -191,46 +188,6 @@ public interface World extends Extent {
*/
void simulateBlockMine(Vector position);
/**
* Kill the entities listed in the provided array.
*
* @param entity an array of entities
* @return the number of entities that were removed
*/
int killEntities(LocalEntity... entity);
/**
* @deprecated Use {@link #killMobs(Vector, double, int)}
*/
@Deprecated
int killMobs(Vector origin, int radius);
/**
* @deprecated Use {@link #killMobs(Vector, double, int)}
*/
@Deprecated
int killMobs(Vector origin, int radius, boolean killPets);
/**
* Kill mobs at the given location with the given radius.
*
* @param origin the origin
* @param radius the radius
* @param flags kill flags (see {@link LocalWorld.KillFlags})
* @return the number of mobs that were killed
*/
int killMobs(Vector origin, double radius, int flags);
/**
* Remove entities in an area.
*
* @param type the type of entity
* @param origin the origin
* @param radius the radius
* @return the number of mobs that were killed
*/
int removeEntities(EntityType type, Vector origin, int radius);
/**
* Regenerate an area.
*

View File

@ -0,0 +1,42 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityType;
import javax.annotation.Nullable;
/**
* Provides information on entities.
*/
public interface EntityRegistry {
/**
* Create a new entity using its ID.
*
* @param id the id
* @return the entity, which may be null if the entity does not exist
*/
@Nullable
BaseEntity createFromId(String id);
}

View File

@ -27,6 +27,7 @@ public final class LegacyWorldData implements WorldData {
private static final LegacyWorldData INSTANCE = new LegacyWorldData();
private final LegacyBlockRegistry blockRegistry = new LegacyBlockRegistry();
private final NullEntityRegistry entityRegistry = new NullEntityRegistry();
/**
* Create a new instance.
@ -39,6 +40,11 @@ public final class LegacyWorldData implements WorldData {
return blockRegistry;
}
@Override
public EntityRegistry getEntityRegistry() {
return entityRegistry;
}
/**
* Get a singleton instance.
*

View File

@ -1,37 +1,37 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit;
/**
* List of removable entity types.
*/
public enum EntityType {
ALL,
@Deprecated ARROWS,
PROJECTILES,
ITEMS,
FALLING_BLOCKS,
PAINTINGS,
ITEM_FRAMES,
BOATS,
MINECARTS,
TNT,
XP_ORBS
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.entity.BaseEntity;
import javax.annotation.Nullable;
/**
* An implementation of an entity registry that knows nothing.
*/
public class NullEntityRegistry implements EntityRegistry {
@Nullable
@Override
public BaseEntity createFromId(String id) {
return null;
}
}

View File

@ -32,4 +32,11 @@ public interface WorldData {
*/
BlockRegistry getBlockRegistry();
/**
* Get the entity registry.
*
* @return the entity registry
*/
EntityRegistry getEntityRegistry();
}