Merge in new block, entity, and biome APIs.

This commit is contained in:
sk89q 2014-07-18 02:16:25 -07:00
commit 5dc462cc42
225 changed files with 17429 additions and 4515 deletions

View File

@ -45,6 +45,8 @@ dependencies {
compile group: 'com.sk89q', name: 'jchronic', version:'0.2.4a' compile group: 'com.sk89q', name: 'jchronic', version:'0.2.4a'
compile group: 'com.google.code.findbugs', name: 'jsr305', version: '1.3.9' compile group: 'com.google.code.findbugs', name: 'jsr305', version: '1.3.9'
compile group: 'com.thoughtworks.paranamer', name: 'paranamer', version: '2.6' compile group: 'com.thoughtworks.paranamer', name: 'paranamer', version: '2.6'
compile group: 'com.google.code.gson', name: 'gson', version: '2.2.4'
compile group: 'net.sf.trove4j', name: 'trove4j', version: '3.0.3'
testCompile group: 'org.mockito', name: 'mockito-core', version:'1.9.0-rc1' testCompile group: 'org.mockito', name: 'mockito-core', version:'1.9.0-rc1'
} }

57
pom.xml
View File

@ -142,6 +142,22 @@
<type>jar</type> <type>jar</type>
</dependency> </dependency>
<!-- JSON parser -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<optional>true</optional>
</dependency>
<!-- Optimized collections -->
<dependency>
<groupId>net.sf.trove4j</groupId>
<artifactId>trove4j</artifactId>
<version>3.0.3</version>
<optional>true</optional>
</dependency>
<!-- @Nullable etc. --> <!-- @Nullable etc. -->
<dependency> <dependency>
<groupId>com.google.code.findbugs</groupId> <groupId>com.google.code.findbugs</groupId>
@ -187,6 +203,18 @@
<defaultGoal>install</defaultGoal> <defaultGoal>install</defaultGoal>
<sourceDirectory>${basedir}/src/main/java/</sourceDirectory> <sourceDirectory>${basedir}/src/main/java/</sourceDirectory>
<resources>
<!-- Data files -->
<resource>
<targetPath>.</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/resources/</directory>
<includes>
<include>**/*.json</include>
</includes>
</resource>
</resources>
<!-- Used for uploading the docs --> <!-- Used for uploading the docs -->
<extensions> <extensions>
<extension> <extension>
@ -367,12 +395,25 @@
<goal>shade</goal> <goal>shade</goal>
</goals> </goals>
<configuration> <configuration>
<minimizeJar>true</minimizeJar>
<artifactSet> <artifactSet>
<includes> <includes>
<include>com.sk89q:jchronic</include> <include>com.sk89q:jchronic</include>
<include>com.thoughtworks.paranamer:paranamer</include> <include>com.thoughtworks.paranamer:paranamer</include>
<include>com.google.code.gson:gson</include>
<include>net.sf.trove4j:trove4j</include>
</includes> </includes>
</artifactSet> </artifactSet>
<relocations>
<relocation>
<pattern>gnu.trove</pattern>
<shadedPattern>com.sk89q.worldedit.internal.trove</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>com.sk89q.worldedit.internal.gson</shadedPattern>
</relocation>
</relocations>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -513,16 +554,6 @@
<type>jar</type> <type>jar</type>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<!-- NMS blocks -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.9-R0.1-SNAPSHOT</version>
<scope>compile</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -549,11 +580,11 @@
<!-- NMS support in Bukkit --> <!-- NMS support in Bukkit -->
<resource> <resource>
<targetPath>nmsblocks/</targetPath> <targetPath>.</targetPath>
<filtering>false</filtering> <filtering>false</filtering>
<directory>${basedir}/src/bukkit/resources/nmsblocks/</directory> <directory>${basedir}/src/bukkit/resources/</directory>
<includes> <includes>
<include>*.class</include> <include>**/*.class</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>

View File

@ -0,0 +1,144 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import org.bukkit.Bukkit;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Adapts between Bukkit and WorldEdit equivalent objects.
*/
final class BukkitAdapter {
private BukkitAdapter() {
}
/**
* Create a WorldEdit world from a Bukkit world.
*
* @param world the Bukkit world
* @return a WorldEdit world
*/
public static World adapt(org.bukkit.World world) {
checkNotNull(world);
return new BukkitWorld(world);
}
/**
* Create a Bukkit world from a WorldEdit world.
*
* @param world the WorldEdit world
* @return a Bukkit world
*/
public static org.bukkit.World adapt(World world) {
checkNotNull(world);
if (world instanceof BukkitWorld) {
return ((BukkitWorld) world).getWorld();
} else {
org.bukkit.World match = Bukkit.getServer().getWorld(world.getName());
if (match != null) {
return match;
} else {
throw new IllegalArgumentException("Can't find a Bukkit world for " + world);
}
}
}
/**
* Create a WorldEdit location from a Bukkit location.
*
* @param location the Bukkit location
* @return a WorldEdit location
*/
public static Location adapt(org.bukkit.Location location) {
checkNotNull(location);
Vector position = BukkitUtil.toVector(location);
return new com.sk89q.worldedit.util.Location(
adapt(location.getWorld()),
position,
location.getYaw(),
location.getPitch());
}
/**
* Create a Bukkit location from a WorldEdit location.
*
* @param location the WorldEdit location
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(Location location) {
checkNotNull(location);
Vector position = location.toVector();
return new org.bukkit.Location(
adapt((World) location.getExtent()),
position.getX(), position.getY(), position.getZ(),
location.getYaw(),
location.getPitch());
}
/**
* Create a Bukkit location from a WorldEdit position with a Bukkit world.
*
* @param world the Bukkit world
* @param position the WorldEdit position
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(org.bukkit.World world, Vector position) {
checkNotNull(world);
checkNotNull(position);
return new org.bukkit.Location(
world,
position.getX(), position.getY(), position.getZ());
}
/**
* Create a Bukkit location from a WorldEdit location with a Bukkit world.
*
* @param world the Bukkit world
* @param location the WorldEdit location
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(org.bukkit.World world, Location location) {
checkNotNull(world);
checkNotNull(location);
return new org.bukkit.Location(
world,
location.getX(), location.getY(), location.getZ(),
location.getYaw(),
location.getPitch());
}
/**
* Create a WorldEdit entity from a Bukkit entity.
*
* @param entity the Bukkit entity
* @return a WorldEdit entity
*/
public static Entity adapt(org.bukkit.entity.Entity entity) {
checkNotNull(entity);
return new BukkitEntity(entity);
}
}

View File

@ -0,0 +1,79 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.biome.BiomeData;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import org.bukkit.block.Biome;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A biome registry for Bukkit.
*/
class BukkitBiomeRegistry implements BiomeRegistry {
BukkitBiomeRegistry() {
}
@Nullable
@Override
public BaseBiome createFromId(int id) {
return new BaseBiome(id);
}
@Override
public List<BaseBiome> getBiomes() {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) {
List<BaseBiome> biomes = new ArrayList<BaseBiome>();
for (Biome biome : Biome.values()) {
int biomeId = adapter.getBiomeId(biome);
biomes.add(new BaseBiome(biomeId));
}
return biomes;
} else {
return Collections.emptyList();
}
}
@Nullable
@Override
public BiomeData getData(BaseBiome biome) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) {
final Biome bukkitBiome = adapter.getBiome(biome.getId());
return new BiomeData() {
@Override
public String getName() {
return bukkitBiome.name();
}
};
} else {
return null;
}
}
}

View File

@ -1,106 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import java.util.Locale;
import org.bukkit.block.Biome;
import com.sk89q.worldedit.BiomeType;
public enum BukkitBiomeType implements BiomeType {
SWAMPLAND(Biome.SWAMPLAND),
FOREST(Biome.FOREST),
TAIGA(Biome.TAIGA),
DESERT(Biome.DESERT),
PLAINS(Biome.PLAINS),
HELL(Biome.HELL),
SKY(Biome.SKY),
RIVER(Biome.RIVER),
EXTREME_HILLS(Biome.EXTREME_HILLS),
OCEAN(Biome.OCEAN),
FROZEN_OCEAN(Biome.FROZEN_OCEAN),
FROZEN_RIVER(Biome.FROZEN_RIVER),
ICE_PLAINS(Biome.ICE_PLAINS),
ICE_MOUNTAINS(Biome.ICE_MOUNTAINS),
MUSHROOM_ISLAND(Biome.MUSHROOM_ISLAND),
MUSHROOM_SHORE(Biome.MUSHROOM_SHORE),
BEACH(Biome.BEACH),
DESERT_HILLS(Biome.DESERT_HILLS),
FOREST_HILLS(Biome.FOREST_HILLS),
TAIGA_HILLS(Biome.TAIGA_HILLS),
SMALL_MOUNTAINS(Biome.SMALL_MOUNTAINS),
JUNGLE(Biome.JUNGLE),
JUNGLE_HILLS(Biome.JUNGLE_HILLS),
JUNGLE_EDGE(Biome.JUNGLE_EDGE),
DEEP_OCEAN(Biome.DEEP_OCEAN),
STONE_BEACH(Biome.STONE_BEACH),
COLD_BEACH(Biome.COLD_BEACH),
BIRCH_FOREST(Biome.BIRCH_FOREST),
BIRCH_FOREST_HILLS(Biome.BIRCH_FOREST_HILLS),
ROOFED_FOREST(Biome.ROOFED_FOREST),
COLD_TAIGA(Biome.COLD_TAIGA),
COLD_TAIGA_HILLS(Biome.COLD_TAIGA_HILLS),
MEGA_TAIGA(Biome.MEGA_TAIGA),
MEGA_TAIGA_HILLS(Biome.MEGA_TAIGA_HILLS),
EXTREME_HILLS_PLUS(Biome.EXTREME_HILLS_PLUS),
SAVANNA(Biome.SAVANNA),
SAVANNA_PLATEAU(Biome.SAVANNA_PLATEAU),
MESA(Biome.MESA),
MESA_PLATEAU_FOREST(Biome.MESA_PLATEAU_FOREST),
MESA_PLATEAU(Biome.MESA_PLATEAU),
SUNFLOWER_PLAINS(Biome.SUNFLOWER_PLAINS),
DESERT_MOUNTAINS(Biome.DESERT_MOUNTAINS),
FLOWER_FOREST(Biome.FLOWER_FOREST),
TAIGA_MOUNTAINS(Biome.TAIGA_MOUNTAINS),
SWAMPLAND_MOUNTAINS(Biome.SWAMPLAND_MOUNTAINS),
ICE_PLAINS_SPIKES(Biome.ICE_PLAINS_SPIKES),
JUNGLE_MOUNTAINS(Biome.JUNGLE_MOUNTAINS),
JUNGLE_EDGE_MOUNTAINS(Biome.JUNGLE_EDGE_MOUNTAINS),
COLD_TAIGA_MOUNTAINS(Biome.COLD_TAIGA_MOUNTAINS),
SAVANNA_MOUNTAINS(Biome.SAVANNA_MOUNTAINS),
SAVANNA_PLATEAU_MOUNTAINS(Biome.SAVANNA_PLATEAU_MOUNTAINS),
MESA_BRYCE(Biome.MESA_BRYCE),
MESA_PLATEAU_FOREST_MOUNTAINS(Biome.MESA_PLATEAU_FOREST_MOUNTAINS),
MESA_PLATEAU_MOUNTAINS(Biome.MESA_PLATEAU_MOUNTAINS),
BIRCH_FOREST_MOUNTAINS(Biome.BIRCH_FOREST_MOUNTAINS),
BIRCH_FOREST_HILLS_MOUNTAINS(Biome.BIRCH_FOREST_HILLS_MOUNTAINS),
ROOFED_FOREST_MOUNTAINS(Biome.ROOFED_FOREST_MOUNTAINS),
MEGA_SPRUCE_TAIGA(Biome.MEGA_SPRUCE_TAIGA),
EXTREME_HILLS_MOUNTAINS(Biome.EXTREME_HILLS_MOUNTAINS),
EXTREME_HILLS_PLUS_MOUNTAINS(Biome.EXTREME_HILLS_PLUS_MOUNTAINS),
MEGA_SPRUCE_TAIGA_HILLS(Biome.MEGA_SPRUCE_TAIGA_HILLS);
private Biome bukkitBiome;
private BukkitBiomeType(Biome biome) {
this.bukkitBiome = biome;
}
@Override
public String getName() {
return name().toLowerCase(Locale.ENGLISH);
}
public Biome getBukkitBiome() {
return bukkitBiome;
}
}

View File

@ -1,59 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.UnknownBiomeTypeException;
public class BukkitBiomeTypes implements BiomeTypes {
public BukkitBiomeTypes() {
}
@Override
public boolean has(String name) {
try {
BukkitBiomeType.valueOf(name.toUpperCase(Locale.ENGLISH));
return true;
} catch (IllegalArgumentException exc) {
return false;
}
}
@Override
public BiomeType get(String name) throws UnknownBiomeTypeException {
try {
return BukkitBiomeType.valueOf(name.toUpperCase(Locale.ENGLISH));
} catch (IllegalArgumentException exc) {
throw new UnknownBiomeTypeException(name);
}
}
@Override
public List<BiomeType> all() {
return Arrays.<BiomeType>asList(BukkitBiomeType.values());
}
}

View File

@ -0,0 +1,110 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.entity.metadata.Tameable;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* An adapter to adapt a Bukkit entity into a WorldEdit one.
*/
class BukkitEntity implements Entity {
private final org.bukkit.entity.Entity entity;
/**
* Create a new instance.
*
* @param entity the entity
*/
BukkitEntity(org.bukkit.entity.Entity entity) {
checkNotNull(entity);
this.entity = entity;
}
/**
* Get the underlying Bukkit entity.
*
* @return the Bukkit entity
*/
protected org.bukkit.entity.Entity getEntity() {
return entity;
}
@SuppressWarnings("unchecked")
<T> T getMetaData(Class<T> metaDataClass) {
if (metaDataClass == Tameable.class && getEntity() instanceof org.bukkit.entity.Tameable) {
return (T) new TameableAdapter((org.bukkit.entity.Tameable) getEntity());
} else {
return null;
}
}
@Override
public Extent getExtent() {
return BukkitAdapter.adapt(getEntity().getWorld());
}
@Override
public Location getLocation() {
return BukkitAdapter.adapt(getEntity().getLocation());
}
@Override
public BaseEntity getState() {
if (entity instanceof Player) {
return null;
}
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) {
return adapter.getEntity(entity);
} else {
return null;
}
}
@Override
public boolean remove() {
entity.remove();
return entity.isDead();
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
if (EntityType.class.isAssignableFrom(cls)) {
return (T) new BukkitEntityType(entity);
} else {
return null;
}
}
}

View File

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

View File

@ -19,22 +19,23 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.util.Vectors;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.sk89q.util.StringUtil; import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface; import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.internal.cui.CUIEvent;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
public class BukkitPlayer extends LocalPlayer { public class BukkitPlayer extends LocalPlayer {
private Player player; private Player player;
@ -170,11 +171,25 @@ public class BukkitPlayer extends LocalPlayer {
player.setFlying(true); player.setFlying(true);
} }
@Override
public BaseEntity getState() {
throw new UnsupportedOperationException("Cannot create a state from this object");
}
@Override @Override
public com.sk89q.worldedit.util.Location getLocation() { public com.sk89q.worldedit.util.Location getLocation() {
Location nativeLocation = player.getLocation(); Location nativeLocation = player.getLocation();
Vector position = BukkitUtil.toVector(nativeLocation); Vector position = BukkitUtil.toVector(nativeLocation);
Vector direction = Vectors.fromEulerDeg(nativeLocation.getYaw(), nativeLocation.getPitch()); return new com.sk89q.worldedit.util.Location(
return new com.sk89q.worldedit.util.Location(getWorld(), position, direction); getWorld(),
position,
nativeLocation.getYaw(),
nativeLocation.getPitch());
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
} }
} }

View File

@ -21,7 +21,6 @@ package com.sk89q.worldedit.bukkit;
import com.sk89q.bukkit.util.CommandInfo; import com.sk89q.bukkit.util.CommandInfo;
import com.sk89q.bukkit.util.CommandRegistration; import com.sk89q.bukkit.util.CommandRegistration;
import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface; import com.sk89q.worldedit.ServerInterface;
@ -50,13 +49,13 @@ public class BukkitServerInterface extends ServerInterface implements MultiUserP
public Server server; public Server server;
public WorldEditPlugin plugin; public WorldEditPlugin plugin;
private CommandRegistration dynamicCommands; private CommandRegistration dynamicCommands;
private BukkitBiomeTypes biomes; private BukkitBiomeRegistry biomes;
private boolean hookingEvents; private boolean hookingEvents;
public BukkitServerInterface(WorldEditPlugin plugin, Server server) { public BukkitServerInterface(WorldEditPlugin plugin, Server server) {
this.plugin = plugin; this.plugin = plugin;
this.server = server; this.server = server;
this.biomes = new BukkitBiomeTypes(); this.biomes = new BukkitBiomeRegistry();
dynamicCommands = new CommandRegistration(plugin); dynamicCommands = new CommandRegistration(plugin);
} }
@ -81,11 +80,6 @@ public class BukkitServerInterface extends ServerInterface implements MultiUserP
plugin.loadConfiguration(); plugin.loadConfiguration();
} }
@Override
public BiomeTypes getBiomes() {
return biomes;
}
@Override @Override
public int schedule(long delay, long period, Runnable task) { public int schedule(long delay, long period, Runnable task) {
return Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, task, delay, period); return Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, task, delay, period);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import com.sk89q.worldedit.world.registry.LegacyWorldData;
/**
* World data for the Bukkit platform.
*/
class BukkitWorldData extends LegacyWorldData {
private static final BukkitWorldData INSTANCE = new BukkitWorldData();
private final BiomeRegistry biomeRegistry = new BukkitBiomeRegistry();
/**
* Create a new instance.
*/
BukkitWorldData() {
}
@Override
public BiomeRegistry getBiomeRegistry() {
return biomeRegistry;
}
/**
* Get a static instance.
*
* @return an instance
*/
public static BukkitWorldData getInstance() {
return INSTANCE;
}
}

View File

