mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Add support for copying entities between Extents.
This commit is contained in:
parent
52f1a7d2d4
commit
0ce7954dc9
@ -39,7 +39,6 @@ import com.sk89q.worldedit.blocks.MobSpawnerBlock;
|
|||||||
import com.sk89q.worldedit.blocks.NoteBlock;
|
import com.sk89q.worldedit.blocks.NoteBlock;
|
||||||
import com.sk89q.worldedit.blocks.SignBlock;
|
import com.sk89q.worldedit.blocks.SignBlock;
|
||||||
import com.sk89q.worldedit.blocks.SkullBlock;
|
import com.sk89q.worldedit.blocks.SkullBlock;
|
||||||
import com.sk89q.worldedit.bukkit.entity.BukkitEntity;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator;
|
import com.sk89q.worldedit.util.TreeGenerator;
|
||||||
@ -222,6 +221,26 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<com.sk89q.worldedit.entity.Entity> getEntities(Region region) {
|
||||||
|
World world = getWorld();
|
||||||
|
|
||||||
|
List<com.sk89q.worldedit.entity.Entity> entities = new ArrayList<com.sk89q.worldedit.entity.Entity>();
|
||||||
|
for (Vector2D pt : region.getChunks()) {
|
||||||
|
if (!world.isChunkLoaded(pt.getBlockX(), pt.getBlockZ())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Entity[] ents = world.getChunkAt(pt.getBlockX(), pt.getBlockZ()).getEntities();
|
||||||
|
for (Entity ent : ents) {
|
||||||
|
if (region.contains(BukkitUtil.toVector(ent.getLocation()))) {
|
||||||
|
entities.add(BukkitAdapter.adapt(ent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<com.sk89q.worldedit.entity.Entity> getEntities() {
|
public List<com.sk89q.worldedit.entity.Entity> getEntities() {
|
||||||
List<com.sk89q.worldedit.entity.Entity> list = new ArrayList<com.sk89q.worldedit.entity.Entity>();
|
List<com.sk89q.worldedit.entity.Entity> list = new ArrayList<com.sk89q.worldedit.entity.Entity>();
|
||||||
@ -1240,26 +1259,6 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally();
|
getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalEntity[] getEntities(Region region) {
|
|
||||||
World world = getWorld();
|
|
||||||
|
|
||||||
List<BukkitEntity> entities = new ArrayList<BukkitEntity>();
|
|
||||||
for (Vector2D pt : region.getChunks()) {
|
|
||||||
if (!world.isChunkLoaded(pt.getBlockX(), pt.getBlockZ())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Entity[] ents = world.getChunkAt(pt.getBlockX(), pt.getBlockZ()).getEntities();
|
|
||||||
for (Entity ent : ents) {
|
|
||||||
if (region.contains(BukkitUtil.toVector(ent.getLocation()))) {
|
|
||||||
entities.add(BukkitUtil.toLocalEntity(ent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return entities.toArray(new BukkitEntity[entities.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int killEntities(LocalEntity... entities) {
|
public int killEntities(LocalEntity... entities) {
|
||||||
World world = getWorld();
|
World world = getWorld();
|
||||||
@ -1267,7 +1266,7 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
int amount = 0;
|
int amount = 0;
|
||||||
Set<UUID> toKill = new HashSet<UUID>();
|
Set<UUID> toKill = new HashSet<UUID>();
|
||||||
for (LocalEntity entity : entities) {
|
for (LocalEntity entity : entities) {
|
||||||
toKill.add(((BukkitEntity) entity).getEntityId());
|
toKill.add(((com.sk89q.worldedit.bukkit.entity.BukkitEntity) entity).getEntityId());
|
||||||
}
|
}
|
||||||
for (Entity entity : world.getEntities()) {
|
for (Entity entity : world.getEntities()) {
|
||||||
if (toKill.contains(entity.getUniqueId())) {
|
if (toKill.contains(entity.getUniqueId())) {
|
||||||
|
@ -23,7 +23,10 @@ import com.sk89q.worldedit.Vector;
|
|||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
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 com.sk89q.worldedit.util.Location;
|
||||||
|
import net.minecraft.entity.EntityHanging;
|
||||||
import net.minecraft.entity.EntityList;
|
import net.minecraft.entity.EntityList;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
|
||||||
@ -40,17 +43,42 @@ class ForgeEntity implements Entity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseEntity getState() {
|
public BaseEntity getState() {
|
||||||
|
String id = EntityList.getEntityString(entity);
|
||||||
|
if (id != null) {
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
entity.writeToNBT(tag);
|
entity.writeToNBT(tag);
|
||||||
return new BaseEntity(EntityList.getEntityString(entity), NBTConverter.fromNative(tag));
|
return new BaseEntity(id, NBTConverter.fromNative(tag));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Location getLocation() {
|
public Location getLocation() {
|
||||||
return new Location(
|
Vector position;
|
||||||
ForgeAdapter.adapt(entity.worldObj),
|
float pitch;
|
||||||
new Vector(entity.posX, entity.posY, entity.posZ),
|
float yaw;
|
||||||
ForgeAdapter.adapt(entity.getLookVec()));
|
|
||||||
|
if (entity instanceof EntityHanging) {
|
||||||
|
EntityHanging hanging = (EntityHanging) entity;
|
||||||
|
|
||||||
|
position = new Vector(hanging.xPosition, hanging.yPosition, hanging.zPosition);
|
||||||
|
|
||||||
|
Direction direction = MCDirections.fromHanging(hanging.hangingDirection);
|
||||||
|
if (direction != null) {
|
||||||
|
yaw = direction.toVector().toYaw();
|
||||||
|
pitch = direction.toVector().toPitch();
|
||||||
|
} else {
|
||||||
|
yaw = (float) Math.toRadians(entity.rotationYaw);
|
||||||
|
pitch = (float) Math.toRadians(entity.rotationPitch);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
position = new Vector(entity.posX, entity.posY, entity.posZ);
|
||||||
|
yaw = (float) Math.toRadians(entity.rotationYaw);
|
||||||
|
pitch = (float) Math.toRadians(entity.rotationPitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Location(ForgeAdapter.adapt(entity.worldObj), position, yaw, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,7 +32,10 @@ import com.sk89q.worldedit.blocks.BaseItemStack;
|
|||||||
import com.sk89q.worldedit.blocks.LazyBlock;
|
import com.sk89q.worldedit.blocks.LazyBlock;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.internal.helper.MCDirections;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
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.Location;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||||
import com.sk89q.worldedit.world.AbstractWorld;
|
import com.sk89q.worldedit.world.AbstractWorld;
|
||||||
@ -500,7 +503,29 @@ public class ForgeWorld extends AbstractWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> getEntities() {
|
@SuppressWarnings("unchecked")
|
||||||
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
|
List<Entity> entities = new ArrayList<Entity>();
|
||||||
|
World world = getWorld();
|
||||||
|
for (Vector2D pt : region.getChunks()) {
|
||||||
|
if (!world.getChunkProvider().chunkExists(pt.getBlockX(), pt.getBlockZ())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk chunk = world.getChunkProvider().provideChunk(pt.getBlockX(), pt.getBlockZ());
|
||||||
|
for (List<net.minecraft.entity.Entity> entitySubList : chunk.entityLists) {
|
||||||
|
for (net.minecraft.entity.Entity entity : entitySubList) {
|
||||||
|
if (region.contains(new Vector(entity.posX, entity.posY, entity.posZ))) {
|
||||||
|
entities.add(new ForgeEntity(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities() {
|
||||||
List<Entity> entities = new ArrayList<Entity>();
|
List<Entity> entities = new ArrayList<Entity>();
|
||||||
for (Object entity : getWorld().getLoadedEntityList()) {
|
for (Object entity : getWorld().getLoadedEntityList()) {
|
||||||
entities.add(new ForgeEntity((net.minecraft.entity.Entity) entity));
|
entities.add(new ForgeEntity((net.minecraft.entity.Entity) entity));
|
||||||
@ -518,6 +543,19 @@ public class ForgeWorld extends AbstractWorld {
|
|||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
createdEntity.readFromNBT(NBTConverter.toNative(entity.getNbtData()));
|
createdEntity.readFromNBT(NBTConverter.toNative(entity.getNbtData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createdEntity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), (float) Math.toDegrees(location.getYaw()), (float) Math.toDegrees(location.getPitch()));
|
||||||
|
|
||||||
|
// Special handling for hanging entities
|
||||||
|
if (createdEntity instanceof EntityHanging) {
|
||||||
|
EntityHanging hanging = (EntityHanging) createdEntity;
|
||||||
|
hanging.xPosition = location.getBlockX();
|
||||||
|
hanging.yPosition = location.getBlockY();
|
||||||
|
hanging.zPosition = location.getBlockZ();
|
||||||
|
Direction direction = Direction.findClosest(location.getDirection(), Flag.CARDINAL);
|
||||||
|
hanging.setDirection(MCDirections.toHanging(direction));
|
||||||
|
}
|
||||||
|
|
||||||
world.spawnEntityInWorld(createdEntity);
|
world.spawnEntityInWorld(createdEntity);
|
||||||
return new ForgeEntity(createdEntity);
|
return new ForgeEntity(createdEntity);
|
||||||
} else {
|
} else {
|
||||||
|
@ -582,15 +582,10 @@ public class EditSession implements Extent {
|
|||||||
return getBlock(position).isAir() && setBlock(position, block);
|
return getBlock(position).isAir() && setBlock(position, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Entity> getEntities() {
|
|
||||||
return world.getEntities();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity) {
|
public Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity) {
|
||||||
return world.createEntity(location, entity);
|
return bypassNone.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -649,6 +644,16 @@ public class EditSession implements Extent {
|
|||||||
return getWorld().getMaximumPoint();
|
return getWorld().getMaximumPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
|
return bypassNone.getEntities(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities() {
|
||||||
|
return bypassNone.getEntities();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finish off the queue.
|
* Finish off the queue.
|
||||||
*/
|
*/
|
||||||
@ -1160,6 +1165,7 @@ public class EditSession implements Extent {
|
|||||||
ForwardExtentCopy copy = new ForwardExtentCopy(this, region, buffer, to);
|
ForwardExtentCopy copy = new ForwardExtentCopy(this, region, buffer, to);
|
||||||
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
|
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
|
||||||
copy.setSourceFunction(remove); // Remove
|
copy.setSourceFunction(remove); // Remove
|
||||||
|
copy.setRemovingEntities(true);
|
||||||
if (!copyAir) {
|
if (!copyAir) {
|
||||||
copy.setSourceMask(new ExistingBlockMask(this));
|
copy.setSourceMask(new ExistingBlockMask(this));
|
||||||
}
|
}
|
||||||
|
@ -652,6 +652,40 @@ public class Vector implements Comparable<Vector> {
|
|||||||
throw new RuntimeException("This should not happen");
|
throw new RuntimeException("This should not happen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get this vector's pitch as used within the game.
|
||||||
|
*
|
||||||
|
* @return pitch in radians
|
||||||
|
*/
|
||||||
|
public float toPitch() {
|
||||||
|
double x = getX();
|
||||||
|
double z = getZ();
|
||||||
|
|
||||||
|
if (x == 0 && z == 0) {
|
||||||
|
return getY() > 0 ? -90 : 90;
|
||||||
|
} else {
|
||||||
|
double x2 = x * x;
|
||||||
|
double z2 = z * z;
|
||||||
|
double xz = Math.sqrt(x2 + z2);
|
||||||
|
return (float) Math.atan(-getY() / xz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get this vector's yaw as used within the game.
|
||||||
|
*
|
||||||
|
* @return yaw in radians
|
||||||
|
*/
|
||||||
|
public float toYaw() {
|
||||||
|
double x = getX();
|
||||||
|
double z = getZ();
|
||||||
|
|
||||||
|
double t = Math.atan2(-x, z);
|
||||||
|
double _2pi = 2 * Math.PI;
|
||||||
|
|
||||||
|
return (float) ((t + _2pi) % _2pi);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a block point from a point.
|
* Get a block point from a point.
|
||||||
*
|
*
|
||||||
@ -792,4 +826,5 @@ public class Vector implements Comparable<Vector> {
|
|||||||
(v1.z + v2.z) / 2
|
(v1.z + v2.z) / 2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import com.sk89q.worldedit.entity.Entity;
|
|||||||
import com.sk89q.worldedit.function.operation.Operation;
|
import com.sk89q.worldedit.function.operation.Operation;
|
||||||
import com.sk89q.worldedit.function.operation.OperationQueue;
|
import com.sk89q.worldedit.function.operation.OperationQueue;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@ -82,10 +83,15 @@ public abstract class AbstractDelegateExtent implements Extent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> getEntities() {
|
public List<? extends Entity> getEntities() {
|
||||||
return extent.getEntities();
|
return extent.getEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
|
return extent.getEntities(region);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector getMinimumPoint() {
|
public Vector getMinimumPoint() {
|
||||||
return extent.getMinimumPoint();
|
return extent.getMinimumPoint();
|
||||||
|
@ -22,8 +22,19 @@ package com.sk89q.worldedit.extent;
|
|||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.history.change.BlockChange;
|
import com.sk89q.worldedit.history.change.BlockChange;
|
||||||
|
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||||
|
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -53,4 +64,65 @@ public class ChangeSetExtent extends AbstractDelegateExtent {
|
|||||||
return super.setBlock(location, block);
|
return super.setBlock(location, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity state) {
|
||||||
|
Entity entity = super.createEntity(location, state);
|
||||||
|
if (state != null) {
|
||||||
|
changeSet.add(new EntityCreate(location, state, entity));
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities() {
|
||||||
|
return wrapEntities(super.getEntities());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
|
return wrapEntities(super.getEntities(region));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<? extends Entity> wrapEntities(List<? extends Entity> entities) {
|
||||||
|
List<Entity> newList = new ArrayList<Entity>(entities.size());
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
newList.add(new TrackedEntity(entity));
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TrackedEntity implements Entity {
|
||||||
|
private final Entity entity;
|
||||||
|
|
||||||
|
private TrackedEntity(Entity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseEntity getState() {
|
||||||
|
return entity.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location getLocation() {
|
||||||
|
return entity.getLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Extent getExtent() {
|
||||||
|
return entity.getExtent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove() {
|
||||||
|
Location location = entity.getLocation();
|
||||||
|
BaseEntity state = entity.getState();
|
||||||
|
boolean success = entity.remove();
|
||||||
|
if (state != null && success) {
|
||||||
|
changeSet.add(new EntityRemove(location, state));
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import com.sk89q.worldedit.Vector;
|
|||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -56,6 +57,17 @@ public interface Extent extends InputExtent, OutputExtent {
|
|||||||
*/
|
*/
|
||||||
Vector getMaximumPoint();
|
Vector getMaximumPoint();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all entities within the given region.
|
||||||
|
* </p>
|
||||||
|
* If the extent is not wholly loaded (i.e. a world being simulated in the
|
||||||
|
* game will not have every chunk loaded), then this list may not be
|
||||||
|
* incomplete.
|
||||||
|
*
|
||||||
|
* @return a list of entities
|
||||||
|
*/
|
||||||
|
List<? extends Entity> getEntities(Region region);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of all entities.
|
* Get a list of all entities.
|
||||||
* </p>
|
* </p>
|
||||||
@ -65,7 +77,7 @@ public interface Extent extends InputExtent, OutputExtent {
|
|||||||
*
|
*
|
||||||
* @return a list of entities
|
* @return a list of entities
|
||||||
*/
|
*/
|
||||||
List<Entity> getEntities();
|
List<? extends Entity> getEntities();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an entity at the given location.
|
* Create an entity at the given location.
|
||||||
|
@ -26,6 +26,7 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
|||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.function.operation.Operation;
|
import com.sk89q.worldedit.function.operation.Operation;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -49,6 +50,11 @@ public class NullExtent implements Extent {
|
|||||||
return nullPoint;
|
return nullPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Entity> getEntities(Region region) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> getEntities() {
|
public List<Entity> getEntities() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -31,6 +31,7 @@ import com.sk89q.worldedit.util.Location;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -93,8 +94,19 @@ public class BlockArrayClipboard implements Clipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> getEntities() {
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
return new ArrayList<Entity>(entities);
|
List<Entity> filtered = new ArrayList<Entity>();
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
if (region.contains(entity.getLocation().toVector())) {
|
||||||
|
filtered.add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities() {
|
||||||
|
return Collections.unmodifiableList(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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.function.entity;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.Vector;
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.function.EntityFunction;
|
||||||
|
import com.sk89q.worldedit.math.transform.Transform;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies entities provided to the function to the provided destination
|
||||||
|
* {@code Extent}.
|
||||||
|
*/
|
||||||
|
public class ExtentEntityCopy implements EntityFunction {
|
||||||
|
|
||||||
|
private final Extent destination;
|
||||||
|
private final Vector from;
|
||||||
|
private final Vector to;
|
||||||
|
private final Transform transform;
|
||||||
|
private boolean removing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param from the from position
|
||||||
|
* @param destination the destination {@code Extent}
|
||||||
|
* @param to the destination position
|
||||||
|
* @param transform the transformation to apply to both position and orientation
|
||||||
|
*/
|
||||||
|
public ExtentEntityCopy(Vector from, Extent destination, Vector to, Transform transform) {
|
||||||
|
checkNotNull(from);
|
||||||
|
checkNotNull(destination);
|
||||||
|
checkNotNull(to);
|
||||||
|
checkNotNull(transform);
|
||||||
|
this.destination = destination;
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether entities that are copied should be removed.
|
||||||
|
*
|
||||||
|
* @return true if removing
|
||||||
|
*/
|
||||||
|
public boolean isRemoving() {
|
||||||
|
return removing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether entities that are copied should be removed.
|
||||||
|
*
|
||||||
|
* @param removing true if removing
|
||||||
|
*/
|
||||||
|
public void setRemoving(boolean removing) {
|
||||||
|
this.removing = removing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Entity entity) throws WorldEditException {
|
||||||
|
BaseEntity state = entity.getState();
|
||||||
|
if (state != null) {
|
||||||
|
Location location = entity.getLocation();
|
||||||
|
Vector newPosition = transform.apply(location.toVector().subtract(from));
|
||||||
|
Vector newDirection = transform.apply(location.getDirection()).subtract(transform.apply(Vector.ZERO)).normalize();
|
||||||
|
Location newLocation = new Location(destination, newPosition.add(to), newDirection);
|
||||||
|
boolean success = destination.createEntity(newLocation, state) != null;
|
||||||
|
|
||||||
|
// Remove
|
||||||
|
if (isRemoving() && success) {
|
||||||
|
entity.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,20 +19,25 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.function.operation;
|
package com.sk89q.worldedit.function.operation;
|
||||||
|
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.function.CombinedRegionFunction;
|
import com.sk89q.worldedit.function.CombinedRegionFunction;
|
||||||
import com.sk89q.worldedit.function.RegionFunction;
|
import com.sk89q.worldedit.function.RegionFunction;
|
||||||
import com.sk89q.worldedit.function.RegionMaskingFilter;
|
import com.sk89q.worldedit.function.RegionMaskingFilter;
|
||||||
import com.sk89q.worldedit.function.block.ExtentBlockCopy;
|
import com.sk89q.worldedit.function.block.ExtentBlockCopy;
|
||||||
|
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.mask.Masks;
|
import com.sk89q.worldedit.function.mask.Masks;
|
||||||
|
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||||
import com.sk89q.worldedit.math.transform.Identity;
|
import com.sk89q.worldedit.math.transform.Identity;
|
||||||
import com.sk89q.worldedit.math.transform.Transform;
|
import com.sk89q.worldedit.math.transform.Transform;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -52,6 +57,7 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
private final Vector to;
|
private final Vector to;
|
||||||
private int repetitions = 1;
|
private int repetitions = 1;
|
||||||
private Mask sourceMask = Masks.alwaysTrue();
|
private Mask sourceMask = Masks.alwaysTrue();
|
||||||
|
private boolean removingEntities;
|
||||||
private RegionFunction sourceFunction = null;
|
private RegionFunction sourceFunction = null;
|
||||||
private Transform transform = new Identity();
|
private Transform transform = new Identity();
|
||||||
private Transform currentTransform = null;
|
private Transform currentTransform = null;
|
||||||
@ -177,6 +183,24 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
this.repetitions = repetitions;
|
this.repetitions = repetitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether entities that are copied should be removed.
|
||||||
|
*
|
||||||
|
* @return true if removing
|
||||||
|
*/
|
||||||
|
public boolean isRemovingEntities() {
|
||||||
|
return removingEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether entities that are copied should be removed.
|
||||||
|
*
|
||||||
|
* @param removing true if removing
|
||||||
|
*/
|
||||||
|
public void setRemovingEntities(boolean removingEntities) {
|
||||||
|
this.removingEntities = removingEntities;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of affected objects.
|
* Get the number of affected objects.
|
||||||
*
|
*
|
||||||
@ -200,13 +224,19 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
currentTransform = transform;
|
currentTransform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtentBlockCopy copy = new ExtentBlockCopy(source, from, destination, to, currentTransform);
|
ExtentBlockCopy blockCopy = new ExtentBlockCopy(source, from, destination, to, currentTransform);
|
||||||
RegionMaskingFilter filter = new RegionMaskingFilter(sourceMask, copy);
|
RegionMaskingFilter filter = new RegionMaskingFilter(sourceMask, blockCopy);
|
||||||
RegionFunction function = sourceFunction != null ? new CombinedRegionFunction(filter, sourceFunction) : filter;
|
RegionFunction function = sourceFunction != null ? new CombinedRegionFunction(filter, sourceFunction) : filter;
|
||||||
RegionVisitor visitor = new RegionVisitor(region, function);
|
RegionVisitor blockVisitor = new RegionVisitor(region, function);
|
||||||
lastVisitor = visitor;
|
|
||||||
|
ExtentEntityCopy entityCopy = new ExtentEntityCopy(from, destination, to, currentTransform);
|
||||||
|
entityCopy.setRemoving(removingEntities);
|
||||||
|
List<? extends Entity> entities = source.getEntities(region);
|
||||||
|
EntityVisitor entityVisitor = new EntityVisitor(entities.iterator(), entityCopy);
|
||||||
|
|
||||||
|
lastVisitor = blockVisitor;
|
||||||
currentTransform = currentTransform.combine(transform);
|
currentTransform = currentTransform.combine(transform);
|
||||||
return new DelegateOperation(this, visitor);
|
return new DelegateOperation(this, new OperationQueue(blockVisitor, entityVisitor));
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
public class EntityVisitor implements Operation {
|
public class EntityVisitor implements Operation {
|
||||||
|
|
||||||
private final Iterator<Entity> iterator;
|
private final Iterator<? extends Entity> iterator;
|
||||||
private final EntityFunction function;
|
private final EntityFunction function;
|
||||||
private int affected = 0;
|
private int affected = 0;
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ public class EntityVisitor implements Operation {
|
|||||||
* @param iterator the iterator
|
* @param iterator the iterator
|
||||||
* @param function the function
|
* @param function the function
|
||||||
*/
|
*/
|
||||||
public EntityVisitor(Iterator<Entity> iterator, EntityFunction function) {
|
public EntityVisitor(Iterator<? extends Entity> iterator, EntityFunction function) {
|
||||||
checkNotNull(iterator);
|
checkNotNull(iterator);
|
||||||
checkNotNull(function);
|
checkNotNull(function);
|
||||||
this.iterator = iterator;
|
this.iterator = iterator;
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.history.change;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.history.UndoContext;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the creation of an entity and removes the entity upon undo.
|
||||||
|
*/
|
||||||
|
public class EntityCreate implements Change {
|
||||||
|
|
||||||
|
private final Location location;
|
||||||
|
private final BaseEntity state;
|
||||||
|
private Entity entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param location the location
|
||||||
|
* @param state the state of the created entity
|
||||||
|
* @param entity the entity that was created
|
||||||
|
*/
|
||||||
|
public EntityCreate(Location location, BaseEntity state, Entity entity) {
|
||||||
|
checkNotNull(location);
|
||||||
|
checkNotNull(state);
|
||||||
|
checkNotNull(entity);
|
||||||
|
this.location = location;
|
||||||
|
this.state = state;
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo(UndoContext context) throws WorldEditException {
|
||||||
|
if (entity != null) {
|
||||||
|
entity.remove();
|
||||||
|
entity = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redo(UndoContext context) throws WorldEditException {
|
||||||
|
entity = checkNotNull(context.getExtent()).createEntity(location, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.history.change;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.history.UndoContext;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks the removal of an entity.
|
||||||
|
*/
|
||||||
|
public class EntityRemove implements Change {
|
||||||
|
|
||||||
|
private final Location location;
|
||||||
|
private final BaseEntity state;
|
||||||
|
private Entity entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param location the location
|
||||||
|
* @param state the state of the created entity
|
||||||
|
*/
|
||||||
|
public EntityRemove(Location location, BaseEntity state) {
|
||||||
|
checkNotNull(location);
|
||||||
|
checkNotNull(state);
|
||||||
|
this.location = location;
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo(UndoContext context) throws WorldEditException {
|
||||||
|
entity = checkNotNull(context.getExtent()).createEntity(location, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redo(UndoContext context) throws WorldEditException {
|
||||||
|
if (entity != null) {
|
||||||
|
entity.remove();
|
||||||
|
entity = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -171,11 +171,6 @@ public class LocalWorldAdapter extends LocalWorld {
|
|||||||
world.simulateBlockMine(position);
|
world.simulateBlockMine(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalEntity[] getEntities(Region region) {
|
|
||||||
return world.getEntities(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int killEntities(LocalEntity... entity) {
|
public int killEntities(LocalEntity... entity) {
|
||||||
return world.killEntities(entity);
|
return world.killEntities(entity);
|
||||||
@ -293,6 +288,11 @@ public class LocalWorldAdapter extends LocalWorld {
|
|||||||
return world.getMaximumPoint();
|
return world.getMaximumPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
|
return world.getEntities(region);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock getBlock(Vector position) {
|
public BaseBlock getBlock(Vector position) {
|
||||||
return world.getBlock(position);
|
return world.getBlock(position);
|
||||||
@ -335,7 +335,7 @@ public class LocalWorldAdapter extends LocalWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> getEntities() {
|
public List<? extends Entity> getEntities() {
|
||||||
return world.getEntities();
|
return world.getEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.internal.helper;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.util.Direction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for working with directions in Minecraft.
|
||||||
|
*/
|
||||||
|
public final class MCDirections {
|
||||||
|
|
||||||
|
private MCDirections() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Direction fromHanging(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return Direction.SOUTH;
|
||||||
|
case 1:
|
||||||
|
return Direction.WEST;
|
||||||
|
case 2:
|
||||||
|
return Direction.NORTH;
|
||||||
|
case 3:
|
||||||
|
return Direction.EAST;
|
||||||
|
default:
|
||||||
|
return Direction.NORTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toHanging(Direction direction) {
|
||||||
|
switch (direction) {
|
||||||
|
case SOUTH:
|
||||||
|
return 0;
|
||||||
|
case WEST:
|
||||||
|
return 1;
|
||||||
|
case NORTH:
|
||||||
|
return 2;
|
||||||
|
case EAST:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
159
src/main/java/com/sk89q/worldedit/util/Direction.java
Normal file
159
src/main/java/com/sk89q/worldedit/util/Direction.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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.Vector;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of cardinal, ordinal, and secondary-ordinal directions.
|
||||||
|
*/
|
||||||
|
public enum Direction {
|
||||||
|
|
||||||
|
NORTH(new Vector(0, 0, -1), Flag.CARDINAL),
|
||||||
|
EAST(new Vector(1, 0, 0), Flag.CARDINAL),
|
||||||
|
SOUTH(new Vector(0, 0, 1), Flag.CARDINAL),
|
||||||
|
WEST(new Vector(-1, 0, 0), Flag.CARDINAL),
|
||||||
|
|
||||||
|
UP(new Vector(0, 1, 0), Flag.UPRIGHT),
|
||||||
|
DOWN(new Vector(0, -1, 0), Flag.UPRIGHT),
|
||||||
|
|
||||||
|
NORTHEAST(new Vector(1, 0, -1), Flag.ORDINAL),
|
||||||
|
NORTHWEST(new Vector(-1, 0, -1), Flag.ORDINAL),
|
||||||
|
SOUTHEAST(new Vector(1, 0, 1), Flag.ORDINAL),
|
||||||
|
SOUTHWEST(new Vector(-1, 0, 1), Flag.ORDINAL),
|
||||||
|
|
||||||
|
WEST_NORTHWEST(new Vector(-Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
WEST_SOUTHWEST(new Vector(-Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
NORTH_NORTHWEST(new Vector(Math.sin(Math.PI / 8), 0, -Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
NORTH_NORTHEAST(new Vector(Math.sin(Math.PI / 8), 0, -Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
EAST_NORTHEAST(new Vector(Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
EAST_SOUTHEAST(new Vector(Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
SOUTH_SOUTHEAST(new Vector(Math.sin(Math.PI / 8), 0, Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||||
|
SOUTH_SOUTHWEST(new Vector(Math.sin(Math.PI / 8), 0, Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL);
|
||||||
|
|
||||||
|
private final Vector direction;
|
||||||
|
private final int flags;
|
||||||
|
|
||||||
|
private Direction(Vector vector, int flags) {
|
||||||
|
this.direction = vector.normalize();
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the direction is of a cardinal direction (north, west
|
||||||
|
* east, and south).
|
||||||
|
*
|
||||||
|
* <p>This evaluates as false for directions that have a non-zero
|
||||||
|
* Y-component.</p>
|
||||||
|
*
|
||||||
|
* @return true if cardinal
|
||||||
|
*/
|
||||||
|
public boolean isCardinal() {
|
||||||
|
return (flags & Flag.CARDINAL) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the direction is of an ordinal direction (northwest,
|
||||||
|
* southwest, southeast, northeaast).
|
||||||
|
*
|
||||||
|
* @return true if ordinal
|
||||||
|
*/
|
||||||
|
public boolean isOrdinal() {
|
||||||
|
return (flags & Flag.ORDINAL) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the direction is of a secondary ordinal direction
|
||||||
|
* (north-northwest, north-northeast, south-southwest, etc.).
|
||||||
|
*
|
||||||
|
* @return true if secondary ordinal
|
||||||
|
*/
|
||||||
|
public boolean isSecondaryOrdinal() {
|
||||||
|
return (flags & Flag.SECONDARY_ORDINAL) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether Y component is non-zero.
|
||||||
|
*
|
||||||
|
* @return true if the Y component is non-zero
|
||||||
|
*/
|
||||||
|
public boolean isUpright() {
|
||||||
|
return (flags & Flag.UPRIGHT) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the vector.
|
||||||
|
*
|
||||||
|
* @return the vector
|
||||||
|
*/
|
||||||
|
public Vector toVector() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the closest direction to the given direction vector.
|
||||||
|
*
|
||||||
|
* @param vector the vector
|
||||||
|
* @param flags the only flags that are permitted (use bitwise math)
|
||||||
|
* @return the closest direction, or null if no direction can be returned
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static Direction findClosest(Vector vector, int flags) {
|
||||||
|
if ((flags & Flag.UPRIGHT) == 0) {
|
||||||
|
vector = vector.setY(0);
|
||||||
|
}
|
||||||
|
vector = vector.normalize();
|
||||||
|
|
||||||
|
Direction closest = null;
|
||||||
|
double closestDot = -2;
|
||||||
|
for (Direction direction : values()) {
|
||||||
|
if ((~flags & direction.flags) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dot = direction.toVector().dot(vector);
|
||||||
|
if (dot >= closestDot) {
|
||||||
|
closest = direction;
|
||||||
|
closestDot = dot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags to use with {@link #findClosest(Vector, int)}.
|
||||||
|
*/
|
||||||
|
public static final class Flag {
|
||||||
|
public static int CARDINAL = 0x1;
|
||||||
|
public static int ORDINAL = 0x2;
|
||||||
|
public static int SECONDARY_ORDINAL = 0x4;
|
||||||
|
public static int UPRIGHT = 0x8;
|
||||||
|
|
||||||
|
public static int ALL = CARDINAL | ORDINAL | SECONDARY_ORDINAL | UPRIGHT;
|
||||||
|
|
||||||
|
private Flag() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -113,8 +113,7 @@ public class Location {
|
|||||||
* @param direction the direction vector
|
* @param direction the direction vector
|
||||||
*/
|
*/
|
||||||
public Location(Extent extent, Vector position, Vector direction) {
|
public Location(Extent extent, Vector position, Vector direction) {
|
||||||
this(extent, position, 0, 0);
|
this(extent, position, direction.toYaw(), direction.toPitch());
|
||||||
this.setDirection(direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,24 +193,7 @@ public class Location {
|
|||||||
* @return the new instance
|
* @return the new instance
|
||||||
*/
|
*/
|
||||||
public Location setDirection(Vector direction) {
|
public Location setDirection(Vector direction) {
|
||||||
double x = direction.getX();
|
return new Location(extent, position, direction.toYaw(), direction.toPitch());
|
||||||
double z = direction.getZ();
|
|
||||||
|
|
||||||
if (x == 0 && z == 0) {
|
|
||||||
float pitch = direction.getY() > 0 ? -90 : 90;
|
|
||||||
return new Location(extent, position, 0, pitch);
|
|
||||||
} else {
|
|
||||||
double t = Math.atan2(-x, z);
|
|
||||||
double x2 = x * x;
|
|
||||||
double z2 = z * z;
|
|
||||||
double xz = Math.sqrt(x2 + z2);
|
|
||||||
double _2pi = 2 * Math.PI;
|
|
||||||
|
|
||||||
float pitch = (float) Math.atan(-direction.getY() / xz);
|
|
||||||
float yaw = (float) ((t + _2pi) % _2pi);
|
|
||||||
|
|
||||||
return new Location(extent, position, yaw, pitch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,13 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.world;
|
package com.sk89q.worldedit.world;
|
||||||
|
|
||||||
import com.sk89q.worldedit.*;
|
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.LocalWorld.KillFlags;
|
||||||
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
|
import com.sk89q.worldedit.Vector;
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||||
import com.sk89q.worldedit.blocks.BlockID;
|
import com.sk89q.worldedit.blocks.BlockID;
|
||||||
@ -29,7 +34,6 @@ import com.sk89q.worldedit.extension.platform.Platform;
|
|||||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.operation.Operation;
|
import com.sk89q.worldedit.function.operation.Operation;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
|
||||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -156,11 +160,6 @@ public abstract class AbstractWorld implements World {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalEntity[] getEntities(Region region) {
|
|
||||||
return new LocalEntity[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int killEntities(LocalEntity... entities) {
|
public int killEntities(LocalEntity... entities) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -109,6 +109,11 @@ public class NullWorld extends AbstractWorld {
|
|||||||
return new BaseBlock(BlockID.AIR);
|
return new BaseBlock(BlockID.AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Entity> getEntities(Region region) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entity> getEntities() {
|
public List<Entity> getEntities() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -209,14 +209,6 @@ public interface World extends Extent {
|
|||||||
*/
|
*/
|
||||||
void simulateBlockMine(Vector position);
|
void simulateBlockMine(Vector position);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of entities in the given region.
|
|
||||||
*
|
|
||||||
* @param region the region
|
|
||||||
* @return a list of entities
|
|
||||||
*/
|
|
||||||
LocalEntity[] getEntities(Region region);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kill the entities listed in the provided array.
|
* Kill the entities listed in the provided array.
|
||||||
*
|
*
|
||||||
|
@ -51,25 +51,6 @@ public class LocationTest {
|
|||||||
assertEquals(world2, location2.getExtent());
|
assertEquals(world2, location2.getExtent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetDirection() throws Exception {
|
|
||||||
World world = mock(World.class);
|
|
||||||
Vector direction = new Vector(1, 1, 1);
|
|
||||||
Location location = new Location(world, new Vector(), direction);
|
|
||||||
assertEquals(direction, location.getDirection());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetDirection() throws Exception {
|
|
||||||
World world = mock(World.class);
|
|
||||||
Vector direction1 = new Vector(1, 1, 1);
|
|
||||||
Vector direction2 = new Vector(2, 2, 2);
|
|
||||||
Location location1 = new Location(world, new Vector(), direction1);
|
|
||||||
Location location2 = location1.setDirection(direction2);
|
|
||||||
assertEquals(direction1, location1.getDirection());
|
|
||||||
assertEquals(direction2, location2.getDirection());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToVector() throws Exception {
|
public void testToVector() throws Exception {
|
||||||
World world = mock(World.class);
|
World world = mock(World.class);
|
||||||
|
Loading…
Reference in New Issue
Block a user