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.google.code.findbugs', name: 'jsr305', version: '1.3.9'
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'
}

57
pom.xml
View File

@ -142,6 +142,22 @@
<type>jar</type>
</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. -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
@ -187,6 +203,18 @@
<defaultGoal>install</defaultGoal>
<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 -->
<extensions>
<extension>
@ -367,12 +395,25 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>com.sk89q:jchronic</include>
<include>com.thoughtworks.paranamer:paranamer</include>
<include>com.google.code.gson:gson</include>
<include>net.sf.trove4j:trove4j</include>
</includes>
</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>
</execution>
</executions>
@ -513,16 +554,6 @@
<type>jar</type>
<optional>true</optional>
</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>
<build>
@ -549,11 +580,11 @@
<!-- NMS support in Bukkit -->
<resource>
<targetPath>nmsblocks/</targetPath>
<targetPath>.</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/bukkit/resources/nmsblocks/</directory>
<directory>${basedir}/src/bukkit/resources/</directory>
<includes>
<include>*.class</include>
<include>**/*.class</include>
</includes>
</resource>
</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;
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.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
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.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 {
private Player player;
@ -170,11 +171,25 @@ public class BukkitPlayer extends LocalPlayer {
player.setFlying(true);
}
@Override
public BaseEntity getState() {
throw new UnsupportedOperationException("Cannot create a state from this object");
}
@Override
public com.sk89q.worldedit.util.Location getLocation() {
Location nativeLocation = player.getLocation();
Vector position = BukkitUtil.toVector(nativeLocation);
Vector direction = Vectors.fromEulerDeg(nativeLocation.getYaw(), nativeLocation.getPitch());
return new com.sk89q.worldedit.util.Location(getWorld(), position, direction);
return new com.sk89q.worldedit.util.Location(
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.CommandRegistration;
import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface;
@ -50,13 +49,13 @@ public class BukkitServerInterface extends ServerInterface implements MultiUserP
public Server server;
public WorldEditPlugin plugin;
private CommandRegistration dynamicCommands;
private BukkitBiomeTypes biomes;
private BukkitBiomeRegistry biomes;
private boolean hookingEvents;
public BukkitServerInterface(WorldEditPlugin plugin, Server server) {
this.plugin = plugin;
this.server = server;
this.biomes = new BukkitBiomeTypes();
this.biomes = new BukkitBiomeRegistry();
dynamicCommands = new CommandRegistration(plugin);
}
@ -81,11 +80,6 @@ public class BukkitServerInterface extends ServerInterface implements MultiUserP
plugin.loadConfiguration();
}
@Override
public BiomeTypes getBiomes() {
return biomes;
}
@Override
public int schedule(long delay, long period, Runnable task) {
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.sk89q.util.yaml.YAMLProcessor;
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.CylinderSelection;
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.extension.platform.Actor;
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.command.Command;
import org.bukkit.command.CommandSender;
@ -40,13 +53,20 @@ import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.*;
import java.util.Enumeration;
import javax.annotation.Nullable;
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.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Plugin for Bukkit.
*
@ -54,27 +74,13 @@ import java.util.zip.ZipEntry;
*/
public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
/**
* The name of the CUI's plugin channel registration
*/
private static final Logger log = Logger.getLogger(WorldEditPlugin.class.getCanonicalName());
public static final String CUI_PLUGIN_CHANNEL = "WECUI";
private static WorldEditPlugin INSTANCE;
/**
* The server interface that all server-related API goes through.
*/
private BukkitImplAdapter bukkitAdapter;
private BukkitServerInterface server;
/**
* Main WorldEdit instance.
*/
private WorldEdit controller;
/**
* Deprecated API.
*/
private WorldEditAPI api;
/**
* Holds the configuration for WorldEdit.
*/
private final WorldEditAPI api = new WorldEditAPI(this);
private BukkitConfiguration config;
/**
@ -82,41 +88,27 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/
@Override
public void onEnable() {
final String pluginYmlVersion = getDescription().getVersion();
final String manifestVersion = WorldEdit.getVersion();
this.INSTANCE = this;
if (!manifestVersion.equalsIgnoreCase(pluginYmlVersion)) {
WorldEdit.setVersion(manifestVersion + " (" + pluginYmlVersion + ")");
}
WorldEdit worldEdit = WorldEdit.getInstance();
// Make the data folders that WorldEdit uses
getDataFolder().mkdirs();
File targetDir = new File(getDataFolder() + File.separator + "nmsblocks");
targetDir.mkdir();
copyNmsBlockClasses(targetDir);
loadAdapter(); // Need an adapter to work with special blocks with NBT data
loadConfig(); // Load configuration
PermissionsResolverManager.initialize(this); // Setup permission resolver
// Create the default configuration file
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
// Setup platform
server = new BukkitServerInterface(this, getServer());
controller = WorldEdit.getInstance();
controller.getPlatformManager().register(server);
api = new WorldEditAPI(this);
worldEdit.getPlatformManager().register(server);
// Register CUI
getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
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().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
// 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());
}
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 {
JarFile jar = new JarFile(getFile());
@SuppressWarnings("rawtypes")
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) entries.nextElement();
if (!jarEntry.getName().startsWith("nmsblocks") || jarEntry.isDirectory()) continue;
adapterLoader.addFromPath(getClass().getClassLoader());
} catch (IOException e) {
log.log(Level.WARNING, "Failed to search path for Bukkit adapters");
}
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();
}
} catch (Throwable e) {}
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());
}
}
/**
@ -156,10 +151,13 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/
@Override
public void onDisable() {
if (controller != null) {
controller.clearSessions();
controller.getPlatformManager().unregister(server);
WorldEdit worldEdit = WorldEdit.getInstance();
worldEdit.clearSessions();
worldEdit.getPlatformManager().unregister(server);
if (config != null) {
config.unload();
}
if (server != null) {
server.unregisterCommands();
}
this.getServer().getScheduler().cancelTasks(this);
@ -177,7 +175,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
/**
* Create a default configuration file from the .jar.
*
* @param name
* @param name the filename
*/
protected void createDefaultConfiguration(String name) {
File actual = new File(getDataFolder(), name);
@ -257,7 +255,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
* @return
*/
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) {
LocalPlayer wePlayer = wrapPlayer(player);
LocalSession session = controller.getSession(wePlayer);
LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
BlockBag blockBag = session.getBlockBag(wePlayer);
EditSession editSession = controller.getEditSessionFactory()
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer);
editSession.enableQueue();
@ -286,12 +284,12 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
*/
public void remember(Player player, EditSession editSession) {
LocalPlayer wePlayer = wrapPlayer(player);
LocalSession session = controller.getSession(wePlayer);
LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
session.remember(editSession);
editSession.flushQueue();
controller.flushBlockBag(wePlayer, editSession);
WorldEdit.getInstance().flushBlockBag(wePlayer, editSession);
}
/**
@ -301,10 +299,9 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
* @param op
* @throws Throwable
*/
public void perform(Player player, WorldEditOperation op)
throws Throwable {
public void perform(Player player, WorldEditOperation op) throws Throwable {
LocalPlayer wePlayer = wrapPlayer(player);
LocalSession session = controller.getSession(wePlayer);
LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
EditSession editSession = createEditSession(player);
try {
@ -379,7 +376,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
* @return
*/
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");
}
LocalSession session = controller.getSession(wrapPlayer(player));
LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
RegionSelector selector = session.getRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()));
try {
@ -434,9 +431,30 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
throw new IllegalArgumentException("Null selection not allowed");
}
LocalSession session = controller.getSession(wrapPlayer(player));
LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
RegionSelector sel = selection.getRegionSelector();
session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel);
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