@ -1,472 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.foundation.Block;
import net.minecraft.server.v1_7_R3.*;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_7_R3.CraftWorld;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Logger;
/**
* A blind handler of blocks with TileEntity data that directly access Minecraft's
* classes through CraftBukkit.
* </p>
* Usage of this class may break terribly in the future, and therefore usage should
* be trapped in a handler for {@link Throwable}.
*/
public class DefaultNmsBlock extends NmsBlock {
private static final Logger logger = WorldEdit.logger;
private static Field compoundMapField;
private static final Field nmsBlock_isTileEntityField; // The field is deobfuscated but the method isn't. No idea why.
private NBTTagCompound nbtData = null;
static {
Field field;
try {
field = net.minecraft.server.v1_7_R3.Block.class.getDeclaredField("isTileEntity");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
// logger.severe("Could not find NMS block tile entity field!");
field = null;
}
nmsBlock_isTileEntityField = field;
}
public static boolean verify() {
return nmsBlock_isTileEntityField != null;
}
/**
* Create a new instance with a given type ID, data value, and previous
* {@link TileEntityBlock}-implementing object.
*
* @param type block type ID
* @param data data value
* @param tileEntityBlock tile entity block
*/
public DefaultNmsBlock(int type, int data, TileEntityBlock tileEntityBlock) {
super(type, data);
nbtData = (NBTTagCompound) fromNative(tileEntityBlock.getNbtData());
}
/**
* Create a new instance with a given type ID, data value, and raw
* {@link NBTTagCompound} copy.
*
* @param type block type ID
* @param data data value
* @param nbtData raw NBT data
*/
public DefaultNmsBlock(int type, int data, NBTTagCompound nbtData) {
super(type, data);
this.nbtData = nbtData;
}
/**
* Build a {@link NBTTagCompound} that has valid coordinates.
*
* @param pt coordinates to set
* @return the tag compound
*/
private NBTTagCompound getNmsData(Vector pt) {
if (nbtData == null) {
return null;
}
nbtData.set("x", new NBTTagInt(pt.getBlockX()));
nbtData.set("y", new NBTTagInt(pt.getBlockY()));
nbtData.set("z", new NBTTagInt(pt.getBlockZ()));
return nbtData;
}
@Override
public boolean hasNbtData() {
return nbtData != null;
}
@Override
public String getNbtId() {
if (nbtData == null) {
return "";
}
return nbtData.getString("id");
}
@Override
public CompoundTag getNbtData() {
if (nbtData == null) {
return new CompoundTag(getNbtId(),
new HashMap<String, Tag>());
}
return (CompoundTag) toNative(nbtData);
}
@Override
public void setNbtData(CompoundTag tag) throws DataException {
if (tag == null) {
this.nbtData = null;
}
this.nbtData = (NBTTagCompound) fromNative(tag);
}
/**
* Build an instance from the given information.
*
* @param world world to get the block from
* @param position position to get the block at
* @param type type ID of block
* @param data data value of block
* @return the block, or null
*/
public static DefaultNmsBlock get(World world, Vector position, int type, int data) {
if (!hasTileEntity(type)) {
return null;
}
TileEntity te = ((CraftWorld) world).getHandle().getTileEntity(
position.getBlockX(), position.getBlockY(), position.getBlockZ());
if (te != null) {
NBTTagCompound tag = new NBTTagCompound();
te.b(tag); // Load data
return new DefaultNmsBlock(type, data, tag);
}
return null;
}
/**
* Set an instance or a {@link TileEntityBlock} to the given position.
*
* @param world world to set the block in
* @param position position to set the block at
* @param block the block to set
* @return true if tile entity data was copied to the world
*/
public static boolean set(World world, Vector position, BaseBlock block) {
NBTTagCompound data = null;
if (!hasTileEntity(world.getBlockTypeIdAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()))) {
return false;
}
if (block instanceof DefaultNmsBlock) {
DefaultNmsBlock nmsProxyBlock = (DefaultNmsBlock) block;
data = nmsProxyBlock.getNmsData(position);
} else if (block instanceof TileEntityBlock) {
DefaultNmsBlock nmsProxyBlock = new DefaultNmsBlock(
block.getId(), block.getData(), block);
data = nmsProxyBlock.getNmsData(position);
}
if (data != null) {
TileEntity te = ((CraftWorld) world).getHandle().getTileEntity(
position.getBlockX(), position.getBlockY(), position.getBlockZ());
if (te != null) {
te.a(data); // Load data
return true;
}
}
return false;
}
/**
* Tries to set a block 'safely', as in setting the block data to the location, and
* then triggering physics only at the end.
*
* @param world world to set the block in
* @param position position to set the block at
* @param block the block to set
* @param notifyAdjacent true to notify physics and what not
* @return true if block id or data was changed
*/
public static boolean setSafely(BukkitWorld world, Vector position,
Block block, boolean notifyAdjacent) {
int x = position.getBlockX();
int y = position.getBlockY();
int z = position.getBlockZ();
CraftWorld craftWorld = ((CraftWorld) world.getWorld());
// TileEntity te = craftWorld.getHandle().getTileEntity(x, y, z);
// craftWorld.getHandle().tileEntityList.remove(te);
boolean changed = craftWorld.getHandle().setTypeAndData(x, y, z, getNmsBlock(block.getId()), block.getData(), 0);
if (block instanceof BaseBlock) {
world.copyToWorld(position, (BaseBlock) block);
}
changed = craftWorld.getHandle().setData(x, y, z, block.getData(), 0) || changed;
if (changed && notifyAdjacent) {
craftWorld.getHandle().notify(x, y, z);
craftWorld.getHandle().update(x, y, z, getNmsBlock(block.getId()));
}
return changed;
}
public static boolean hasTileEntity(int type) {
net.minecraft.server.v1_7_R3.Block nmsBlock = getNmsBlock(type);
if (nmsBlock == null) {
return false;
}
try {
return nmsBlock_isTileEntityField.getBoolean(nmsBlock); // Once we have the field stord, gets are fast
} catch (IllegalAccessException e) {
return false;
}
}
public static net.minecraft.server.v1_7_R3.Block getNmsBlock(int type) {
return net.minecraft.server.v1_7_R3.Block.e(type);
}
/**
* Converts from a non-native NMS NBT structure to a native WorldEdit NBT
* structure.
*
* @param foreign non-native NMS NBT structure
* @return native WorldEdit NBT structure
*/
private static Tag toNative(NBTBase foreign) {
// temporary fix since mojang removed names from tags
// our nbt spec will need to be updated to theirs
return toNative(getTagName(foreign.getTypeId()), foreign);
}
// seriously these two methods are hacky - our jnbt spec needs updating
// copied from NMS 1.7.5- code, since it was removed in 1.7.8
private static String getTagName(int i) {
switch (i) {
case 0:
return "TAG_End";
case 1:
return "TAG_Byte";
case 2:
return "TAG_Short";
case 3:
return "TAG_Int";
case 4:
return "TAG_Long";
case 5:
return "TAG_Float";
case 6:
return "TAG_Double";
case 7:
return "TAG_Byte_Array";
case 8:
return "TAG_String";
case 9:
return "TAG_List";
case 10:
return "TAG_Compound";
case 11:
return "TAG_Int_Array";
case 99:
return "Any Numeric Tag";
default:
return "UNKNOWN";
}
}
/**
* Converts from a non-native NMS NBT structure to a native WorldEdit NBT
* structure.
*
* @param foreign non-native NMS NBT structure
* @param name name for the tag, if it has one
* @return native WorldEdit NBT structure
*/
@SuppressWarnings("unchecked")
private static Tag toNative(String name, NBTBase foreign) {
if (foreign == null) {
return null;
}
if (foreign instanceof NBTTagCompound) {
Map<String, Tag> values = new HashMap<String, Tag>();
Collection<Object> foreignKeys = null;
if (compoundMapField == null) {
try {
// Method name may change!
foreignKeys = ((NBTTagCompound) foreign).c();
} catch (Throwable t) {
try {
logger.warning("WorldEdit: Couldn't get NBTTagCompound.c(), " +
"so we're going to try to get at the 'map' field directly from now on");
if (compoundMapField == null) {
compoundMapField = NBTTagCompound.class.getDeclaredField("map");
compoundMapField.setAccessible(true);
}
} catch (Throwable e) {
// Can't do much beyond this
throw new RuntimeException(e);
}
}
}
if (compoundMapField != null) {
try {
foreignKeys = ((HashMap<Object, Object>) compoundMapField.get(foreign)).keySet();
} catch (Throwable e) {
// Can't do much beyond this
throw new RuntimeException(e);
}
}
for (Object obj : foreignKeys) {
String key = (String) obj;
NBTBase base = (NBTBase) ((NBTTagCompound) foreign).get(key);
values.put(key, toNative(key, base));
}
return new CompoundTag(name, values);
} else if (foreign instanceof NBTTagByte) {
return new ByteTag(name, ((NBTTagByte) foreign).f()); // getByte
} else if (foreign instanceof NBTTagByteArray) {
return new ByteArrayTag(name,
((NBTTagByteArray) foreign).c()); // data
} else if (foreign instanceof NBTTagDouble) {
return new DoubleTag(name,
((NBTTagDouble) foreign).g()); // getDouble
} else if (foreign instanceof NBTTagFloat) {
return new FloatTag(name, ((NBTTagFloat) foreign).h()); // getFloat
} else if (foreign instanceof NBTTagInt) {
return new IntTag(name, ((NBTTagInt) foreign).d()); // getInt
} else if (foreign instanceof NBTTagIntArray) {
return new IntArrayTag(name,
((NBTTagIntArray) foreign).c()); // data
} else if (foreign instanceof NBTTagList) {
try {
return transmorgifyList(name, (NBTTagList) foreign);
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {}
return new ListTag(name, ByteTag.class, new ArrayList<ByteTag>());
} else if (foreign instanceof NBTTagLong) {
return new LongTag(name, ((NBTTagLong) foreign).c()); // getLong
} else if (foreign instanceof NBTTagShort) {
return new ShortTag(name, ((NBTTagShort) foreign).e()); // getShort
} else if (foreign instanceof NBTTagString) {
return new StringTag(name,
((NBTTagString) foreign).a_()); // data
} else if (foreign instanceof NBTTagEnd) {
return new EndTag();
} else {
throw new IllegalArgumentException("Don't know how to make native "
+ foreign.getClass().getCanonicalName());
}
}
private static ListTag transmorgifyList(String name, NBTTagList foreign)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
List<Tag> values = new ArrayList<Tag>();
int type = foreign.d();
Field listField = NBTTagList.class.getDeclaredField("list");
listField.setAccessible(true);
List foreignList;
foreignList = (List) listField.get(foreign);
for (int i = 0; i < foreign.size(); i++) {
NBTBase element = (NBTBase) foreignList.get(i);
values.add(toNative(null, element)); // list elements shouldn't have names
}
Class<? extends Tag> cls = NBTConstants.getClassFromType(type);
return new ListTag(name, cls, values);
}
/**
* Converts a WorldEdit-native NBT structure to a NMS structure.
*
* @param foreign structure to convert
* @return non-native structure
*/
private static NBTBase fromNative(Tag foreign) {
if (foreign == null) {
return null;
}
if (foreign instanceof CompoundTag) {
NBTTagCompound tag = new NBTTagCompound();
for (Map.Entry<String, Tag> entry : ((CompoundTag) foreign)
.getValue().entrySet()) {
tag.set(entry.getKey(), fromNative(entry.getValue()));
}
return tag;
} else if (foreign instanceof ByteTag) {
return new NBTTagByte(((ByteTag) foreign).getValue());
} else if (foreign instanceof ByteArrayTag) {
return new NBTTagByteArray(((ByteArrayTag) foreign).getValue());
} else if (foreign instanceof DoubleTag) {
return new NBTTagDouble(((DoubleTag) foreign).getValue());
} else if (foreign instanceof FloatTag) {
return new NBTTagFloat(((FloatTag) foreign).getValue());
} else if (foreign instanceof IntTag) {
return new NBTTagInt(((IntTag) foreign).getValue());
} else if (foreign instanceof IntArrayTag) {
return new NBTTagIntArray(((IntArrayTag) foreign).getValue());
} else if (foreign instanceof ListTag) {
NBTTagList tag = new NBTTagList();
ListTag foreignList = (ListTag) foreign;
for (Tag t : foreignList.getValue()) {
tag.add(fromNative(t));
}
return tag;
} else if (foreign instanceof LongTag) {
return new NBTTagLong(((LongTag) foreign).getValue());
} else if (foreign instanceof ShortTag) {
return new NBTTagShort(((ShortTag) foreign).getValue());
} else if (foreign instanceof StringTag) {
return new NBTTagString(((StringTag) foreign).getValue());
} else if (foreign instanceof EndTag) {
try {
Method tagMaker = NBTBase.class.getDeclaredMethod("createTag", byte.class);
tagMaker.setAccessible(true);
return (NBTBase) tagMaker.invoke(null, (byte) 0);
} catch (Exception e) {
return null;
}
} else {
throw new IllegalArgumentException("Don't know how to make NMS "
+ foreign.getClass().getCanonicalName());
}
}
public static boolean isValidBlockType(int type) throws NoClassDefFoundError {
return type == 0 || (type >= 1 && net.minecraft.server.v1_7_R3.Block.e(type) != null);
}
}

View File

@ -1,61 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import org.bukkit.World;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.foundation.Block;
public abstract class NmsBlock extends BaseBlock {
protected NmsBlock(int type) {
super(type);
}
protected NmsBlock(int type, int data) {
super(type, data);
}
public static boolean verify() {
return false;
}
public static NmsBlock get(World world, Vector vector, int type, int data) {
return null;
}
public static boolean set(World world, Vector vector, Block block) {
return false;
}
public static boolean setSafely(World world, Vector vector, Block block, boolean notify) {
return false;
}
public static boolean hasTileEntity(int type) {
return false;
}
public static boolean isValidBlockType(int type) {
return false;
}
}

View File

@ -0,0 +1,40 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.entity.metadata.Tameable;
import com.sk89q.worldedit.internal.util.AbstractAdapter;
/**
* Adapts a Bukkit {@link org.bukkit.entity.Tameable} into a WorldEdit
* equivalent.
*/
public class TameableAdapter extends AbstractAdapter<org.bukkit.entity.Tameable> implements Tameable {
TameableAdapter(org.bukkit.entity.Tameable entity) {
super(entity);
}
@Override
public boolean isTamed() {
return getHandle().isTamed();
}
}

View File

