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

@ -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();
}