@ -1,36 +1,39 @@
/*
* 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 net.minecraft.world.biome.BiomeGenBase;
import com.sk89q.worldedit.BiomeType;
public class ForgeBiomeType implements BiomeType {
private BiomeGenBase biome;
public ForgeBiomeType(BiomeGenBase biome) {
this.biome = biome;
}
public String getName() {
return this.biome.biomeName;
}
}
/*
* 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.world.World;
import net.minecraft.util.Vec3;
final class ForgeAdapter {
private ForgeAdapter() {
}
public static World adapt(net.minecraft.world.World world) {
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;
import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.entity.Player;
@ -56,13 +56,13 @@ class ForgePlatform extends ServerInterface implements MultiUserPlatform {
private final ForgeWorldEdit mod;
private final MinecraftServer server;
private final ForgeBiomeTypes biomes;
private final ForgeBiomeRegistry biomes;
private boolean hookingEvents = false;
ForgePlatform(ForgeWorldEdit mod) {
this.mod = mod;
this.server = FMLCommonHandler.instance().getMinecraftServerInstance();
this.biomes = new ForgeBiomeTypes();
this.biomes = new ForgeBiomeRegistry();
}
boolean isHookingEvents() {
@ -95,11 +95,6 @@ class ForgePlatform extends ServerInterface implements MultiUserPlatform {
public void reload() {
}
@Override
public BiomeTypes getBiomes() {
return this.biomes;
}
@Override
public int schedule(long delay, long period, Runnable task) {
return -1;

View File

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

View File

@ -20,24 +20,26 @@
package com.sk89q.worldedit.forge;
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.BaseItemStack;
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.util.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
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.entity.Entity;
import net.minecraft.entity.EntityHanging;
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.entity.EntityList;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.NBTTagCompound;
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.gen.ChunkProviderServer;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
@ -176,22 +180,23 @@ public class ForgeWorld extends AbstractWorld {
}
@Override
public BiomeType getBiome(Vector2D position) {
public BaseBiome getBiome(Vector2D position) {
checkNotNull(position);
return ForgeBiomeTypes.getFromBaseBiome(getWorld().getBiomeGenForCoords(position.getBlockX(), position.getBlockZ()));
return new BaseBiome(getWorld().getBiomeGenForCoords(position.getBlockX(), position.getBlockZ()).biomeID);
}
@Override
public void setBiome(Vector2D position, BiomeType biome) {
public boolean setBiome(Vector2D position, BaseBiome biome) {
checkNotNull(position);
checkNotNull(biome);
if (getWorld().getChunkProvider().chunkExists(position.getBlockX(), position.getBlockZ())) {
Chunk chunk = getWorld().getChunkFromBlockCoords(position.getBlockX(), position.getBlockZ());
if ((chunk != null) && (chunk.isChunkLoaded)) {
chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) ForgeBiomeTypes.getFromBiomeType(biome).biomeID;
}
Chunk chunk = getWorld().getChunkFromBlockCoords(position.getBlockX(), position.getBlockZ());
if ((chunk != null) && (chunk.isChunkLoaded)) {
chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) biome.getId();
return true;
}
return false;
}
@Override
@ -199,7 +204,7 @@ public class ForgeWorld extends AbstractWorld {
checkNotNull(position);
checkNotNull(item);
if ((item == null) || (item.getType() == 0)) {
if (item.getType() == 0) {
return;
}
@ -208,121 +213,6 @@ public class ForgeWorld extends AbstractWorld {
getWorld().spawnEntityInWorld(entity);
}
@Override
@SuppressWarnings({"unchecked", "ConstantConditions"})
public int killMobs(Vector origin, double radius, int flags) {
boolean killPets = (flags & 0x1) != 0;
boolean killNPCs = (flags & 0x2) != 0;
boolean killAnimals = (flags & 0x4) != 0;
boolean killGolems = (flags & 0x8) != 0;
boolean killAmbient = (flags & 0x10) != 0;
int num = 0;
double radiusSq = radius * radius;
for (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
public boolean regenerate(Region region, EditSession editSession) {
BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)];
@ -425,6 +315,11 @@ public class ForgeWorld extends AbstractWorld {
return false;
}
@Override
public WorldData getWorldData() {
return ForgeWorldData.getInstance();
}
@Override
public boolean isValidBlockType(int id) {
return (id == 0) || (net.minecraft.block.Block.blocksList[id] != null);
@ -462,10 +357,10 @@ public class ForgeWorld extends AbstractWorld {
if (o == null) {
return false;
} else if ((o instanceof ForgeWorld)) {
ForgeWorld other = ((ForgeWorld) o);
World otherWorld = other.worldRef.get();
World thisWorld = other.worldRef.get();
return otherWorld != null && thisWorld != null && otherWorld.equals(thisWorld);
ForgeWorld other = ((ForgeWorld) o);
World otherWorld = other.worldRef.get();
World thisWorld = other.worldRef.get();
return otherWorld != null && thisWorld != null && otherWorld.equals(thisWorld);
} else if (o instanceof com.sk89q.worldedit.world.World) {
return ((com.sk89q.worldedit.world.World) o).getName().equals(getName());
} else {
@ -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.
*/

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);
}
ForgeBiomeRegistry.populate();
this.platform = new ForgePlatform(this);
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.TileEntityBlock;
import com.sk89q.worldedit.world.DataException;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
@ -29,10 +28,7 @@ public class TileEntityBaseBlock extends BaseBlock implements TileEntityBlock {
public TileEntityBaseBlock(int type, int data, TileEntity tile) {
super(type, data);
try {
setNbtData(NBTConverter.fromNative(copyNbtData(tile)));
} catch (DataException ignored) {
}
setNbtData(NBTConverter.fromNative(copyNbtData(tile)));
}
private static NBTTagCompound copyNbtData(TileEntity tile) {

View File

@ -1,32 +1,32 @@
#Don't put comments; they get removed
default-max-polygon-points=-1
schematic-save-dir=schematics
allow-extra-data-values=false
super-pickaxe-many-drop-items=true
register-help=true
nav-wand-item=345
profile=false
super-pickaxe-drop-items=true
disallowed-blocks=6,26,27,28,31,32,34,36,37,38,39,40,46,50,51,55,59,66,69,75,76,93,94,77,81,83,7,14,15,16,56
max-super-pickaxe-size=5
max-brush-radius=10
craftscript-dir=craftscripts
no-double-slash=false
wand-item=271
shell-save-type=
scripting-timeout=3000
snapshots-dir=
use-inventory-creative-override=false
log-file=worldedit.log
max-changed-blocks=-1
nav-wand-distance=50
butcher-default-radius=-1
default-max-changed-blocks=-1
history-size=15
use-inventory=false
allow-symbolic-links=false
use-inventory-override=false
log-commands=false
butcher-max-radius=-1
max-polygon-points=20
max-radius=-1
#Don't put comments; they get removed
default-max-polygon-points=-1
schematic-save-dir=schematics
allow-extra-data-values=false
super-pickaxe-many-drop-items=true
register-help=true
nav-wand-item=345
profile=false
super-pickaxe-drop-items=true
disallowed-blocks=6,26,27,28,31,32,34,36,37,38,39,40,46,50,51,55,59,66,69,75,76,93,94,77,81,83,7,14,15,16,56
max-super-pickaxe-size=5
max-brush-radius=10
craftscript-dir=craftscripts
no-double-slash=false
wand-item=271
shell-save-type=
scripting-timeout=3000
snapshots-dir=
use-inventory-creative-override=false
log-file=worldedit.log
max-changed-blocks=-1
nav-wand-distance=50
butcher-default-radius=-1
default-max-changed-blocks=-1
history-size=15
use-inventory=false
allow-symbolic-links=false
use-inventory-override=false
log-commands=false
butcher-max-radius=-1
max-polygon-points=20
max-radius=-1

View File

@ -19,17 +19,18 @@
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.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
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.
@ -78,7 +79,7 @@ public class ChestBlock extends ContainerBlock {
}
@Override
public void setNbtData(CompoundTag rootTag) throws DataException {
public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) {
return;
}
@ -87,19 +88,25 @@ public class ChestBlock extends ContainerBlock {
Tag t = values.get("id");
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>();
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new DataException("CompoundTag expected as child tag of Chest's Items");
try {
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new RuntimeException("CompoundTag expected as child tag of Chest's Items");
}
items.add((CompoundTag) tag);
}
items.add((CompoundTag) tag);
setItems(deserializeInventory(items));
} catch (InvalidFormatException e) {
throw new RuntimeException(e);
} catch (DataException e) {
throw new RuntimeException(e);
}
setItems(deserializeInventory(items));
}
}

View File

@ -1,142 +1,142 @@
/*
* 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
/**
* Represents a block that stores items.
*
* @author sk89q
*/
public abstract class ContainerBlock extends BaseBlock implements TileEntityBlock {
private BaseItemStack[] items;
public ContainerBlock(int type, int inventorySize) {
super(type);
this.items = new BaseItemStack[inventorySize];
}
public ContainerBlock(int type, int data, int inventorySize) {
super(type, data);
this.items = new BaseItemStack[inventorySize];
}
/**
* Get the list of items.
*
* @return
*/
public BaseItemStack[] getItems() {
return this.items;
}
/**
* Set the list of items.
*
* @param items
*/
public void setItems(BaseItemStack[] items) {
this.items = items;
}
@Override
public boolean hasNbtData() {
return true;
}
public Map<String, Tag> serializeItem(BaseItemStack item) {
Map<String, Tag> data = new HashMap<String, Tag>();
data.put("id", new ShortTag("id", (short) item.getType()));
data.put("Damage", new ShortTag("Damage", item.getData()));
data.put("Count", new ByteTag("Count", (byte) item.getAmount()));
if (item.getEnchantments().size() > 0) {
List<CompoundTag> enchantmentList = new ArrayList<CompoundTag>();
for(Map.Entry<Integer, Integer> entry : item.getEnchantments().entrySet()) {
Map<String, Tag> enchantment = new HashMap<String, Tag>();
enchantment.put("id", new ShortTag("id", entry.getKey().shortValue()));
enchantment.put("lvl", new ShortTag("lvl", entry.getValue().shortValue()));
enchantmentList.add(new CompoundTag(null, enchantment));
}
Map<String, Tag> auxData = new HashMap<String, Tag>();
auxData.put("ench", new ListTag("ench", CompoundTag.class, enchantmentList));
data.put("tag", new CompoundTag("tag", auxData));
}
return data;
}
public BaseItemStack deserializeItem(Map<String, Tag> data) throws DataException {
short id = NBTUtils.getChildTag(data, "id", ShortTag.class).getValue();
short damage = NBTUtils.getChildTag(data, "Damage", ShortTag.class).getValue();
byte count = NBTUtils.getChildTag(data, "Count", ByteTag.class).getValue();
BaseItemStack stack = new BaseItemStack(id, count, damage);
if (data.containsKey("tag")) {
Map<String, Tag> auxData = NBTUtils.getChildTag(data, "tag", CompoundTag.class).getValue();
ListTag ench = (ListTag)auxData.get("ench");
for(Tag e : ench.getValue()) {
Map<String, Tag> vars = ((CompoundTag) e).getValue();
short enchId = NBTUtils.getChildTag(vars, "id", ShortTag.class).getValue();
short enchLevel = NBTUtils.getChildTag(vars, "lvl", ShortTag.class).getValue();
stack.getEnchantments().put((int) enchId, (int) enchLevel);
}
}
return stack;
}
public BaseItemStack[] deserializeInventory(List<CompoundTag> items) throws DataException {
BaseItemStack[] stacks = new BaseItemStack[items.size()];
for (CompoundTag tag : items) {
Map<String, Tag> item = tag.getValue();
BaseItemStack stack = deserializeItem(item);
byte slot = NBTUtils.getChildTag(item, "Slot", ByteTag.class).getValue();
if (slot >= 0 && slot < stacks.length) {
stacks[slot] = stack;
}
}
return stacks;
}
public List<CompoundTag> serializeInventory(BaseItemStack[] items) {
List<CompoundTag> tags = new ArrayList<CompoundTag>();
for (int i = 0; i < items.length; ++i) {
if (items[i] != null) {
Map<String, Tag> tagData = serializeItem(items[i]);
tagData.put("Slot", new ByteTag("Slot", (byte) i));
tags.add(new CompoundTag("", tagData));
}
}
return tags;
}
}
/*
* 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
/**
* Represents a block that stores items.
*
* @author sk89q
*/
public abstract class ContainerBlock extends BaseBlock implements TileEntityBlock {
private BaseItemStack[] items;
public ContainerBlock(int type, int inventorySize) {
super(type);
this.items = new BaseItemStack[inventorySize];
}
public ContainerBlock(int type, int data, int inventorySize) {
super(type, data);
this.items = new BaseItemStack[inventorySize];
}
/**
* Get the list of items.
*
* @return
*/
public BaseItemStack[] getItems() {
return this.items;
}
/**
* Set the list of items.
*
* @param items
*/
public void setItems(BaseItemStack[] items) {
this.items = items;
}
@Override
public boolean hasNbtData() {
return true;
}
public Map<String, Tag> serializeItem(BaseItemStack item) {
Map<String, Tag> data = new HashMap<String, Tag>();
data.put("id", new ShortTag("id", (short) item.getType()));
data.put("Damage", new ShortTag("Damage", item.getData()));
data.put("Count", new ByteTag("Count", (byte) item.getAmount()));
if (item.getEnchantments().size() > 0) {
List<CompoundTag> enchantmentList = new ArrayList<CompoundTag>();
for(Map.Entry<Integer, Integer> entry : item.getEnchantments().entrySet()) {
Map<String, Tag> enchantment = new HashMap<String, Tag>();
enchantment.put("id", new ShortTag("id", entry.getKey().shortValue()));
enchantment.put("lvl", new ShortTag("lvl", entry.getValue().shortValue()));
enchantmentList.add(new CompoundTag(null, enchantment));
}
Map<String, Tag> auxData = new HashMap<String, Tag>();
auxData.put("ench", new ListTag("ench", CompoundTag.class, enchantmentList));
data.put("tag", new CompoundTag("tag", auxData));
}
return data;
}
public BaseItemStack deserializeItem(Map<String, Tag> data) throws DataException {
short id = NBTUtils.getChildTag(data, "id", ShortTag.class).getValue();
short damage = NBTUtils.getChildTag(data, "Damage", ShortTag.class).getValue();
byte count = NBTUtils.getChildTag(data, "Count", ByteTag.class).getValue();
BaseItemStack stack = new BaseItemStack(id, count, damage);
if (data.containsKey("tag")) {
Map<String, Tag> auxData = NBTUtils.getChildTag(data, "tag", CompoundTag.class).getValue();
ListTag ench = (ListTag)auxData.get("ench");
for(Tag e : ench.getValue()) {
Map<String, Tag> vars = ((CompoundTag) e).getValue();
short enchId = NBTUtils.getChildTag(vars, "id", ShortTag.class).getValue();
short enchLevel = NBTUtils.getChildTag(vars, "lvl", ShortTag.class).getValue();
stack.getEnchantments().put((int) enchId, (int) enchLevel);
}
}
return stack;
}
public BaseItemStack[] deserializeInventory(List<CompoundTag> items) throws DataException {
BaseItemStack[] stacks = new BaseItemStack[items.size()];
for (CompoundTag tag : items) {
Map<String, Tag> item = tag.getValue();
BaseItemStack stack = deserializeItem(item);
byte slot = NBTUtils.getChildTag(item, "Slot", ByteTag.class).getValue();
if (slot >= 0 && slot < stacks.length) {
stacks[slot] = stack;
}
}
return stacks;
}
public List<CompoundTag> serializeInventory(BaseItemStack[] items) {
List<CompoundTag> tags = new ArrayList<CompoundTag>();
for (int i = 0; i < items.length; ++i) {
if (items[i] != null) {
Map<String, Tag> tagData = serializeItem(items[i]);
tagData.put("Slot", new ByteTag("Slot", (byte) i));
tags.add(new CompoundTag("", tagData));
}
}
return tags;
}
}