@ -22,7 +22,16 @@ package com.sk89q.worldedit.bukkit;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.sk89q.util.yaml.YAMLProcessor; import com.sk89q.util.yaml.YAMLProcessor;
import com.sk89q.wepif.PermissionsResolverManager; import com.sk89q.wepif.PermissionsResolverManager;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditOperation;
import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader;
import com.sk89q.worldedit.bukkit.selections.CuboidSelection; import com.sk89q.worldedit.bukkit.selections.CuboidSelection;
import com.sk89q.worldedit.bukkit.selections.CylinderSelection; import com.sk89q.worldedit.bukkit.selections.CylinderSelection;
import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection; import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection;
@ -32,7 +41,11 @@ import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.regions.*; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -40,13 +53,20 @@ import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.*; import javax.annotation.Nullable;
import java.util.Enumeration; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Plugin for Bukkit. * Plugin for Bukkit.
* *
@ -54,27 +74,13 @@ import java.util.zip.ZipEntry;
*/ */
public class WorldEditPlugin extends JavaPlugin implements TabCompleter { public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
/** private static final Logger log = Logger.getLogger(WorldEditPlugin.class.getCanonicalName());
* The name of the CUI's plugin channel registration
*/
public static final String CUI_PLUGIN_CHANNEL = "WECUI"; public static final String CUI_PLUGIN_CHANNEL = "WECUI";
private static WorldEditPlugin INSTANCE;
/** private BukkitImplAdapter bukkitAdapter;
* The server interface that all server-related API goes through.
*/
private BukkitServerInterface server; private BukkitServerInterface server;
/** private final WorldEditAPI api = new WorldEditAPI(this);
* Main WorldEdit instance.
*/
private WorldEdit controller;
/**
* Deprecated API.
*/
private WorldEditAPI api;
/**
* Holds the configuration for WorldEdit.
*/
private BukkitConfiguration config; private BukkitConfiguration config;
/** /**
@ -82,41 +88,27 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/ */
@Override @Override
public void onEnable() { public void onEnable() {
final String pluginYmlVersion = getDescription().getVersion(); this.INSTANCE = this;
final String manifestVersion = WorldEdit.getVersion();
if (!manifestVersion.equalsIgnoreCase(pluginYmlVersion)) { WorldEdit worldEdit = WorldEdit.getInstance();
WorldEdit.setVersion(manifestVersion + " (" + pluginYmlVersion + ")");
}
// Make the data folders that WorldEdit uses loadAdapter(); // Need an adapter to work with special blocks with NBT data
getDataFolder().mkdirs(); loadConfig(); // Load configuration
File targetDir = new File(getDataFolder() + File.separator + "nmsblocks"); PermissionsResolverManager.initialize(this); // Setup permission resolver
targetDir.mkdir();
copyNmsBlockClasses(targetDir);
// Create the default configuration file // Setup platform
createDefaultConfiguration("config.yml");
// Set up configuration and such, including the permissions
// resolver
config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config.yml"), true), this);
PermissionsResolverManager.initialize(this);
// Load the configuration
config.load();
// Setup interfaces
server = new BukkitServerInterface(this, getServer()); server = new BukkitServerInterface(this, getServer());
controller = WorldEdit.getInstance(); worldEdit.getPlatformManager().register(server);
controller.getPlatformManager().register(server);
api = new WorldEditAPI(this); // Register CUI
getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this)); getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL); getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL);
// Now we can register events!
// Now we can register events
getServer().getPluginManager().registerEvents(new WorldEditListener(this), this); getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
getServer().getScheduler().runTaskTimerAsynchronously(this, new SessionTimer(controller, getServer()), 120, 120); // Register session timer
getServer().getScheduler().runTaskTimerAsynchronously(this, new SessionTimer(worldEdit, getServer()), 120, 120);
// If we are on MCPC+/Cauldron, then Forge will have already loaded // If we are on MCPC+/Cauldron, then Forge will have already loaded
// Forge WorldEdit and there's (probably) not going to be any other // Forge WorldEdit and there's (probably) not going to be any other
@ -124,31 +116,34 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent()); WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
} }
private void copyNmsBlockClasses(File target) { private void loadConfig() {
createDefaultConfiguration("config.yml"); // Create the default configuration file
config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config.yml"), true), this);
config.load();
}
private void loadAdapter() {
// Attempt to load a Bukkit adapter
BukkitImplLoader adapterLoader = new BukkitImplLoader();
try { try {
JarFile jar = new JarFile(getFile()); adapterLoader.addFromPath(getClass().getClassLoader());
@SuppressWarnings("rawtypes") } catch (IOException e) {
Enumeration entries = jar.entries(); log.log(Level.WARNING, "Failed to search path for Bukkit adapters");
while (entries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) entries.nextElement();
if (!jarEntry.getName().startsWith("nmsblocks") || jarEntry.isDirectory()) continue;
File file = new File(target + File.separator + jarEntry.getName().replace("nmsblocks", ""));
if (file.exists()) continue;
InputStream is = jar.getInputStream(jarEntry);
FileOutputStream fos = new FileOutputStream(file);
fos = new FileOutputStream(file);
byte[] buf = new byte[8192];
int length = 0;
while ((length = is.read(buf)) > 0) {
fos.write(buf, 0, length);
} }
fos.close();
is.close(); try {
adapterLoader.addFromJar(getFile());
} catch (IOException e) {
log.log(Level.WARNING, "Failed to search " + getFile() + " for Bukkit adapters", e);
}
try {
bukkitAdapter = adapterLoader.loadAdapter();
log.log(Level.INFO, "Using " + bukkitAdapter.getClass().getCanonicalName() + " as the Bukkit adapter");
} catch (AdapterLoadException e) {
log.log(Level.WARNING, e.getMessage());
} }
} catch (Throwable e) {}
} }
/** /**
@ -156,10 +151,13 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/ */
@Override @Override
public void onDisable() { public void onDisable() {
if (controller != null) { WorldEdit worldEdit = WorldEdit.getInstance();
controller.clearSessions(); worldEdit.clearSessions();
controller.getPlatformManager().unregister(server); worldEdit.getPlatformManager().unregister(server);
if (config != null) {
config.unload(); config.unload();
}
if (server != null) {
server.unregisterCommands(); server.unregisterCommands();
} }
this.getServer().getScheduler().cancelTasks(this); this.getServer().getScheduler().cancelTasks(this);
@ -177,7 +175,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
/** /**
* Create a default configuration file from the .jar. * Create a default configuration file from the .jar.
* *
* @param name * @param name the filename
*/ */
protected void createDefaultConfiguration(String name) { protected void createDefaultConfiguration(String name) {
File actual = new File(getDataFolder(), name); File actual = new File(getDataFolder(), name);
@ -257,7 +255,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
* @return * @return
*/ */
public LocalSession getSession(Player player) { public LocalSession getSession(Player player) {
return controller.getSession(wrapPlayer(player)); return WorldEdit.getInstance().getSession(wrapPlayer(player));
} }
/** /**
@ -268,10 +266,10 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/ */
public EditSession createEditSession(Player player) { public EditSession createEditSession(Player player) {
LocalPlayer wePlayer = wrapPlayer(player); LocalPlayer wePlayer = wrapPlayer(player);
LocalSession session = controller.getSession(wePlayer); LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
BlockBag blockBag = session.getBlockBag(wePlayer); BlockBag blockBag = session.getBlockBag(wePlayer);
EditSession editSession = controller.getEditSessionFactory() EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer); .getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer);
editSession.enableQueue(); editSession.enableQueue();
@ -286,12 +284,12 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/ */
public void remember(Player player, EditSession editSession) { public void remember(Player player, EditSession editSession) {
LocalPlayer wePlayer = wrapPlayer(player); LocalPlayer wePlayer = wrapPlayer(player);
LocalSession session = controller.getSession(wePlayer); LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
session.remember(editSession); session.remember(editSession);
editSession.flushQueue(); editSession.flushQueue();
controller.flushBlockBag(wePlayer, editSession); WorldEdit.getInstance().flushBlockBag(wePlayer, editSession);
} }
/** /**
@ -301,10 +299,9 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
* @param op * @param op
* @throws Throwable * @throws Throwable
*/ */
public void perform(Player player, WorldEditOperation op) public void perform(Player player, WorldEditOperation op) throws Throwable {
throws Throwable {
LocalPlayer wePlayer = wrapPlayer(player); LocalPlayer wePlayer = wrapPlayer(player);
LocalSession session = controller.getSession(wePlayer); LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
EditSession editSession = createEditSession(player); EditSession editSession = createEditSession(player);
try { try {
@ -379,7 +376,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
* @return * @return
*/ */
public WorldEdit getWorldEdit() { public WorldEdit getWorldEdit() {
return controller; return WorldEdit.getInstance();
} }
/** /**
@ -396,7 +393,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
throw new IllegalArgumentException("Offline player not allowed"); throw new IllegalArgumentException("Offline player not allowed");
} }
LocalSession session = controller.getSession(wrapPlayer(player)); LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
RegionSelector selector = session.getRegionSelector(BukkitUtil.getLocalWorld(player.getWorld())); RegionSelector selector = session.getRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()));
try { try {
@ -434,9 +431,30 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
throw new IllegalArgumentException("Null selection not allowed"); throw new IllegalArgumentException("Null selection not allowed");
} }
LocalSession session = controller.getSession(wrapPlayer(player)); LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
RegionSelector sel = selection.getRegionSelector(); RegionSelector sel = selection.getRegionSelector();
session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel); session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel);
session.dispatchCUISelection(wrapPlayer(player)); session.dispatchCUISelection(wrapPlayer(player));
} }
/**
* Gets the instance of this plugin.
*
* @return an instance of the plugin
* @throws NullPointerException if the plugin hasn't been enabled
*/
static WorldEditPlugin getInstance() {
return checkNotNull(INSTANCE);
}
/**
* Get the Bukkit implementation adapter.
*
* @return the adapter
*/
@Nullable
BukkitImplAdapter getBukkitImplAdapter() {
return bukkitAdapter;
}
} }

View File

@ -0,0 +1,41 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter;
/**
* Thrown when no adapter can be found.
*/
public class AdapterLoadException extends Exception {
public AdapterLoadException() {
}
public AdapterLoadException(String message) {
super(message);
}
public AdapterLoadException(String message, Throwable cause) {
super(message, cause);
}
public AdapterLoadException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,114 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.entity.Entity;
import javax.annotation.Nullable;
/**
* An interface for adapters of various Bukkit implementations.
*/
public interface BukkitImplAdapter {
/**
* Get the block ID for the given material.
*
* <p>Returns 0 if it is not known or it doesn't exist.</p>
*
* @param material the material
* @return the block ID
*/
int getBlockId(Material material);
/**
* Get the material for the given block ID.
*
* <p>Returns {@link Material#AIR} if it is not known or it doesn't exist.</p>
*
* @param id the block ID
* @return the material
*/
Material getMaterial(int id);
/**
* Get the biome ID for the given biome.
*
* <p>Returns 0 if it is not known or it doesn't exist.</p>
*
* @param biome biome
* @return the biome ID
*/
int getBiomeId(Biome biome);
/**
* Get the biome ID for the given biome ID..
*
* <p>Returns {@link Biome#OCEAN} if it is not known or it doesn't exist.</p>
*
* @param id the biome ID
* @return the biome
*/
Biome getBiome(int id);
/**
* Get the block at the given location.
*
* @param location the location
* @return the block
*/
BaseBlock getBlock(Location location);
/**
* Set the block at the given location.
*
* @param location the location
* @param state the block
* @param notifyAndLight notify and light if set
* @return true if a block was likely changed
*/
boolean setBlock(Location location, BaseBlock state, boolean notifyAndLight);
/**
* Get the state for the given entity.
*
* @param entity the entity
* @return the state, or null
*/
@Nullable
BaseEntity getEntity(Entity entity);
/**
* Create the given entity.
*
* @param location the location
* @param state the state
* @return the created entity or null
*/
@Nullable
Entity createEntity(Location location, BaseEntity state);
}

View File

@ -0,0 +1,197 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.util.io.Closer;
import org.bukkit.Bukkit;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Loads Bukkit implementation adapters.
*/
public class BukkitImplLoader {
private static final Logger log = Logger.getLogger(BukkitImplLoader.class.getCanonicalName());
private final List<String> adapterCandidates = new ArrayList<String>();
private String customCandidate;
private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.bukkit.adapter.impl";
private static final String SEARCH_PACKAGE_DOT = SEARCH_PACKAGE + ".";
private static final String SEARCH_PATH = SEARCH_PACKAGE.replace(".", "/");
private static final String CLASS_SUFFIX = ".class";
private static final String LOAD_ERROR_MESSAGE =
"Failed to find an adapter for Bukkit!\n\n" +
"This version of WorldEdit (%s) does not fully support your version of Bukkit (%s).\n\n" +
"What this means:\n" +
"1) Block operations will work, but chests will be empty, signs will be blank, and so on.\n" +
"2) You won't be able to save and load chests, signs, etc. with .schematic files.\n" +
"3) You won't be able to work with entities properly.\n" +
"4) Undo will will not be able to restore chests, signs, and etc.\n\n" +
"Possible solutions:\n" +
"1) If this is a new version of Minecraft, please wait for us to update. " +
"You can also put in a ticket at http://youtrack.sk89q.com (check for an existing ticket first).\n" +
"2) If you are using an older version of Minecraft, you may need to downgrade WorldEdit.\n" +
"3) If you are using an older version of WorldEdit, you may need to update your WorldEdit.\n" +
"4) If you are not using CraftBukkit, then report this issue to http://youtrack.sk89q.com " +
"(check for an existing ticket first).\n" +
"5) If you are developing WorldEdit, you can force an adapter with " +
"-Dworldedit.bukkit.adapter=the_class_name.\n\n" +
"Can I ignore this error? Yes! Just be aware of the undo issue.\n" +
"Am I using CraftBukkit? %s.\n";
/**
* Create a new instance.
*/
public BukkitImplLoader() {
addDefaults();
}
/**
* Add default candidates, such as any defined with
* {@code -Dworldedit.bukkit.adapter}.
*/
private void addDefaults() {
String className = System.getProperty("worldedit.bukkit.adapter");
if (className != null) {
customCandidate = className;
adapterCandidates.add(className);
log.log(Level.INFO, "-Dworldedit.bukkit.adapter used to add " + className + " to the list of available Bukkit adapters");
}
}
/**
* Search the given JAR for candidate implementations.
*
* @param file the file
* @throws IOException thrown on I/O error
*/
public void addFromJar(File file) throws IOException {
Closer closer = Closer.create();
JarFile jar = closer.register(new JarFile(file));
try {
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) entries.nextElement();
String className = jarEntry.getName().replaceAll("[/\\\\]+", ".");
if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory()) continue;
int beginIndex = 0;
int endIndex = className.length() - CLASS_SUFFIX.length();
className = className.substring(beginIndex, endIndex);
adapterCandidates.add(className);
}
} finally {
closer.close();
}
}
/**
* Search for classes stored as separate files available via the given
* class loader.
*
* @param classLoader the class loader
* @throws IOException thrown on error
*/
public void addFromPath(ClassLoader classLoader) throws IOException {
Enumeration<URL> resources = classLoader.getResources(SEARCH_PATH);
while (resources.hasMoreElements()) {
File file = new File(resources.nextElement().getFile());
addFromPath(file);
}
}
/**
* Search for classes stored as separate files available via the given
* path.
*
* @param file the path
*/
private void addFromPath(File file) {
String resource = SEARCH_PACKAGE_DOT + file.getName();
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File child : files) {
addFromPath(child);
}
}
} else if (resource.endsWith(CLASS_SUFFIX)) {
int beginIndex = 0;
int endIndex = resource.length() - CLASS_SUFFIX.length();
String className = resource.substring(beginIndex, endIndex);
adapterCandidates.add(className);
}
}
/**
* Iterate through the list of candidates and load an adapter.
*
* @return an adapter
* @throws AdapterLoadException thrown if no adapter could be found
*/
public BukkitImplAdapter loadAdapter() throws AdapterLoadException {
for (String className : adapterCandidates) {
try {
Class<?> cls = Class.forName(className);
if (BukkitImplAdapter.class.isAssignableFrom(cls)) {
return (BukkitImplAdapter) cls.newInstance();
} else {
log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className +
"' because it does not implement " + BukkitImplAdapter.class.getCanonicalName());
}
} catch (ClassNotFoundException e) {
log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className +
"' that is not supposed to be missing", e);
} catch (IllegalAccessException e) {
log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className +
"' that is not supposed to be raising this error", e);
} catch (Throwable e) {
if (className.equals(customCandidate)) {
log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + "'", e);
}
}
}
String weVersion = WorldEdit.getVersion();
String bukkitVersion = Bukkit.getBukkitVersion() + " implemented by " + Bukkit.getName() + " " + Bukkit.getVersion();
String usingCraftBukkit =
Bukkit.getName().equals("CraftBukkit")
? "Probably (if you got it from dl.bukkit.org, then yes)"
: "No! You are using " + Bukkit.getName();
throw new AdapterLoadException(
String.format(LOAD_ERROR_MESSAGE, weVersion, bukkitVersion, usingCraftBukkit));
}
}

View File

@ -19,18 +19,21 @@
package com.sk89q.worldedit.forge; package com.sk89q.worldedit.forge;
import net.minecraft.world.biome.BiomeGenBase; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.world.World;
import net.minecraft.util.Vec3;
import com.sk89q.worldedit.BiomeType; final class ForgeAdapter {
public class ForgeBiomeType implements BiomeType { private ForgeAdapter() {
private BiomeGenBase biome;
public ForgeBiomeType(BiomeGenBase biome) {
this.biome = biome;
} }
public String getName() { public static World adapt(net.minecraft.world.World world) {
return this.biome.biomeName; return new ForgeWorld(world);
} }
public static Vector adapt(Vec3 vector) {
return new Vector(vector.xCoord, vector.yCoord, vector.zCoord);
}
} }

View File

@ -0,0 +1,107 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import com.google.common.collect.HashBiMap;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.biome.BiomeData;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import net.minecraft.world.biome.BiomeGenBase;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Provides access to biome data in Forge.
*/
class ForgeBiomeRegistry implements BiomeRegistry {
private static Map<Integer, BiomeGenBase> biomes = Collections.emptyMap();
private static Map<Integer, BiomeData> biomeData = Collections.emptyMap();
@Nullable
@Override
public BaseBiome createFromId(int id) {
return new BaseBiome(id);
}
@Override
public List<BaseBiome> getBiomes() {
List<BaseBiome> list = new ArrayList<BaseBiome>();
for (int biome : biomes.keySet()) {
list.add(new BaseBiome(biome));
}
return list;
}
@Nullable
@Override
public BiomeData getData(BaseBiome biome) {
return biomeData.get(biome.getId());
}
/**
* Populate the internal static list of biomes.
*
* <p>If called repeatedly, the last call will overwrite all previous
* calls.</p>
*/
static void populate() {
Map<Integer, BiomeGenBase> biomes = HashBiMap.create();
Map<Integer, BiomeData> biomeData = new HashMap<Integer, BiomeData>();
for (BiomeGenBase biome : BiomeGenBase.biomeList) {
if ((biome == null) || (biomes.containsValue(biome))) {
continue;
}
biomes.put(biome.biomeID, biome);
biomeData.put(biome.biomeID, new ForgeBiomeData(biome));
}
ForgeBiomeRegistry.biomes = biomes;
ForgeBiomeRegistry.biomeData = biomeData;
}
/**
* Cached biome data information.
*/
private static class ForgeBiomeData implements BiomeData {
private final BiomeGenBase biome;
/**
* Create a new instance.
*
* @param biome the base biome
*/
private ForgeBiomeData(BiomeGenBase biome) {
this.biome = biome;
}
@Override
public String getName() {
return biome.biomeName;
}
}
}

View File

@ -1,87 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import net.minecraft.world.biome.BiomeGenBase;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.UnknownBiomeTypeException;
public class ForgeBiomeTypes implements BiomeTypes {
private static BiMap<BiomeType, BiomeGenBase> biomes = HashBiMap.create();
public ForgeBiomeTypes() {
all();
}
public boolean has(String name) {
for (BiomeGenBase biome : BiomeGenBase.biomeList) {
if ((biome != null) && (biome.biomeName.equalsIgnoreCase(name))) {
return true;
}
}
return false;
}
public BiomeType get(String name) throws UnknownBiomeTypeException {
if (biomes == null) {
all();
}
Iterator<BiomeType> it = biomes.keySet().iterator();
while (it.hasNext()) {
BiomeType test = (BiomeType) it.next();
if (test.getName().equalsIgnoreCase(name)) {
return test;
}
}
throw new UnknownBiomeTypeException(name);
}
public List<BiomeType> all() {
if (biomes.isEmpty()) {
biomes = HashBiMap.create(new HashMap<BiomeType, BiomeGenBase>());
for (BiomeGenBase biome : BiomeGenBase.biomeList) {
if ((biome == null) || (biomes.containsValue(biome))) {
continue;
}
biomes.put(new ForgeBiomeType(biome), biome);
}
}
List<BiomeType> retBiomes = new ArrayList<BiomeType>();
retBiomes.addAll(biomes.keySet());
return retBiomes;
}
public static BiomeType getFromBaseBiome(BiomeGenBase biome) {
return biomes.containsValue(biome) ? (BiomeType) biomes.inverse().get(biome) : BiomeType.UNKNOWN;
}
public static BiomeGenBase getFromBiomeType(BiomeType biome) {
return (BiomeGenBase) biomes.get(biome);
}
}

View File

@ -0,0 +1,95 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;
import net.minecraft.entity.EntityList;
import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
class ForgeEntity implements Entity {
private final net.minecraft.entity.Entity entity;
ForgeEntity(net.minecraft.entity.Entity entity) {
checkNotNull(entity);
this.entity = entity;
}
/**
* Return the underlying entity.
*
* @return the underlying entity
*/
net.minecraft.entity.Entity getEntity() {
return entity;
}
@Override
public BaseEntity getState() {
String id = EntityList.getEntityString(entity);
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
entity.writeToNBT(tag);
return new BaseEntity(id, NBTConverter.fromNative(tag));
} else {
return null;
}
}
@Override
public Location getLocation() {
Vector position = new Vector(entity.posX, entity.posY, entity.posZ);
float yaw = entity.rotationYaw;
float pitch = entity.rotationPitch;
return new Location(ForgeAdapter.adapt(entity.worldObj), position, yaw, pitch);
}
@Override
public Extent getExtent() {
return ForgeAdapter.adapt(entity.worldObj);
}
@Override
public boolean remove() {
entity.setDead();
return true;
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
if (EntityType.class.isAssignableFrom(cls)) {
return (T) new ForgeEntityType(entity);
} else {
return null;
}
}
}

View File

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

View File