View File

@ -1,105 +1,109 @@
/*
* 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;
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.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
/**
* Represents dispensers.
*
* @author sk89q
*/
public class DispenserBlock extends ContainerBlock {
/**
* Construct an empty dispenser block.
*/
public DispenserBlock() {
super(BlockID.DISPENSER, 9);
}
/**
* Construct an empty dispenser block.
*
* @param data data value (orientation)
*/
public DispenserBlock(int data) {
super(BlockID.DISPENSER, data, 9);
}
/**
* Construct a dispenser block with the given orientation and inventory.
*
* @param data data value (orientation)
* @param items array of items in the inventory
*/
public DispenserBlock(int data, BaseItemStack[] items) {
super(BlockID.DISPENSER, data, 9);
this.setItems(items);
}
@Override
public String getNbtId() {
return "Trap";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Items", new ListTag("Items", CompoundTag.class,
serializeInventory(getItems())));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) throws DataException {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) {
throw new DataException("'Trap' tile entity expected");
}
List<CompoundTag> items = new ArrayList<CompoundTag>();
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new DataException("CompoundTag expected as child tag of Trap Items");
}
items.add((CompoundTag) tag);
}
setItems(deserializeInventory(items));
}
}
/*
* 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;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Represents dispensers.
*
* @author sk89q
*/
public class DispenserBlock extends ContainerBlock {
/**
* Construct an empty dispenser block.
*/
public DispenserBlock() {
super(BlockID.DISPENSER, 9);
}
/**
* Construct an empty dispenser block.
*
* @param data data value (orientation)
*/
public DispenserBlock(int data) {
super(BlockID.DISPENSER, data, 9);
}
/**
* Construct a dispenser block with the given orientation and inventory.
*
* @param data data value (orientation)
* @param items array of items in the inventory
*/
public DispenserBlock(int data, BaseItemStack[] items) {
super(BlockID.DISPENSER, data, 9);
this.setItems(items);
}
@Override
public String getNbtId() {
return "Trap";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Items", new ListTag("Items", CompoundTag.class,
serializeInventory(getItems())));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) {
try {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) {
throw new DataException("'Trap' tile entity expected");
}
List<CompoundTag> items = new ArrayList<CompoundTag>();
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new DataException("CompoundTag expected as child tag of Trap Items");
}
items.add((CompoundTag) tag);
}
setItems(deserializeInventory(items));
} catch (DataException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,164 +1,167 @@
/*
* 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;
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.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.world.DataException;
/**
* Represents a furnace block.
*
* @author sk89q
*/
public class FurnaceBlock extends ContainerBlock {
private short burnTime;
private short cookTime;
/**
* Construct an empty furnace block with the default orientation.
*
* @param type type ID
*/
public FurnaceBlock(int type) {
super(type, 2);
}
/**
* Construct an empty furnace block with a given orientation.
*
* @param type type ID
* @param data orientation
*/
public FurnaceBlock(int type, int data) {
super(type, data, 2);
}
/**
* Construct an furnace block with a given orientation and inventory.
*
* @param type type ID
* @param data orientation
* @param items inventory items
*/
public FurnaceBlock(int type, int data, BaseItemStack[] items) {
super(type, data, 2);
setItems(items);
}
/**
* Get the burn time.
*
* @return the burn time
*/
public short getBurnTime() {
return burnTime;
}
/**
* Set the burn time.
*
* @param burnTime the burn time
*/
public void setBurnTime(short burnTime) {
this.burnTime = burnTime;
}
/**
* Get the cook time.
*
* @return the cook time
*/
public short getCookTime() {
return cookTime;
}
/**
* Set the cook time.
*
* @param cookTime the cook time to set
*/
public void setCookTime(short cookTime) {
this.cookTime = cookTime;
}
@Override
public String getNbtId() {
return "Furnace";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Items", new ListTag("Items", CompoundTag.class,
serializeInventory(getItems())));
values.put("BurnTime", new ShortTag("BurnTime", burnTime));
values.put("CookTime", new ShortTag("CookTime", cookTime));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) throws DataException {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id");
if (!(t instanceof StringTag)
|| !((StringTag) t).getValue().equals("Furnace")) {
throw new DataException("'Furnace' tile entity expected");
}
ListTag items = NBTUtils.getChildTag(values, "Items", ListTag.class);
List<CompoundTag> compound = new ArrayList<CompoundTag>();
for (Tag tag : items.getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new DataException(
"CompoundTag expected as child tag of Furnace Items");
}
compound.add((CompoundTag) tag);
}
setItems(deserializeInventory(compound));
t = values.get("BurnTime");
if (t instanceof ShortTag) {
burnTime = ((ShortTag) t).getValue();
}
t = values.get("CookTime");
if (t instanceof ShortTag) {
cookTime = ((ShortTag) t).getValue();
}
}
}
/*
* 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;
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.world.DataException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Represents a furnace block.
*
* @author sk89q
*/
public class FurnaceBlock extends ContainerBlock {
private short burnTime;
private short cookTime;
/**
* Construct an empty furnace block with the default orientation.
*
* @param type type ID
*/
public FurnaceBlock(int type) {
super(type, 2);
}
/**
* Construct an empty furnace block with a given orientation.
*
* @param type type ID
* @param data orientation
*/
public FurnaceBlock(int type, int data) {
super(type, data, 2);
}
/**
* Construct an furnace block with a given orientation and inventory.
*
* @param type type ID
* @param data orientation
* @param items inventory items
*/
public FurnaceBlock(int type, int data, BaseItemStack[] items) {
super(type, data, 2);
setItems(items);
}
/**
* Get the burn time.
*
* @return the burn time
*/
public short getBurnTime() {
return burnTime;
}
/**
* Set the burn time.
*
* @param burnTime the burn time
*/
public void setBurnTime(short burnTime) {
this.burnTime = burnTime;
}
/**
* Get the cook time.
*
* @return the cook time
*/
public short getCookTime() {
return cookTime;
}
/**
* Set the cook time.
*
* @param cookTime the cook time to set
*/
public void setCookTime(short cookTime) {
this.cookTime = cookTime;
}
@Override
public String getNbtId() {
return "Furnace";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Items", new ListTag("Items", CompoundTag.class,
serializeInventory(getItems())));
values.put("BurnTime", new ShortTag("BurnTime", burnTime));
values.put("CookTime", new ShortTag("CookTime", cookTime));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) {
return;
}
try {
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id");
if (!(t instanceof StringTag)
|| !((StringTag) t).getValue().equals("Furnace")) {
throw new RuntimeException("'Furnace' tile entity expected");
}
ListTag items = NBTUtils.getChildTag(values, "Items", ListTag.class);
List<CompoundTag> compound = new ArrayList<CompoundTag>();
for (Tag tag : items.getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new RuntimeException("CompoundTag expected as child tag of Furnace Items");
}
compound.add((CompoundTag) tag);
}
setItems(deserializeInventory(compound));
t = values.get("BurnTime");
if (t instanceof ShortTag) {
burnTime = ((ShortTag) t).getValue();
}
t = values.get("CookTime");
if (t instanceof ShortTag) {
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.worldedit.Vector;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.extent.Extent;
import static com.google.common.base.Preconditions.checkNotNull;
@ -88,17 +87,13 @@ public class LazyBlock extends BaseBlock {
public CompoundTag getNbtData() {
if (!loaded) {
BaseBlock loadedBlock = extent.getBlock(position);
try {
super.setNbtData(loadedBlock.getNbtData());
} catch (DataException e) {
throw new RuntimeException(e);
}
super.setNbtData(loadedBlock.getNbtData());
}
return super.getNbtData();
}
@Override
public void setNbtData(CompoundTag nbtData) throws DataException {
public void setNbtData(CompoundTag nbtData) {
throw new UnsupportedOperationException("This object is immutable");
}

View File

@ -19,9 +19,13 @@
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.world.DataException;
import com.sk89q.worldedit.world.storage.InvalidFormatException;
import java.util.HashMap;
@ -153,7 +157,7 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
}
@Override
public void setNbtData(CompoundTag rootTag) throws DataException {
public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) {
return;
}
@ -162,11 +166,18 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
Tag t = values.get("id");
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);
ShortTag delayTag = NBTUtils.getChildTag(values, "Delay", ShortTag.class);
StringTag mobTypeTag;
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.delay = delayTag.getValue();

View File

@ -1,125 +1,123 @@
/*
* 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;
import java.util.HashMap;
import java.util.Map;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
/**
* A note block.
*
* @author sk89q
*/
public class NoteBlock extends BaseBlock implements TileEntityBlock {
private byte note;
/**
* Construct the note block with a data value of 0.
*/
public NoteBlock() {
super(BlockID.NOTE_BLOCK);
this.note = 0;
}
/**
* Construct the note block with a given data value.
*
* @param data data value
*/
public NoteBlock(int data) {
super(BlockID.NOTE_BLOCK, data);
this.note = 0;
}
/**
* Construct the note block with a given data value and note.
*
* @param data data value
* @param note note
*/
public NoteBlock(int data, byte note) {
super(BlockID.NOTE_BLOCK, data);
this.note = note;
}
/**
* Get the note.
*
* @return the note
*/
public byte getNote() {
return note;
}
/**
* Set the note.
*
* @param note the note to set
*/
public void setNote(byte note) {
this.note = note;
}
@Override
public boolean hasNbtData() {
return true;
}
@Override
public String getNbtId() {
return "Music";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("note", new ByteTag("note", note));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) throws DataException {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t;
t = values.get("id");
if (!(t instanceof StringTag)
|| !((StringTag) t).getValue().equals("Music")) {
throw new DataException("'Music' tile entity expected");
}
t = values.get("note");
if (t instanceof ByteTag) {
note = ((ByteTag) t).getValue();
}
}
}
/*
* 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;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import java.util.HashMap;
import java.util.Map;
/**
* A note block.
*
* @author sk89q
*/
public class NoteBlock extends BaseBlock implements TileEntityBlock {
private byte note;
/**
* Construct the note block with a data value of 0.
*/
public NoteBlock() {
super(BlockID.NOTE_BLOCK);
this.note = 0;
}
/**
* Construct the note block with a given data value.
*
* @param data data value
*/
public NoteBlock(int data) {
super(BlockID.NOTE_BLOCK, data);
this.note = 0;
}
/**
* Construct the note block with a given data value and note.
*
* @param data data value
* @param note note
*/
public NoteBlock(int data, byte note) {
super(BlockID.NOTE_BLOCK, data);
this.note = note;
}
/**
* Get the note.
*
* @return the note
*/
public byte getNote() {
return note;
}
/**
* Set the note.
*
* @param note the note to set
*/
public void setNote(byte note) {
this.note = note;
}
@Override
public boolean hasNbtData() {
return true;
}
@Override
public String getNbtId() {
return "Music";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("note", new ByteTag("note", note));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t;
t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Music")) {
throw new RuntimeException("'Music' tile entity expected");
}
t = values.get("note");
if (t instanceof ByteTag) {
note = ((ByteTag) t).getValue();
}
}
}

View File

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

View File

@ -1,196 +1,194 @@
/*
* 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;
import java.util.HashMap;
import java.util.Map;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.DataException;
/**
* A skull block.
*/
public class SkullBlock extends BaseBlock implements TileEntityBlock {
private String owner = ""; // notchian
private byte skullType; // stored here for block, in damage value for item
private byte rot; // only matters if block data == 0x1 (on floor)
/**
* Construct the skull block with a default type of skelton.
* @param data data value to set, controls placement
*/
public SkullBlock(int data) {
this(data, (byte) 0);
}
/**
* Construct the skull block with a given type.
* 0 - skeleton
* 1 - wither skelly
* 2 - zombie
* 3 - human
* 4 - creeper
* @param data data value to set, controls placement
* @param type type of skull
*/
public SkullBlock(int data, byte type) {
this(data, type, (byte) 0);
}
/**
* Construct the skull block with a given type and rotation.
* @param data data value to set, controls placement
* @param type type of skull
* @param rot rotation (if on floor)
*/
public SkullBlock(int data, byte type, byte rot) {
super(BlockID.HEAD, data);
if (type < (byte) 0 || type > (byte) 4) {
this.skullType = (byte) 0;
} else {
this.skullType = type;
}
this.rot = rot;
this.owner = "";
}
/**
* Construct the skull block with a given rotation and owner.
* The type is assumed to be player unless owner is null or empty.
* @param data data value to set, controls placement
* @param rot rotation of skull
* @param owner name of player
*/
public SkullBlock(int data, byte rot, String owner) {
super(BlockID.HEAD, data);
this.rot = rot;
this.setOwner(owner);
if (owner == null || owner.isEmpty()) this.skullType = (byte) 0;
}
/**
* Set the skull's owner. Automatically sets type to player if not empty or null.
* @param owner player name to set the skull to
*/
public void setOwner(String owner) {
if (owner == null) {
this.owner = "";
} else {
if (owner.length() > 16 || owner.isEmpty()) this.owner = "";
else this.owner = owner;
}
if (this.owner != null && !this.owner.isEmpty()) this.skullType = (byte) 3;
}
/**
* Get the skull's owner. Returns null if unset.
* @return player name or null
*/
public String getOwner() {
return owner;
}
/**
* Get the type of skull.
* @return the skullType
*/
public byte getSkullType() {
return skullType;
}
/**
* Set the type of skull;
* @param skullType the skullType to set
*/
public void setSkullType(byte skullType) {
this.skullType = skullType;
}
/**
* Get rotation of skull. This only means anything if the block data is 1.
* @return the rotation
*/
public byte getRot() {
return rot;
}
/**
* Set the rotation of skull.
* @param rot the rotation to set
*/
public void setRot(byte rot) {
this.rot = rot;
}
@Override
public boolean hasNbtData() {
return true;
}
@Override
public String getNbtId() {
return "Skull";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("SkullType", new ByteTag("SkullType", skullType));
if (owner == null) owner = "";
values.put("ExtraType", new StringTag("ExtraType", owner));
values.put("Rot", new ByteTag("Rot", rot));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) throws DataException {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t;
t = values.get("id");
if (!(t instanceof StringTag)
|| !((StringTag) t).getValue().equals("Skull")) {
throw new DataException("'Skull' tile entity expected");
}
t = values.get("SkullType");
if (t instanceof ByteTag) {
skullType = ((ByteTag) t).getValue();
}
t = values.get("ExtraType");
if (t != null && t instanceof StringTag) {
owner = ((StringTag) t).getValue();
}
t = values.get("Rot");
if (t instanceof ByteTag) {
rot = ((ByteTag) t).getValue();
}
}
}
/*
* 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;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import java.util.HashMap;
import java.util.Map;
/**
* A skull block.
*/
public class SkullBlock extends BaseBlock implements TileEntityBlock {
private String owner = ""; // notchian
private byte skullType; // stored here for block, in damage value for item
private byte rot; // only matters if block data == 0x1 (on floor)
/**
* Construct the skull block with a default type of skelton.
* @param data data value to set, controls placement
*/
public SkullBlock(int data) {
this(data, (byte) 0);
}
/**
* Construct the skull block with a given type.
* 0 - skeleton
* 1 - wither skelly
* 2 - zombie
* 3 - human
* 4 - creeper
* @param data data value to set, controls placement
* @param type type of skull
*/
public SkullBlock(int data, byte type) {
this(data, type, (byte) 0);
}
/**
* Construct the skull block with a given type and rotation.
* @param data data value to set, controls placement
* @param type type of skull
* @param rot rotation (if on floor)
*/
public SkullBlock(int data, byte type, byte rot) {
super(BlockID.HEAD, data);
if (type < (byte) 0 || type > (byte) 4) {
this.skullType = (byte) 0;
} else {
this.skullType = type;
}
this.rot = rot;
this.owner = "";
}
/**
* Construct the skull block with a given rotation and owner.
* The type is assumed to be player unless owner is null or empty.
* @param data data value to set, controls placement
* @param rot rotation of skull
* @param owner name of player
*/
public SkullBlock(int data, byte rot, String owner) {
super(BlockID.HEAD, data);
this.rot = rot;
this.setOwner(owner);
if (owner == null || owner.isEmpty()) this.skullType = (byte) 0;
}
/**
* Set the skull's owner. Automatically sets type to player if not empty or null.
* @param owner player name to set the skull to
*/
public void setOwner(String owner) {
if (owner == null) {
this.owner = "";
} else {
if (owner.length() > 16 || owner.isEmpty()) this.owner = "";
else this.owner = owner;
}
if (this.owner != null && !this.owner.isEmpty()) this.skullType = (byte) 3;
}
/**
* Get the skull's owner. Returns null if unset.
* @return player name or null
*/
public String getOwner() {
return owner;
}
/**
* Get the type of skull.
* @return the skullType
*/
public byte getSkullType() {
return skullType;
}
/**
* Set the type of skull;
* @param skullType the skullType to set
*/
public void setSkullType(byte skullType) {
this.skullType = skullType;
}
/**
* Get rotation of skull. This only means anything if the block data is 1.
* @return the rotation
*/
public byte getRot() {
return rot;
}
/**
* Set the rotation of skull.
* @param rot the rotation to set
*/
public void setRot(byte rot) {
this.rot = rot;
}
@Override
public boolean hasNbtData() {
return true;
}
@Override
public String getNbtId() {
return "Skull";
}
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<String, Tag>();
values.put("SkullType", new ByteTag("SkullType", skullType));
if (owner == null) owner = "";
values.put("ExtraType", new StringTag("ExtraType", owner));
values.put("Rot", new ByteTag("Rot", rot));
return new CompoundTag(getNbtId(), values);
}
@Override
public void setNbtData(CompoundTag rootTag) {
if (rootTag == null) {
return;
}
Map<String, Tag> values = rootTag.getValue();
Tag t;
t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Skull")) {
throw new RuntimeException("'Skull' tile entity expected");
}
t = values.get("SkullType");
if (t instanceof ByteTag) {
skullType = ((ByteTag) t).getValue();
}
t = values.get("ExtraType");
if (t != null && t instanceof StringTag) {
owner = ((StringTag) t).getValue();
}
t = values.get("Rot");
if (t instanceof ByteTag) {
rot = ((ByteTag) t).getValue();
}
}
}