@ -19,7 +19,7 @@
package com.sk89q.worldedit.forge; package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.BiomeTypes; import com.sk89q.worldedit.world.registry.BiomeRegistry;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.ServerInterface; import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
@ -56,13 +56,13 @@ class ForgePlatform extends ServerInterface implements MultiUserPlatform {
private final ForgeWorldEdit mod; private final ForgeWorldEdit mod;
private final MinecraftServer server; private final MinecraftServer server;
private final ForgeBiomeTypes biomes; private final ForgeBiomeRegistry biomes;
private boolean hookingEvents = false; private boolean hookingEvents = false;
ForgePlatform(ForgeWorldEdit mod) { ForgePlatform(ForgeWorldEdit mod) {
this.mod = mod; this.mod = mod;
this.server = FMLCommonHandler.instance().getMinecraftServerInstance(); this.server = FMLCommonHandler.instance().getMinecraftServerInstance();
this.biomes = new ForgeBiomeTypes(); this.biomes = new ForgeBiomeRegistry();
} }
boolean isHookingEvents() { boolean isHookingEvents() {
@ -95,11 +95,6 @@ class ForgePlatform extends ServerInterface implements MultiUserPlatform {
public void reload() { public void reload() {
} }
@Override
public BiomeTypes getBiomes() {
return this.biomes;
}
@Override @Override
public int schedule(long delay, long period, Runnable task) { public int schedule(long delay, long period, Runnable task) {
return -1; return -1;

View File

@ -20,21 +20,23 @@
package com.sk89q.worldedit.forge; package com.sk89q.worldedit.forge;
import com.sk89q.util.StringUtil; import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.LocalWorldAdapter; import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.Vectors;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.Packet250CustomPayload; import net.minecraft.network.packet.Packet250CustomPayload;
import net.minecraft.util.ChatMessageComponent; import net.minecraft.util.ChatMessageComponent;
public class ForgePlayer extends LocalPlayer { import javax.annotation.Nullable;
public class ForgePlayer extends AbstractPlayerActor {
private EntityPlayerMP player; private EntityPlayerMP player;
protected ForgePlayer(EntityPlayerMP player) { protected ForgePlayer(EntityPlayerMP player) {
@ -50,11 +52,19 @@ public class ForgePlayer extends LocalPlayer {
return this.player.username; return this.player.username;
} }
@Override
public BaseEntity getState() {
throw new UnsupportedOperationException("Cannot create a state from this object");
}
@Override @Override
public Location getLocation() { public Location getLocation() {
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ); Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
Vector direction = Vectors.fromEulerDeg(this.player.cameraYaw, this.player.cameraPitch); return new Location(
return new Location(ForgeWorldEdit.inst.getWorld(this.player.worldObj), position, direction); ForgeWorldEdit.inst.getWorld(this.player.worldObj),
position,
this.player.cameraYaw,
this.player.cameraPitch);
} }
public WorldVector getPosition() { public WorldVector getPosition() {
@ -126,4 +136,11 @@ public class ForgePlayer extends LocalPlayer {
public boolean hasPermission(String perm) { public boolean hasPermission(String perm) {
return ForgeUtil.hasPermission(this.player, perm); return ForgeUtil.hasPermission(this.player, perm);
} }
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
}
} }

View File

@ -20,24 +20,26 @@
package com.sk89q.worldedit.forge; package com.sk89q.worldedit.forge;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
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.LazyBlock; import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
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;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.WorldData;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityHanging; import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.item.*;
import net.minecraft.entity.monster.EntityGolem;
import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -48,8 +50,10 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.ChunkProviderServer; import net.minecraft.world.gen.ChunkProviderServer;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
@ -176,22 +180,23 @@ public class ForgeWorld extends AbstractWorld {
} }
@Override @Override
public BiomeType getBiome(Vector2D position) { public BaseBiome getBiome(Vector2D position) {
checkNotNull(position); checkNotNull(position);
return ForgeBiomeTypes.getFromBaseBiome(getWorld().getBiomeGenForCoords(position.getBlockX(), position.getBlockZ())); return new BaseBiome(getWorld().getBiomeGenForCoords(position.getBlockX(), position.getBlockZ()).biomeID);
} }
@Override @Override
public void setBiome(Vector2D position, BiomeType biome) { public boolean setBiome(Vector2D position, BaseBiome biome) {
checkNotNull(position); checkNotNull(position);
checkNotNull(biome); checkNotNull(biome);
if (getWorld().getChunkProvider().chunkExists(position.getBlockX(), position.getBlockZ())) {
Chunk chunk = getWorld().getChunkFromBlockCoords(position.getBlockX(), position.getBlockZ()); Chunk chunk = getWorld().getChunkFromBlockCoords(position.getBlockX(), position.getBlockZ());
if ((chunk != null) && (chunk.isChunkLoaded)) { if ((chunk != null) && (chunk.isChunkLoaded)) {
chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) ForgeBiomeTypes.getFromBiomeType(biome).biomeID; chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) biome.getId();
} return true;
} }
return false;
} }
@Override @Override
@ -199,7 +204,7 @@ public class ForgeWorld extends AbstractWorld {
checkNotNull(position); checkNotNull(position);
checkNotNull(item); checkNotNull(item);
if ((item == null) || (item.getType() == 0)) { if (item.getType() == 0) {
return; return;
} }
@ -208,121 +213,6 @@ public class ForgeWorld extends AbstractWorld {
getWorld().spawnEntityInWorld(entity); getWorld().spawnEntityInWorld(entity);
} }
@Override
@SuppressWarnings({"unchecked", "ConstantConditions"})
public int killMobs(Vector origin, double radius, int flags) {
boolean killPets = (flags & 0x1) != 0;
boolean killNPCs = (flags & 0x2) != 0;
boolean killAnimals = (flags & 0x4) != 0;
boolean killGolems = (flags & 0x8) != 0;
boolean killAmbient = (flags & 0x10) != 0;
int num = 0;
double radiusSq = radius * radius;
for (Entity obj : (Iterable<Entity>) getWorld().loadedEntityList) {
if ((obj instanceof EntityLiving)) {
EntityLiving ent = (EntityLiving) obj;
if (!killAnimals && ent instanceof EntityAnimal) {
continue;
}
if (!killPets && ent instanceof EntityTameable && ((EntityTameable) ent).isTamed()) {
continue; // tamed pet
}
if (!killGolems && ent instanceof EntityGolem) {
continue;
}
if (!killNPCs && ent instanceof EntityVillager) {
continue;
}
if (!killAmbient && ent instanceof EntityAmbientCreature) {
continue;
}
if ((radius < 0.0D) || (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) <= radiusSq)) {
ent.isDead = true;
num++;
}
}
}
return num;
}
@Override
@SuppressWarnings("unchecked")
public int removeEntities(EntityType type, Vector origin, int radius) {
checkNotNull(type);
checkNotNull(origin);
int num = 0;
double radiusSq = Math.pow(radius, 2.0D);
for (Entity ent : (Iterable<Entity>) getWorld().loadedEntityList) {
if ((radius != -1) && (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) > radiusSq)) {
continue;
}
if (type == EntityType.ALL) {
if (((ent instanceof EntityBoat)) || ((ent instanceof EntityItem)) || ((ent instanceof EntityFallingSand)) || ((ent instanceof EntityMinecart)) || ((ent instanceof EntityHanging)) || ((ent instanceof EntityTNTPrimed)) || ((ent instanceof EntityXPOrb)) || ((ent instanceof EntityEnderEye)) || ((ent instanceof IProjectile))) {
ent.isDead = true;
num++;
}
} else if ((type == EntityType.PROJECTILES) || (type == EntityType.ARROWS)) {
if (((ent instanceof EntityEnderEye)) || ((ent instanceof IProjectile))) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.BOATS) {
if ((ent instanceof EntityBoat)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.ITEMS) {
if ((ent instanceof EntityItem)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.FALLING_BLOCKS) {
if ((ent instanceof EntityFallingSand)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.MINECARTS) {
if ((ent instanceof EntityMinecart)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.PAINTINGS) {
if ((ent instanceof EntityPainting)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.ITEM_FRAMES) {
if ((ent instanceof EntityItemFrame)) {
ent.isDead = true;
num++;
}
} else if (type == EntityType.TNT) {
if ((ent instanceof EntityTNTPrimed)) {
ent.isDead = true;
num++;
}
} else if ((type == EntityType.XP_ORBS) && ((ent instanceof EntityXPOrb))) {
ent.isDead = true;
num++;
}
}
return num;
}
@Override @Override
public boolean regenerate(Region region, EditSession editSession) { public boolean regenerate(Region region, EditSession editSession) {
BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)]; BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)];
@ -425,6 +315,11 @@ public class ForgeWorld extends AbstractWorld {
return false; return false;
} }
@Override
public WorldData getWorldData() {
return ForgeWorldData.getInstance();
}
@Override @Override
public boolean isValidBlockType(int id) { public boolean isValidBlockType(int id) {
return (id == 0) || (net.minecraft.block.Block.blocksList[id] != null); return (id == 0) || (net.minecraft.block.Block.blocksList[id] != null);
@ -473,6 +368,61 @@ public class ForgeWorld extends AbstractWorld {
} }
} }
@Override
@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>();
for (Object entity : getWorld().getLoadedEntityList()) {
entities.add(new ForgeEntity((net.minecraft.entity.Entity) entity));
}
return entities;
}
@Nullable
@Override
public Entity createEntity(Location location, BaseEntity entity) {
World world = getWorld();
net.minecraft.entity.Entity createdEntity = EntityList.createEntityByName(entity.getTypeId(), world);
if (createdEntity != null) {
CompoundTag nativeTag = entity.getNbtData();
if (nativeTag != null) {
NBTTagCompound tag = NBTConverter.toNative(entity.getNbtData());
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.removeTag(name);
}
createdEntity.readFromNBT(tag);
}
createdEntity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
world.spawnEntityInWorld(createdEntity);
return new ForgeEntity(createdEntity);
} else {
return null;
}
}
/** /**
* Thrown when the reference to the world is lost. * Thrown when the reference to the world is lost.
*/ */

View File

@ -0,0 +1,53 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import com.sk89q.worldedit.world.registry.LegacyWorldData;
/**
* World data for the Forge platform.
*/
class ForgeWorldData extends LegacyWorldData {
private static final ForgeWorldData INSTANCE = new ForgeWorldData();
private final BiomeRegistry biomeRegistry = new ForgeBiomeRegistry();
/**
* Create a new instance.
*/
ForgeWorldData() {
}
@Override
public BiomeRegistry getBiomeRegistry() {
return biomeRegistry;
}
/**
* Get a static instance.
*
* @return an instance
*/
public static ForgeWorldData getInstance() {
return INSTANCE;
}
}

View File

@ -103,6 +103,8 @@ public class ForgeWorldEdit {
WorldEdit.getInstance().getPlatformManager().unregister(platform); WorldEdit.getInstance().getPlatformManager().unregister(platform);
} }
ForgeBiomeRegistry.populate();
this.platform = new ForgePlatform(this); this.platform = new ForgePlatform(this);
WorldEdit.getInstance().getPlatformManager().register(platform); WorldEdit.getInstance().getPlatformManager().register(platform);

View File

@ -21,7 +21,6 @@ package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.world.DataException;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -29,10 +28,7 @@ public class TileEntityBaseBlock extends BaseBlock implements TileEntityBlock {
public TileEntityBaseBlock(int type, int data, TileEntity tile) { public TileEntityBaseBlock(int type, int data, TileEntity tile) {
super(type, data); super(type, data);
try {
setNbtData(NBTConverter.fromNative(copyNbtData(tile))); setNbtData(NBTConverter.fromNative(copyNbtData(tile)));
} catch (DataException ignored) {
}
} }
private static NBTTagCompound copyNbtData(TileEntity tile) { private static NBTTagCompound copyNbtData(TileEntity tile) {

View File

@ -19,17 +19,18 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils; import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.storage.InvalidFormatException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Represents a chest block. * Represents a chest block.
@ -78,7 +79,7 @@ public class ChestBlock extends ContainerBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
@ -87,19 +88,25 @@ public class ChestBlock extends ContainerBlock {
Tag t = values.get("id"); Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Chest")) { if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Chest")) {
throw new DataException("'Chest' tile entity expected"); throw new RuntimeException("'Chest' tile entity expected");
} }
List<CompoundTag> items = new ArrayList<CompoundTag>(); List<CompoundTag> items = new ArrayList<CompoundTag>();
try {
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) { for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) { if (!(tag instanceof CompoundTag)) {
throw new DataException("CompoundTag expected as child tag of Chest's Items"); throw new RuntimeException("CompoundTag expected as child tag of Chest's Items");
} }
items.add((CompoundTag) tag); items.add((CompoundTag) tag);
} }
setItems(deserializeInventory(items)); setItems(deserializeInventory(items));
} catch (InvalidFormatException e) {
throw new RuntimeException(e);
} catch (DataException e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -19,11 +19,6 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils; import com.sk89q.jnbt.NBTUtils;
@ -31,6 +26,11 @@ import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.DataException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Represents dispensers. * Represents dispensers.
* *
@ -79,7 +79,8 @@ public class DispenserBlock extends ContainerBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
try {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
@ -101,5 +102,8 @@ public class DispenserBlock extends ContainerBlock {
} }
setItems(deserializeInventory(items)); setItems(deserializeInventory(items));
} catch (DataException e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -19,11 +19,6 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils; import com.sk89q.jnbt.NBTUtils;
@ -32,6 +27,11 @@ import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.DataException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Represents a furnace block. * Represents a furnace block.
* *
@ -125,17 +125,18 @@ public class FurnaceBlock extends ContainerBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
try {
Map<String, Tag> values = rootTag.getValue(); Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id"); Tag t = values.get("id");
if (!(t instanceof StringTag) if (!(t instanceof StringTag)
|| !((StringTag) t).getValue().equals("Furnace")) { || !((StringTag) t).getValue().equals("Furnace")) {
throw new DataException("'Furnace' tile entity expected"); throw new RuntimeException("'Furnace' tile entity expected");
} }
ListTag items = NBTUtils.getChildTag(values, "Items", ListTag.class); ListTag items = NBTUtils.getChildTag(values, "Items", ListTag.class);
@ -144,8 +145,7 @@ public class FurnaceBlock extends ContainerBlock {
for (Tag tag : items.getValue()) { for (Tag tag : items.getValue()) {
if (!(tag instanceof CompoundTag)) { if (!(tag instanceof CompoundTag)) {
throw new DataException( throw new RuntimeException("CompoundTag expected as child tag of Furnace Items");
"CompoundTag expected as child tag of Furnace Items");
} }
compound.add((CompoundTag) tag); compound.add((CompoundTag) tag);
} }
@ -160,5 +160,8 @@ public class FurnaceBlock extends ContainerBlock {
if (t instanceof ShortTag) { if (t instanceof ShortTag) {
cookTime = ((ShortTag) t).getValue(); cookTime = ((ShortTag) t).getValue();
} }
} catch (DataException e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -21,7 +21,6 @@ package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -88,17 +87,13 @@ public class LazyBlock extends BaseBlock {
public CompoundTag getNbtData() { public CompoundTag getNbtData() {
if (!loaded) { if (!loaded) {
BaseBlock loadedBlock = extent.getBlock(position); BaseBlock loadedBlock = extent.getBlock(position);
try {
super.setNbtData(loadedBlock.getNbtData()); super.setNbtData(loadedBlock.getNbtData());
} catch (DataException e) {
throw new RuntimeException(e);
}
} }
return super.getNbtData(); return super.getNbtData();
} }
@Override @Override
public void setNbtData(CompoundTag nbtData) throws DataException { public void setNbtData(CompoundTag nbtData) {
throw new UnsupportedOperationException("This object is immutable"); throw new UnsupportedOperationException("This object is immutable");
} }

View File

@ -19,9 +19,13 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.*; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.MobType; import com.sk89q.worldedit.MobType;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.storage.InvalidFormatException; import com.sk89q.worldedit.world.storage.InvalidFormatException;
import java.util.HashMap; import java.util.HashMap;
@ -153,7 +157,7 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
@ -162,11 +166,18 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
Tag t = values.get("id"); Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) { if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) {
throw new DataException("'MobSpawner' tile entity expected"); throw new RuntimeException("'MobSpawner' tile entity expected");
} }
StringTag mobTypeTag = NBTUtils.getChildTag(values, "EntityId", StringTag.class); StringTag mobTypeTag;
ShortTag delayTag = NBTUtils.getChildTag(values, "Delay", ShortTag.class); ShortTag delayTag;
try {
mobTypeTag = NBTUtils.getChildTag(values, "EntityId", StringTag.class);
delayTag = NBTUtils.getChildTag(values, "Delay", ShortTag.class);
} catch (InvalidFormatException ignored) {
throw new RuntimeException("Invalid mob spawner data: no EntityId and/or no Delay");
}
this.mobType = mobTypeTag.getValue(); this.mobType = mobTypeTag.getValue();
this.delay = delayTag.getValue(); this.delay = delayTag.getValue();

View File

@ -19,14 +19,13 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import java.util.HashMap;
import java.util.Map;
import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
import java.util.HashMap;
import java.util.Map;
/** /**
* A note block. * A note block.
@ -102,7 +101,7 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
@ -112,9 +111,8 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
Tag t; Tag t;
t = values.get("id"); t = values.get("id");
if (!(t instanceof StringTag) if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Music")) {
|| !((StringTag) t).getValue().equals("Music")) { throw new RuntimeException("'Music' tile entity expected");
throw new DataException("'Music' tile entity expected");
} }
t = values.get("note"); t = values.get("note");

View File

@ -19,13 +19,12 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import java.util.HashMap;
import java.util.Map;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
import java.util.HashMap;
import java.util.Map;
/** /**
* Represents a sign block. * Represents a sign block.
@ -104,7 +103,7 @@ public class SignBlock extends BaseBlock implements TileEntityBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
@ -116,9 +115,8 @@ public class SignBlock extends BaseBlock implements TileEntityBlock {
text = new String[] { "", "", "", "" }; text = new String[] { "", "", "", "" };
t = values.get("id"); t = values.get("id");
if (!(t instanceof StringTag) if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Sign")) {
|| !((StringTag) t).getValue().equals("Sign")) { throw new RuntimeException("'Sign' tile entity expected");
throw new DataException("'Sign' tile entity expected");
} }
t = values.get("Text1"); t = values.get("Text1");

View File

@ -19,14 +19,13 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import java.util.HashMap;
import java.util.Map;
import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
import java.util.HashMap;
import java.util.Map;
/** /**
* A skull block. * A skull block.
@ -165,7 +164,7 @@ public class SkullBlock extends BaseBlock implements TileEntityBlock {
} }
@Override @Override
public void setNbtData(CompoundTag rootTag) throws DataException { public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) { if (rootTag == null) {
return; return;
} }
@ -175,9 +174,8 @@ public class SkullBlock extends BaseBlock implements TileEntityBlock {
Tag t; Tag t;
t = values.get("id"); t = values.get("id");
if (!(t instanceof StringTag) if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Skull")) {
|| !((StringTag) t).getValue().equals("Skull")) { throw new RuntimeException("'Skull' tile entity expected");
throw new DataException("'Skull' tile entity expected");
} }
t = values.get("SkullType"); t = values.get("SkullType");

View File

@ -10,6 +10,8 @@
<allow pkg="com.sk89q"/> <allow pkg="com.sk89q"/>
<allow pkg="com.google.common"/> <allow pkg="com.google.common"/>
<allow pkg="com.thoughtworks.paranamer"/> <allow pkg="com.thoughtworks.paranamer"/>
<allow pkg="gnu.trove"/>
<allow pkg="com.google.gson"/>
<subpackage name="util.yaml"> <subpackage name="util.yaml">
<allow pkg="org.yaml.snakeyaml"/> <allow pkg="org.yaml.snakeyaml"/>

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Byte_Array</code> tag. * The {@code TAG_Byte_Array} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class ByteArrayTag extends Tag { public final class ByteArrayTag extends Tag {
/**
* The value.
*/
private final byte[] value; private final byte[] value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public ByteArrayTag(byte[] value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public ByteArrayTag(String name, byte[] value) { public ByteArrayTag(String name, byte[] value) {
super(name); super(name);
@ -67,7 +67,7 @@ public final class ByteArrayTag extends Tag {
if (name != null && !name.equals("")) { if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")"; append = "(\"" + this.getName() + "\")";
} }
return "TAG_Byte_Array" + append + ": " + hex.toString(); return "TAG_Byte_Array" + append + ": " + hex;
} }
} }

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Byte</code> tag. * The {@code TAG_Byte} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class ByteTag extends Tag { public final class ByteTag extends Tag {
/**
* The value.
*/
private final byte value; private final byte value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public ByteTag(byte value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public ByteTag(String name, byte value) { public ByteTag(String name, byte value) {
super(name); super(name);

View File

@ -20,40 +20,401 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Compound</code> tag. * The {@code TAG_Compound} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class CompoundTag extends Tag { public final class CompoundTag extends Tag {
/**
* The value.
*/
private final Map<String, Tag> value; private final Map<String, Tag> value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public CompoundTag(Map<String, Tag> value) {
super();
this.value = Collections.unmodifiableMap(value);
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public CompoundTag(String name, Map<String, Tag> value) { public CompoundTag(String name, Map<String, Tag> value) {
super(name); super(name);
this.value = Collections.unmodifiableMap(value); this.value = Collections.unmodifiableMap(value);
} }
/**
* Returns whether this compound tag contains the given key.
*
* @param key the given key
* @return true if the tag contains the given key
*/
public boolean containsKey(String key) {
return value.containsKey(key);
}
@Override @Override
public Map<String, Tag> getValue() { public Map<String, Tag> getValue() {
return value; return value;
} }
/**
* Return a new compound tag with the given values.
*
* @param value the value
* @return the new compound tag
*/
public CompoundTag setValue(Map<String, Tag> value) {
return new CompoundTag(getName(), value);
}
/**
* Create a compound tag builder.
*
* @return the builder
*/
public CompoundTagBuilder createBuilder() {
return new CompoundTagBuilder(new HashMap<String, Tag>(value));
}
/**
* Get a byte array named with the given key.
*
* <p>If the key does not exist or its value is not a byte array tag,
* then an empty byte array will be returned.</p>
*
* @param key the key
* @return a byte array
*/
public byte[] getByteArray(String key) {
Tag tag = value.get(key);
if (tag instanceof ByteArrayTag) {
return ((ByteArrayTag) tag).getValue();
} else {
return new byte[0];
}
}
/**
* Get a byte named with the given key.
*
* <p>If the key does not exist or its value is not a byte tag,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a byte
*/
public byte getByte(String key) {
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else {
return (byte) 0;
}
}
/**
* Get a double named with the given key.
*
* <p>If the key does not exist or its value is not a double tag,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a double
*/
public double getDouble(String key) {
Tag tag = value.get(key);
if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a double named with the given key, even if it's another
* type of number.
*
* <p>If the key does not exist or its value is not a number,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a double
*/
public double asDouble(String key) {
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a float named with the given key.
*
* <p>If the key does not exist or its value is not a float tag,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a float
*/
public float getFloat(String key) {
Tag tag = value.get(key);
if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a {@code int[]} named with the given key.
*
* <p>If the key does not exist or its value is not an int array tag,
* then an empty array will be returned.</p>
*
* @param key the key
* @return an int array
*/
public int[] getIntArray(String key) {
Tag tag = value.get(key);
if (tag instanceof IntArrayTag) {
return ((IntArrayTag) tag).getValue();
} else {
return new int[0];
}
}
/**
* Get an int named with the given key.
*
* <p>If the key does not exist or its value is not an int tag,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return an int
*/
public int getInt(String key) {
Tag tag = value.get(key);
if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get an int named with the given key, even if it's another
* type of number.
*
* <p>If the key does not exist or its value is not a number,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return an int
*/
public int asInt(String key) {
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue().intValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue().intValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue().intValue();
} else {
return 0;
}
}
/**
* Get a list of tags named with the given key.
*
* <p>If the key does not exist or its value is not a list tag,
* then an empty list will be returned.</p>
*
* @param key the key
* @return a list of tags
*/
public List<Tag> getList(String key) {
Tag tag = value.get(key);
if (tag instanceof ListTag) {
return ((ListTag) tag).getValue();
} else {
return Collections.emptyList();
}
}
/**
* Get a {@code TagList} named with the given key.
*
* <p>If the key does not exist or its value is not a list tag,
* then an empty tag list will be returned.</p>
*
* @param key the key
* @return a tag list instance
*/
public ListTag getListTag(String key) {
Tag tag = value.get(key);
if (tag instanceof ListTag) {
return (ListTag) tag;
} else {
return new ListTag(key, StringTag.class, Collections.<Tag>emptyList());
}
}
/**
* Get a list of tags named with the given key.
*
* <p>If the key does not exist or its value is not a list tag,
* then an empty list will be returned. If the given key references
* a list but the list of of a different type, then an empty
* list will also be returned.</p>
*
* @param key the key
* @return a list of tags
*/
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
Tag tag = value.get(key);
if (tag instanceof ListTag) {
ListTag listTag = (ListTag) tag;
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
} else {
return Collections.emptyList();
}
}
/**
* Get a long named with the given key.
*
* <p>If the key does not exist or its value is not a long tag,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a long
*/
public long getLong(String key) {
Tag tag = value.get(key);
if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else {
return 0L;
}
}
/**
* Get a long named with the given key, even if it's another
* type of number.
*
* <p>If the key does not exist or its value is not a number,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a long
*/
public long asLong(String key) {
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue().longValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue().longValue();
} else {
return 0L;
}
}
/**
* Get a short named with the given key.
*
* <p>If the key does not exist or its value is not a short tag,
* then {@code 0} will be returned.</p>
*
* @param key the key
* @return a short
*/
public short getShort(String key) {
Tag tag = value.get(key);
if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a string named with the given key.
*
* <p>If the key does not exist or its value is not a string tag,
* then {@code ""} will be returned.</p>
*
* @param key the key
* @return a string
*/
public String getString(String key) {
Tag tag = value.get(key);
if (tag instanceof StringTag) {
return ((StringTag) tag).getValue();
} else {
return "";
}
}
@Override @Override
public String toString() { public String toString() {
String name = getName(); String name = getName();
@ -62,12 +423,9 @@ public final class CompoundTag extends Tag {
append = "(\"" + this.getName() + "\")"; append = "(\"" + this.getName() + "\")";
} }
StringBuilder bldr = new StringBuilder(); StringBuilder bldr = new StringBuilder();
bldr.append("TAG_Compound" + append + ": " + value.size() bldr.append("TAG_Compound").append(append).append(": ").append(value.size()).append(" entries\r\n{\r\n");
+ " entries\r\n{\r\n");
for (Map.Entry<String, Tag> entry : value.entrySet()) { for (Map.Entry<String, Tag> entry : value.entrySet()) {
bldr.append(" " bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
+ entry.getValue().toString().replaceAll("\r\n", "\r\n ")
+ "\r\n");
} }
bldr.append("}"); bldr.append("}");
return bldr.toString(); return bldr.toString();

View File

@ -0,0 +1,214 @@
/*
* 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.jnbt;
import java.util.HashMap;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Helps create compound tags.
*/
public class CompoundTagBuilder {
private final Map<String, Tag> entries;
/**
* Create a new instance.
*/
CompoundTagBuilder() {
this.entries = new HashMap<String, Tag>();
}
/**
* Create a new instance and use the given map (which will be modified).
*
* @param value the value
*/
CompoundTagBuilder(Map<String, Tag> value) {
checkNotNull(value);
this.entries = value;
}
/**
* Put the given key and tag into the compound tag.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder put(String key, Tag value) {
checkNotNull(key);
checkNotNull(value);
entries.put(key, value);
return this;
}
/**
* Put the given key and value into the compound tag as a
* {@code ByteArrayTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putByteArray(String key, byte[] value) {
return put(key, new ByteArrayTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code ByteTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putByte(String key, byte value) {
return put(key, new ByteTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code DoubleTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putDouble(String key, double value) {
return put(key, new DoubleTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code FloatTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putFloat(String key, float value) {
return put(key, new FloatTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code IntArrayTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putIntArray(String key, int[] value) {
return put(key, new IntArrayTag(key, value));
}
/**
* Put the given key and value into the compound tag as an {@code IntTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putInt(String key, int value) {
return put(key, new IntTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code LongTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putLong(String key, long value) {
return put(key, new LongTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code ShortTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putShort(String key, short value) {
return put(key, new ShortTag(key, value));
}
/**
* Put the given key and value into the compound tag as a
* {@code StringTag}.
*
* @param key they key
* @param value the value
* @return this object
*/
public CompoundTagBuilder putString(String key, String value) {
return put(key, new StringTag(key, value));
}
/**
* Put all the entries from the given map into this map.
*
* @param value the map of tags
* @return this object
*/
public CompoundTagBuilder putAll(Map<String, ? extends Tag> value) {
checkNotNull(value);
for (Map.Entry<String, ? extends Tag> entry : value.entrySet()) {
put(entry.getKey(), entry.getValue());
}
return this;
}
/**
* Build an unnamed compound tag with this builder's entries.
*
* @return the new compound tag
*/
public CompoundTag build() {
return new CompoundTag(new HashMap<String, Tag>(entries));
}
/**
* Build a new compound tag with this builder's entries.
*
* @param name the name of the tag
* @return the created compound tag
*/
public CompoundTag build(String name) {
return new CompoundTag(name, new HashMap<String, Tag>(entries));
}
/**
* Create a new builder instance.
*
* @return a new builder
*/
public static CompoundTagBuilder create() {
return new CompoundTagBuilder();
}
}

View File

@ -19,28 +19,29 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Double</code> tag. * The {@code TAG_Double} tag.
*
* @author Graham Edgecombe
* *
*/ */
public final class DoubleTag extends Tag { public final class DoubleTag extends Tag {
/**
* The value.
*/
private final double value; private final double value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public DoubleTag(double value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public DoubleTag(String name, double value) { public DoubleTag(String name, double value) {
super(name); super(name);

View File

@ -19,8 +19,6 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_End</code> tag. * The <code>TAG_End</code> tag.
* *
@ -33,7 +31,7 @@ public final class EndTag extends Tag {
* Creates the tag. * Creates the tag.
*/ */
public EndTag() { public EndTag() {
super(""); super();
} }
@Override @Override

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Float</code> tag. * The {@code TAG_Float} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class FloatTag extends Tag { public final class FloatTag extends Tag {
/**
* The value.
*/
private final float value; private final float value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public FloatTag(float value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public FloatTag(String name, float value) { public FloatTag(String name, float value) {
super(name); super(name);

View File

@ -19,31 +19,35 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag; import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* The <code>TAG_Int_Array</code> tag. * The {@code TAG_Int_Array} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class IntArrayTag extends Tag { public final class IntArrayTag extends Tag {
/**
* The value.
*/
private final int[] value; private final int[] value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public IntArrayTag(int[] value) {
super();
checkNotNull(value);
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public IntArrayTag(String name, int[] value) { public IntArrayTag(String name, int[] value) {
super(name); super(name);
checkNotNull(value);
this.value = value; this.value = value;
} }

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Int</code> tag. * The {@code TAG_Int} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class IntTag extends Tag { public final class IntTag extends Tag {
/**
* The value.
*/
private final int value; private final int value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public IntTag(int value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public IntTag(String name, int value) { public IntTag(String name, int value) {
super(name); super(name);

View File

@ -19,41 +19,44 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import com.sk89q.jnbt.NBTUtils; import java.util.NoSuchElementException;
import com.sk89q.jnbt.Tag;
import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* The <code>TAG_List</code> tag. * The {@code TAG_List} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class ListTag extends Tag { public final class ListTag extends Tag {
/**
* The type.
*/
private final Class<? extends Tag> type; private final Class<? extends Tag> type;
private final List<Tag> value;
/** /**
* The value. * Creates the tag with an empty name.
*
* @param type the type of tag
* @param value the value of the tag
*/ */
private final List<Tag> value; public ListTag(Class<? extends Tag> type, List<? extends Tag> value) {
super();
checkNotNull(value);
this.type = type;
this.value = Collections.unmodifiableList(value);
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param type the type of tag
* @param type * @param value the value of the tag
* The type of item in the list.
* @param value
* The value.
*/ */
public ListTag(String name, Class<? extends Tag> type, List<? extends Tag> value) { public ListTag(String name, Class<? extends Tag> type, List<? extends Tag> value) {
super(name); super(name);
checkNotNull(value);
this.type = type; this.type = type;
this.value = Collections.unmodifiableList(value); this.value = Collections.unmodifiableList(value);
} }
@ -72,6 +75,360 @@ public final class ListTag extends Tag {
return value; return value;
} }
/**
* Create a new list tag with this tag's name and type.
*
* @param list the new list
* @return a new list tag
*/
public ListTag setValue(List<Tag> list) {
return new ListTag(getName(), getType(), list);
}
/**
* Get the tag if it exists at the given index.
*
* @param index the index
* @return the tag or null
*/
@Nullable
public Tag getIfExists(int index) {
try {
return value.get(index);
} catch (NoSuchElementException e) {
return null;
}
}
/**
* Get a byte array named with the given index.
*
* <p>If the index does not exist or its value is not a byte array tag,
* then an empty byte array will be returned.</p>
*
* @param index the index
* @return a byte array
*/
public byte[] getByteArray(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ByteArrayTag) {
return ((ByteArrayTag) tag).getValue();
} else {
return new byte[0];
}
}
/**
* Get a byte named with the given index.
*
* <p>If the index does not exist or its value is not a byte tag,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a byte
*/
public byte getByte(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else {
return (byte) 0;
}
}
/**
* Get a double named with the given index.
*
* <p>If the index does not exist or its value is not a double tag,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a double
*/
public double getDouble(int index) {
Tag tag = getIfExists(index);
if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a double named with the given index, even if it's another
* type of number.
*
* <p>If the index does not exist or its value is not a number,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a double
*/
public double asDouble(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a float named with the given index.
*
* <p>If the index does not exist or its value is not a float tag,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a float
*/
public float getFloat(int index) {
Tag tag = getIfExists(index);
if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a {@code int[]} named with the given index.
*
* <p>If the index does not exist or its value is not an int array tag,
* then an empty array will be returned.</p>
*
* @param index the index
* @return an int array
*/
public int[] getIntArray(int index) {
Tag tag = getIfExists(index);
if (tag instanceof IntArrayTag) {
return ((IntArrayTag) tag).getValue();
} else {
return new int[0];
}
}
/**
* Get an int named with the given index.
*
* <p>If the index does not exist or its value is not an int tag,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return an int
*/
public int getInt(int index) {
Tag tag = getIfExists(index);
if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get an int named with the given index, even if it's another
* type of number.
*
* <p>If the index does not exist or its value is not a number,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return an int
*/
public int asInt(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue().intValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue().intValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue().intValue();
} else {
return 0;
}
}
/**
* Get a list of tags named with the given index.
*
* <p>If the index does not exist or its value is not a list tag,
* then an empty list will be returned.</p>
*
* @param index the index
* @return a list of tags
*/
public List<Tag> getList(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ListTag) {
return ((ListTag) tag).getValue();
} else {
return Collections.emptyList();
}
}
/**
* Get a {@code TagList} named with the given index.
*
* <p>If the index does not exist or its value is not a list tag,
* then an empty tag list will be returned.</p>
*
* @param index the index
* @return a tag list instance
*/
public ListTag getListTag(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ListTag) {
return (ListTag) tag;
} else {
return new ListTag(StringTag.class, Collections.<Tag>emptyList());
}
}
/**
* Get a list of tags named with the given index.
*
* <p>If the index does not exist or its value is not a list tag,
* then an empty list will be returned. If the given index references
* a list but the list of of a different type, then an empty
* list will also be returned.</p>
*
* @param index the index
* @return a list of tags
*/
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(int index, Class<T> listType) {
Tag tag = getIfExists(index);
if (tag instanceof ListTag) {
ListTag listTag = (ListTag) tag;
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
} else {
return Collections.emptyList();
}
}
/**
* Get a long named with the given index.
*
* <p>If the index does not exist or its value is not a long tag,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a long
*/
public long getLong(int index) {
Tag tag = getIfExists(index);
if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else {
return 0L;
}
}
/**
* Get a long named with the given index, even if it's another
* type of number.
*
* <p>If the index does not exist or its value is not a number,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a long
*/
public long asLong(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue().longValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue().longValue();
} else {
return 0;
}
}
/**
* Get a short named with the given index.
*
* <p>If the index does not exist or its value is not a short tag,
* then {@code 0} will be returned.</p>
*
* @param index the index
* @return a short
*/
public short getShort(int index) {
Tag tag = getIfExists(index);
if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else {
return 0;
}
}
/**
* Get a string named with the given index.
*
* <p>If the index does not exist or its value is not a string tag,
* then {@code ""} will be returned.</p>
*
* @param index the index
* @return a string
*/
public String getString(int index) {
Tag tag = getIfExists(index);
if (tag instanceof StringTag) {
return ((StringTag) tag).getValue();
} else {
return "";
}
}
@Override @Override
public String toString() { public String toString() {
String name = getName(); String name = getName();

View File

@ -0,0 +1,129 @@
/*
* 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.jnbt;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Helps create list tags.
*/
public class ListTagBuilder {
private final Class<? extends Tag> type;
private final List<Tag> entries;
/**
* Create a new instance.
*
* @param type of tag contained in this list
*/
ListTagBuilder(Class<? extends Tag> type) {
checkNotNull(type);
this.type = type;
this.entries = new ArrayList<Tag>();
}
/**
* Add the given tag.
*
* @param value the tag
* @return this object
*/
public ListTagBuilder add(Tag value) {
checkNotNull(value);
if (!type.isInstance(value)) {
throw new IllegalArgumentException(value.getClass().getCanonicalName() + " is not of expected type " + type.getCanonicalName());
}
entries.add(value);
return this;
}
/**
* Add all the tags in the given list.
*
* @param value a list of tags
* @return this object
*/
public ListTagBuilder addAll(Collection<? extends Tag> value) {
checkNotNull(value);
for (Tag v : value) {
add(v);
}
return this;
}
/**
* Build an unnamed list tag with this builder's entries.
*
* @return the new list tag
*/
public ListTag build() {
return new ListTag(type, new ArrayList<Tag>(entries));
}
/**
* Build a new list tag with this builder's entries.
*
* @param name the name of the tag
* @return the created list tag
*/
public ListTag build(String name) {
return new ListTag(name, type, new ArrayList<Tag>(entries));
}
/**
* Create a new builder instance.
*
* @return a new builder
*/
public static ListTagBuilder create(Class<? extends Tag> type) {
return new ListTagBuilder(type);
}
/**
* Create a new builder instance.
*
* @return a new builder
*/
public static <T extends Tag> ListTagBuilder createWith(T ... entries) {
checkNotNull(entries);
if (entries.length == 0) {
throw new IllegalArgumentException("This method needs an array of at least one entry");
}
Class<? extends Tag> type = entries[0].getClass();
for (int i = 1; i < entries.length; i++) {
if (!type.isInstance(entries[i])) {
throw new IllegalArgumentException("An array of different tag types was provided");
}
}
ListTagBuilder builder = new ListTagBuilder(type);
builder.addAll(Arrays.asList(entries));
return builder;
}
}

View File

@ -19,28 +19,29 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Long</code> tag. * The {@code TAG_Long} tag.
*
* @author Graham Edgecombe
* *
*/ */
public final class LongTag extends Tag { public final class LongTag extends Tag {
/**
* The value.
*/
private final long value; private final long value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public LongTag(long value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public LongTag(String name, long value) { public LongTag(String name, long value) {
super(name); super(name);

View File

@ -29,14 +29,8 @@ import java.nio.charset.Charset;
*/ */
public final class NBTConstants { public final class NBTConstants {
/**
* The character set used by NBT (UTF-8).
*/
public static final Charset CHARSET = Charset.forName("UTF-8"); public static final Charset CHARSET = Charset.forName("UTF-8");
/**
* Tag type constants.
*/
public static final int TYPE_END = 0, TYPE_BYTE = 1, TYPE_SHORT = 2, public static final int TYPE_END = 0, TYPE_BYTE = 1, TYPE_SHORT = 2,
TYPE_INT = 3, TYPE_LONG = 4, TYPE_FLOAT = 5, TYPE_DOUBLE = 6, TYPE_INT = 3, TYPE_LONG = 4, TYPE_FLOAT = 5, TYPE_DOUBLE = 6,
TYPE_BYTE_ARRAY = 7, TYPE_STRING = 8, TYPE_LIST = 9, TYPE_BYTE_ARRAY = 7, TYPE_STRING = 8, TYPE_LIST = 9,

View File

@ -27,20 +27,6 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.EndTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
/** /**
* <p> * <p>
@ -60,19 +46,14 @@ import com.sk89q.jnbt.Tag;
*/ */
public final class NBTInputStream implements Closeable { public final class NBTInputStream implements Closeable {
/**
* The data input stream.
*/
private final DataInputStream is; private final DataInputStream is;
/** /**
* Creates a new <code>NBTInputStream</code>, which will source its data * Creates a new {@code NBTInputStream}, which will source its data
* from the specified input stream. * from the specified input stream.
* *
* @param is * @param is the input stream
* The input stream. * @throws IOException if an I/O error occurs
* @throws IOException
* if an I/O error occurs.
*/ */
public NBTInputStream(InputStream is) throws IOException { public NBTInputStream(InputStream is) throws IOException {
this.is = new DataInputStream(is); this.is = new DataInputStream(is);
@ -82,8 +63,7 @@ public final class NBTInputStream implements Closeable {
* Reads an NBT tag from the stream. * Reads an NBT tag from the stream.
* *
* @return The tag that was read. * @return The tag that was read.
* @throws IOException * @throws IOException if an I/O error occurs.
* if an I/O error occurs.
*/ */
public Tag readTag() throws IOException { public Tag readTag() throws IOException {
return readTag(0); return readTag(0);
@ -92,11 +72,9 @@ public final class NBTInputStream implements Closeable {
/** /**
* Reads an NBT from the stream. * Reads an NBT from the stream.
* *
* @param depth * @param depth the depth of this tag
* The depth of this tag.
* @return The tag that was read. * @return The tag that was read.
* @throws IOException * @throws IOException if an I/O error occurs.
* if an I/O error occurs.
*/ */
private Tag readTag(int depth) throws IOException { private Tag readTag(int depth) throws IOException {
int type = is.readByte() & 0xFF; int type = is.readByte() & 0xFF;
@ -117,18 +95,13 @@ public final class NBTInputStream implements Closeable {
/** /**
* Reads the payload of a tag, given the name and type. * Reads the payload of a tag, given the name and type.
* *
* @param type * @param type the type
* The type. * @param name the name
* @param name * @param depth the depth
* The name. * @return the tag
* @param depth * @throws IOException if an I/O error occurs.
* The depth.
* @return The tag.
* @throws IOException
* if an I/O error occurs.
*/ */
private Tag readTagPayload(int type, String name, int depth) private Tag readTagPayload(int type, String name, int depth) throws IOException {
throws IOException {
switch (type) { switch (type) {
case NBTConstants.TYPE_END: case NBTConstants.TYPE_END:
if (depth == 0) { if (depth == 0) {
@ -197,6 +170,7 @@ public final class NBTInputStream implements Closeable {
} }
} }
@Override
public void close() throws IOException { public void close() throws IOException {
is.close(); is.close();
} }

View File

@ -24,21 +24,6 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List; import java.util.List;
import java.util.zip.GZIPOutputStream;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.EndTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
/** /**
* <p> * <p>
@ -72,7 +57,7 @@ public final class NBTOutputStream implements Closeable {
* if an I/O error occurs. * if an I/O error occurs.
*/ */
public NBTOutputStream(OutputStream os) throws IOException { public NBTOutputStream(OutputStream os) throws IOException {
this.os = new DataOutputStream(new GZIPOutputStream(os)); this.os = new DataOutputStream(os);
} }
/** /**

View File

@ -19,23 +19,31 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.storage.InvalidFormatException; import com.sk89q.worldedit.world.storage.InvalidFormatException;
import java.util.Map; import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* A class which contains NBT-related utility methods. * A class which contains NBT-related utility methods.
* *
* @author Graham Edgecombe
*
*/ */
public final class NBTUtils { public final class NBTUtils {
/**
* Default private constructor.
*/
private NBTUtils() {
}
/** /**
* Gets the type name of a tag. * Gets the type name of a tag.
* *
* @param clazz * @param clazz the tag class
* The tag class.
* @return The type name. * @return The type name.
*/ */
public static String getTypeName(Class<? extends Tag> clazz) { public static String getTypeName(Class<? extends Tag> clazz) {
@ -72,11 +80,9 @@ public final class NBTUtils {
/** /**
* Gets the type code of a tag class. * Gets the type code of a tag class.
* *
* @param clazz * @param clazz the tag class
* The tag class.
* @return The type code. * @return The type code.
* @throws IllegalArgumentException * @throws IllegalArgumentException if the tag class is invalid.
* if the tag class is invalid.
*/ */
public static int getTypeCode(Class<? extends Tag> clazz) { public static int getTypeCode(Class<? extends Tag> clazz) {
if (clazz.equals(ByteArrayTag.class)) { if (clazz.equals(ByteArrayTag.class)) {
@ -112,11 +118,9 @@ public final class NBTUtils {
/** /**
* Gets the class of a type of tag. * Gets the class of a type of tag.
* *
* @param type * @param type the type
* The type.
* @return The class. * @return The class.
* @throws IllegalArgumentException * @throws IllegalArgumentException if the tag type is invalid.
* if the tag type is invalid.
*/ */
public static Class<? extends Tag> getTypeClass(int type) { public static Class<? extends Tag> getTypeClass(int type) {
switch (type) { switch (type) {
@ -151,10 +155,17 @@ public final class NBTUtils {
} }
/** /**
* Default private constructor. * Read a vector from a list tag containing ideally three values: the
* X, Y, and Z components.
*
* <p>For values that are unavailable, their values will be 0.</p>
*
* @param listTag the list tag
* @return a vector
*/ */
private NBTUtils() { public static Vector toVector(ListTag listTag) {
checkNotNull(listTag);
return new Vector(listTag.asDouble(0), listTag.asDouble(1), listTag.asDouble(2));
} }
/** /**

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/** /**
* The <code>TAG_Short</code> tag. * The {@code TAG_Short} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class ShortTag extends Tag { public final class ShortTag extends Tag {
/**
* The value.
*/
private final short value; private final short value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public ShortTag(short value) {
super();
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public ShortTag(String name, short value) { public ShortTag(String name, short value) {
super(name); super(name);

View File

@ -19,31 +19,35 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag; import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* The <code>TAG_String</code> tag. * The {@code TAG_String} tag.
*
* @author Graham Edgecombe
*
*/ */
public final class StringTag extends Tag { public final class StringTag extends Tag {
/**
* The value.
*/
private final String value; private final String value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public StringTag(String value) {
super();
checkNotNull(value);
this.value = value;
}
/** /**
* Creates the tag. * Creates the tag.
* *
* @param name * @param name the name of the tag
* The name. * @param value the value of the tag
* @param value
* The value.
*/ */
public StringTag(String name, String value) { public StringTag(String name, String value) {
super(name); super(name);
checkNotNull(value);
this.value = value; this.value = value;
} }

View File

@ -20,32 +20,35 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
/** /**
* Represents a single NBT tag. * Represents a NBT tag.
*
* @author Graham Edgecombe
*
*/ */
public abstract class Tag { public abstract class Tag {
/**
* The name of this tag.
*/
private final String name; private final String name;
/**
* Create a new tag with an empty name.
*/
Tag() {
this("");
}
/** /**
* Creates the tag with the specified name. * Creates the tag with the specified name.
* *
* @param name * @param name the name
* The name.
*/ */
public Tag(String name) { Tag(String name) {
if (name == null) {
name = "";
}
this.name = name; this.name = name;
} }
/** /**
* Gets the name of this tag. * Gets the name of this tag.
* *
* @return The name of this tag. * @return the name of this tag
*/ */
public final String getName() { public final String getName() {
return name; return name;
@ -54,7 +57,7 @@ public abstract class Tag {
/** /**
* Gets the value of this tag. * Gets the value of this tag.
* *
* @return The value of this tag. * @return the value
*/ */
public abstract Object getValue(); public abstract Object getValue();

View File

@ -22,6 +22,8 @@ package com.sk89q.worldedit;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extent.ChangeSetExtent; import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
@ -69,12 +71,12 @@ import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape;
import com.sk89q.worldedit.regions.shape.ArbitraryShape; import com.sk89q.worldedit.regions.shape.ArbitraryShape;
import com.sk89q.worldedit.regions.shape.RegionShape; import com.sk89q.worldedit.regions.shape.RegionShape;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.*;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.collection.DoubleArrayList; import com.sk89q.worldedit.util.collection.DoubleArrayList;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.NullWorld;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.*; import java.util.*;
@ -376,6 +378,16 @@ public class EditSession implements Extent {
return changeSet.size(); return changeSet.size();
} }
@Override
public BaseBiome getBiome(Vector2D position) {
return bypassNone.getBiome(position);
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
return bypassNone.setBiome(position, biome);
}
@Override @Override
public BaseBlock getLazyBlock(Vector position) { public BaseBlock getLazyBlock(Vector position) {
return world.getLazyBlock(position); return world.getLazyBlock(position);
@ -581,6 +593,12 @@ public class EditSession implements Extent {
return getBlock(position).isAir() && setBlock(position, block); return getBlock(position).isAir() && setBlock(position, block);
} }
@Override
@Nullable
public Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity) {
return bypassNone.createEntity(location, entity);
}
/** /**
* Insert a contrived block change into the history. * Insert a contrived block change into the history.
* *
@ -637,6 +655,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.
*/ */
@ -1148,6 +1176,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));
} }
@ -2230,7 +2259,7 @@ public class EditSession implements Extent {
} // while } // while
} }
public int makeBiomeShape(final Region region, final Vector zero, final Vector unit, final BiomeType biomeType, final String expressionString, final boolean hollow) throws ExpressionException, MaxChangedBlocksException { public int makeBiomeShape(final Region region, final Vector zero, final Vector unit, final BaseBiome biomeType, final String expressionString, final boolean hollow) throws ExpressionException, MaxChangedBlocksException {
final Vector2D zero2D = zero.toVector2D(); final Vector2D zero2D = zero.toVector2D();
final Vector2D unit2D = unit.toVector2D(); final Vector2D unit2D = unit.toVector2D();
@ -2243,7 +2272,7 @@ public class EditSession implements Extent {
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) { final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
@Override @Override
protected BiomeType getBiome(int x, int z, BiomeType defaultBiomeType) { protected BaseBiome getBiome(int x, int z, BaseBiome defaultBiomeType) {
final Vector2D current = new Vector2D(x, z); final Vector2D current = new Vector2D(x, z);
environment.setCurrentBlock(current.toVector(0)); environment.setCurrentBlock(current.toVector(0));
final Vector2D scaled = current.subtract(zero2D).divide(unit2D); final Vector2D scaled = current.subtract(zero2D).divide(unit2D);

View File

@ -38,11 +38,17 @@ import com.sk89q.worldedit.internal.cui.SelectionShapeEvent;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.snapshot.Snapshot;
import java.util.*; import javax.annotation.Nullable;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.TimeZone;
/** /**
* An instance of this represents the WorldEdit session of a user. A session * An instance of this represents the WorldEdit session of a user. A session
@ -62,7 +68,7 @@ public class LocalSession {
private boolean placeAtPos1 = false; private boolean placeAtPos1 = false;
private LinkedList<EditSession> history = new LinkedList<EditSession>(); private LinkedList<EditSession> history = new LinkedList<EditSession>();
private int historyPointer = 0; private int historyPointer = 0;
private CuboidClipboard clipboard; private ClipboardHolder clipboard;
private boolean toolControl = true; private boolean toolControl = true;
private boolean superPickaxe = false; private boolean superPickaxe = false;
private BlockTool pickaxeMode = new SinglePickaxe(); private BlockTool pickaxeMode = new SinglePickaxe();
@ -324,9 +330,9 @@ public class LocalSession {
* Gets the clipboard. * Gets the clipboard.
* *
* @return clipboard, may be null * @return clipboard, may be null
* @throws EmptyClipboardException * @throws EmptyClipboardException thrown if no clipboard is set
*/ */
public CuboidClipboard getClipboard() throws EmptyClipboardException { public ClipboardHolder getClipboard() throws EmptyClipboardException {
if (clipboard == null) { if (clipboard == null) {
throw new EmptyClipboardException(); throw new EmptyClipboardException();
} }
@ -336,9 +342,11 @@ public class LocalSession {
/** /**
* Sets the clipboard. * Sets the clipboard.
* *
* @param clipboard * <p>Pass {@code null} to clear the clipboard.</p>
*
* @param clipboard the clipboard, or null if the clipboard is to be cleared
*/ */
public void setClipboard(CuboidClipboard clipboard) { public void setClipboard(@Nullable ClipboardHolder clipboard) {
this.clipboard = clipboard; this.clipboard = clipboard;
} }

View File

@ -19,13 +19,11 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.util.Random;
/** /**
* A legacy abstract implementation of {@link World}. New implementations * A legacy abstract implementation of {@link World}. New implementations
* should use {@link AbstractWorld} when possible. * should use {@link AbstractWorld} when possible.
@ -35,140 +33,11 @@ import java.util.Random;
@Deprecated @Deprecated
public abstract class LocalWorld extends AbstractWorld { 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() {
}
}
/**
* @deprecated Don't use this anymore. It will be removed
*/
@SuppressWarnings("ProtectedField")
@Deprecated
protected Random random = new Random();
@Override
public BaseBlock getBlock(Vector pt) {
checkLoadedChunk(pt);
@SuppressWarnings("deprecation") int type = getBlockType(pt);
@SuppressWarnings("deprecation") int data = getBlockData(pt);
switch (type) {
case BlockID.WALL_SIGN:
case BlockID.SIGN_POST: {
SignBlock block = new SignBlock(type, data);
copyFromWorld(pt, block);
return block;
}
case BlockID.CHEST: {
ChestBlock block = new ChestBlock(data);
copyFromWorld(pt, block);
return block;
}
case BlockID.FURNACE:
case BlockID.BURNING_FURNACE: {
FurnaceBlock block = new FurnaceBlock(type, data);
copyFromWorld(pt, block);
return block;
}
case BlockID.DISPENSER: {
DispenserBlock block = new DispenserBlock(data);
copyFromWorld(pt, block);
return block;
}
case BlockID.MOB_SPAWNER: {
MobSpawnerBlock block = new MobSpawnerBlock(data);
copyFromWorld(pt, block);
return block;
}
case BlockID.NOTE_BLOCK: {
NoteBlock block = new NoteBlock(data);
copyFromWorld(pt, block);
return block;
}
case BlockID.HEAD: {
SkullBlock block = new SkullBlock(data);
copyFromWorld(pt, block);
return block;
}
default:
return new BaseBlock(type, data);
}
}
/**
* Given a block and a position, copy data from the world to the block
* based on the type of block.
* </p>
* The provided {@link BaseBlock} should match that of the one in the
* world.
*
* @param position the position
* @param block the block
* @return true if the copy operation succeeded, false otherwise
*/
public abstract boolean copyFromWorld(Vector position, BaseBlock block);
@Override @Override
public BaseBlock getLazyBlock(Vector position) { public BaseBlock getLazyBlock(Vector position) {
return getBlock(position); return getBlock(position);
} }
@Override
public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
boolean successful;
// Default implementation will call the old deprecated methods
if (notifyAdjacent) {
successful = setTypeIdAndData(pt, block.getId(), block.getData());
} else {
successful = setTypeIdAndDataFast(pt, block.getId(), block.getData());
}
copyToWorld(pt, block);
return successful;
}
/**
* Given a block and a position, copy data to the world from the block
* based on the type of block.
* </p>
* The provided {@link BaseBlock} should match that of the one in the
* world.
*
* @param position the position
* @param block the block
* @return true if the copy operation succeeded, false otherwise
*/
public abstract boolean copyToWorld(Vector position, BaseBlock block);
@Override
public boolean setBlock(Vector pt, BaseBlock block) throws WorldEditException {
return setBlock(pt, block, true);
}
@Override @Override
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException { public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException {
switch (type) { switch (type) {

View File

@ -600,8 +600,7 @@ public class Vector implements Comparable<Vector> {
* @param translateZ what to add after rotation * @param translateZ what to add after rotation
* @return * @return
*/ */
public Vector transform2D(double angle, public Vector transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
double aboutX, double aboutZ, double translateX, double translateZ) {
angle = Math.toRadians(angle); angle = Math.toRadians(angle);
double x = this.x - aboutX; double x = this.x - aboutX;
double z = this.z - aboutZ; double z = this.z - aboutZ;
@ -652,6 +651,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.toDegrees(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) Math.toDegrees(((t + _2pi) % _2pi));
}
/** /**
* Get a block point from a point. * Get a block point from a point.
* *
@ -792,4 +825,5 @@ public class Vector implements Comparable<Vector> {
(v1.z + v2.z) / 2 (v1.z + v2.z) / 2
); );
} }
} }

View File

@ -517,8 +517,7 @@ public class Vector2D {
* @param translateZ what to add after rotation * @param translateZ what to add after rotation
* @return * @return
*/ */
public Vector2D transform2D(double angle, public Vector2D transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
double aboutX, double aboutZ, double translateX, double translateZ) {
angle = Math.toRadians(angle); angle = Math.toRadians(angle);
double x = this.x - aboutX; double x = this.x - aboutX;
double z = this.z - aboutZ; double z = this.z - aboutZ;

View File

@ -27,13 +27,13 @@ import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.event.platform.BlockInteractEvent; import com.sk89q.worldedit.event.platform.BlockInteractEvent;
import com.sk89q.worldedit.event.platform.InputType; import com.sk89q.worldedit.event.platform.InputType;
import com.sk89q.worldedit.event.platform.PlayerInputEvent; import com.sk89q.worldedit.event.platform.PlayerInputEvent;
import com.sk89q.worldedit.extension.factory.BlockFactory;
import com.sk89q.worldedit.extension.factory.MaskFactory;
import com.sk89q.worldedit.extension.factory.PatternFactory;
import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extension.platform.PlatformManager; import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.extension.registry.BlockRegistry;
import com.sk89q.worldedit.extension.registry.MaskRegistry;
import com.sk89q.worldedit.extension.registry.PatternRegistry;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.function.pattern.Patterns;
@ -46,9 +46,14 @@ import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler; import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import javax.script.ScriptException; import javax.script.ScriptException;
import java.io.*; import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -84,13 +89,14 @@ public class WorldEdit {
private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus); private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
private final SessionManager sessions = new SessionManager(this); private final SessionManager sessions = new SessionManager(this);
private final BlockRegistry blockRegistry = new BlockRegistry(this); private final BlockFactory blockFactory = new BlockFactory(this);
private final MaskRegistry maskRegistry = new MaskRegistry(this); private final MaskFactory maskFactory = new MaskFactory(this);
private final PatternRegistry patternRegistry = new PatternRegistry(this); private final PatternFactory patternFactory = new PatternFactory(this);
static { static {
WorldEditPrefixHandler.register("com.sk89q.worldedit"); WorldEditPrefixHandler.register("com.sk89q.worldedit");
getVersion(); getVersion();
BundledBlockData.getInstance(); // Load block registry
} }
private WorldEdit() { private WorldEdit() {
@ -132,33 +138,33 @@ public class WorldEdit {
} }
/** /**
* Get the block registry from which new {@link BaseBlock}s can be * Get the block factory from which new {@link BaseBlock}s can be
* constructed. * constructed.
* *
* @return the block registry * @return the block factory
*/ */
public BlockRegistry getBlockRegistry() { public BlockFactory getBlockFactory() {
return blockRegistry; return blockFactory;
} }
/** /**
* Get the mask registry from which new {@link com.sk89q.worldedit.function.mask.Mask}s * Get the mask factory from which new {@link com.sk89q.worldedit.function.mask.Mask}s
* can be constructed. * can be constructed.
* *
* @return the mask registry * @return the mask factory
*/ */
public MaskRegistry getMaskRegistry() { public MaskFactory getMaskFactory() {
return maskRegistry; return maskFactory;
} }
/** /**
* Get the pattern registry from which new {@link com.sk89q.worldedit.function.pattern.Pattern}s * Get the pattern factory from which new {@link com.sk89q.worldedit.function.pattern.Pattern}s
* can be constructed. * can be constructed.
* *
* @return the pattern registry * @return the pattern factory
*/ */
public PatternRegistry getPatternRegistry() { public PatternFactory getPatternFactory() {
return patternRegistry; return patternFactory;
} }
/** /**
@ -211,7 +217,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Deprecated @Deprecated
@ -220,7 +226,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Deprecated @Deprecated
@ -231,11 +237,11 @@ public class WorldEdit {
context.setSession(getSession(player)); context.setSession(getSession(player));
context.setRestricted(!allAllowed); context.setRestricted(!allAllowed);
context.setPreferringWildcard(allowNoData); context.setPreferringWildcard(allowNoData);
return getBlockRegistry().parseFromInput(arg, context); return getBlockFactory().parseFromInput(arg, context);
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Deprecated @Deprecated
@ -244,7 +250,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromListInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -258,7 +264,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -267,7 +273,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromListInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -276,7 +282,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getBlockRegistry()} and {@link BlockRegistry#parseFromListInput(String, ParserContext)} * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -290,7 +296,7 @@ public class WorldEdit {
} }
/** /**
* @deprecated Use {@link #getPatternRegistry()} and {@link BlockRegistry#parseFromInput(String, ParserContext)} * @deprecated Use {@link #getPatternFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -299,11 +305,11 @@ public class WorldEdit {
context.setActor(player); context.setActor(player);
context.setWorld(player.getWorld()); context.setWorld(player.getWorld());
context.setSession(getSession(player)); context.setSession(getSession(player));
return Patterns.wrap(getPatternRegistry().parseFromInput(input, context)); return Patterns.wrap(getPatternFactory().parseFromInput(input, context));
} }
/** /**
* @deprecated Use {@link #getMaskRegistry()} ()} and {@link MaskRegistry#parseFromInput(String, ParserContext)} * @deprecated Use {@link #getMaskFactory()} ()} and {@link MaskFactory#parseFromInput(String, ParserContext)}
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -312,7 +318,7 @@ public class WorldEdit {
context.setActor(player); context.setActor(player);
context.setWorld(player.getWorld()); context.setWorld(player.getWorld());
context.setSession(session); context.setSession(session);
return Masks.wrap(getMaskRegistry().parseFromInput(input, context)); return Masks.wrap(getMaskFactory().parseFromInput(input, context));
} }
/** /**

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.sk89q.worldedit.internal.LocalWorldAdapter; import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.world.World;
/** /**
* @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible * @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible
@ -97,7 +98,7 @@ public class WorldVector extends Vector {
* @param location the location * @param location the location
*/ */
public WorldVector(com.sk89q.worldedit.util.Location location) { public WorldVector(com.sk89q.worldedit.util.Location location) {
this(LocalWorldAdapter.adapt(location.getWorld()), location.getX(), location.getY(), location.getZ()); this(LocalWorldAdapter.adapt((World) location.getExtent()), location.getX(), location.getY(), location.getZ());
} }
/** /**

View File

@ -100,17 +100,27 @@ public class BaseBlock extends Block implements TileEntityBlock {
* @see #setData(int) * @see #setData(int)
* @see #setNbtData(CompoundTag) * @see #setNbtData(CompoundTag)
*/ */
public BaseBlock(int id, int data, CompoundTag nbtData) throws DataException { public BaseBlock(int id, int data, CompoundTag nbtData) {
setId(id); setId(id);
setData(data); setData(data);
setNbtData(nbtData); setNbtData(nbtData);
} }
/**
* Create a clone of another block.
*
* @param other the other block
*/
public BaseBlock(BaseBlock other) {
this(other.getId(), other.getData(), other.getNbtData());
}
/** /**
* Get the ID of the block. * Get the ID of the block.
* *
* @return ID (between 0 and {@link #MAX_ID}) * @return ID (between 0 and {@link #MAX_ID})
*/ */
@Override
public int getId() { public int getId() {
return id; return id;
} }
@ -138,6 +148,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
* *
* @param id block id (between 0 and {@link #MAX_ID}). * @param id block id (between 0 and {@link #MAX_ID}).
*/ */
@Override
public void setId(int id) { public void setId(int id) {
internalSetId(id); internalSetId(id);
} }
@ -147,6 +158,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
* *
* @return data value (0-15) * @return data value (0-15)
*/ */
@Override
public int getData() { public int getData() {
return data; return data;
} }
@ -175,6 +187,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
* *
* @param data block data value (between 0 and {@link #MAX_DATA}). * @param data block data value (between 0 and {@link #MAX_DATA}).
*/ */
@Override
public void setData(int data) { public void setData(int data) {
internalSetData(data); internalSetData(data);
} }
@ -187,6 +200,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
* @see #setId(int) * @see #setId(int)
* @see #setData(int) * @see #setData(int)
*/ */
@Override
public void setIdAndData(int id, int data) { public void setIdAndData(int id, int data) {
setId(id); setId(id);
setData(data); setData(data);
@ -198,6 +212,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
* *
* @return true if the data value is -1 * @return true if the data value is -1
*/ */
@Override
public boolean hasWildcardData() { public boolean hasWildcardData() {
return getData() == -1; return getData() == -1;
} }
@ -227,7 +242,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
} }
@Override @Override
public void setNbtData(CompoundTag nbtData) throws DataException { public void setNbtData(CompoundTag nbtData) {
this.nbtData = nbtData; this.nbtData = nbtData;
} }

View File

@ -0,0 +1,71 @@
/*
* 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.blocks;
/**
* Describes the material for a block.
*/
public interface BlockMaterial {
boolean isRenderedAsNormalBlock();
boolean isFullCube();
boolean isOpaque();
boolean isPowerSource();
boolean isLiquid();
boolean isSolid();
float getHardness();
float getResistance();
float getSlipperiness();
boolean isGrassBlocking();
float getAmbientOcclusionLightValue();
int getLightOpacity();
int getLightValue();
boolean isFragileWhenPushed();
boolean isUnpushable();
boolean isAdventureModeExempt();
boolean isTicksRandomly();
boolean isUsingNeighborLight();
boolean isMovementBlocker();
boolean isBurnable();
boolean isToolRequired();
boolean isReplacedDuringPlacement();
}

View File

@ -23,15 +23,29 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.FlatRegionFunction;
import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
import com.sk89q.worldedit.function.biome.BiomeReplace;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.masks.BiomeTypeMask; import com.sk89q.worldedit.function.mask.Mask2D;
import com.sk89q.worldedit.masks.InvertedMask; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.Regions;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.biome.BiomeData;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -64,7 +78,7 @@ public class BiomeCommands {
max = 1 max = 1
) )
@CommandPermissions("worldedit.biome.list") @CommandPermissions("worldedit.biome.list")
public void biomeList(Actor actor, CommandContext args) throws WorldEditException { public void biomeList(Player player, CommandContext args) throws WorldEditException {
int page; int page;
int offset; int offset;
int count = 0; int count = 0;
@ -76,17 +90,23 @@ public class BiomeCommands {
offset = (page - 1) * 19; offset = (page - 1) * 19;
} }
List<BiomeType> biomes = worldEdit.getServer().getBiomes().all(); BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
List<BaseBiome> biomes = biomeRegistry.getBiomes();
int totalPages = biomes.size() / 19 + 1; int totalPages = biomes.size() / 19 + 1;
actor.print("Available Biomes (page " + page + "/" + totalPages + ") :"); player.print("Available Biomes (page " + page + "/" + totalPages + ") :");
for (BiomeType biome : biomes) { for (BaseBiome biome : biomes) {
if (offset > 0) { if (offset > 0) {
offset--; offset--;
} else { } else {
actor.print(" " + biome.getName()); BiomeData data = biomeRegistry.getData(biome);
if (data != null) {
player.print(" " + data.getName());
if (++count == 19) { if (++count == 19) {
break; break;
} }
} else {
player.print(" <unknown #" + biome.getId() + ">");
}
} }
} }
} }
@ -103,7 +123,11 @@ public class BiomeCommands {
max = 0 max = 0
) )
@CommandPermissions("worldedit.biome.info") @CommandPermissions("worldedit.biome.info")
public void biomeInfo(CommandContext args, Player player, LocalSession session) throws WorldEditException { public void biomeInfo(Player player, LocalSession session, CommandContext args) throws WorldEditException {
BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
Set<BaseBiome> biomes = new HashSet<BaseBiome>();
String qualifier;
if (args.hasFlag('t')) { if (args.hasFlag('t')) {
Vector blockPosition = player.getBlockTrace(300); Vector blockPosition = player.getBlockTrace(300);
if (blockPosition == null) { if (blockPosition == null) {
@ -111,15 +135,18 @@ public class BiomeCommands {
return; return;
} }
BiomeType biome = player.getWorld().getBiome(blockPosition.toVector2D()); BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
player.print("Biome: " + biome.getName()); biomes.add(biome);
qualifier = "at line of sight point";
} else if (args.hasFlag('p')) { } else if (args.hasFlag('p')) {
BiomeType biome = player.getWorld().getBiome(player.getPosition().toVector2D()); BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D());
player.print("Biome: " + biome.getName()); biomes.add(biome);
qualifier = "at your position";
} else { } else {
World world = player.getWorld(); World world = player.getWorld();
Region region = session.getSelection(world); Region region = session.getSelection(world);
Set<BiomeType> biomes = new HashSet<BiomeType>();
if (region instanceof FlatRegion) { if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) { for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
@ -131,9 +158,16 @@ public class BiomeCommands {
} }
} }
player.print("Biomes:"); qualifier = "in your selection";
for (BiomeType biome : biomes) { }
player.print(" " + biome.getName());
player.print(biomes.size() != 1 ? "Biomes " + qualifier + ":" : "Biome " + qualifier + ":");
for (BaseBiome biome : biomes) {
BiomeData data = biomeRegistry.getData(biome);
if (data != null) {
player.print(" " + data.getName());
} else {
player.print(" <unknown #" + biome.getId() + ">");
} }
} }
} }
@ -146,64 +180,30 @@ public class BiomeCommands {
help = help =
"Set the biome of the region.\n" + "Set the biome of the region.\n" +
"By default use all the blocks contained in your selection.\n" + "By default use all the blocks contained in your selection.\n" +
"-p use the block you are currently in", "-p use the block you are currently in"
min = 1,
max = 1
) )
@Logging(REGION) @Logging(REGION)
@CommandPermissions("worldedit.biome.set") @CommandPermissions("worldedit.biome.set")
public void setBiome(CommandContext args, Player player, LocalSession session, EditSession editSession) throws WorldEditException { public void setBiome(Player player, LocalSession session, EditSession editSession, BaseBiome target, @Switch('p') boolean atPosition) throws WorldEditException {
final BiomeType target = worldEdit.getServer().getBiomes().get(args.getString(0));
if (target == null) {
player.printError("Biome '" + args.getString(0) + "' does not exist!");
return;
}
Mask mask = editSession.getMask();
BiomeTypeMask biomeMask = null;
boolean inverted = false;
if (mask instanceof BiomeTypeMask) {
biomeMask = (BiomeTypeMask) mask;
} else if (mask instanceof InvertedMask && ((InvertedMask) mask).getInvertedMask() instanceof BiomeTypeMask) {
inverted = true;
biomeMask = (BiomeTypeMask) ((InvertedMask) mask).getInvertedMask();
}
if (args.hasFlag('p')) {
Vector2D pos = player.getPosition().toVector2D();
if (biomeMask == null || (biomeMask.matches2D(editSession, pos) ^ inverted)) {
player.getWorld().setBiome(pos, target);
player.print("Biome changed to " + target.getName() + " at your current location.");
} else {
player.print("Your global mask doesn't match this biome. Type //gmask to disable it.");
}
} else {
int affected = 0;
World world = player.getWorld(); World world = player.getWorld();
Region region = session.getSelection(world); Region region;
Mask mask = editSession.getMask();
Mask2D mask2d = mask != null ? mask.toMask2D() : null;
if (region instanceof FlatRegion) { if (atPosition) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) { region = new CuboidRegion(player.getPosition(), player.getPosition());
if (biomeMask == null || (biomeMask.matches2D(editSession, pt) ^ inverted)) {
world.setBiome(pt, target);
++affected;
}
}
} else { } else {
HashSet<Long> alreadyVisited = new HashSet<Long>(); region = session.getSelection(world);
for (Vector pt : region) {
if (!alreadyVisited.contains((long)pt.getBlockX() << 32 | pt.getBlockZ())) {
alreadyVisited.add(((long)pt.getBlockX() << 32 | pt.getBlockZ()));
if (biomeMask == null || (biomeMask.matches(editSession, pt) ^ inverted)) {
world.setBiome(pt.toVector2D(), target);
++affected;
}
}
}
} }
player.print("Biome changed to " + target.getName() + ". " + affected + " columns affected."); FlatRegionFunction replace = new BiomeReplace(editSession, target);
if (mask2d != null) {
replace = new FlatRegionMaskingFilter(mask2d, replace);
} }
FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace);
Operations.completeLegacy(visitor);
player.print("Biomes were changed in " + visitor.getAffected() + " columns. You may have to rejoin your game (or close and reopen your world) to see a change.");
} }
} }

View File

@ -22,17 +22,30 @@ package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalWorld.KillFlags; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
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.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID; 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.BrushTool;
import com.sk89q.worldedit.command.tool.brush.*; import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
import com.sk89q.worldedit.command.tool.brush.CylinderBrush;
import com.sk89q.worldedit.command.tool.brush.GravityBrush;
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.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
@ -117,32 +130,27 @@ public class BrushCommands {
@Command( @Command(
aliases = { "clipboard", "copy" }, aliases = { "clipboard", "copy" },
usage = "", usage = "",
flags = "a",
desc = "Choose the clipboard brush", desc = "Choose the clipboard brush",
help = help =
"Chooses the clipboard brush.\n" + "Chooses the clipboard brush.\n" +
"The -a flag makes it not paste air.", "The -a flag makes it not paste air.\n" +
min = 0, "Without the -p flag, the paste will appear centered at the target location. " +
max = 0 "With the flag, then the paste will appear relative to where you had " +
"stood relative to the copied area when you copied it."
) )
@CommandPermissions("worldedit.brush.clipboard") @CommandPermissions("worldedit.brush.clipboard")
public void clipboardBrush(Player player, LocalSession session, EditSession editSession, @Switch('a') boolean ignoreAir) throws WorldEditException { public void clipboardBrush(Player player, LocalSession session, EditSession editSession, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
CuboidClipboard clipboard = session.getClipboard(); Vector size = clipboard.getDimensions();
if (clipboard == null) {
player.printError("Copy something first.");
return;
}
Vector size = clipboard.getSize();
worldEdit.checkMaxBrushRadius(size.getBlockX()); worldEdit.checkMaxBrushRadius(size.getBlockX());
worldEdit.checkMaxBrushRadius(size.getBlockY()); worldEdit.checkMaxBrushRadius(size.getBlockY());
worldEdit.checkMaxBrushRadius(size.getBlockZ()); worldEdit.checkMaxBrushRadius(size.getBlockZ());
BrushTool tool = session.getBrushTool(player.getItemInHand()); BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setBrush(new ClipboardBrush(clipboard, ignoreAir), "worldedit.brush.clipboard"); tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard");
player.print("Clipboard brush shape equipped."); player.print("Clipboard brush shape equipped.");
} }
@ -220,13 +228,21 @@ public class BrushCommands {
@Command( @Command(
aliases = { "butcher", "kill" }, aliases = { "butcher", "kill" },
usage = "[radius] [command flags]", usage = "[radius]",
flags = "plangbtf",
desc = "Butcher brush", desc = "Butcher brush",
help = "Kills nearby mobs within the specified radius.\n" + help = "Kills nearby mobs within the specified radius.\n" +
"Any number of 'flags' that the //butcher command uses\n" + "Flags:" +
"may be specified as an argument", " -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, min = 0,
max = 2 max = 1
) )
@CommandPermissions("worldedit.brush.butcher") @CommandPermissions("worldedit.brush.butcher")
public void butcherBrush(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void butcherBrush(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
@ -245,24 +261,13 @@ public class BrushCommands {
return; return;
} }
FlagContainer flags = new FlagContainer(player); CreatureButcher flags = new CreatureButcher(player);
if (args.argsLength() == 2) { flags.fromCommand(args);
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");
}
BrushTool tool = session.getBrushTool(player.getItemInHand()); BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius); 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).", player.print(String.format("Butcher brush equipped (%.0f).", radius));
radius));
} }
} }

View File

@ -20,19 +20,32 @@
package com.sk89q.worldedit.command; package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.World;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
@ -57,87 +70,63 @@ public class ClipboardCommands {
@Command( @Command(
aliases = { "/copy" }, aliases = { "/copy" },
flags = "e", flags = "em",
desc = "Copy the selection to the clipboard", desc = "Copy the selection to the clipboard",
help = "Copy the selection to the clipboard\n" + help = "Copy the selection to the clipboard\n" +
"Flags:\n" + "Flags:\n" +
" -e controls whether entities are copied\n" + " -e controls whether entities are copied\n" +
" -m sets a source mask so that excluded blocks become air\n" +
"WARNING: Pasting entities cannot yet be undone!", "WARNING: Pasting entities cannot yet be undone!",
min = 0, min = 0,
max = 0 max = 0
) )
@CommandPermissions("worldedit.clipboard.copy") @CommandPermissions("worldedit.clipboard.copy")
public void copy(Player player, LocalSession session, EditSession editSession, @Switch('e') boolean copyEntities) throws WorldEditException { public void copy(Player player, LocalSession session, EditSession editSession,
Region region = session.getSelection(player.getWorld()); @Selection Region region, @Switch('e') boolean copyEntities,
Vector min = region.getMinimumPoint(); @Switch('m') Mask mask) throws WorldEditException {
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
CuboidClipboard clipboard = new CuboidClipboard( BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
max.subtract(min).add(Vector.ONE), clipboard.setOrigin(session.getPlacementPosition(player));
min, min.subtract(pos)); ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
if (mask != null) {
if (region instanceof CuboidRegion) { copy.setSourceMask(mask);
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
} }
Operations.completeLegacy(copy);
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
if (copyEntities) { player.print(region.getArea() + " block(s) were copied.");
for (LocalEntity entity : player.getWorld().getEntities(region)) {
clipboard.storeEntity(entity);
}
}
session.setClipboard(clipboard);
player.print("Block(s) copied.");
} }
@Command( @Command(
aliases = { "/cut" }, aliases = { "/cut" },
flags = "em",
usage = "[leave-id]", usage = "[leave-id]",
desc = "Cut the selection to the clipboard", desc = "Cut the selection to the clipboard",
help = "Copy the selection to the clipboard\n" + help = "Copy the selection to the clipboard\n" +
"Flags:\n" + "Flags:\n" +
" -e controls whether entities are copied\n" + " -e controls whether entities are copied\n" +
" -m sets a source mask so that excluded blocks become air\n" +
"WARNING: Cutting and pasting entities cannot yet be undone!", "WARNING: Cutting and pasting entities cannot yet be undone!",
flags = "e",
min = 0, min = 0,
max = 1 max = 1
) )
@CommandPermissions("worldedit.clipboard.cut") @CommandPermissions("worldedit.clipboard.cut")
@Logging(REGION) @Logging(REGION)
public void cut(Player player, LocalSession session, EditSession editSession, @Optional("air") BaseBlock block, @Switch('e') boolean copyEntities) throws WorldEditException { public void cut(Player player, LocalSession session, EditSession editSession,
World world = player.getWorld(); @Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean copyEntities,
@Switch('m') Mask mask) throws WorldEditException {
Region region = session.getSelection(world); BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
Vector min = region.getMinimumPoint(); clipboard.setOrigin(session.getPlacementPosition(player));
Vector max = region.getMaximumPoint(); ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
Vector pos = session.getPlacementPosition(player); copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
if (mask != null) {
CuboidClipboard clipboard = new CuboidClipboard( copy.setSourceMask(mask);
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
} }
Operations.completeLegacy(copy);
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
if (copyEntities) { player.print(region.getArea() + " block(s) were copied.");
LocalEntity[] entities = world.getEntities(region);
for (LocalEntity entity : entities) {
clipboard.storeEntity(entity);
}
world.killEntities(entities);
}
session.setClipboard(clipboard);
editSession.setBlocks(region, block);
player.print("Block(s) cut.");
} }
@Command( @Command(
@ -156,79 +145,76 @@ public class ClipboardCommands {
) )
@CommandPermissions("worldedit.clipboard.paste") @CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT) @Logging(PLACEMENT)
public void paste(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void paste(Player player, LocalSession session, EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
boolean atOrigin = args.hasFlag('o'); ClipboardHolder holder = session.getClipboard();
boolean pasteNoAir = args.hasFlag('a'); Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
CuboidClipboard clipboard = session.getClipboard(); Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
Operation operation = holder
.createPaste(editSession, editSession.getWorld().getWorldData())
.to(to)
.ignoreAirBlocks(ignoreAirBlocks)
.build();
Operations.completeLegacy(operation);
Vector pos = atOrigin ? session.getClipboard().getOrigin() if (selectPasted) {
: session.getPlacementPosition(player); Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);
if (atOrigin) { session.setRegionSelector(player.getWorld(), selector);
clipboard.place(editSession, pos, pasteNoAir); selector.learnChanges();
clipboard.pasteEntities(pos); selector.explainRegionAdjust(player, session);
player.findFreePosition();
player.print("Pasted to copy origin. Undo with //undo");
} else {
clipboard.paste(editSession, pos, pasteNoAir, true);
player.findFreePosition();
player.print("Pasted relative to you. Undo with //undo");
} }
if (args.hasFlag('s')) { player.print("The clipboard has been pasted at " + to);
World world = player.getWorld();
Vector pos2 = pos.add(clipboard.getSize().subtract(1, 1, 1));
if (!atOrigin) {
pos2 = pos2.add(clipboard.getOffset());
pos = pos.add(clipboard.getOffset());
}
session.setRegionSelector(world, new CuboidRegionSelector(world, pos, pos2));
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(player, session);
}
} }
@Command( @Command(
aliases = { "/rotate" }, aliases = { "/rotate" },
usage = "<angle-in-degrees>", usage = "<y-axis> [<x-axis>] [<z-axis>]",
desc = "Rotate the contents of the clipboard", desc = "Rotate the contents of the clipboard",
min = 1, help = "Non-destructively rotate the contents of the clipboard.\n" +
max = 1 "Angles are provided in degrees and a positive angle will result in a clockwise rotation. " +
"Multiple rotations can be stacked. Interpolation is not performed so angles should be a multiple of 90 degrees.\n"
) )
@CommandPermissions("worldedit.clipboard.rotate") @CommandPermissions("worldedit.clipboard.rotate")
public void rotate(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void rotate(Player player, LocalSession session, Double yRotate, @Optional Double xRotate, @Optional Double zRotate) throws WorldEditException {
if ((yRotate != null && Math.abs(yRotate % 90) > 0.001) ||
int angle = args.getInteger(0); xRotate != null && Math.abs(xRotate % 90) > 0.001 ||
zRotate != null && Math.abs(zRotate % 90) > 0.001) {
if (angle % 90 == 0) { player.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.");
CuboidClipboard clipboard = session.getClipboard();
clipboard.rotate2D(angle);
player.print("Clipboard rotated by " + angle + " degrees.");
} else {
player.printError("Angles must be divisible by 90 degrees.");
} }
ClipboardHolder holder = session.getClipboard();
AffineTransform transform = new AffineTransform();
transform = transform.rotateY(-(yRotate != null ? yRotate : 0));
transform = transform.rotateX(-(xRotate != null ? xRotate : 0));
transform = transform.rotateZ(-(zRotate != null ? zRotate : 0));
holder.setTransform(holder.getTransform().combine(transform));
player.print("The clipboard copy has been rotated.");
} }
@Command( @Command(
aliases = { "/flip" }, aliases = { "/flip" },
usage = "[dir]", usage = "[<direction>]",
flags = "p", desc = "Flip the contents of the clipboard",
desc = "Flip the contents of the clipboard.",
help = help =
"Flips the contents of the clipboard.\n" + "Flips the contents of the clipboard across the point from which the copy was made.\n",
"The -p flag flips the selection around the player,\n" +
"instead of the selections center.",
min = 0, min = 0,
max = 1 max = 1
) )
@CommandPermissions("worldedit.clipboard.flip") @CommandPermissions("worldedit.clipboard.flip")
public void flip(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void flip(Player player, LocalSession session, EditSession editSession,
CuboidClipboard.FlipDirection dir = worldEdit.getFlipDirection(player, args.argsLength() > 0 ? args.getString(0).toLowerCase() : "me"); @Optional(Direction.AIM) @Direction Vector direction) throws WorldEditException {
CuboidClipboard clipboard = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
clipboard.flip(dir, args.hasFlag('p')); Clipboard clipboard = holder.getClipboard();
player.print("Clipboard flipped."); AffineTransform transform = new AffineTransform();
transform = transform.scale(direction.positive().multiply(-2).add(1, 1, 1));
holder.setTransform(holder.getTransform().combine(transform));
player.print("The clipboard copy has been flipped.");
} }
@Command( @Command(

View File

@ -0,0 +1,143 @@
/*
* 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;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.CombinedTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.registry.WorldData;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Helper class to 'bake' a transform into a clipboard.
*
* <p>This class needs a better name and may need to be made more generic.</p>
*
* @see Clipboard
* @see Transform
*/
class FlattenedClipboardTransform {
private final Clipboard original;
private final Transform transform;
private final WorldData worldData;
/**
* Create a new instance.
*
* @param original the original clipboard
* @param transform the transform
* @param worldData the world data instance
*/
private FlattenedClipboardTransform(Clipboard original, Transform transform, WorldData worldData) {
checkNotNull(original);
checkNotNull(transform);
checkNotNull(worldData);
this.original = original;
this.transform = transform;
this.worldData = worldData;
}
/**
* Get the transformed region.
*
* @return the transformed region
*/
public Region getTransformedRegion() {
Region region = original.getRegion();
Vector minimum = region.getMinimumPoint();
Vector maximum = region.getMaximumPoint();
Transform transformAround =
new CombinedTransform(
new AffineTransform().translate(original.getOrigin().multiply(-1)),
transform,
new AffineTransform().translate(original.getOrigin()));
Vector[] corners = new Vector[] {
minimum,
maximum,
minimum.setX(maximum.getX()),
minimum.setY(maximum.getY()),
minimum.setZ(maximum.getZ()),
maximum.setX(minimum.getX()),
maximum.setY(minimum.getY()),
maximum.setZ(minimum.getZ()) };
for (int i = 0; i < corners.length; i++) {
corners[i] = transformAround.apply(corners[i]);
}
Vector newMinimum = corners[0];
Vector newMaximum = corners[0];
for (int i = 1; i < corners.length; i++) {
newMinimum = Vector.getMinimum(newMinimum, corners[i]);
newMaximum = Vector.getMaximum(newMaximum, corners[i]);
}
// After transformation, the points may not really sit on a block,
// so we should expand the region for edge cases
newMinimum = newMinimum.setX(Math.floor(newMinimum.getX()));
newMinimum = newMinimum.setY(Math.floor(newMinimum.getY()));
newMinimum = newMinimum.setZ(Math.floor(newMinimum.getZ()));
newMaximum = newMaximum.setX(Math.ceil(newMaximum.getX()));
newMaximum = newMaximum.setY(Math.ceil(newMaximum.getY()));
newMaximum = newMaximum.setZ(Math.ceil(newMaximum.getZ()));
return new CuboidRegion(newMinimum, newMaximum);
}
/**
* Create an operation to copy from the original clipboard to the given extent.
*
* @param target the target
* @return the operation
*/
public Operation copyTo(Extent target) {
BlockTransformExtent extent = new BlockTransformExtent(original, transform, worldData.getBlockRegistry());
ForwardExtentCopy copy = new ForwardExtentCopy(extent, original.getRegion(), original.getOrigin(), target, original.getOrigin());
copy.setTransform(transform);
return copy;
}
/**
* Create a new instance to bake the transform with.
*
* @param original the original clipboard
* @param transform the transform
* @param worldData the world data instance
* @return a builder
*/
public static FlattenedClipboardTransform transform(Clipboard original, Transform transform, WorldData worldData) {
return new FlattenedClipboardTransform(original, transform, worldData);
}
}

View File

@ -22,7 +22,11 @@ package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.function.pattern.Patterns;
@ -35,6 +39,7 @@ import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.binding.Text; import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.biome.BaseBiome;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*; import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
@ -332,7 +337,7 @@ public class GenerationCommands {
@Logging(ALL) @Logging(ALL)
public void generateBiome(Player player, LocalSession session, EditSession editSession, public void generateBiome(Player player, LocalSession session, EditSession editSession,
@Selection Region region, @Selection Region region,
BiomeType target, BaseBiome target,
@Text String expression, @Text String expression,
@Switch('h') boolean hollow, @Switch('h') boolean hollow,
@Switch('r') boolean useRawCoords, @Switch('r') boolean useRawCoords,
@ -368,7 +373,7 @@ public class GenerationCommands {
try { try {
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow); final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow);
player.findFreePosition(); player.findFreePosition();
player.print("Biome changed to " + target.getName() + ". " + affected + " columns affected."); player.print("" + affected + " columns affected.");
} catch (ExpressionException e) { } catch (ExpressionException e) {
player.printError(e.getMessage()); player.printError(e.getMessage());
} }

View File

@ -19,18 +19,42 @@
package com.sk89q.worldedit.command; package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.*; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.worldedit.*; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.FilenameException;
import com.sk89q.worldedit.FilenameResolutionException;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.schematic.SchematicFormat; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -39,6 +63,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/ */
public class SchematicCommands { public class SchematicCommands {
private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName());
private final WorldEdit worldEdit; private final WorldEdit worldEdit;
/** /**
@ -52,113 +77,94 @@ public class SchematicCommands {
} }
@Command( @Command(
aliases = { "load", "l" }, aliases = { "load" },
usage = "[format] <filename>", usage = "[<format>] <filename>",
desc = "Load a file into your clipboard", desc = "Load a schematic into your clipboard"
help = "Load a schematic file into your clipboard\n" +
"Format is a format from \"//schematic formats\"\n" +
"If the format is not provided, WorldEdit will\n" +
"attempt to automatically detect the format of the schematic",
flags = "f",
min = 1,
max = 2
) )
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"}) // TODO: Remove 'clipboard' perm @Deprecated
public void load(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { @CommandPermissions({ "worldedit.clipboard.load", "worldedit.schematic.load" })
public void load(Player player, LocalSession session, @Optional("schematic") String formatName, String filename) throws FilenameException {
LocalConfiguration config = worldEdit.getConfiguration(); LocalConfiguration config = worldEdit.getConfiguration();
String fileName;
String formatName;
if (args.argsLength() == 1) {
formatName = null;
fileName = args.getString(0);
} else {
formatName = args.getString(0);
fileName = args.getString(1);
}
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
File f = worldEdit.getSafeOpenFile(player, dir, fileName, "schematic", "schematic"); File f = worldEdit.getSafeOpenFile(player, dir, filename, "schematic", "schematic");
if (!f.exists()) { if (!f.exists()) {
player.printError("Schematic " + fileName + " does not exist!"); player.printError("Schematic " + filename + " does not exist!");
return; return;
} }
SchematicFormat format = formatName == null ? null : SchematicFormat.getFormat(formatName); ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) {
format = SchematicFormat.getFormat(f);
}
if (format == null) { if (format == null) {
player.printError("Unknown schematic format: " + formatName); player.printError("Unknown schematic format: " + formatName);
return; return;
} }
if (!format.isOfFormat(f) && !args.hasFlag('f')) { Closer closer = Closer.create();
player.printError(fileName + " is not of the " + format.getName() + " schematic format!");
return;
}
try { try {
String filePath = f.getCanonicalPath(); String filePath = f.getCanonicalPath();
String dirPath = dir.getCanonicalPath(); String dirPath = dir.getCanonicalPath();
if (!filePath.substring(0, dirPath.length()).equals(dirPath)) { if (!filePath.substring(0, dirPath.length()).equals(dirPath)) {
player.printError("Schematic could not read or it does not exist."); player.printError("Clipboard file could not read or it does not exist.");
} else { } else {
session.setClipboard(format.load(f)); FileInputStream fis = closer.register(new FileInputStream(f));
WorldEdit.logger.info(player.getName() + " loaded " + filePath); BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
player.print(fileName + " loaded. Paste it with //paste"); ClipboardReader reader = format.getReader(bis);
WorldData worldData = player.getWorld().getWorldData();
Clipboard clipboard = reader.read(player.getWorld().getWorldData());
session.setClipboard(new ClipboardHolder(clipboard, worldData));
log.info(player.getName() + " loaded " + filePath);
player.print(filename + " loaded. Paste it with //paste");
} }
} catch (DataException e) {
player.printError("Load error: " + e.getMessage());
} catch (IOException e) { } catch (IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage()); player.printError("Schematic could not read or it does not exist: " + e.getMessage());
log.log(Level.WARNING, "Failed to load a saved clipboard", e);
} finally {
try {
closer.close();
} catch (IOException ignored) {
}
} }
} }
@Command( @Command(
aliases = { "save", "s" }, aliases = { "save" },
usage = "[format] <filename>", usage = "[<format>] <filename>",
desc = "Save your clipboard to file", desc = "Save a schematic into your clipboard"
help = "Save your clipboard to file\n" +
"Format is a format from \"//schematic formats\"\n",
min = 1,
max = 2
) )
@CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"}) // TODO: Remove 'clipboard' perm @Deprecated
public void save(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException { @CommandPermissions({ "worldedit.clipboard.save", "worldedit.schematic.save" })
public void save(Player player, LocalSession session, @Optional("schematic") String formatName, String filename) throws CommandException, WorldEditException {
LocalConfiguration config = worldEdit.getConfiguration(); LocalConfiguration config = worldEdit.getConfiguration();
SchematicFormat format;
if (args.argsLength() == 1) {
if (SchematicFormat.getFormats().size() == 1) {
format = SchematicFormat.getFormats().iterator().next();
} else {
player.printError("More than one schematic format is available. Please provide the desired format");
return;
}
} else {
format = SchematicFormat.getFormat(args.getString(0));
if (format == null) {
player.printError("Unknown schematic format: " + args.getString(0));
return;
}
}
String filename = args.getString(args.argsLength() - 1);
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
File f = worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic"); File f = worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
if (!dir.exists()) { ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (!dir.mkdir()) { if (format == null) {
player.printError("The storage folder could not be created."); player.printError("Unknown schematic format: " + formatName);
return; return;
} }
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Transform transform = holder.getTransform();
Clipboard target;
// If we have a transform, bake it into the copy
if (!transform.isIdentity()) {
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform, holder.getWorldData());
target = new BlockArrayClipboard(result.getTransformedRegion());
target.setOrigin(clipboard.getOrigin());
Operations.completeLegacy(result.copyTo(target));
} else {
target = clipboard;
} }
Closer closer = Closer.create();
try { try {
// Create parent directories // Create parent directories
File parent = f.getParentFile(); File parent = f.getParentFile();
@ -168,13 +174,20 @@ public class SchematicCommands {
} }
} }
format.save(session.getClipboard(), f); FileOutputStream fos = closer.register(new FileOutputStream(f));
WorldEdit.logger.info(player.getName() + " saved " + f.getCanonicalPath()); BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target, holder.getWorldData());
log.info(player.getName() + " saved " + f.getCanonicalPath());
player.print(filename + " saved."); player.print(filename + " saved.");
} catch (DataException se) {
player.printError("Save error: " + se.getMessage());
} catch (IOException e) { } catch (IOException e) {
player.printError("Schematic could not written: " + e.getMessage()); player.printError("Schematic could not written: " + e.getMessage());
log.log(Level.WARNING, "Failed to write a saved clipboard", e);
} finally {
try {
closer.close();
} catch (IOException ignored) {
}
} }
} }
@ -215,13 +228,13 @@ public class SchematicCommands {
) )
@CommandPermissions("worldedit.schematic.formats") @CommandPermissions("worldedit.schematic.formats")
public void formats(Actor actor) throws WorldEditException { public void formats(Actor actor) throws WorldEditException {
actor.print("Available schematic formats (Name: Lookup names)"); actor.print("Available clipboard formats (Name: Lookup names)");
StringBuilder builder; StringBuilder builder;
boolean first = true; boolean first = true;
for (SchematicFormat format : SchematicFormat.getFormats()) { for (ClipboardFormat format : ClipboardFormat.values()) {
builder = new StringBuilder(); builder = new StringBuilder();
builder.append(format.getName()).append(": "); builder.append(format.name()).append(": ");
for (String lookupName : format.getLookupNames()) { for (String lookupName : format.getAliases()) {
if (!first) { if (!first) {
builder.append(", "); builder.append(", ");
} }
@ -292,9 +305,8 @@ public class SchematicCommands {
} }
build.append("\n\u00a79"); build.append("\n\u00a79");
SchematicFormat format = SchematicFormat.getFormat(file); ClipboardFormat format = ClipboardFormat.findByFile(file);
build.append(prefix).append(file.getName()) build.append(prefix).append(file.getName()).append(": ").append(format == null ? "Unknown" : format.name());
.append(": ").append(format == null ? "Unknown" : format.getName());
} }
return build.toString(); return build.toString();
} }

View File

@ -21,9 +21,9 @@ package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -33,6 +33,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.RegionSelector;
@ -43,6 +44,7 @@ import com.sk89q.worldedit.regions.selector.EllipsoidRegionSelector;
import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector; import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector; import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
import com.sk89q.worldedit.regions.selector.SphereRegionSelector; import com.sk89q.worldedit.regions.selector.SphereRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.ChunkStore;
@ -582,15 +584,16 @@ public class SelectionCommands {
public void size(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void size(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
if (args.hasFlag('c')) { if (args.hasFlag('c')) {
CuboidClipboard clipboard = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
Vector size = clipboard.getSize(); Clipboard clipboard = holder.getClipboard();
Vector offset = clipboard.getOffset(); Region region = clipboard.getRegion();
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
Vector origin = clipboard.getOrigin();
player.print("Size: " + size); player.print("Cuboid dimensions (max - min): " + size);
player.print("Offset: " + offset); player.print("Offset: " + origin);
player.print("Cuboid distance: " + size.distance(Vector.ONE)); player.print("Cuboid distance: " + size.distance(Vector.ONE));
player.print("# of blocks: " player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
+ (int) (size.getX() * size.getY() * size.getZ()));
return; return;
} }
@ -608,8 +611,7 @@ public class SelectionCommands {
} }
player.print("Size: " + size); player.print("Size: " + size);
player.print("Cuboid distance: " + region.getMaximumPoint() player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
.distance(region.getMinimumPoint()));
player.print("# of blocks: " + region.getArea()); player.print("# of blocks: " + region.getArea());
} }
@ -653,7 +655,7 @@ public class SelectionCommands {
max = 0 max = 0
) )
@CommandPermissions("worldedit.analysis.distr") @CommandPermissions("worldedit.analysis.distr")
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
int size; int size;
boolean useData = args.hasFlag('d'); boolean useData = args.hasFlag('d');
@ -661,13 +663,8 @@ public class SelectionCommands {
List<Countable<BaseBlock>> distributionData = null; List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) { if (args.hasFlag('c')) {
CuboidClipboard clip = session.getClipboard(); // TODO: Update for new clipboard
if (useData) { throw new CommandException("Needs to be re-written again");
distributionData = clip.getBlockDistributionWithData();
} else {
distribution = clip.getBlockDistribution();
}
size = clip.getHeight() * clip.getLength() * clip.getWidth();
} else { } else {
if (useData) { if (useData) {
distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld())); distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));

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

View File

@ -25,6 +25,7 @@ import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.world.World;
/** /**
* A super pickaxe mode that will remove blocks in an area. * A super pickaxe mode that will remove blocks in an area.
@ -48,7 +49,7 @@ public class AreaPickaxe implements BlockTool {
int ox = clicked.getBlockX(); int ox = clicked.getBlockX();
int oy = clicked.getBlockY(); int oy = clicked.getBlockY();
int oz = clicked.getBlockZ(); int oz = clicked.getBlockZ();
int initialType = clicked.getWorld().getBlockType(clicked.toVector()); int initialType = ((World) clicked.getExtent()).getBlockType(clicked.toVector());
if (initialType == 0) { if (initialType == 0) {
return true; return true;
@ -70,7 +71,7 @@ public class AreaPickaxe implements BlockTool {
continue; continue;
} }
clicked.getWorld().queueBlockBreakEffect(server, pos, initialType, clicked.toVector().distanceSq(pos)); ((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, clicked.toVector().distanceSq(pos));
editSession.setBlock(pos, air); editSession.setBlock(pos, air);
} }

View File

@ -41,7 +41,7 @@ public class BlockDataCyler implements DoubleActionBlockTool {
private boolean handleCycle(Platform server, LocalConfiguration config, private boolean handleCycle(Platform server, LocalConfiguration config,
Player player, LocalSession session, Location clicked, boolean forward) { Player player, LocalSession session, Location clicked, boolean forward) {
World world = clicked.getWorld(); World world = (World) clicked.getExtent();
int type = world.getBlockType(clicked.toVector()); int type = world.getBlockType(clicked.toVector());
int data = world.getBlockData(clicked.toVector()); int data = world.getBlockData(clicked.toVector());

View File

@ -48,7 +48,7 @@ public class BlockReplacer implements DoubleActionBlockTool {
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
BlockBag bag = session.getBlockBag(player); BlockBag bag = session.getBlockBag(player);
World world = clicked.getWorld(); World world = (World) clicked.getExtent();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, bag, player); EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, bag, player);
try { try {
@ -67,7 +67,7 @@ BlockBag bag = session.getBlockBag(player);
@Override @Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
World world = clicked.getWorld(); World world = (World) clicked.getExtent();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, player); EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, player);
targetBlock = (editSession).getBlock(clicked.toVector()); targetBlock = (editSession).getBlock(clicked.toVector());
BlockType type = BlockType.fromID(targetBlock.getType()); BlockType type = BlockType.fromID(targetBlock.getType());

View File

@ -53,7 +53,7 @@ public class FloatingTreeRemover implements BlockTool {
public boolean actPrimary(Platform server, LocalConfiguration config, public boolean actPrimary(Platform server, LocalConfiguration config,
Player player, LocalSession session, Location clicked) { Player player, LocalSession session, Location clicked) {
final World world = clicked.getWorld(); final World world = (World) clicked.getExtent();
switch (world.getBlockType(clicked.toVector())) { switch (world.getBlockType(clicked.toVector())) {
case BlockID.LOG: case BlockID.LOG:

Some files were not shown because too many files have changed in this diff Show More