View File

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

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Byte_Array</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_Byte_Array} tag.
*/
public final class ByteArrayTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public ByteArrayTag(String name, byte[] value) {
super(name);
@ -67,7 +67,7 @@ public final class ByteArrayTag extends Tag {
if (name != null && !name.equals("")) {
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;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Byte</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_Byte} tag.
*/
public final class ByteTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public ByteTag(String name, byte value) {
super(name);

View File

@ -20,40 +20,401 @@
package com.sk89q.jnbt;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Compound</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_Compound} tag.
*/
public final class CompoundTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public CompoundTag(String name, Map<String, Tag> value) {
super(name);
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
public Map<String, Tag> getValue() {
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
public String toString() {
String name = getName();
@ -62,12 +423,9 @@ public final class CompoundTag extends Tag {
append = "(\"" + this.getName() + "\")";
}
StringBuilder bldr = new StringBuilder();
bldr.append("TAG_Compound" + append + ": " + value.size()
+ " entries\r\n{\r\n");
bldr.append("TAG_Compound").append(append).append(": ").append(value.size()).append(" entries\r\n{\r\n");
for (Map.Entry<String, Tag> entry : value.entrySet()) {
bldr.append(" "
+ entry.getValue().toString().replaceAll("\r\n", "\r\n ")
+ "\r\n");
bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
}
bldr.append("}");
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;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Double</code> tag.
*
* @author Graham Edgecombe
* The {@code TAG_Double} tag.
*
*/
public final class DoubleTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public DoubleTag(String name, double value) {
super(name);

View File

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

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Float</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_Float} tag.
*/
public final class FloatTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public FloatTag(String name, float value) {
super(name);

View File

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

View File

@ -19,28 +19,28 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Int</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_Int} tag.
*/
public final class IntTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public IntTag(String name, int value) {
super(name);

View File

@ -19,41 +19,44 @@
package com.sk89q.jnbt;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.Tag;
import java.util.NoSuchElementException;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The <code>TAG_List</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_List} tag.
*/
public final class ListTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param type
* The type of item in the list.
* @param value
* The value.
* @param name the name of the tag
* @param type the type of tag
* @param value the value of the tag
*/
public ListTag(String name, Class<? extends Tag> type, List<? extends Tag> value) {
super(name);
checkNotNull(value);
this.type = type;
this.value = Collections.unmodifiableList(value);
}
@ -72,6 +75,360 @@ public final class ListTag extends Tag {
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
public String toString() {
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;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Long</code> tag.
*
* @author Graham Edgecombe
* The {@code TAG_Long} tag.
*
*/
public final class LongTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public LongTag(String name, long value) {
super(name);

View File

@ -29,14 +29,8 @@ import java.nio.charset.Charset;
*/
public final class NBTConstants {
/**
* The character set used by NBT (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,
TYPE_INT = 3, TYPE_LONG = 4, TYPE_FLOAT = 5, TYPE_DOUBLE = 6,
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.List;
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>
@ -60,19 +46,14 @@ import com.sk89q.jnbt.Tag;
*/
public final class NBTInputStream implements Closeable {
/**
* The data input stream.
*/
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.
*
* @param is
* The input stream.
* @throws IOException
* if an I/O error occurs.
* @param is the input stream
* @throws IOException if an I/O error occurs
*/
public NBTInputStream(InputStream is) throws IOException {
this.is = new DataInputStream(is);
@ -82,8 +63,7 @@ public final class NBTInputStream implements Closeable {
* Reads an NBT tag from the stream.
*
* @return The tag that was read.
* @throws IOException
* if an I/O error occurs.
* @throws IOException if an I/O error occurs.
*/
public Tag readTag() throws IOException {
return readTag(0);
@ -92,11 +72,9 @@ public final class NBTInputStream implements Closeable {
/**
* Reads an NBT from the stream.
*
* @param depth
* The depth of this tag.
* @param depth the depth of this tag
* @return The tag that was read.
* @throws IOException
* if an I/O error occurs.
* @throws IOException if an I/O error occurs.
*/
private Tag readTag(int depth) throws IOException {
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.
*
* @param type
* The type.
* @param name
* The name.
* @param depth
* The depth.
* @return The tag.
* @throws IOException
* if an I/O error occurs.
* @param type the type
* @param name the name
* @param depth the depth
* @return the tag
* @throws IOException if an I/O error occurs.
*/
private Tag readTagPayload(int type, String name, int depth)
throws IOException {
private Tag readTagPayload(int type, String name, int depth) throws IOException {
switch (type) {
case NBTConstants.TYPE_END:
if (depth == 0) {
@ -197,6 +170,7 @@ public final class NBTInputStream implements Closeable {
}
}
@Override
public void close() throws IOException {
is.close();
}

View File

@ -24,21 +24,6 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
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>
@ -72,7 +57,7 @@ public final class NBTOutputStream implements Closeable {
* if an I/O error occurs.
*/
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;
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 java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A class which contains NBT-related utility methods.
*
* @author Graham Edgecombe
*
*/
public final class NBTUtils {
/**
* Default private constructor.
*/
private NBTUtils() {
}
/**
* Gets the type name of a tag.
*
* @param clazz
* The tag class.
* @param clazz the tag class
* @return The type name.
*/
public static String getTypeName(Class<? extends Tag> clazz) {
@ -72,11 +80,9 @@ public final class NBTUtils {
/**
* Gets the type code of a tag class.
*
* @param clazz
* The tag class.
* @param clazz the tag class
* @return The type code.
* @throws IllegalArgumentException
* if the tag class is invalid.
* @throws IllegalArgumentException if the tag class is invalid.
*/
public static int getTypeCode(Class<? extends Tag> clazz) {
if (clazz.equals(ByteArrayTag.class)) {
@ -112,11 +118,9 @@ public final class NBTUtils {
/**
* Gets the class of a type of tag.
*
* @param type
* The type.
* @param type the type
* @return The class.
* @throws IllegalArgumentException
* if the tag type is invalid.
* @throws IllegalArgumentException if the tag type is invalid.
*/
public static Class<? extends Tag> getTypeClass(int 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;
import com.sk89q.jnbt.Tag;
/**
* The <code>TAG_Short</code> tag.
*
* @author Graham Edgecombe
*
* The {@code TAG_Short} tag.
*/
public final class ShortTag extends Tag {
/**
* The 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.
*
* @param name
* The name.
* @param value
* The value.
*
* @param name the name of the tag
* @param value the value of the tag
*/
public ShortTag(String name, short value) {
super(name);

View File

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

View File

@ -20,32 +20,35 @@
package com.sk89q.jnbt;
/**
* Represents a single NBT tag.
*
* @author Graham Edgecombe
*
* Represents a NBT tag.
*/
public abstract class Tag {
/**
* The name of this tag.
*/
private final String name;
/**
* Create a new tag with an empty name.
*/
Tag() {
this("");
}
/**
* Creates the tag with the specified name.
*
* @param name
* The name.
* @param name the name
*/
public Tag(String name) {
Tag(String name) {
if (name == null) {
name = "";
}
this.name = name;
}
/**
* Gets the name of this tag.
*
* @return The name of this tag.
* @return the name of this tag
*/
public final String getName() {
return name;
@ -54,7 +57,7 @@ public abstract class Tag {
/**
* Gets the value of this tag.
*
* @return The value of this tag.
* @return the value
*/
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.BlockID;
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.extent.ChangeSetExtent;
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.RegionShape;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.*;
import com.sk89q.worldedit.util.collection.DoubleArrayList;
import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.NullWorld;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import javax.annotation.Nullable;
import java.util.*;
@ -376,6 +378,16 @@ public class EditSession implements Extent {
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
public BaseBlock getLazyBlock(Vector position) {
return world.getLazyBlock(position);
@ -581,6 +593,12 @@ public class EditSession implements Extent {
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.
*
@ -637,6 +655,16 @@ public class EditSession implements Extent {
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.
*/
@ -1148,6 +1176,7 @@ public class EditSession implements Extent {
ForwardExtentCopy copy = new ForwardExtentCopy(this, region, buffer, to);
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
copy.setSourceFunction(remove); // Remove
copy.setRemovingEntities(true);
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(this));
}
@ -2230,7 +2259,7 @@ public class EditSession implements Extent {
} // 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 unit2D = unit.toVector2D();
@ -2243,7 +2272,7 @@ public class EditSession implements Extent {
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
@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);
environment.setCurrentBlock(current.toVector(0));
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.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.world.World;
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
@ -62,7 +68,7 @@ public class LocalSession {
private boolean placeAtPos1 = false;
private LinkedList<EditSession> history = new LinkedList<EditSession>();
private int historyPointer = 0;
private CuboidClipboard clipboard;
private ClipboardHolder clipboard;
private boolean toolControl = true;
private boolean superPickaxe = false;
private BlockTool pickaxeMode = new SinglePickaxe();
@ -324,9 +330,9 @@ public class LocalSession {
* Gets the clipboard.
*
* @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) {
throw new EmptyClipboardException();
}
@ -336,9 +342,11 @@ public class LocalSession {
/**
* 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;
}

View File

@ -19,13 +19,11 @@
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.world.AbstractWorld;
import com.sk89q.worldedit.world.World;
import java.util.Random;
/**
* A legacy abstract implementation of {@link World}. New implementations
* should use {@link AbstractWorld} when possible.
@ -35,140 +33,11 @@ import java.util.Random;
@Deprecated
public abstract class LocalWorld extends AbstractWorld {
/**
* Named flags to use as parameters to {@link LocalWorld#killMobs(Vector, double, int)}
*/
@SuppressWarnings("PointlessBitwiseExpression")
public final class KillFlags {
public static final int PETS = 1 << 0;
public static final int NPCS = 1 << 1;
public static final int ANIMALS = 1 << 2;
public static final int GOLEMS = 1 << 3;
public static final int AMBIENT = 1 << 4;
public static final int TAGGED = 1 << 5;
public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED;
public static final int WITH_LIGHTNING = 1 << 20;
private KillFlags() {
}
}
/**
* @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
public BaseBlock getLazyBlock(Vector 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
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException {
switch (type) {

View File

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

View File

@ -517,8 +517,7 @@ public class Vector2D {
* @param translateZ what to add after rotation
* @return
*/
public Vector2D transform2D(double angle,
double aboutX, double aboutZ, double translateX, double translateZ) {
public Vector2D transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
angle = Math.toRadians(angle);
double x = this.x - aboutX;
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.InputType;
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.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
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.function.mask.Masks;
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.util.eventbus.EventBus;
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
import com.sk89q.worldedit.world.registry.BundledBlockData;
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.HashSet;
import java.util.Map;
@ -84,13 +89,14 @@ public class WorldEdit {
private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
private final SessionManager sessions = new SessionManager(this);
private final BlockRegistry blockRegistry = new BlockRegistry(this);
private final MaskRegistry maskRegistry = new MaskRegistry(this);
private final PatternRegistry patternRegistry = new PatternRegistry(this);
private final BlockFactory blockFactory = new BlockFactory(this);
private final MaskFactory maskFactory = new MaskFactory(this);
private final PatternFactory patternFactory = new PatternFactory(this);
static {
WorldEditPrefixHandler.register("com.sk89q.worldedit");
getVersion();
BundledBlockData.getInstance(); // Load block registry
}
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.
*
* @return the block registry
* @return the block factory
*/
public BlockRegistry getBlockRegistry() {
return blockRegistry;
public BlockFactory getBlockFactory() {
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.
*
* @return the mask registry
* @return the mask factory
*/
public MaskRegistry getMaskRegistry() {
return maskRegistry;
public MaskFactory getMaskFactory() {
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.
*
* @return the pattern registry
* @return the pattern factory
*/
public PatternRegistry getPatternRegistry() {
return patternRegistry;
public PatternFactory getPatternFactory() {
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")
@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")
@Deprecated
@ -231,11 +237,11 @@ public class WorldEdit {
context.setSession(getSession(player));
context.setRestricted(!allAllowed);
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")
@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
@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
@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
@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
@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
@SuppressWarnings("deprecation")
@ -299,11 +305,11 @@ public class WorldEdit {
context.setActor(player);
context.setWorld(player.getWorld());
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
@SuppressWarnings("deprecation")
@ -312,7 +318,7 @@ public class WorldEdit {
context.setActor(player);
context.setWorld(player.getWorld());
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;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.world.World;
/**
* @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible
@ -97,7 +98,7 @@ public class WorldVector extends Vector {
* @param location the 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 #setNbtData(CompoundTag)
*/
public BaseBlock(int id, int data, CompoundTag nbtData) throws DataException {
public BaseBlock(int id, int data, CompoundTag nbtData) {
setId(id);
setData(data);
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.
*
* @return ID (between 0 and {@link #MAX_ID})
*/
@Override
public int getId() {
return id;
}
@ -138,6 +148,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
*
* @param id block id (between 0 and {@link #MAX_ID}).
*/
@Override
public void setId(int id) {
internalSetId(id);
}
@ -147,6 +158,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
*
* @return data value (0-15)
*/
@Override
public int getData() {
return data;
}
@ -175,6 +187,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
*
* @param data block data value (between 0 and {@link #MAX_DATA}).
*/
@Override
public void setData(int data) {
internalSetData(data);
}
@ -187,6 +200,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
* @see #setId(int)
* @see #setData(int)
*/
@Override
public void setIdAndData(int id, int data) {
setId(id);
setData(data);
@ -198,6 +212,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
*
* @return true if the data value is -1
*/
@Override
public boolean hasWildcardData() {
return getData() == -1;
}
@ -227,7 +242,7 @@ public class BaseBlock extends Block implements TileEntityBlock {
}
@Override
public void setNbtData(CompoundTag nbtData) throws DataException {
public void setNbtData(CompoundTag 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.CommandPermissions;
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.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.masks.BiomeTypeMask;
import com.sk89q.worldedit.masks.InvertedMask;
import com.sk89q.worldedit.function.mask.Mask2D;
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.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.biome.BaseBiome;
import com.sk89q.worldedit.world.biome.BiomeData;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import java.util.HashSet;
import java.util.List;
@ -64,7 +78,7 @@ public class BiomeCommands {
max = 1
)
@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 offset;
int count = 0;
@ -76,16 +90,22 @@ public class BiomeCommands {
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;
actor.print("Available Biomes (page " + page + "/" + totalPages + ") :");
for (BiomeType biome : biomes) {
player.print("Available Biomes (page " + page + "/" + totalPages + ") :");
for (BaseBiome biome : biomes) {
if (offset > 0) {
offset--;
} else {
actor.print(" " + biome.getName());
if (++count == 19) {
break;
BiomeData data = biomeRegistry.getData(biome);
if (data != null) {
player.print(" " + data.getName());
if (++count == 19) {
break;
}
} else {
player.print(" <unknown #" + biome.getId() + ">");
}
}
}
@ -103,7 +123,11 @@ public class BiomeCommands {
max = 0
)
@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')) {
Vector blockPosition = player.getBlockTrace(300);
if (blockPosition == null) {
@ -111,15 +135,18 @@ public class BiomeCommands {
return;
}
BiomeType biome = player.getWorld().getBiome(blockPosition.toVector2D());
player.print("Biome: " + biome.getName());
BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
biomes.add(biome);
qualifier = "at line of sight point";
} else if (args.hasFlag('p')) {
BiomeType biome = player.getWorld().getBiome(player.getPosition().toVector2D());
player.print("Biome: " + biome.getName());
BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D());
biomes.add(biome);
qualifier = "at your position";
} else {
World world = player.getWorld();
Region region = session.getSelection(world);
Set<BiomeType> biomes = new HashSet<BiomeType>();
if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
@ -131,9 +158,16 @@ public class BiomeCommands {
}
}
player.print("Biomes:");
for (BiomeType biome : biomes) {
player.print(" " + biome.getName());
qualifier = "in your selection";
}
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() + ">");
}
}
}
@ -145,65 +179,31 @@ public class BiomeCommands {
desc = "Sets the biome of the player's current block or region.",
help =
"Set the biome of the region.\n" +
"By default use all the blocks contained in your selection.\n" +
"-p use the block you are currently in",
min = 1,
max = 1
"By default use all the blocks contained in your selection.\n" +
"-p use the block you are currently in"
)
@Logging(REGION)
@CommandPermissions("worldedit.biome.set")
public void setBiome(CommandContext args, Player player, LocalSession session, EditSession editSession) 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;
}
public void setBiome(Player player, LocalSession session, EditSession editSession, BaseBiome target, @Switch('p') boolean atPosition) throws WorldEditException {
World world = player.getWorld();
Region region;
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();
}
Mask2D mask2d = mask != null ? mask.toMask2D() : null;
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.");
}
if (atPosition) {
region = new CuboidRegion(player.getPosition(), player.getPosition());
} else {
int affected = 0;
World world = player.getWorld();
Region region = session.getSelection(world);
if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
if (biomeMask == null || (biomeMask.matches2D(editSession, pt) ^ inverted)) {
world.setBiome(pt, target);
++affected;
}
}
} else {
HashSet<Long> alreadyVisited = new HashSet<Long>();
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.");
region = session.getSelection(world);
}
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.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.EditSession;
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.BlockID;
import com.sk89q.worldedit.command.UtilityCommands.FlagContainer;
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.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
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.parametric.Optional;
@ -117,32 +130,27 @@ public class BrushCommands {
@Command(
aliases = { "clipboard", "copy" },
usage = "",
flags = "a",
desc = "Choose the clipboard brush",
help =
"Chooses the clipboard brush.\n" +
"The -a flag makes it not paste air.",
min = 0,
max = 0
"The -a flag makes it not paste air.\n" +
"Without the -p flag, the paste will appear centered at the target location. " +
"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")
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();
if (clipboard == null) {
player.printError("Copy something first.");
return;
}
Vector size = clipboard.getSize();
Vector size = clipboard.getDimensions();
worldEdit.checkMaxBrushRadius(size.getBlockX());
worldEdit.checkMaxBrushRadius(size.getBlockY());
worldEdit.checkMaxBrushRadius(size.getBlockZ());
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.");
}
@ -220,13 +228,21 @@ public class BrushCommands {
@Command(
aliases = { "butcher", "kill" },
usage = "[radius] [command flags]",
usage = "[radius]",
flags = "plangbtf",
desc = "Butcher brush",
help = "Kills nearby mobs within the specified radius.\n" +
"Any number of 'flags' that the //butcher command uses\n" +
"may be specified as an argument",
"Flags:" +
" -p also kills pets.\n" +
" -n also kills NPCs.\n" +
" -g also kills Golems.\n" +
" -a also kills animals.\n" +
" -b also kills ambient mobs.\n" +
" -t also kills mobs with name tags.\n" +
" -f compounds all previous flags.\n" +
" -l currently does nothing.",
min = 0,
max = 2
max = 1
)
@CommandPermissions("worldedit.brush.butcher")
public void butcherBrush(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
@ -245,24 +261,13 @@ public class BrushCommands {
return;
}
FlagContainer flags = new FlagContainer(player);
if (args.argsLength() == 2) {
String flagString = args.getString(1);
// straight from the command, using contains instead of hasflag
flags.or(KillFlags.FRIENDLY , flagString.contains("f")); // No permission check here. Flags will instead be filtered by the subsequent calls.
flags.or(KillFlags.PETS , flagString.contains("p"), "worldedit.butcher.pets");
flags.or(KillFlags.NPCS , flagString.contains("n"), "worldedit.butcher.npcs");
flags.or(KillFlags.GOLEMS , flagString.contains("g"), "worldedit.butcher.golems");
flags.or(KillFlags.ANIMALS , flagString.contains("a"), "worldedit.butcher.animals");
flags.or(KillFlags.AMBIENT , flagString.contains("b"), "worldedit.butcher.ambient");
flags.or(KillFlags.TAGGED , flagString.contains("t"), "worldedit.butcher.tagged");
flags.or(KillFlags.WITH_LIGHTNING, flagString.contains("l"), "worldedit.butcher.lightning");
}
CreatureButcher flags = new CreatureButcher(player);
flags.fromCommand(args);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new ButcherBrush(flags.flags), "worldedit.brush.butcher");
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");
player.print(String.format("Butcher brush equipped (%.0f).",
radius));
player.print(String.format("Butcher brush equipped (%.0f).", radius));
}
}

View File

@ -20,19 +20,32 @@
package com.sk89q.worldedit.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.Logging;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
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.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.RegionSelector;
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.parametric.Optional;
import com.sk89q.worldedit.world.World;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
@ -57,87 +70,63 @@ public class ClipboardCommands {
@Command(
aliases = { "/copy" },
flags = "e",
flags = "em",
desc = "Copy the selection to the clipboard",
help = "Copy the selection to the clipboard\n" +
"Flags:\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!",
min = 0,
max = 0
)
@CommandPermissions("worldedit.clipboard.copy")
public void copy(Player player, LocalSession session, EditSession editSession, @Switch('e') boolean copyEntities) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
public void copy(Player player, LocalSession session, EditSession editSession,
@Selection Region region, @Switch('e') boolean copyEntities,
@Switch('m') Mask mask) throws WorldEditException {
CuboidClipboard clipboard = new CuboidClipboard(
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
if (mask != null) {
copy.setSourceMask(mask);
}
Operations.completeLegacy(copy);
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
if (copyEntities) {
for (LocalEntity entity : player.getWorld().getEntities(region)) {
clipboard.storeEntity(entity);
}
}
session.setClipboard(clipboard);
player.print("Block(s) copied.");
player.print(region.getArea() + " block(s) were copied.");
}
@Command(
aliases = { "/cut" },
flags = "em",
usage = "[leave-id]",
desc = "Cut the selection to the clipboard",
help = "Copy the selection to the clipboard\n" +
"Flags:\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!",
flags = "e",
min = 0,
max = 1
)
@CommandPermissions("worldedit.clipboard.cut")
@Logging(REGION)
public void cut(Player player, LocalSession session, EditSession editSession, @Optional("air") BaseBlock block, @Switch('e') boolean copyEntities) throws WorldEditException {
World world = player.getWorld();
public void cut(Player player, LocalSession session, EditSession editSession,
@Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean copyEntities,
@Switch('m') Mask mask) throws WorldEditException {
Region region = session.getSelection(world);
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
CuboidClipboard clipboard = new CuboidClipboard(
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
if (mask != null) {
copy.setSourceMask(mask);
}
Operations.completeLegacy(copy);
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
if (copyEntities) {
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.");
player.print(region.getArea() + " block(s) were copied.");
}
@Command(
@ -156,79 +145,76 @@ public class ClipboardCommands {
)
@CommandPermissions("worldedit.clipboard.paste")
@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');
boolean pasteNoAir = args.hasFlag('a');
ClipboardHolder holder = session.getClipboard();
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()
: session.getPlacementPosition(player);
if (atOrigin) {
clipboard.place(editSession, pos, pasteNoAir);
clipboard.pasteEntities(pos);
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 (selectPasted) {
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);
session.setRegionSelector(player.getWorld(), selector);
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
if (args.hasFlag('s')) {
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);
}
player.print("The clipboard has been pasted at " + to);
}
@Command(
aliases = { "/rotate" },
usage = "<angle-in-degrees>",
usage = "<y-axis> [<x-axis>] [<z-axis>]",
desc = "Rotate the contents of the clipboard",
min = 1,
max = 1
help = "Non-destructively rotate the contents of the clipboard.\n" +
"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")
public void rotate(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int angle = args.getInteger(0);
if (angle % 90 == 0) {
CuboidClipboard clipboard = session.getClipboard();
clipboard.rotate2D(angle);
player.print("Clipboard rotated by " + angle + " degrees.");
} else {
player.printError("Angles must be divisible by 90 degrees.");
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) ||
xRotate != null && Math.abs(xRotate % 90) > 0.001 ||
zRotate != null && Math.abs(zRotate % 90) > 0.001) {
player.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.");
}
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(
aliases = { "/flip" },
usage = "[dir]",
flags = "p",
desc = "Flip the contents of the clipboard.",
usage = "[<direction>]",
desc = "Flip the contents of the clipboard",
help =
"Flips the contents of the clipboard.\n" +
"The -p flag flips the selection around the player,\n" +
"instead of the selections center.",
"Flips the contents of the clipboard across the point from which the copy was made.\n",
min = 0,
max = 1
)
@CommandPermissions("worldedit.clipboard.flip")
public void flip(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
CuboidClipboard.FlipDirection dir = worldEdit.getFlipDirection(player, args.argsLength() > 0 ? args.getString(0).toLowerCase() : "me");
CuboidClipboard clipboard = session.getClipboard();
clipboard.flip(dir, args.hasFlag('p'));
player.print("Clipboard flipped.");
public void flip(Player player, LocalSession session, EditSession editSession,
@Optional(Direction.AIM) @Direction Vector direction) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
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(

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.CommandPermissions;
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.function.pattern.Pattern;
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.Text;
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.sk89q.minecraft.util.commands.Logging.LogMode.*;
@ -332,7 +337,7 @@ public class GenerationCommands {
@Logging(ALL)
public void generateBiome(Player player, LocalSession session, EditSession editSession,
@Selection Region region,
BiomeType target,
BaseBiome target,
@Text String expression,
@Switch('h') boolean hollow,
@Switch('r') boolean useRawCoords,
@ -368,7 +373,7 @@ public class GenerationCommands {
try {
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow);
player.findFreePosition();
player.print("Biome changed to " + target.getName() + ". " + affected + " columns affected.");
player.print("" + affected + " columns affected.");
} catch (ExpressionException e) {
player.printError(e.getMessage());
}

View File

@ -19,18 +19,42 @@
package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.worldedit.*;
import com.sk89q.minecraft.util.commands.Command;
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.extension.platform.Actor;
import com.sk89q.worldedit.schematic.SchematicFormat;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
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.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
@ -39,6 +63,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class SchematicCommands {
private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName());
private final WorldEdit worldEdit;
/**
@ -52,113 +77,94 @@ public class SchematicCommands {
}
@Command(
aliases = { "load", "l" },
usage = "[format] <filename>",
desc = "Load a file 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
aliases = { "load" },
usage = "[<format>] <filename>",
desc = "Load a schematic into your clipboard"
)
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"}) // TODO: Remove 'clipboard' perm
public void load(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
@Deprecated
@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();
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 f = worldEdit.getSafeOpenFile(player, dir, fileName, "schematic", "schematic");
File f = worldEdit.getSafeOpenFile(player, dir, filename, "schematic", "schematic");
if (!f.exists()) {
player.printError("Schematic " + fileName + " does not exist!");
player.printError("Schematic " + filename + " does not exist!");
return;
}
SchematicFormat format = formatName == null ? null : SchematicFormat.getFormat(formatName);
if (format == null) {
format = SchematicFormat.getFormat(f);
}
ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
return;
}
if (!format.isOfFormat(f) && !args.hasFlag('f')) {
player.printError(fileName + " is not of the " + format.getName() + " schematic format!");
return;
}
Closer closer = Closer.create();
try {
String filePath = f.getCanonicalPath();
String dirPath = dir.getCanonicalPath();
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 {
session.setClipboard(format.load(f));
WorldEdit.logger.info(player.getName() + " loaded " + filePath);
player.print(fileName + " loaded. Paste it with //paste");
FileInputStream fis = closer.register(new FileInputStream(f));
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
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) {
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(
aliases = { "save", "s" },
usage = "[format] <filename>",
desc = "Save your clipboard to file",
help = "Save your clipboard to file\n" +
"Format is a format from \"//schematic formats\"\n",
min = 1,
max = 2
aliases = { "save" },
usage = "[<format>] <filename>",
desc = "Save a schematic into your clipboard"
)
@CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"}) // TODO: Remove 'clipboard' perm
public void save(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
@Deprecated
@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();
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 f = worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
if (!dir.exists()) {
if (!dir.mkdir()) {
player.printError("The storage folder could not be created.");
return;
}
ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
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 {
// Create parent directories
File parent = f.getParentFile();
@ -168,13 +174,20 @@ public class SchematicCommands {
}
}
format.save(session.getClipboard(), f);
WorldEdit.logger.info(player.getName() + " saved " + f.getCanonicalPath());
FileOutputStream fos = closer.register(new FileOutputStream(f));
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.");
} catch (DataException se) {
player.printError("Save error: " + se.getMessage());
} catch (IOException e) {
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")
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;
boolean first = true;
for (SchematicFormat format : SchematicFormat.getFormats()) {
for (ClipboardFormat format : ClipboardFormat.values()) {
builder = new StringBuilder();
builder.append(format.getName()).append(": ");
for (String lookupName : format.getLookupNames()) {
builder.append(format.name()).append(": ");
for (String lookupName : format.getAliases()) {
if (!first) {
builder.append(", ");
}
@ -292,9 +305,8 @@ public class SchematicCommands {
}
build.append("\n\u00a79");
SchematicFormat format = SchematicFormat.getFormat(file);
build.append(prefix).append(file.getName())
.append(": ").append(format == null ? "Unknown" : format.getName());
ClipboardFormat format = ClipboardFormat.findByFile(file);
build.append(prefix).append(file.getName()).append(": ").append(format == null ? "Unknown" : format.name());
}
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.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
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.BlockType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
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.Polygonal2DRegionSelector;
import com.sk89q.worldedit.regions.selector.SphereRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.World;
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 {
if (args.hasFlag('c')) {
CuboidClipboard clipboard = session.getClipboard();
Vector size = clipboard.getSize();
Vector offset = clipboard.getOffset();
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
Vector origin = clipboard.getOrigin();
player.print("Size: " + size);
player.print("Offset: " + offset);
player.print("Cuboid dimensions (max - min): " + size);
player.print("Offset: " + origin);
player.print("Cuboid distance: " + size.distance(Vector.ONE));
player.print("# of blocks: "
+ (int) (size.getX() * size.getY() * size.getZ()));
player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
return;
}
@ -608,8 +611,7 @@ public class SelectionCommands {
}
player.print("Size: " + size);
player.print("Cuboid distance: " + region.getMaximumPoint()
.distance(region.getMinimumPoint()));
player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
player.print("# of blocks: " + region.getArea());
}
@ -653,7 +655,7 @@ public class SelectionCommands {
max = 0
)
@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;
boolean useData = args.hasFlag('d');
@ -661,13 +663,8 @@ public class SelectionCommands {
List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) {
CuboidClipboard clip = session.getClipboard();
if (useData) {
distributionData = clip.getBlockDistributionWithData();
} else {
distribution = clip.getBlockDistribution();
}
size = clip.getHeight() * clip.getLength() * clip.getWidth();
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
} else {
if (useData) {
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.Logging;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.util.CreatureButcher;
import com.sk89q.worldedit.command.util.EntityRemover;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.EntityVisitor;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
import com.sk89q.worldedit.util.formatting.Style;
import com.sk89q.worldedit.util.formatting.StyledFragment;
@ -374,7 +379,7 @@ public class UtilityCommands {
" -b also kills ambient mobs.\n" +
" -t also kills mobs with name tags.\n" +
" -f compounds all previous flags.\n" +
" -l strikes lightning on each killed mob.",
" -l currently does nothing.",
min = 0,
max = 1
)
@ -399,26 +404,37 @@ public class UtilityCommands {
}
}
FlagContainer flags = new FlagContainer(actor);
flags.or(KillFlags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls.
flags.or(KillFlags.PETS , args.hasFlag('p'), "worldedit.butcher.pets");
flags.or(KillFlags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs");
flags.or(KillFlags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems");
flags.or(KillFlags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals");
flags.or(KillFlags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient");
flags.or(KillFlags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged");
flags.or(KillFlags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning");
// If you add flags here, please add them to com.sk89q.worldedit.commands.BrushCommands.butcherBrush() as well
CreatureButcher flags = new CreatureButcher(actor);
flags.fromCommand(args);
List<EntityVisitor> visitors = new ArrayList<EntityVisitor>();
LocalSession session = null;
EditSession editSession = null;
int killed;
if (player != null) {
LocalSession session = we.getSessionManager().get(player);
killed = player.getWorld().killMobs(session.getPlacementPosition(player), radius, flags.flags);
} else {
killed = 0;
for (World world : we.getServer().getWorlds()) {
killed += world.killMobs(new Vector(), radius, flags.flags);
session = we.getSessionManager().get(player);
Vector center = session.getPlacementPosition(player);
editSession = session.createEditSession(player);
List<? extends Entity> entities;
if (radius >= 0) {
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
entities = editSession.getEntities(region);
} else {
entities = editSession.getEntities();
}
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
} else {
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
for (World world : platform.getWorlds()) {
List<? extends Entity> entities = world.getEntities();
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction(world.getWorldData().getEntityRegistry())));
}
}
int killed = 0;
for (EntityVisitor visitor : visitors) {
Operations.completeLegacy(visitor);
killed += visitor.getAffected();
}
if (radius < 0) {
@ -426,25 +442,10 @@ public class UtilityCommands {
} else {
actor.print("Killed " + killed + " mobs in a radius of " + radius + ".");
}
}
public static class FlagContainer {
private final Actor player;
public int flags = 0;
public FlagContainer(Actor player) {
this.player = player;
}
public void or(int flag, boolean on) {
if (on) flags |= flag;
}
public void or(int flag, boolean on, String permission) {
or(flag, on);
if ((flags & flag) != 0 && !player.hasPermission(permission)) {
flags &= ~flag;
}
if (editSession != null) {
session.remember(editSession);
editSession.flushQueue();
}
}
@ -457,56 +458,55 @@ public class UtilityCommands {
)
@CommandPermissions("worldedit.remove")
@Logging(PLACEMENT)
public void remove(Actor actor, @Optional Player player, @Optional LocalSession session, CommandContext args) throws WorldEditException {
public void remove(Actor actor, CommandContext args) throws WorldEditException, CommandException {
String typeStr = args.getString(0);
int radius = args.getInteger(1);
Player player = actor instanceof Player ? (Player) actor : null;
if (radius < -1) {
actor.printError("Use -1 to remove all entities in loaded chunks");
return;
}
EntityType type = null;
EntityRemover remover = new EntityRemover();
remover.fromString(typeStr);
if (typeStr.matches("all")) {
type = EntityType.ALL;
} else if (typeStr.matches("projectiles?|arrows?")) {
type = EntityType.PROJECTILES;
} else if (typeStr.matches("items?")
|| typeStr.matches("drops?")) {
type = EntityType.ITEMS;
} else if (typeStr.matches("falling(blocks?|sand|gravel)")) {
type = EntityType.FALLING_BLOCKS;
} else if (typeStr.matches("paintings?")
|| typeStr.matches("art")) {
type = EntityType.PAINTINGS;
} else if (typeStr.matches("(item)frames?")) {
type = EntityType.ITEM_FRAMES;
} else if (typeStr.matches("boats?")) {
type = EntityType.BOATS;
} else if (typeStr.matches("minecarts?")
|| typeStr.matches("carts?")) {
type = EntityType.MINECARTS;
} else if (typeStr.matches("tnt")) {
type = EntityType.TNT;
} else if (typeStr.matches("xp")) {
type = EntityType.XP_ORBS;
List<EntityVisitor> visitors = new ArrayList<EntityVisitor>();
LocalSession session = null;
EditSession editSession = null;
if (player != null) {
session = we.getSessionManager().get(player);
Vector center = session.getPlacementPosition(player);
editSession = session.createEditSession(player);
List<? extends Entity> entities;
if (radius >= 0) {
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
entities = editSession.getEntities(region);
} else {
entities = editSession.getEntities();
}
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
} else {
actor.printError("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
return;
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
for (World world : platform.getWorlds()) {
List<? extends Entity> entities = world.getEntities();
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction(world.getWorldData().getEntityRegistry())));
}
}
int removed = 0;
if (player != null) {
Vector origin = session.getPlacementPosition(player);
removed = player.getWorld().removeEntities(type, origin, radius);
} else {
for (World world : we.getServer().getWorlds()) {
removed += world.removeEntities(type, new Vector(), radius);
}
for (EntityVisitor visitor : visitors) {
Operations.completeLegacy(visitor);
removed += visitor.getAffected();
}
actor.print("Marked " + (removed != 1 ? "entities" : "entity") + " for removal.");
if (editSession != null) {
session.remember(editSession);
editSession.flushQueue();
}
player.print("Marked " + removed + " entit(ies) for removal.");
}
@Command(

View File

@ -25,6 +25,7 @@ import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.world.World;
/**
* 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 oy = clicked.getBlockY();
int oz = clicked.getBlockZ();
int initialType = clicked.getWorld().getBlockType(clicked.toVector());
int initialType = ((World) clicked.getExtent()).getBlockType(clicked.toVector());
if (initialType == 0) {
return true;
@ -70,7 +71,7 @@ public class AreaPickaxe implements BlockTool {
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);
}

View File

@ -41,7 +41,7 @@ public class BlockDataCyler implements DoubleActionBlockTool {
private boolean handleCycle(Platform server, LocalConfiguration config,
Player player, LocalSession session, Location clicked, boolean forward) {
World world = clicked.getWorld();
World world = (World) clicked.getExtent();
int type = world.getBlockType(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) {
BlockBag bag = session.getBlockBag(player);
World world = clicked.getWorld();
World world = (World) clicked.getExtent();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, bag, player);
try {
@ -67,7 +67,7 @@ BlockBag bag = session.getBlockBag(player);
@Override
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);
targetBlock = (editSession).getBlock(clicked.toVector());
BlockType type = BlockType.fromID(targetBlock.getType());

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