Switch to Gradle. Use git log --follow for history.

This converts the project into a multi-module Gradle build.

By default, Git does not show history past a rename, so use git log
--follow to see further history.
This commit is contained in:
sk89q
2014-11-14 11:27:39 -08:00
parent 44559cde68
commit 7192780251
714 changed files with 333 additions and 834 deletions

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>tar.gz</format>
<format>tar.bz2</format>
<format>zip</format>
</formats>
<files>
<file>
<source>${project.build.directory}/${artifactId}-${project.version}.jar</source>
<destName>WorldEdit.jar</destName>
<outputDirectory>/</outputDirectory>
<filtered>false</filtered>
</file>
<file>
<source>README.html</source>
<outputDirectory>/</outputDirectory>
<filtered>true</filtered>
</file>
</files>
<fileSets>
<fileSet>
<includes>
<include>LICENSE.txt</include>
<include>CHANGELOG.txt</include>
<include>contrib/craftscripts/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,73 @@
/*
* 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;
/**
* The {@code TAG_Byte_Array} tag.
*/
public final class ByteArrayTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public ByteArrayTag(String name, byte[] value) {
super(name);
this.value = value;
}
@Override
public byte[] getValue() {
return value;
}
@Override
public String toString() {
StringBuilder hex = new StringBuilder();
for (byte b : value) {
String hexDigits = Integer.toHexString(b).toUpperCase();
if (hexDigits.length() == 1) {
hex.append("0");
}
hex.append(hexDigits).append(" ");
}
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Byte_Array" + append + ": " + hex;
}
}

View File

@ -0,0 +1,65 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.jnbt;
/**
* The {@code TAG_Byte} tag.
*/
public final class ByteTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public ByteTag(String name, byte value) {
super(name);
this.value = value;
}
@Override
public Byte getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Byte" + append + ": " + value;
}
}

View File

@ -0,0 +1,436 @@
/*
* 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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The {@code TAG_Compound} tag.
*/
public final class CompoundTag extends Tag {
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 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
* @param listType the class of the contained type
* @return a list of tags
* @param <T> the type of list
*/
@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();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
StringBuilder bldr = new StringBuilder();
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(" ").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

@ -0,0 +1,66 @@
/*
* 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;
/**
* The {@code TAG_Double} tag.
*
*/
public final class DoubleTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public DoubleTag(String name, double value) {
super(name);
this.value = value;
}
@Override
public Double getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Double" + append + ": " + value;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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;
/**
* The {@code TAG_End} tag.
*/
public final class EndTag extends Tag {
/**
* Creates the tag.
*/
public EndTag() {
super();
}
@Override
public Object getValue() {
return null;
}
@Override
public String toString() {
return "TAG_End";
}
}

View File

@ -0,0 +1,65 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.jnbt;
/**
* The {@code TAG_Float} tag.
*/
public final class FloatTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public FloatTag(String name, float value) {
super(name);
this.value = value;
}
@Override
public Float getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Float" + append + ": " + value;
}
}

View File

@ -0,0 +1,77 @@
/*
* 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 static com.google.common.base.Preconditions.checkNotNull;
/**
* The {@code TAG_Int_Array} tag.
*/
public final class IntArrayTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public IntArrayTag(String name, int[] value) {
super(name);
checkNotNull(value);
this.value = value;
}
@Override
public int[] getValue() {
return value;
}
@Override
public String toString() {
StringBuilder hex = new StringBuilder();
for (int b : value) {
String hexDigits = Integer.toHexString(b).toUpperCase();
if (hexDigits.length() == 1) {
hex.append("0");
}
hex.append(hexDigits).append(" ");
}
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Int_Array" + append + ": " + hex;
}
}

View File

@ -0,0 +1,65 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.jnbt;
/**
* The {@code TAG_Int} tag.
*/
public final class IntTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public IntTag(String name, int value) {
super(name);
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Int" + append + ": " + value;
}
}

View File

@ -0,0 +1,450 @@
/*
* 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 javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The {@code TAG_List} tag.
*/
public final class ListTag extends Tag {
private final Class<? extends Tag> type;
private final List<Tag> value;
/**
* Creates the tag with an empty name.
*
* @param type the type of tag
* @param value the value of the tag
*/
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 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);
}
/**
* Gets the type of item in this list.
*
* @return The type of item in this list.
*/
public Class<? extends Tag> getType() {
return type;
}
@Override
public List<Tag> getValue() {
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
* @param listType the class of the contained type
* @return a list of tags
* @param <T> the NBT type
*/
@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();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
StringBuilder bldr = new StringBuilder();
bldr.append("TAG_List").append(append).append(": ").append(value.size()).append(" entries of type ").append(NBTUtils.getTypeName(type)).append("\r\n{\r\n");
for (Tag t : value) {
bldr.append(" ").append(t.toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
}
bldr.append("}");
return bldr.toString();
}
}

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

@ -0,0 +1,66 @@
/*
* 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;
/**
* The {@code TAG_Long} tag.
*
*/
public final class LongTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public LongTag(String name, long value) {
super(name);
this.value = value;
}
@Override
public Long getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Long" + append + ": " + value;
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.nio.charset.Charset;
/**
* A class which holds constant values.
*/
public final class NBTConstants {
public static final Charset CHARSET = Charset.forName("UTF-8");
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,
TYPE_COMPOUND = 10, TYPE_INT_ARRAY = 11;
/**
* Default private constructor.
*/
private NBTConstants() {
}
/**
* Convert a type ID to its corresponding {@link Tag} class.
*
* @param id type ID
* @return tag class
* @throws IllegalArgumentException thrown if the tag ID is not valid
*/
public static Class<? extends Tag> getClassFromType(int id) {
switch (id) {
case TYPE_END:
return EndTag.class;
case TYPE_BYTE:
return ByteTag.class;
case TYPE_SHORT:
return ShortTag.class;
case TYPE_INT:
return IntTag.class;
case TYPE_LONG:
return LongTag.class;
case TYPE_FLOAT:
return FloatTag.class;
case TYPE_DOUBLE:
return DoubleTag.class;
case TYPE_BYTE_ARRAY:
return ByteArrayTag.class;
case TYPE_STRING:
return StringTag.class;
case TYPE_LIST:
return ListTag.class;
case TYPE_COMPOUND:
return CompoundTag.class;
case TYPE_INT_ARRAY:
return IntArrayTag.class;
default:
throw new IllegalArgumentException("Unknown tag type ID of " + id);
}
}
}

View File

@ -0,0 +1,171 @@
/*
* 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.io.Closeable;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* streams, and produces an object graph of subclasses of the {@code Tag}
* object.
*
* <p>The NBT format was created by Markus Persson, and the specification may be
* found at <a href="http://www.minecraft.net/docs/NBT.txt">
* http://www.minecraft.net/docs/NBT.txt</a>.</p>
*/
public final class NBTInputStream implements Closeable {
private final DataInputStream is;
/**
* 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
*/
public NBTInputStream(InputStream is) throws IOException {
this.is = new DataInputStream(is);
}
/**
* Reads an NBT tag from the stream.
*
* @return The tag that was read.
* @throws IOException if an I/O error occurs.
*/
public Tag readTag() throws IOException {
return readTag(0);
}
/**
* Reads an NBT from the stream.
*
* @param depth the depth of this tag
* @return The tag that was read.
* @throws IOException if an I/O error occurs.
*/
private Tag readTag(int depth) throws IOException {
int type = is.readByte() & 0xFF;
String name;
if (type != NBTConstants.TYPE_END) {
int nameLength = is.readShort() & 0xFFFF;
byte[] nameBytes = new byte[nameLength];
is.readFully(nameBytes);
name = new String(nameBytes, NBTConstants.CHARSET);
} else {
name = "";
}
return readTagPayload(type, name, depth);
}
/**
* 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.
*/
private Tag readTagPayload(int type, String name, int depth) throws IOException {
switch (type) {
case NBTConstants.TYPE_END:
if (depth == 0) {
throw new IOException(
"TAG_End found without a TAG_Compound/TAG_List tag preceding it.");
} else {
return new EndTag();
}
case NBTConstants.TYPE_BYTE:
return new ByteTag(name, is.readByte());
case NBTConstants.TYPE_SHORT:
return new ShortTag(name, is.readShort());
case NBTConstants.TYPE_INT:
return new IntTag(name, is.readInt());
case NBTConstants.TYPE_LONG:
return new LongTag(name, is.readLong());
case NBTConstants.TYPE_FLOAT:
return new FloatTag(name, is.readFloat());
case NBTConstants.TYPE_DOUBLE:
return new DoubleTag(name, is.readDouble());
case NBTConstants.TYPE_BYTE_ARRAY:
int length = is.readInt();
byte[] bytes = new byte[length];
is.readFully(bytes);
return new ByteArrayTag(name, bytes);
case NBTConstants.TYPE_STRING:
length = is.readShort();
bytes = new byte[length];
is.readFully(bytes);
return new StringTag(name, new String(bytes, NBTConstants.CHARSET));
case NBTConstants.TYPE_LIST:
int childType = is.readByte();
length = is.readInt();
List<Tag> tagList = new ArrayList<Tag>();
for (int i = 0; i < length; ++i) {
Tag tag = readTagPayload(childType, "", depth + 1);
if (tag instanceof EndTag) {
throw new IOException("TAG_End not permitted in a list.");
}
tagList.add(tag);
}
return new ListTag(name, NBTUtils.getTypeClass(childType), tagList);
case NBTConstants.TYPE_COMPOUND:
Map<String, Tag> tagMap = new HashMap<String, Tag>();
while (true) {
Tag tag = readTag(depth + 1);
if (tag instanceof EndTag) {
break;
} else {
tagMap.put(tag.getName(), tag);
}
}
return new CompoundTag(name, tagMap);
case NBTConstants.TYPE_INT_ARRAY:
length = is.readInt();
int[] data = new int[length];
for (int i = 0; i < length; i++) {
data[i] = is.readInt();
}
return new IntArrayTag(name, data);
default:
throw new IOException("Invalid tag type: " + type + ".");
}
}
@Override
public void close() throws IOException {
is.close();
}
}

View File

@ -0,0 +1,289 @@
/*
* 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.io.Closeable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
/**
* This class writes <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* {@code Tag} objects to an underlying {@code OutputStream}.
*
* <p>The NBT format was created by Markus Persson, and the specification may be
* found at <a href="http://www.minecraft.net/docs/NBT.txt">
* http://www.minecraft.net/docs/NBT.txt</a>.</p>
*/
public final class NBTOutputStream implements Closeable {
/**
* The output stream.
*/
private final DataOutputStream os;
/**
* Creates a new {@code NBTOutputStream}, which will write data to the
* specified underlying output stream.
*
* @param os
* The output stream.
* @throws IOException
* if an I/O error occurs.
*/
public NBTOutputStream(OutputStream os) throws IOException {
this.os = new DataOutputStream(os);
}
/**
* Writes a tag.
*
* @param tag
* The tag to write.
* @throws IOException
* if an I/O error occurs.
*/
public void writeTag(Tag tag) throws IOException {
int type = NBTUtils.getTypeCode(tag.getClass());
String name = tag.getName();
byte[] nameBytes = name.getBytes(NBTConstants.CHARSET);
os.writeByte(type);
os.writeShort(nameBytes.length);
os.write(nameBytes);
if (type == NBTConstants.TYPE_END) {
throw new IOException("Named TAG_End not permitted.");
}
writeTagPayload(tag);
}
/**
* Writes tag payload.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeTagPayload(Tag tag) throws IOException {
int type = NBTUtils.getTypeCode(tag.getClass());
switch (type) {
case NBTConstants.TYPE_END:
writeEndTagPayload((EndTag) tag);
break;
case NBTConstants.TYPE_BYTE:
writeByteTagPayload((ByteTag) tag);
break;
case NBTConstants.TYPE_SHORT:
writeShortTagPayload((ShortTag) tag);
break;
case NBTConstants.TYPE_INT:
writeIntTagPayload((IntTag) tag);
break;
case NBTConstants.TYPE_LONG:
writeLongTagPayload((LongTag) tag);
break;
case NBTConstants.TYPE_FLOAT:
writeFloatTagPayload((FloatTag) tag);
break;
case NBTConstants.TYPE_DOUBLE:
writeDoubleTagPayload((DoubleTag) tag);
break;
case NBTConstants.TYPE_BYTE_ARRAY:
writeByteArrayTagPayload((ByteArrayTag) tag);
break;
case NBTConstants.TYPE_STRING:
writeStringTagPayload((StringTag) tag);
break;
case NBTConstants.TYPE_LIST:
writeListTagPayload((ListTag) tag);
break;
case NBTConstants.TYPE_COMPOUND:
writeCompoundTagPayload((CompoundTag) tag);
break;
case NBTConstants.TYPE_INT_ARRAY:
writeIntArrayTagPayload((IntArrayTag) tag);
break;
default:
throw new IOException("Invalid tag type: " + type + ".");
}
}
/**
* Writes a {@code TAG_Byte} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeByteTagPayload(ByteTag tag) throws IOException {
os.writeByte(tag.getValue());
}
/**
* Writes a {@code TAG_Byte_Array} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeByteArrayTagPayload(ByteArrayTag tag) throws IOException {
byte[] bytes = tag.getValue();
os.writeInt(bytes.length);
os.write(bytes);
}
/**
* Writes a {@code TAG_Compound} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeCompoundTagPayload(CompoundTag tag) throws IOException {
for (Tag childTag : tag.getValue().values()) {
writeTag(childTag);
}
os.writeByte((byte) 0); // end tag - better way?
}
/**
* Writes a {@code TAG_List} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeListTagPayload(ListTag tag) throws IOException {
Class<? extends Tag> clazz = tag.getType();
List<Tag> tags = tag.getValue();
int size = tags.size();
os.writeByte(NBTUtils.getTypeCode(clazz));
os.writeInt(size);
for (Tag tag1 : tags) {
writeTagPayload(tag1);
}
}
/**
* Writes a {@code TAG_String} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeStringTagPayload(StringTag tag) throws IOException {
byte[] bytes = tag.getValue().getBytes(NBTConstants.CHARSET);
os.writeShort(bytes.length);
os.write(bytes);
}
/**
* Writes a {@code TAG_Double} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeDoubleTagPayload(DoubleTag tag) throws IOException {
os.writeDouble(tag.getValue());
}
/**
* Writes a {@code TAG_Float} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeFloatTagPayload(FloatTag tag) throws IOException {
os.writeFloat(tag.getValue());
}
/**
* Writes a {@code TAG_Long} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeLongTagPayload(LongTag tag) throws IOException {
os.writeLong(tag.getValue());
}
/**
* Writes a {@code TAG_Int} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeIntTagPayload(IntTag tag) throws IOException {
os.writeInt(tag.getValue());
}
/**
* Writes a {@code TAG_Short} tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeShortTagPayload(ShortTag tag) throws IOException {
os.writeShort(tag.getValue());
}
/**
* Writes a {@code TAG_Empty} tag.
*
* @param tag the tag
*/
private void writeEndTagPayload(EndTag tag) {
/* empty */
}
private void writeIntArrayTagPayload(IntArrayTag tag) throws IOException {
int[] data = tag.getValue();
os.writeInt(data.length);
for (int aData : data) {
os.writeInt(aData);
}
}
@Override
public void close() throws IOException {
os.close();
}
}

View File

@ -0,0 +1,189 @@
/*
* 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 com.sk89q.worldedit.Vector;
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.
*
*/
public final class NBTUtils {
/**
* Default private constructor.
*/
private NBTUtils() {
}
/**
* Gets the type name of a tag.
*
* @param clazz the tag class
* @return The type name.
*/
public static String getTypeName(Class<? extends Tag> clazz) {
if (clazz.equals(ByteArrayTag.class)) {
return "TAG_Byte_Array";
} else if (clazz.equals(ByteTag.class)) {
return "TAG_Byte";
} else if (clazz.equals(CompoundTag.class)) {
return "TAG_Compound";
} else if (clazz.equals(DoubleTag.class)) {
return "TAG_Double";
} else if (clazz.equals(EndTag.class)) {
return "TAG_End";
} else if (clazz.equals(FloatTag.class)) {
return "TAG_Float";
} else if (clazz.equals(IntTag.class)) {
return "TAG_Int";
} else if (clazz.equals(ListTag.class)) {
return "TAG_List";
} else if (clazz.equals(LongTag.class)) {
return "TAG_Long";
} else if (clazz.equals(ShortTag.class)) {
return "TAG_Short";
} else if (clazz.equals(StringTag.class)) {
return "TAG_String";
} else if (clazz.equals(IntArrayTag.class)) {
return "TAG_Int_Array";
} else {
throw new IllegalArgumentException("Invalid tag classs ("
+ clazz.getName() + ").");
}
}
/**
* Gets the type code of a tag class.
*
* @param clazz the tag class
* @return The type code.
* @throws IllegalArgumentException if the tag class is invalid.
*/
public static int getTypeCode(Class<? extends Tag> clazz) {
if (clazz.equals(ByteArrayTag.class)) {
return NBTConstants.TYPE_BYTE_ARRAY;
} else if (clazz.equals(ByteTag.class)) {
return NBTConstants.TYPE_BYTE;
} else if (clazz.equals(CompoundTag.class)) {
return NBTConstants.TYPE_COMPOUND;
} else if (clazz.equals(DoubleTag.class)) {
return NBTConstants.TYPE_DOUBLE;
} else if (clazz.equals(EndTag.class)) {
return NBTConstants.TYPE_END;
} else if (clazz.equals(FloatTag.class)) {
return NBTConstants.TYPE_FLOAT;
} else if (clazz.equals(IntTag.class)) {
return NBTConstants.TYPE_INT;
} else if (clazz.equals(ListTag.class)) {
return NBTConstants.TYPE_LIST;
} else if (clazz.equals(LongTag.class)) {
return NBTConstants.TYPE_LONG;
} else if (clazz.equals(ShortTag.class)) {
return NBTConstants.TYPE_SHORT;
} else if (clazz.equals(StringTag.class)) {
return NBTConstants.TYPE_STRING;
} else if (clazz.equals(IntArrayTag.class)) {
return NBTConstants.TYPE_INT_ARRAY;
} else {
throw new IllegalArgumentException("Invalid tag classs ("
+ clazz.getName() + ").");
}
}
/**
* Gets the class of a type of tag.
*
* @param type the type
* @return The class.
* @throws IllegalArgumentException if the tag type is invalid.
*/
public static Class<? extends Tag> getTypeClass(int type) {
switch (type) {
case NBTConstants.TYPE_END:
return EndTag.class;
case NBTConstants.TYPE_BYTE:
return ByteTag.class;
case NBTConstants.TYPE_SHORT:
return ShortTag.class;
case NBTConstants.TYPE_INT:
return IntTag.class;
case NBTConstants.TYPE_LONG:
return LongTag.class;
case NBTConstants.TYPE_FLOAT:
return FloatTag.class;
case NBTConstants.TYPE_DOUBLE:
return DoubleTag.class;
case NBTConstants.TYPE_BYTE_ARRAY:
return ByteArrayTag.class;
case NBTConstants.TYPE_STRING:
return StringTag.class;
case NBTConstants.TYPE_LIST:
return ListTag.class;
case NBTConstants.TYPE_COMPOUND:
return CompoundTag.class;
case NBTConstants.TYPE_INT_ARRAY:
return IntArrayTag.class;
default:
throw new IllegalArgumentException("Invalid tag type : " + type
+ ".");
}
}
/**
* 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
*/
public static Vector toVector(ListTag listTag) {
checkNotNull(listTag);
return new Vector(listTag.asDouble(0), listTag.asDouble(1), listTag.asDouble(2));
}
/**
* Get child tag of a NBT structure.
*
* @param items the map to read from
* @param key the key to look for
* @param expected the expected NBT class type
* @return child tag
* @throws InvalidFormatException
*/
public static <T extends Tag> T getChildTag(Map<String, Tag> items, String key, Class<T> expected) throws InvalidFormatException {
if (!items.containsKey(key)) {
throw new InvalidFormatException("Missing a \"" + key + "\" tag");
}
Tag tag = items.get(key);
if (!expected.isInstance(tag)) {
throw new InvalidFormatException(key + " tag is not of tag type " + expected.getName());
}
return expected.cast(tag);
}
}

View File

@ -0,0 +1,65 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.jnbt;
/**
* The {@code TAG_Short} tag.
*/
public final class ShortTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public ShortTag(String name, short value) {
super(name);
this.value = value;
}
@Override
public Short getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Short" + append + ": " + value;
}
}

View File

@ -0,0 +1,69 @@
/*
* 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 static com.google.common.base.Preconditions.checkNotNull;
/**
* The {@code TAG_String} tag.
*/
public final class StringTag extends Tag {
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 of the tag
* @param value the value of the tag
*/
public StringTag(String name, String value) {
super(name);
checkNotNull(value);
this.value = value;
}
@Override
public String getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_String" + append + ": " + value;
}
}

View File

@ -0,0 +1,64 @@
/*
* 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;
/**
* Represents a NBT tag.
*/
public abstract class 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
*/
Tag(String name) {
if (name == null) {
name = "";
}
this.name = name;
}
/**
* Gets the name of this tag.
*
* @return the name of this tag
*/
public final String getName() {
return name;
}
/**
* Gets the value of this tag.
*
* @return the value
*/
public abstract Object getValue();
}

View File

@ -0,0 +1,93 @@
/*
* 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.minecraft.util.commands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* This annotation indicates a command. Methods should be marked with this
* annotation to tell {@link CommandsManager} that the method is a command.
* Note that the method name can actually be anything.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Command {
/**
* A list of aliases for the command. The first alias is the most
* important -- it is the main name of the command. (The method name
* is never used for anything).
*
* @return Aliases for a command
*/
String[] aliases();
/**
* Usage instruction. Example text for usage could be
* {@code [-h harps] [name] [message]}.
*
* @return Usage instructions for a command
*/
String usage() default "";
/**
* @return A short description for the command.
*/
String desc();
/**
* The minimum number of arguments. This should be 0 or above.
*
* @return the minimum number of arguments
*/
int min() default 0;
/**
* The maximum number of arguments. Use -1 for an unlimited number
* of arguments.
*
* @return the maximum number of arguments
*/
int max() default -1;
/**
* Flags allow special processing for flags such as -h in the command,
* allowing users to easily turn on a flag. This is a string with
* each character being a flag. Use A-Z and a-z as possible flags.
* Appending a flag with a : makes the flag character before a value flag,
* meaning that if it is given it must have a value
*
* @return Flags matching a-zA-Z
*/
String flags() default "";
/**
* @return A long description for the command.
*/
String help() default "";
/**
* Get whether any flag can be used.
*
* @return true if so
*/
boolean anyFlags() default 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.minecraft.util.commands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Any command with this annotation will run the raw command as shown in the
* thing, as long as it is registered in the current {@link CommandsManager}.
* Mostly to move commands around without breaking things.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandAlias {
/**
* Get the raw {@link CommandsManager}-formatted command arg array to run
*
* @return the command
*/
String[] value();
}

View File

@ -0,0 +1,339 @@
/*
* 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.minecraft.util.commands;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class CommandContext {
protected final String command;
protected final List<String> parsedArgs;
protected final List<Integer> originalArgIndices;
protected final String[] originalArgs;
protected final Set<Character> booleanFlags = new HashSet<Character>();
protected final Map<Character, String> valueFlags = new HashMap<Character, String>();
protected final SuggestionContext suggestionContext;
protected final CommandLocals locals;
public static String[] split(String args) {
return args.split(" ", -1);
}
public CommandContext(String args) throws CommandException {
this(args.split(" ", -1), null);
}
public CommandContext(String[] args) throws CommandException {
this(args, null);
}
public CommandContext(String args, Set<Character> valueFlags) throws CommandException {
this(args.split(" ", -1), valueFlags);
}
public CommandContext(String args, Set<Character> valueFlags, boolean allowHangingFlag)
throws CommandException {
this(args.split(" ", -1), valueFlags, allowHangingFlag, new CommandLocals());
}
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
this(args, valueFlags, false, null);
}
/**
* Parse the given array of arguments.
*
* <p>Empty arguments are removed from the list of arguments.</p>
*
* @param args an array with arguments
* @param valueFlags a set containing all value flags (pass null to disable value flag parsing)
* @param allowHangingFlag true if hanging flags are allowed
* @param locals the locals, null to create empty one
* @throws CommandException thrown on a parsing error
*/
public CommandContext(String[] args, Set<Character> valueFlags,
boolean allowHangingFlag, CommandLocals locals) throws CommandException {
if (valueFlags == null) {
valueFlags = Collections.emptySet();
}
originalArgs = args;
command = args[0];
this.locals = locals != null ? locals : new CommandLocals();
boolean isHanging = false;
SuggestionContext suggestionContext = SuggestionContext.hangingValue();
// Eliminate empty args and combine multiword args first
List<Integer> argIndexList = new ArrayList<Integer>(args.length);
List<String> argList = new ArrayList<String>(args.length);
for (int i = 1; i < args.length; ++i) {
isHanging = false;
String arg = args[i];
if (arg.isEmpty()) {
isHanging = true;
continue;
}
argIndexList.add(i);
switch (arg.charAt(0)) {
case '\'':
case '"':
final StringBuilder build = new StringBuilder();
final char quotedChar = arg.charAt(0);
int endIndex;
for (endIndex = i; endIndex < args.length; ++endIndex) {
final String arg2 = args[endIndex];
if (arg2.charAt(arg2.length() - 1) == quotedChar && arg2.length() > 1) {
if (endIndex != i) build.append(' ');
build.append(arg2.substring(endIndex == i ? 1 : 0, arg2.length() - 1));
break;
} else if (endIndex == i) {
build.append(arg2.substring(1));
} else {
build.append(' ').append(arg2);
}
}
if (endIndex < args.length) {
arg = build.toString();
i = endIndex;
}
// In case there is an empty quoted string
if (arg.isEmpty()) {
continue;
}
// else raise exception about hanging quotes?
}
argList.add(arg);
}
// Then flags
this.originalArgIndices = new ArrayList<Integer>(argIndexList.size());
this.parsedArgs = new ArrayList<String>(argList.size());
for (int nextArg = 0; nextArg < argList.size(); ) {
// Fetch argument
String arg = argList.get(nextArg++);
suggestionContext = SuggestionContext.hangingValue();
// Not a flag?
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z\\?]+$")) {
if (!isHanging) {
suggestionContext = SuggestionContext.lastValue();
}
originalArgIndices.add(argIndexList.get(nextArg - 1));
parsedArgs.add(arg);
continue;
}
// Handle flag parsing terminator --
if (arg.equals("--")) {
while (nextArg < argList.size()) {
originalArgIndices.add(argIndexList.get(nextArg));
parsedArgs.add(argList.get(nextArg++));
}
break;
}
// Go through the flag characters
for (int i = 1; i < arg.length(); ++i) {
char flagName = arg.charAt(i);
if (valueFlags.contains(flagName)) {
if (this.valueFlags.containsKey(flagName)) {
throw new CommandException("Value flag '" + flagName + "' already given");
}
if (nextArg >= argList.size()) {
if (allowHangingFlag) {
suggestionContext = SuggestionContext.flag(flagName);
break;
} else {
throw new CommandException("No value specified for the '-" + flagName + "' flag.");
}
}
// If it is a value flag, read another argument and add it
this.valueFlags.put(flagName, argList.get(nextArg++));
if (!isHanging) {
suggestionContext = SuggestionContext.flag(flagName);
}
} else {
booleanFlags.add(flagName);
}
}
}
this.suggestionContext = suggestionContext;
}
public SuggestionContext getSuggestionContext() {
return suggestionContext;
}
public String getCommand() {
return command;
}
public boolean matches(String command) {
return this.command.equalsIgnoreCase(command);
}
public String getString(int index) {
return parsedArgs.get(index);
}
public String getString(int index, String def) {
return index < parsedArgs.size() ? parsedArgs.get(index) : def;
}
public String getJoinedStrings(int initialIndex) {
initialIndex = originalArgIndices.get(initialIndex);
StringBuilder buffer = new StringBuilder(originalArgs[initialIndex]);
for (int i = initialIndex + 1; i < originalArgs.length; ++i) {
buffer.append(" ").append(originalArgs[i]);
}
return buffer.toString();
}
public String getRemainingString(int start) {
return getString(start, parsedArgs.size() - 1);
}
public String getString(int start, int end) {
StringBuilder buffer = new StringBuilder(parsedArgs.get(start));
for (int i = start + 1; i < end + 1; ++i) {
buffer.append(" ").append(parsedArgs.get(i));
}
return buffer.toString();
}
public int getInteger(int index) throws NumberFormatException {
return Integer.parseInt(parsedArgs.get(index));
}
public int getInteger(int index, int def) throws NumberFormatException {
return index < parsedArgs.size() ? Integer.parseInt(parsedArgs.get(index)) : def;
}
public double getDouble(int index) throws NumberFormatException {
return Double.parseDouble(parsedArgs.get(index));
}
public double getDouble(int index, double def) throws NumberFormatException {
return index < parsedArgs.size() ? Double.parseDouble(parsedArgs.get(index)) : def;
}
public String[] getSlice(int index) {
String[] slice = new String[originalArgs.length - index];
System.arraycopy(originalArgs, index, slice, 0, originalArgs.length - index);
return slice;
}
public String[] getPaddedSlice(int index, int padding) {
String[] slice = new String[originalArgs.length - index + padding];
System.arraycopy(originalArgs, index, slice, padding, originalArgs.length - index);
return slice;
}
public String[] getParsedSlice(int index) {
String[] slice = new String[parsedArgs.size() - index];
System.arraycopy(parsedArgs.toArray(new String[parsedArgs.size()]), index, slice, 0, parsedArgs.size() - index);
return slice;
}
public String[] getParsedPaddedSlice(int index, int padding) {
String[] slice = new String[parsedArgs.size() - index + padding];
System.arraycopy(parsedArgs.toArray(new String[parsedArgs.size()]), index, slice, padding, parsedArgs.size() - index);
return slice;
}
public boolean hasFlag(char ch) {
return booleanFlags.contains(ch) || valueFlags.containsKey(ch);
}
public Set<Character> getFlags() {
return booleanFlags;
}
public Map<Character, String> getValueFlags() {
return valueFlags;
}
public String getFlag(char ch) {
return valueFlags.get(ch);
}
public String getFlag(char ch, String def) {
final String value = valueFlags.get(ch);
if (value == null) {
return def;
}
return value;
}
public int getFlagInteger(char ch) throws NumberFormatException {
return Integer.parseInt(valueFlags.get(ch));
}
public int getFlagInteger(char ch, int def) throws NumberFormatException {
final String value = valueFlags.get(ch);
if (value == null) {
return def;
}
return Integer.parseInt(value);
}
public double getFlagDouble(char ch) throws NumberFormatException {
return Double.parseDouble(valueFlags.get(ch));
}
public double getFlagDouble(char ch, double def) throws NumberFormatException {
final String value = valueFlags.get(ch);
if (value == null) {
return def;
}
return Double.parseDouble(value);
}
public int argsLength() {
return parsedArgs.size();
}
public CommandLocals getLocals() {
return locals;
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.minecraft.util.commands;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import static com.google.common.base.Preconditions.checkNotNull;
public class CommandException extends Exception {
private List<String> commandStack = new ArrayList<String>();
public CommandException() {
super();
}
public CommandException(String message) {
super(message);
}
public CommandException(String message, Throwable t) {
super(message, t);
}
public CommandException(Throwable t) {
super(t);
}
public void prependStack(String name) {
commandStack.add(name);
}
/**
* Gets the command that was called, which will include the sub-command
* (i.e. "/br sphere").
*
* @param prefix the command shebang character (such as "/") -- may be empty
* @param spacedSuffix a suffix to put at the end (optional) -- may be null
* @return the command that was used
*/
public String getCommandUsed(String prefix, @Nullable String spacedSuffix) {
checkNotNull(prefix);
StringBuilder builder = new StringBuilder();
if (prefix != null) {
builder.append(prefix);
}
ListIterator<String> li = commandStack.listIterator(commandStack.size());
while (li.hasPrevious()) {
if (li.previousIndex() != commandStack.size() - 1) {
builder.append(" ");
}
builder.append(li.previous());
}
if (spacedSuffix != null) {
if (builder.length() > 0) {
builder.append(" ");
}
builder.append(spacedSuffix);
}
return builder.toString().trim();
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.minecraft.util.commands;
import java.util.HashMap;
import java.util.Map;
public class CommandLocals {
private final Map<Object, Object> locals = new HashMap<Object, Object>();
public boolean containsKey(Object key) {
return locals.containsKey(key);
}
public boolean containsValue(Object value) {
return locals.containsValue(value);
}
public Object get(Object key) {
return locals.get(key);
}
@SuppressWarnings("unchecked")
public <T> T get(Class<T> key) {
return (T) locals.get(key);
}
public Object put(Object key, Object value) {
return locals.put(key, value);
}
}

View File

@ -0,0 +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.minecraft.util.commands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Indicates a list of permissions that should be checked.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandPermissions {
/**
* A list of permissions. Only one permission has to be met
* for the command to be permitted.
*
* @return a list of permissions strings
*/
String[] value();
}

View File

@ -0,0 +1,27 @@
/*
* 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.minecraft.util.commands;
/**
* Thrown when not enough permissions are satisfied.
*/
public class CommandPermissionsException extends CommandException {
}

View File

@ -0,0 +1,34 @@
/*
* 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.minecraft.util.commands;
public class CommandUsageException extends CommandException {
protected String usage;
public CommandUsageException(String message, String usage) {
super(message);
this.usage = usage;
}
public String getUsage() {
return usage;
}
}

View File

@ -0,0 +1,591 @@
/*
* 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.minecraft.util.commands;
import com.sk89q.util.StringUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Manager for handling commands. This allows you to easily process commands,
* including nested commands, by correctly annotating methods of a class.
*
* <p>To use this, it is merely a matter of registering classes containing
* the commands (as methods with the proper annotations) with the
* manager. When you want to process a command, use one of the
* {@code execute} methods. If something is wrong, such as incorrect
* usage, insufficient permissions, or a missing command altogether, an
* exception will be raised for upstream handling.</p>
*
* <p>Methods of a class to be registered can be static, but if an injector
* is registered with the class, the instances of the command classes
* will be created automatically and methods will be called non-statically.</p>
*
* <p>To mark a method as a command, use {@link Command}. For nested commands,
* see {@link NestedCommand}. To handle permissions, use
* {@link CommandPermissions}.</p>
*
* <p>This uses Java reflection extensively, but to reduce the overhead of
* reflection, command lookups are completely cached on registration. This
* allows for fast command handling. Method invocation still has to be done
* with reflection, but this is quite fast in that of itself.</p>
*
* @param <T> command sender class
*/
@SuppressWarnings("ProtectedField")
public abstract class CommandsManager<T> {
protected static final Logger logger =
Logger.getLogger(CommandsManager.class.getCanonicalName());
/**
* Mapping of commands (including aliases) with a description. Root
* commands are stored under a key of null, whereas child commands are
* cached under their respective {@link Method}. The child map has
* the key of the command name (one for each alias) with the
* method.
*/
protected Map<Method, Map<String, Method>> commands = new HashMap<Method, Map<String, Method>>();
/**
* Used to store the instances associated with a method.
*/
protected Map<Method, Object> instances = new HashMap<Method, Object>();
/**
* Mapping of commands (not including aliases) with a description. This
* is only for top level commands.
*/
protected Map<String, String> descs = new HashMap<String, String>();
/**
* Stores the injector used to getInstance.
*/
protected Injector injector;
/**
* Mapping of commands (not including aliases) with a description. This
* is only for top level commands.
*/
protected Map<String, String> helpMessages = new HashMap<String, String>();
/**
* Register an class that contains commands (denoted by {@link Command}.
* If no dependency injector is specified, then the methods of the
* class will be registered to be called statically. Otherwise, new
* instances will be created of the command classes and methods will
* not be called statically.
*
* @param cls the class to register
*/
public void register(Class<?> cls) {
registerMethods(cls, null);
}
/**
* Register an class that contains commands (denoted by {@link Command}.
* If no dependency injector is specified, then the methods of the
* class will be registered to be called statically. Otherwise, new
* instances will be created of the command classes and methods will
* not be called statically. A List of {@link Command} annotations from
* registered commands is returned.
*
* @param cls the class to register
* @return A List of {@link Command} annotations from registered commands,
* for use in eg. a dynamic command registration system.
*/
public List<Command> registerAndReturn(Class<?> cls) {
return registerMethods(cls, null);
}
/**
* Register the methods of a class. This will automatically construct
* instances as necessary.
*
* @param cls the class to register
* @param parent the parent method
* @return Commands Registered
*/
public List<Command> registerMethods(Class<?> cls, Method parent) {
try {
if (getInjector() == null) {
return registerMethods(cls, parent, null);
} else {
Object obj = getInjector().getInstance(cls);
return registerMethods(cls, parent, obj);
}
} catch (InvocationTargetException e) {
logger.log(Level.SEVERE, "Failed to register commands", e);
} catch (IllegalAccessException e) {
logger.log(Level.SEVERE, "Failed to register commands", e);
} catch (InstantiationException e) {
logger.log(Level.SEVERE, "Failed to register commands", e);
}
return null;
}
/**
* Register the methods of a class.
*
* @param cls the class to register
* @param parent the parent method
* @param obj the object whose methods will become commands if they are annotated
* @return a list of commands
*/
private List<Command> registerMethods(Class<?> cls, Method parent, Object obj) {
Map<String, Method> map;
List<Command> registered = new ArrayList<Command>();
// Make a new hash map to cache the commands for this class
// as looking up methods via reflection is fairly slow
if (commands.containsKey(parent)) {
map = commands.get(parent);
} else {
map = new HashMap<String, Method>();
commands.put(parent, map);
}
for (Method method : cls.getMethods()) {
if (!method.isAnnotationPresent(Command.class)) {
continue;
}
boolean isStatic = Modifier.isStatic(method.getModifiers());
Command cmd = method.getAnnotation(Command.class);
// Cache the aliases too
for (String alias : cmd.aliases()) {
map.put(alias, method);
}
// We want to be able invoke with an instance
if (!isStatic) {
// Can't register this command if we don't have an instance
if (obj == null) {
continue;
}
instances.put(method, obj);
}
// Build a list of commands and their usage details, at least for
// root level commands
if (parent == null) {
final String commandName = cmd.aliases()[0];
final String desc = cmd.desc();
final String usage = cmd.usage();
if (usage.isEmpty()) {
descs.put(commandName, desc);
} else {
descs.put(commandName, usage + " - " + desc);
}
String help = cmd.help();
if (help.isEmpty()) {
help = desc;
}
final CharSequence arguments = getArguments(cmd);
for (String alias : cmd.aliases()) {
final String helpMessage = "/" + alias + " " + arguments + "\n\n" + help;
final String key = alias.replaceAll("/", "");
String previous = helpMessages.put(key, helpMessage);
if (previous != null && !previous.replaceAll("^/[^ ]+ ", "").equals(helpMessage.replaceAll("^/[^ ]+ ", ""))) {
helpMessages.put(key, previous + "\n\n" + helpMessage);
}
}
}
// Add the command to the registered command list for return
registered.add(cmd);
// Look for nested commands -- if there are any, those have
// to be cached too so that they can be quickly looked
// up when processing commands
if (method.isAnnotationPresent(NestedCommand.class)) {
NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class);
for (Class<?> nestedCls : nestedCmd.value()) {
registerMethods(nestedCls, method);
}
}
}
if (cls.getSuperclass() != null) {
registerMethods(cls.getSuperclass(), parent, obj);
}
return registered;
}
/**
* Checks to see whether there is a command named such at the root level.
* This will check aliases as well.
*
* @param command the command
* @return true if the command exists
*/
public boolean hasCommand(String command) {
return commands.get(null).containsKey(command.toLowerCase());
}
/**
* Get a list of command descriptions. This is only for root commands.
*
* @return a map of commands
*/
public Map<String, String> getCommands() {
return descs;
}
/**
* Get the mapping of methods under a parent command.
*
* @return the mapping
*/
public Map<Method, Map<String, Method>> getMethods() {
return commands;
}
/**
* Get a map from command name to help message. This is only for root commands.
*
* @return a map of help messages for each command
*/
public Map<String, String> getHelpMessages() {
return helpMessages;
}
/**
* Get the usage string for a command.
*
* @param args the arguments
* @param level the depth of the command
* @param cmd the command annotation
* @return the usage string
*/
protected String getUsage(String[] args, int level, Command cmd) {
final StringBuilder command = new StringBuilder();
command.append('/');
for (int i = 0; i <= level; ++i) {
command.append(args[i]);
command.append(' ');
}
command.append(getArguments(cmd));
final String help = cmd.help();
if (!help.isEmpty()) {
command.append("\n\n");
command.append(help);
}
return command.toString();
}
protected CharSequence getArguments(Command cmd) {
final String flags = cmd.flags();
final StringBuilder command2 = new StringBuilder();
if (!flags.isEmpty()) {
String flagString = flags.replaceAll(".:", "");
if (!flagString.isEmpty()) {
command2.append("[-");
for (int i = 0; i < flagString.length(); ++i) {
command2.append(flagString.charAt(i));
}
command2.append("] ");
}
}
command2.append(cmd.usage());
return command2;
}
/**
* Get the usage string for a nested command.
*
* @param args the arguments
* @param level the depth of the command
* @param method the parent method
* @param player the player
* @return the usage string
* @throws CommandException on some error
*/
protected String getNestedUsage(String[] args, int level, Method method, T player) throws CommandException {
StringBuilder command = new StringBuilder();
command.append("/");
for (int i = 0; i <= level; ++i) {
command.append(args[i]).append(" ");
}
Map<String, Method> map = commands.get(method);
boolean found = false;
command.append("<");
Set<String> allowedCommands = new HashSet<String>();
for (Map.Entry<String, Method> entry : map.entrySet()) {
Method childMethod = entry.getValue();
found = true;
if (hasPermission(childMethod, player)) {
Command childCmd = childMethod.getAnnotation(Command.class);
allowedCommands.add(childCmd.aliases()[0]);
}
}
if (!allowedCommands.isEmpty()) {
command.append(StringUtil.joinString(allowedCommands, "|", 0));
} else {
if (!found) {
command.append("?");
} else {
//command.append("action");
throw new CommandPermissionsException();
}
}
command.append(">");
return command.toString();
}
/**
* Attempt to execute a command. This version takes a separate command
* name (for the root command) and then a list of following arguments.
*
* @param cmd command to run
* @param args arguments
* @param player command source
* @param methodArgs method arguments
* @throws CommandException thrown when the command throws an error
*/
public void execute(String cmd, String[] args, T player, Object... methodArgs) throws CommandException {
String[] newArgs = new String[args.length + 1];
System.arraycopy(args, 0, newArgs, 1, args.length);
newArgs[0] = cmd;
Object[] newMethodArgs = new Object[methodArgs.length + 1];
System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length);
executeMethod(null, newArgs, player, newMethodArgs, 0);
}
/**
* Attempt to execute a command.
*
* @param args the arguments
* @param player the player
* @param methodArgs the arguments for the method
* @throws CommandException thrown on command error
*/
public void execute(String[] args, T player, Object... methodArgs) throws CommandException {
Object[] newMethodArgs = new Object[methodArgs.length + 1];
System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length);
executeMethod(null, args, player, newMethodArgs, 0);
}
/**
* Attempt to execute a command.
*
* @param parent the parent method
* @param args an array of arguments
* @param player the player
* @param methodArgs the array of method arguments
* @param level the depth of the command
* @throws CommandException thrown on a command error
*/
public void executeMethod(Method parent, String[] args, T player, Object[] methodArgs, int level) throws CommandException {
String cmdName = args[level];
Map<String, Method> map = commands.get(parent);
Method method = map.get(cmdName.toLowerCase());
if (method == null) {
if (parent == null) { // Root
throw new UnhandledCommandException();
} else {
throw new MissingNestedCommandException("Unknown command: " + cmdName,
getNestedUsage(args, level - 1, parent, player));
}
}
checkPermission(player, method);
int argsCount = args.length - 1 - level;
// checks if we need to execute the body of the nested command method (false)
// or display the help what commands are available (true)
// this is all for an args count of 0 if it is > 0 and a NestedCommand Annotation is present
// it will always handle the methods that NestedCommand points to
// e.g.:
// - /cmd - @NestedCommand(executeBody = true) will go into the else loop and execute code in that method
// - /cmd <arg1> <arg2> - @NestedCommand(executeBody = true) will always go to the nested command class
// - /cmd <arg1> - @NestedCommand(executeBody = false) will always go to the nested command class not matter the args
boolean executeNested = method.isAnnotationPresent(NestedCommand.class)
&& (argsCount > 0 || !method.getAnnotation(NestedCommand.class).executeBody());
if (executeNested) {
if (argsCount == 0) {
throw new MissingNestedCommandException("Sub-command required.",
getNestedUsage(args, level, method, player));
} else {
executeMethod(method, args, player, methodArgs, level + 1);
}
} else if (method.isAnnotationPresent(CommandAlias.class)) {
CommandAlias aCmd = method.getAnnotation(CommandAlias.class);
executeMethod(parent, aCmd.value(), player, methodArgs, level);
} else {
Command cmd = method.getAnnotation(Command.class);
String[] newArgs = new String[args.length - level];
System.arraycopy(args, level, newArgs, 0, args.length - level);
final Set<Character> valueFlags = new HashSet<Character>();
char[] flags = cmd.flags().toCharArray();
Set<Character> newFlags = new HashSet<Character>();
for (int i = 0; i < flags.length; ++i) {
if (flags.length > i + 1 && flags[i + 1] == ':') {
valueFlags.add(flags[i]);
++i;
}
newFlags.add(flags[i]);
}
CommandContext context = new CommandContext(newArgs, valueFlags);
if (context.argsLength() < cmd.min()) {
throw new CommandUsageException("Too few arguments.", getUsage(args, level, cmd));
}
if (cmd.max() != -1 && context.argsLength() > cmd.max()) {
throw new CommandUsageException("Too many arguments.", getUsage(args, level, cmd));
}
if (!cmd.anyFlags()) {
for (char flag : context.getFlags()) {
if (!newFlags.contains(flag)) {
throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, level, cmd));
}
}
}
methodArgs[0] = context;
Object instance = instances.get(method);
invokeMethod(parent, args, player, method, instance, methodArgs, argsCount);
}
}
protected void checkPermission(T player, Method method) throws CommandException {
if (!hasPermission(method, player)) {
throw new CommandPermissionsException();
}
}
public void invokeMethod(Method parent, String[] args, T player, Method method, Object instance, Object[] methodArgs, int level) throws CommandException {
try {
method.invoke(instance, methodArgs);
} catch (IllegalArgumentException e) {
logger.log(Level.SEVERE, "Failed to execute command", e);
} catch (IllegalAccessException e) {
logger.log(Level.SEVERE, "Failed to execute command", e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof CommandException) {
throw (CommandException) e.getCause();
}
throw new WrappedCommandException(e.getCause());
}
}
/**
* Returns whether a player has access to a command.
*
* @param method the method
* @param player the player
* @return true if permission is granted
*/
protected boolean hasPermission(Method method, T player) {
CommandPermissions perms = method.getAnnotation(CommandPermissions.class);
if (perms == null) {
return true;
}
for (String perm : perms.value()) {
if (hasPermission(player, perm)) {
return true;
}
}
return false;
}
/**
* Returns whether a player permission..
*
* @param player the player
* @param permission the permission
* @return true if permission is granted
*/
public abstract boolean hasPermission(T player, String permission);
/**
* Get the injector used to create new instances. This can be
* null, in which case only classes will be registered statically.
*
* @return an injector instance
*/
public Injector getInjector() {
return injector;
}
/**
* Set the injector for creating new instances.
*
* @param injector injector or null
*/
public void setInjector(Injector injector) {
this.injector = injector;
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.minecraft.util.commands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* This annotation indicates that a command can be used from the console.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Console {
}

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.minecraft.util.commands;
import java.lang.reflect.InvocationTargetException;
/**
* Constructs new instances.
*/
public interface Injector {
/**
* Constructs a new instance of the given class.
*
* @param cls class
* @return object
* @throws IllegalAccessException thrown on injection fault
* @throws InstantiationException thrown on injection fault
* @throws InvocationTargetException thrown on injection fault
*/
public Object getInstance(Class<?> cls) throws InvocationTargetException, IllegalAccessException, InstantiationException;
}

View File

@ -0,0 +1,68 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//$Id$
package com.sk89q.minecraft.util.commands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Indicates how the affected blocks should be hinted at in the log.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Logging {
public enum LogMode {
/**
* Player position
*/
POSITION,
/**
* Region selection
*/
REGION,
/**
* Player orientation and region selection
*/
ORIENTATION_REGION,
/**
* Either the player position or pos1, depending on the placeAtPos1 flag
*/
PLACEMENT,
/**
* Log all information available
*/
ALL
}
/**
* Log mode.
*
* @return either POSITION, REGION, ORIENTATION_REGION, PLACEMENT or ALL
*/
LogMode value();
}

View File

@ -0,0 +1,28 @@
/*
* 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.minecraft.util.commands;
public class MissingNestedCommandException extends CommandUsageException {
public MissingNestedCommandException(String message, String usage) {
super(message, usage);
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.minecraft.util.commands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Indicates a nested command. Mark methods with this annotation to tell
* {@link CommandsManager} that a method is merely a shell for child
* commands. Note that the body of a method marked with this annotation
* will never called. Additionally, not all fields of {@link Command} apply
* when it is used in conjunction with this annotation, although both
* are still required.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface NestedCommand {
/**
* A list of classes with the child commands.
*
* @return a list of classes
*/
Class<?>[] value();
/**
* If set to true it will execute the body of the tagged method.
*
* @return true to execute the body of the annotated method
*/
boolean executeBody() default false;
}

View File

@ -0,0 +1,61 @@
/*
* 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.minecraft.util.commands;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SimpleInjector implements Injector {
private static final Logger log = Logger.getLogger(SimpleInjector.class.getCanonicalName());
private Object[] args;
private Class<?>[] argClasses;
public SimpleInjector(Object... args) {
this.args = args;
argClasses = new Class[args.length];
for (int i = 0; i < args.length; ++i) {
argClasses[i] = args[i].getClass();
}
}
@Override
public Object getInstance(Class<?> clazz) {
try {
Constructor<?> ctr = clazz.getConstructor(argClasses);
ctr.setAccessible(true);
return ctr.newInstance(args);
} catch (NoSuchMethodException e) {
log.log(Level.SEVERE, "Error initializing commands class " + clazz, e);
return null;
} catch (InvocationTargetException e) {
log.log(Level.SEVERE, "Error initializing commands class " + clazz, e);
return null;
} catch (InstantiationException e) {
log.log(Level.SEVERE, "Error initializing commands class " + clazz, e);
return null;
} catch (IllegalAccessException e) {
log.log(Level.SEVERE, "Error initializing commands class " + clazz, e);
return null;
}
}
}

View File

@ -0,0 +1,68 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.minecraft.util.commands;
public class SuggestionContext {
private static final SuggestionContext FOR_LAST = new SuggestionContext(null, true);
private static final SuggestionContext FOR_HANGING = new SuggestionContext(null, false);
private final Character flag;
private final boolean forLast;
private SuggestionContext(Character flag, boolean forLast) {
this.flag = flag;
this.forLast = forLast;
}
public boolean forHangingValue() {
return flag == null && !forLast;
}
public boolean forLastValue() {
return flag == null && forLast;
}
public boolean forFlag() {
return flag != null;
}
public Character getFlag() {
return flag;
}
@Override
public String toString() {
return forFlag() ? ("-" + getFlag()) : (forHangingValue() ? "hanging" : "last");
}
public static SuggestionContext flag(Character flag) {
return new SuggestionContext(flag, false);
}
public static SuggestionContext lastValue() {
return FOR_LAST;
}
public static SuggestionContext hangingValue() {
return FOR_HANGING;
}
}

View File

@ -0,0 +1,24 @@
/*
* 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.minecraft.util.commands;
public class UnhandledCommandException extends CommandException {
}

View File

@ -0,0 +1,28 @@
/*
* 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.minecraft.util.commands;
public class WrappedCommandException extends CommandException {
public WrappedCommandException(Throwable t) {
super(t);
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.util;
public final class ArrayUtil {
private ArrayUtil() {
}
public static String[] removePortionOfArray(String[] array, int from, int to, String replace) {
String[] newArray = new String[from + array.length - to - (replace == null ? 1 : 0)];
System.arraycopy(array, 0, newArray, 0, from);
if (replace != null) newArray[from] = replace;
System.arraycopy(array, to + 1, newArray, from + (replace == null ? 0 : 1),
array.length - to - 1);
return newArray;
}
public static char[] removePortionOfArray(char[] array, int from, int to, Character replace) {
char[] newArray = new char[from + array.length - to - (replace == null ? 1 : 0)];
System.arraycopy(array, 0, newArray, 0, from);
if (replace != null) newArray[from] = replace;
System.arraycopy(array, to + 1, newArray, from + (replace == null ? 0 : 1),
array.length - to - 1);
return newArray;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.util;
import java.lang.reflect.Field;
public final class ReflectionUtil {
private ReflectionUtil() {
}
@SuppressWarnings("unchecked")
public static <T> T getField(Object from, String name) {
Class<?> checkClass = from.getClass();
do {
try {
Field field = checkClass.getDeclaredField(name);
field.setAccessible(true);
return (T) field.get(from);
} catch (NoSuchFieldException ignored) {
} catch (IllegalAccessException ignored) {
}
} while (checkClass.getSuperclass() != Object.class && ((checkClass = checkClass.getSuperclass()) != null));
return null;
}
}

View File

@ -0,0 +1,304 @@
/*
* 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.util;
import java.util.Collection;
import java.util.Map;
/**
* String utilities.
*/
public final class StringUtil {
private StringUtil() {
}
/**
* Trim a string if it is longer than a certain length.
*
* @param str the stirng
* @param len the length to trim to
* @return a new string
*/
public static String trimLength(String str, int len) {
if (str.length() > len) {
return str.substring(0, len);
}
return str;
}
/**
* Join an array of strings into a string.
*
* @param str the string array
* @param delimiter the delimiter
* @param initialIndex the initial index to start form
* @return a new string
*/
public static String joinString(String[] str, String delimiter, int initialIndex) {
if (str.length == 0) {
return "";
}
StringBuilder buffer = new StringBuilder(str[initialIndex]);
for (int i = initialIndex + 1; i < str.length; ++i) {
buffer.append(delimiter).append(str[i]);
}
return buffer.toString();
}
/**
* Join an array of strings into a string.
*
* @param str the string array
* @param delimiter the delimiter
* @param initialIndex the initial index to start form
* @param quote the character to put around each entry
* @return a new string
*/
public static String joinQuotedString(String[] str, String delimiter,
int initialIndex, String quote) {
if (str.length == 0) {
return "";
}
StringBuilder buffer = new StringBuilder();
buffer.append(quote);
buffer.append(str[initialIndex]);
buffer.append(quote);
for (int i = initialIndex + 1; i < str.length; ++i) {
buffer.append(delimiter).append(quote).append(str[i]).append(quote);
}
return buffer.toString();
}
/**
* Join an array of strings into a string.
*
* @param str the string array
* @param delimiter the delimiter
* @return a new string
*/
public static String joinString(String[] str, String delimiter) {
return joinString(str, delimiter, 0);
}
/**
* Join an array of strings into a string.
*
* @param str an array of objects
* @param delimiter the delimiter
* @param initialIndex the initial index to start form
* @return a new string
*/
public static String joinString(Object[] str, String delimiter, int initialIndex) {
if (str.length == 0) {
return "";
}
StringBuilder buffer = new StringBuilder(str[initialIndex].toString());
for (int i = initialIndex + 1; i < str.length; ++i) {
buffer.append(delimiter).append(str[i]);
}
return buffer.toString();
}
/**
* Join an array of strings into a string.
*
* @param str a list of integers
* @param delimiter the delimiter
* @param initialIndex the initial index to start form
* @return a new string
*/
public static String joinString(int[] str, String delimiter, int initialIndex) {
if (str.length == 0) {
return "";
}
StringBuilder buffer = new StringBuilder(Integer.toString(str[initialIndex]));
for (int i = initialIndex + 1; i < str.length; ++i) {
buffer.append(delimiter).append(Integer.toString(str[i]));
}
return buffer.toString();
}
/**
* Join an list of strings into a string.
*
* @param str a list of strings
* @param delimiter the delimiter
* @param initialIndex the initial index to start form
* @return a new string
*/
public static String joinString(Collection<?> str, String delimiter,int initialIndex) {
if (str.isEmpty()) {
return "";
}
StringBuilder buffer = new StringBuilder();
int i = 0;
for (Object o : str) {
if (i >= initialIndex) {
if (i > 0) {
buffer.append(delimiter);
}
buffer.append(o);
}
++i;
}
return buffer.toString();
}
/**
* <p>Find the Levenshtein distance between two Strings.</p>
*
* <p>This is the number of changes needed to change one String into
* another, where each change is a single character modification (deletion,
* insertion or substitution).</p>
*
* <p>The previous implementation of the Levenshtein distance algorithm
* was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
*
* <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
* which can occur when my Java implementation is used with very large strings.<br>
* This implementation of the Levenshtein distance algorithm
* is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
*
* <pre>
* StringUtil.getLevenshteinDistance(null, *) = IllegalArgumentException
* StringUtil.getLevenshteinDistance(*, null) = IllegalArgumentException
* StringUtil.getLevenshteinDistance("","") = 0
* StringUtil.getLevenshteinDistance("","a") = 1
* StringUtil.getLevenshteinDistance("aaapppp", "") = 7
* StringUtil.getLevenshteinDistance("frog", "fog") = 1
* StringUtil.getLevenshteinDistance("fly", "ant") = 3
* StringUtil.getLevenshteinDistance("elephant", "hippo") = 7
* StringUtil.getLevenshteinDistance("hippo", "elephant") = 7
* StringUtil.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
* StringUtil.getLevenshteinDistance("hello", "hallo") = 1
* </pre>
*
* @param s the first String, must not be null
* @param t the second String, must not be null
* @return result distance
* @throws IllegalArgumentException if either String input {@code null}
*/
public static int getLevenshteinDistance(String s, String t) {
if (s == null || t == null) {
throw new IllegalArgumentException("Strings must not be null");
}
/*
* The difference between this impl. and the previous is that, rather
* than creating and retaining a matrix of size s.length()+1 by
* t.length()+1, we maintain two single-dimensional arrays of length
* s.length()+1. The first, d, is the 'current working' distance array
* that maintains the newest distance cost counts as we iterate through
* the characters of String s. Each time we increment the index of
* String t we are comparing, d is copied to p, the second int[]. Doing
* so allows us to retain the previous cost counts as required by the
* algorithm (taking the minimum of the cost count to the left, up one,
* and diagonally up and to the left of the current cost count being
* calculated). (Note that the arrays aren't really copied anymore, just
* switched...this is clearly much better than cloning an array or doing
* a System.arraycopy() each time through the outer loop.)
*
* Effectively, the difference between the two implementations is this
* one does not cause an out of memory condition when calculating the LD
* over two very large strings.
*/
int n = s.length(); // length of s
int m = t.length(); // length of t
if (n == 0) {
return m;
} else if (m == 0) {
return n;
}
int[] p = new int[n + 1]; // 'previous' cost array, horizontally
int[] d = new int[n + 1]; // cost array, horizontally
int[] _d; // placeholder to assist in swapping p and d
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
char tj; // jth character of t
int cost; // cost
for (i = 0; i <= n; ++i) {
p[i] = i;
}
for (j = 1; j <= m; ++j) {
tj = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; ++i) {
cost = s.charAt(i - 1) == tj ? 0 : 1;
// minimum of cell to the left+1, to the top+1, diagonally left
// and up +cost
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1]
+ cost);
}
// copy current distance counts to 'previous row' distance counts
_d = p;
p = d;
d = _d;
}
// our last action in the above loop was to switch d and p, so p now
// actually has the most recent cost counts
return p[n];
}
public static <T extends Enum<?>> T lookup(Map<String, T> lookup, String name, boolean fuzzy) {
String testName = name.replaceAll("[ _]", "").toLowerCase();
T type = lookup.get(testName);
if (type != null) {
return type;
}
if (!fuzzy) {
return null;
}
int minDist = -1;
for (Map.Entry<String, T> entry : lookup.entrySet()) {
final String key = entry.getKey();
if (key.charAt(0) != testName.charAt(0)) {
continue;
}
int dist = getLevenshteinDistance(key, testName);
if ((dist < minDist || minDist == -1) && dist < 2) {
minDist = dist;
type = entry.getValue();
}
}
return type;
}
}

View File

@ -0,0 +1,37 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.util.yaml;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
public enum YAMLFormat {
EXTENDED(FlowStyle.BLOCK),
COMPACT(FlowStyle.AUTO);
private final FlowStyle style;
YAMLFormat(FlowStyle style) {
this.style = style;
}
public FlowStyle getStyle() {
return style;
}
}

View File

@ -0,0 +1,804 @@
/*
* 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.util.yaml;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Represents a configuration node.
*/
public class YAMLNode {
protected Map<String, Object> root;
private boolean writeDefaults;
public YAMLNode(Map<String, Object> root, boolean writeDefaults) {
this.root = root;
this.writeDefaults = writeDefaults;
}
/**
* Return the underlying map.
*
* @return the map
*/
public Map<String, Object> getMap() {
return root;
}
/**
* Clear all nodes.
*/
public void clear() {
root.clear();
}
/**
* Gets a property at a location. This will either return an Object
* or null, with null meaning that no configuration value exists at
* that location. This could potentially return a default value (not yet
* implemented) as defined by a plugin, if this is a plugin-tied
* configuration.
*
* @param path path to node (dot notation)
* @return object or null
*/
@SuppressWarnings("unchecked")
public Object getProperty(String path) {
if (!path.contains(".")) {
Object val = root.get(path);
if (val == null) {
return null;
}
return val;
}
String[] parts = path.split("\\.");
Map<String, Object> node = root;
for (int i = 0; i < parts.length; i++) {
Object o = node.get(parts[i]);
if (o == null) {
return null;
}
if (i == parts.length - 1) {
return o;
}
try {
node = (Map<String, Object>) o;
} catch (ClassCastException e) {
return null;
}
}
return null;
}
/**
* Prepare a value for serialization, in case it's not a native type
* (and we don't want to serialize objects as YAML objects).
*
* @param value the value to serialize
* @return the new object
*/
private Object prepareSerialization(Object value) {
if (value instanceof Vector) {
Map<String, Double> out = new LinkedHashMap<String, Double>();
Vector vec = (Vector) value;
out.put("x", vec.getX());
out.put("y", vec.getY());
out.put("z", vec.getZ());
return out;
}
return value;
}
/**
* Set the property at a location. This will override existing
* configuration data to have it conform to key/value mappings.
*
* @param path the path
* @param value the new value
*/
@SuppressWarnings("unchecked")
public void setProperty(String path, Object value) {
value = prepareSerialization(value);
if (!path.contains(".")) {
root.put(path, value);
return;
}
String[] parts = path.split("\\.");
Map<String, Object> node = root;
for (int i = 0; i < parts.length; i++) {
Object o = node.get(parts[i]);
// Found our target!
if (i == parts.length - 1) {
node.put(parts[i], value);
return;
}
if (o == null || !(o instanceof Map)) {
// This will override existing configuration data!
o = new LinkedHashMap<String, Object>();
node.put(parts[i], o);
}
node = (Map<String, Object>) o;
}
}
/**
* Adds a new node to the given path. The returned object is a reference
* to the new node. This method will replace an existing node at
* the same path. See {@code setProperty}.
*
* @param path the path
* @return a node for the path
*/
public YAMLNode addNode(String path) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
YAMLNode node = new YAMLNode(map, writeDefaults);
setProperty(path, map);
return node;
}
/**
* Gets a string at a location. This will either return an String
* or null, with null meaning that no configuration value exists at
* that location. If the object at the particular location is not actually
* a string, it will be converted to its string representation.
*
* @param path path to node (dot notation)
* @return string or null
*/
public String getString(String path) {
Object o = getProperty(path);
if (o == null) {
return null;
}
return o.toString();
}
/**
* Gets a vector at a location. This will either return an Vector
* or a null. If the object at the particular location is not
* actually a string, it will be converted to its string representation.
*
* @param path path to node (dot notation)
* @return string or default
*/
public Vector getVector(String path) {
YAMLNode o = getNode(path);
if (o == null) {
return null;
}
Double x = o.getDouble("x");
Double y = o.getDouble("y");
Double z = o.getDouble("z");
if (x == null || y == null || z == null) {
return null;
}
return new Vector(x, y, z);
}
/**
* Gets a 2D vector at a location. This will either return an Vector
* or a null. If the object at the particular location is not
* actually a string, it will be converted to its string representation.
*
* @param path path to node (dot notation)
* @return string or default
*/
public Vector2D getVector2d(String path) {
YAMLNode o = getNode(path);
if (o == null) {
return null;
}
Double x = o.getDouble("x");
Double z = o.getDouble("z");
if (x == null || z == null) {
return null;
}
return new Vector2D(x, z);
}
/**
* Gets a string at a location. This will either return an Vector
* or the default value. If the object at the particular location is not
* actually a string, it will be converted to its string representation.
*
* @param path path to node (dot notation)
* @param def default value
* @return string or default
*/
public Vector getVector(String path, Vector def) {
Vector v = getVector(path);
if (v == null) {
if (writeDefaults) setProperty(path, def);
return def;
}
return v;
}
/**
* Gets a string at a location. This will either return an String
* or the default value. If the object at the particular location is not
* actually a string, it will be converted to its string representation.
*
* @param path path to node (dot notation)
* @param def default value
* @return string or default
*/
public String getString(String path, String def) {
String o = getString(path);
if (o == null) {
if (writeDefaults) setProperty(path, def);
return def;
}
return o;
}
/**
* Gets an integer at a location. This will either return an integer
* or null. If the object at the particular location is not
* actually a integer, the default value will be returned. However, other
* number types will be casted to an integer.
*
* @param path path to node (dot notation)
* @return integer or null
*/
public Integer getInt(String path) {
Integer o = castInt(getProperty(path));
if (o == null) {
return null;
} else {
return o;
}
}
/**
* Gets an integer at a location. This will either return an integer
* or the default value. If the object at the particular location is not
* actually a integer, the default value will be returned. However, other
* number types will be casted to an integer.
*
* @param path path to node (dot notation)
* @param def default value
* @return int or default
*/
public int getInt(String path, int def) {
Integer o = castInt(getProperty(path));
if (o == null) {
if (writeDefaults) setProperty(path, def);
return def;
} else {
return o;
}
}
/**
* Gets a double at a location. This will either return an double
* or null. If the object at the particular location is not
* actually a double, the default value will be returned. However, other
* number types will be casted to an double.
*
* @param path path to node (dot notation)
* @return double or null
*/
public Double getDouble(String path) {
Double o = castDouble(getProperty(path));
if (o == null) {
return null;
} else {
return o;
}
}
/**
* Gets a double at a location. This will either return an double
* or the default value. If the object at the particular location is not
* actually a double, the default value will be returned. However, other
* number types will be casted to an double.
*
* @param path path to node (dot notation)
* @param def default value
* @return double or default
*/
public double getDouble(String path, double def) {
Double o = castDouble(getProperty(path));
if (o == null) {
if (writeDefaults) setProperty(path, def);
return def;
} else {
return o;
}
}
/**
* Gets a boolean at a location. This will either return an boolean
* or null. If the object at the particular location is not
* actually a boolean, the default value will be returned.
*
* @param path path to node (dot notation)
* @return boolean or null
*/
public Boolean getBoolean(String path) {
Boolean o = castBoolean(getProperty(path));
if (o == null) {
return null;
} else {
return o;
}
}
/**
* Gets a boolean at a location. This will either return an boolean
* or the default value. If the object at the particular location is not
* actually a boolean, the default value will be returned.
*
* @param path path to node (dot notation)
* @param def default value
* @return boolean or default
*/
public boolean getBoolean(String path, boolean def) {
Boolean o = castBoolean(getProperty(path));
if (o == null) {
if (writeDefaults) setProperty(path, def);
return def;
} else {
return o;
}
}
/**
* Get a list of keys at a location. If the map at the particular location
* does not exist or it is not a map, null will be returned.
*
* @param path path to node (dot notation)
* @return list of keys
*/
@SuppressWarnings("unchecked")
public List<String> getKeys(String path) {
if (path == null) return new ArrayList<String>(root.keySet());
Object o = getProperty(path);
if (o == null) {
return null;
} else if (o instanceof Map) {
return new ArrayList<String>(((Map<String, Object>) o).keySet());
} else {
return null;
}
}
/**
* Gets a list of objects at a location. If the list is not defined,
* null will be returned. The node must be an actual list.
*
* @param path path to node (dot notation)
* @return boolean or default
*/
@SuppressWarnings("unchecked")
public List<Object> getList(String path) {
Object o = getProperty(path);
if (o == null) {
return null;
} else if (o instanceof List) {
return (List<Object>) o;
} else {
return null;
}
}
/**
* Gets a list of strings. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. If an item in the list
* is not a string, it will be converted to a string. The node must be
* an actual list and not just a string.
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of strings
*/
public List<String> getStringList(String path, List<String> def) {
List<Object> raw = getList(path);
if (raw == null) {
if (writeDefaults && def != null) setProperty(path, def);
return def != null ? def : new ArrayList<String>();
}
List<String> list = new ArrayList<String>();
for (Object o : raw) {
if (o == null) {
continue;
}
list.add(o.toString());
}
return list;
}
/**
* Gets a list of integers. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual list and not just an integer.
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
public List<Integer> getIntList(String path, List<Integer> def) {
List<Object> raw = getList(path);
if (raw == null) {
if (writeDefaults && def != null) setProperty(path, def);
return def != null ? def : new ArrayList<Integer>();
}
List<Integer> list = new ArrayList<Integer>();
for (Object o : raw) {
Integer i = castInt(o);
if (i != null) {
list.add(i);
}
}
return list;
}
/**
* Gets a list of doubles. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual list and cannot be just a double.
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
public List<Double> getDoubleList(String path, List<Double> def) {
List<Object> raw = getList(path);
if (raw == null) {
if (writeDefaults && def != null) setProperty(path, def);
return def != null ? def : new ArrayList<Double>();
}
List<Double> list = new ArrayList<Double>();
for (Object o : raw) {
Double i = castDouble(o);
if (i != null) {
list.add(i);
}
}
return list;
}
/**
* Gets a list of booleans. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual list and cannot be just a boolean,
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
public List<Boolean> getBooleanList(String path, List<Boolean> def) {
List<Object> raw = getList(path);
if (raw == null) {
if (writeDefaults && def != null) setProperty(path, def);
return def != null ? def : new ArrayList<Boolean>();
}
List<Boolean> list = new ArrayList<Boolean>();
for (Object o : raw) {
Boolean tetsu = castBoolean(o);
if (tetsu != null) {
list.add(tetsu);
}
}
return list;
}
/**
* Gets a list of vectors. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual node and cannot be just a vector,
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
public List<Vector> getVectorList(String path, List<Vector> def) {
List<YAMLNode> raw = getNodeList(path, null);
List<Vector> list = new ArrayList<Vector>();
for (YAMLNode o : raw) {
Double x = o.getDouble("x");
Double y = o.getDouble("y");
Double z = o.getDouble("z");
if (x == null || y == null || z == null) {
continue;
}
list.add(new Vector(x, y, z));
}
return list;
}
/**
* Gets a list of 2D vectors. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual node and cannot be just a vector,
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
public List<Vector2D> getVector2dList(String path, List<Vector2D> def) {
List<YAMLNode> raw = getNodeList(path, null);
List<Vector2D> list = new ArrayList<Vector2D>();
for (YAMLNode o : raw) {
Double x = o.getDouble("x");
Double z = o.getDouble("z");
if (x == null || z == null) {
continue;
}
list.add(new Vector2D(x, z));
}
return list;
}
/**
* Gets a list of 2D vectors. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual node and cannot be just a vector,
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
public List<BlockVector2D> getBlockVector2dList(String path, List<BlockVector2D> def) {
List<YAMLNode> raw = getNodeList(path, null);
List<BlockVector2D> list = new ArrayList<BlockVector2D>();
for (YAMLNode o : raw) {
Double x = o.getDouble("x");
Double z = o.getDouble("z");
if (x == null || z == null) {
continue;
}
list.add(new BlockVector2D(x, z));
}
return list;
}
/**
* Gets a list of nodes. Non-valid entries will not be in the list.
* There will be no null slots. If the list is not defined, the
* default will be returned. 'null' can be passed for the default
* and an empty list will be returned instead. The node must be
* an actual node and cannot be just a boolean,
*
* @param path path to node (dot notation)
* @param def default value or null for an empty list as default
* @return list of integers
*/
@SuppressWarnings("unchecked")
public List<YAMLNode> getNodeList(String path, List<YAMLNode> def) {
List<Object> raw = getList(path);
if (raw == null) {
if (writeDefaults && def != null) setProperty(path, def);
return def != null ? def : new ArrayList<YAMLNode>();
}
List<YAMLNode> list = new ArrayList<YAMLNode>();
for (Object o : raw) {
if (o instanceof Map) {
list.add(new YAMLNode((Map<String, Object>) o, writeDefaults));
}
}
return list;
}
/**
* Get a configuration node at a path. If the node doesn't exist or the
* path does not lead to a node, null will be returned. A node has
* key/value mappings.
*
* @param path the path
* @return node or null
*/
@Nullable
@SuppressWarnings("unchecked")
public YAMLNode getNode(String path) {
Object raw = getProperty(path);
if (raw instanceof Map) {
return new YAMLNode((Map<String, Object>) raw, writeDefaults);
}
return null;
}
/**
* Get a list of nodes at a location. If the map at the particular location
* does not exist or it is not a map, null will be returned.
*
* @param path path to node (dot notation)
* @return map of nodes
*/
@SuppressWarnings("unchecked")
public Map<String, YAMLNode> getNodes(String path) {
Object o = getProperty(path);
if (o == null) {
return null;
} else if (o instanceof Map) {
Map<String, YAMLNode> nodes =
new LinkedHashMap<String, YAMLNode>();
for (Map.Entry<String, Object> entry : ((Map<String, Object>) o).entrySet()) {
if (entry.getValue() instanceof Map) {
nodes.put(entry.getKey(),
new YAMLNode((Map<String, Object>) entry.getValue(), writeDefaults));
}
}
return nodes;
} else {
return null;
}
}
/**
* Casts a value to an integer. May return null.
*
* @param o the object
* @return an integer or null
*/
@Nullable
private static Integer castInt(Object o) {
if (o == null) {
return null;
} else if (o instanceof Number) {
return ((Number) o).intValue();
} else {
return null;
}
}
/**
* Casts a value to a double. May return null.
*
* @param o the object
* @return a double or null
*/
@Nullable
private static Double castDouble(Object o) {
if (o == null) {
return null;
} else if (o instanceof Number) {
return ((Number) o).doubleValue();
} else {
return null;
}
}
/**
* Casts a value to a boolean. May return null.
*
* @param o the object
* @return a boolean or null
*/
@Nullable
private static Boolean castBoolean(Object o) {
if (o == null) {
return null;
} else if (o instanceof Boolean) {
return (Boolean) o;
} else {
return null;
}
}
/**
* Remove the property at a location. This will override existing
* configuration data to have it conform to key/value mappings.
*
* @param path a path
*/
@SuppressWarnings("unchecked")
public void removeProperty(String path) {
if (!path.contains(".")) {
root.remove(path);
return;
}
String[] parts = path.split("\\.");
Map<String, Object> node = root;
for (int i = 0; i < parts.length; i++) {
Object o = node.get(parts[i]);
// Found our target!
if (i == parts.length - 1) {
node.remove(parts[i]);
return;
}
node = (Map<String, Object>) o;
}
}
public boolean writeDefaults() {
return writeDefaults;
}
public void setWriteDefaults(boolean writeDefaults) {
this.writeDefaults = writeDefaults;
}
}

View File

@ -0,0 +1,333 @@
/*
* 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.util.yaml;
import com.sk89q.util.StringUtil;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.emitter.ScalarAnalysis;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.reader.UnicodeReader;
import org.yaml.snakeyaml.representer.Represent;
import org.yaml.snakeyaml.representer.Representer;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
/**
* YAML configuration loader. To use this class, construct it with path to
* a file and call its load() method. For specifying node paths in the
* various get*() methods, they support SK's path notation, allowing you to
* select child nodes by delimiting node names with periods.
*
* <p>
* For example, given the following configuration file:</p>
*
* <pre>members:
* - Hollie
* - Jason
* - Bobo
* - Aya
* - Tetsu
* worldguard:
* fire:
* spread: false
* blocks: [cloth, rock, glass]
* sturmeh:
* cool: false
* eats:
* babies: true</pre>
*
* <p>Calling code could access sturmeh's baby eating state by using
* {@code getBoolean("sturmeh.eats.babies", false)}. For lists, there are
* methods such as {@code getStringList} that will return a type safe list.
*/
public class YAMLProcessor extends YAMLNode {
public static final String LINE_BREAK = DumperOptions.LineBreak.getPlatformLineBreak().getString();
public static final char COMMENT_CHAR = '#';
protected final Yaml yaml;
protected final File file;
protected String header = null;
protected YAMLFormat format;
/*
* Map from property key to comment. Comment may have multiple lines that are newline-separated.
* Comments support based on ZerothAngel's AnnotatedYAMLConfiguration
* Comments are only supported with YAMLFormat.EXTENDED
*/
private final Map<String, String> comments = new HashMap<String, String>();
public YAMLProcessor(File file, boolean writeDefaults, YAMLFormat format) {
super(new LinkedHashMap<String, Object>(), writeDefaults);
this.format = format;
DumperOptions options = new FancyDumperOptions();
options.setIndent(4);
options.setDefaultFlowStyle(format.getStyle());
Representer representer = new FancyRepresenter();
representer.setDefaultFlowStyle(format.getStyle());
yaml = new Yaml(new SafeConstructor(), representer, options);
this.file = file;
}
public YAMLProcessor(File file, boolean writeDefaults) {
this(file, writeDefaults, YAMLFormat.COMPACT);
}
/**
* Loads the configuration file.
*
* @throws java.io.IOException on load error
*/
public void load() throws IOException {
InputStream stream = null;
try {
stream = getInputStream();
if (stream == null) throw new IOException("Stream is null!");
read(yaml.load(new UnicodeReader(stream)));
} catch (YAMLProcessorException e) {
root = new LinkedHashMap<String, Object>();
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (IOException ignored) {
}
}
}
/**
* Set the header for the file as a series of lines that are terminated
* by a new line sequence.
*
* @param headerLines header lines to prepend
*/
public void setHeader(String... headerLines) {
StringBuilder header = new StringBuilder();
for (String line : headerLines) {
if (header.length() > 0) {
header.append(LINE_BREAK);
}
header.append(line);
}
setHeader(header.toString());
}
/**
* Set the header for the file. A header can be provided to prepend the
* YAML data output on configuration save. The header is
* printed raw and so must be manually commented if used. A new line will
* be appended after the header, however, if a header is provided.
*
* @param header header to prepend
*/
public void setHeader(String header) {
this.header = header;
}
/**
* Return the set header.
*
* @return the header text
*/
public String getHeader() {
return header;
}
/**
* Saves the configuration to disk. All errors are clobbered.
*
* @return true if it was successful
*/
public boolean save() {
OutputStream stream = null;
File parent = file.getParentFile();
if (parent != null) {
parent.mkdirs();
}
try {
stream = getOutputStream();
if (stream == null) return false;
OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8");
if (header != null) {
writer.append(header);
writer.append(LINE_BREAK);
}
if (comments.isEmpty() || format != YAMLFormat.EXTENDED) {
yaml.dump(root, writer);
} else {
// Iterate over each root-level property and dump
for (Entry<String, Object> entry : root.entrySet()) {
// Output comment, if present
String comment = comments.get(entry.getKey());
if (comment != null) {
writer.append(LINE_BREAK);
writer.append(comment);
writer.append(LINE_BREAK);
}
// Dump property
yaml.dump(Collections.singletonMap(entry.getKey(), entry.getValue()), writer);
}
}
return true;
} catch (IOException ignored) {
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (IOException ignored) {}
}
return false;
}
@SuppressWarnings("unchecked")
private void read(Object input) throws YAMLProcessorException {
try {
if (null == input) {
root = new LinkedHashMap<String, Object>();
} else {
root = new LinkedHashMap<String, Object>((Map<String, Object>) input);
}
} catch (ClassCastException e) {
throw new YAMLProcessorException("Root document must be an key-value structure");
}
}
public InputStream getInputStream() throws IOException {
return new FileInputStream(file);
}
public OutputStream getOutputStream() throws IOException {
return new FileOutputStream(file);
}
/**
* Returns a root-level comment.
*
* @param key the property key
* @return the comment or {@code null}
*/
public String getComment(String key) {
return comments.get(key);
}
public void setComment(String key, String comment) {
if (comment != null) {
setComment(key, comment.split("\\r?\\n"));
} else {
comments.remove(key);
}
}
/**
* Set a root-level comment.
*
* @param key the property key
* @param comment the comment. May be {@code null}, in which case the comment
* is removed.
*/
public void setComment(String key, String... comment) {
if (comment != null && comment.length > 0) {
for (int i = 0; i < comment.length; ++i) {
if (!comment[i].matches("^" + COMMENT_CHAR + " ?")) {
comment[i] = COMMENT_CHAR + " " + comment[i];
}
}
String s = StringUtil.joinString(comment, LINE_BREAK);
comments.put(key, s);
} else {
comments.remove(key);
}
}
/**
* Returns root-level comments.
*
* @return map of root-level comments
*/
public Map<String, String> getComments() {
return Collections.unmodifiableMap(comments);
}
/**
* Set root-level comments from a map.
*
* @param comments comment map
*/
public void setComments(Map<String, String> comments) {
this.comments.clear();
if (comments != null) {
this.comments.putAll(comments);
}
}
/**
* This method returns an empty ConfigurationNode for using as a
* default in methods that select a node from a node list.
*
* @param writeDefaults true to write default values when a property is requested that doesn't exist
* @return a node
*/
public static YAMLNode getEmptyNode(boolean writeDefaults) {
return new YAMLNode(new LinkedHashMap<String, Object>(), writeDefaults);
}
// This will be included in snakeyaml 1.10, but until then we have to do it manually.
private class FancyDumperOptions extends DumperOptions {
@Override
public DumperOptions.ScalarStyle calculateScalarStyle(ScalarAnalysis analysis,
DumperOptions.ScalarStyle style) {
if (format == YAMLFormat.EXTENDED
&& (analysis.scalar.contains("\n") || analysis.scalar.contains("\r"))) {
return ScalarStyle.LITERAL;
} else {
return super.calculateScalarStyle(analysis, style);
}
}
}
private static class FancyRepresenter extends Representer {
private FancyRepresenter() {
this.nullRepresenter = new Represent() {
@Override
public Node representData(Object o) {
return representScalar(Tag.NULL, "");
}
};
}
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.util.yaml;
/**
* YAMLProcessor exception.
*/
public class YAMLProcessorException extends Exception {
public YAMLProcessorException() {
super();
}
public YAMLProcessorException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,99 @@
/*
* 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;
/**
* Extension of {@code Vector} that that compares with other instances
* using integer components.
*/
public class BlockVector extends Vector {
public static final BlockVector ZERO = new BlockVector(0, 0, 0);
public static final BlockVector UNIT_X = new BlockVector(1, 0, 0);
public static final BlockVector UNIT_Y = new BlockVector(0, 1, 0);
public static final BlockVector UNIT_Z = new BlockVector(0, 0, 1);
public static final BlockVector ONE = new BlockVector(1, 1, 1);
/**
* Construct an instance as a copy of another instance.
*
* @param position the other position
*/
public BlockVector(Vector position) {
super(position);
}
/**
* Construct a new instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockVector(int x, int y, int z) {
super(x, y, z);
}
/**
* Construct a new instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockVector(float x, float y, float z) {
super(x, y, z);
}
/**
* Construct a new instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockVector(double x, double y, double z) {
super(x, y, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector)) {
return false;
}
Vector other = (Vector) obj;
return (int) other.getX() == (int) this.x && (int) other.getY() == (int) this.y
&& (int) other.getZ() == (int) this.z;
}
@Override
public int hashCode() {
return ((int) x << 19) ^
((int) y << 12) ^
(int) z;
}
@Override
public BlockVector toBlockVector() {
return this;
}
}

View File

@ -0,0 +1,94 @@
/*
* 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;
/**
* Extension of {@code Vector2D} that that compares with other instances
* using integer components.
*/
public class BlockVector2D extends Vector2D {
public static final BlockVector2D ZERO = new BlockVector2D(0, 0);
public static final BlockVector2D UNIT_X = new BlockVector2D(1, 0);
public static final BlockVector2D UNIT_Z = new BlockVector2D(0, 1);
public static final BlockVector2D ONE = new BlockVector2D(1, 1);
/**
* Construct an instance from another instance.
*
* @param position the position to copy
*/
public BlockVector2D(Vector2D position) {
super(position);
}
/**
* Construct a new instance.
*
* @param x the X coordinate
* @param z the Z coordinate
*/
public BlockVector2D(int x, int z) {
super(x, z);
}
/**
* Construct a new instance.
*
* @param x the X coordinate
* @param z the Z coordinate
*/
public BlockVector2D(float x, float z) {
super(x, z);
}
/**
* Construct a new instance.
*
* @param x the X coordinate
* @param z the Z coordinate
*/
public BlockVector2D(double x, double z) {
super(x, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector2D)) {
return false;
}
Vector2D other = (Vector2D) obj;
return (int) other.x == (int) this.x && (int) other.z == (int) this.z;
}
@Override
public int hashCode() {
return (Integer.valueOf((int) x).hashCode() >> 13) ^
Integer.valueOf((int) z).hashCode();
}
@Override
public BlockVector2D toBlockVector2D() {
return this;
}
}

View File

@ -0,0 +1,124 @@
/*
* 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;
/**
* @deprecated Replace all uses of {@link WorldVector}s with {@link Location}s
*/
@SuppressWarnings("deprecation")
@Deprecated
public class BlockWorldVector extends WorldVector {
/**
* Construct an instance from another instance.
*
* @param position the position to copy
*/
public BlockWorldVector(WorldVector position) {
super(position.getWorld(), position);
}
/**
* Construct an instance from another instance.
*
* @param world the world
* @param position the position to copy
*/
public BlockWorldVector(LocalWorld world, Vector position) {
super(world, position);
}
/**
* Construct a new instance.
*
* @param world another instance
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockWorldVector(WorldVector world, int x, int y, int z) {
super(world.getWorld(), x, y, z);
}
/**
* Construct a new instance.
*
* @param world another instance
* @param v the other vector
*/
public BlockWorldVector(WorldVector world, Vector v) {
super(world.getWorld(), v.getX(), v.getY(), v.getZ());
}
/**
* Construct a new instance.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockWorldVector(LocalWorld world, int x, int y, int z) {
super(world, x, y, z);
}
/**
* Construct a new instance.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockWorldVector(LocalWorld world, float x, float y, float z) {
super(world, x, y, z);
}
/**
* Construct a new instance.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public BlockWorldVector(LocalWorld world, double x, double y, double z) {
super(world, x, y, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector)) {
return false;
}
Vector other = (Vector) obj;
return (int) other.getX() == (int) this.x && (int) other.getY() == (int) this.y
&& (int) other.getZ() == (int) this.z;
}
@Override
public int hashCode() {
return (Integer.valueOf((int) x).hashCode() << 19) ^
(Integer.valueOf((int) y).hashCode() << 12) ^
Integer.valueOf((int) z).hashCode();
}
}

View File

@ -0,0 +1,105 @@
/*
* 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;
/**
* @deprecated Replace all uses of {@link WorldVector}s with {@link Location}s
*/
@SuppressWarnings("deprecation")
@Deprecated
public class BlockWorldVector2D extends WorldVector2D {
/**
* Construct a new instance.
*
* @param world the world
* @param x the X coordinate
* @param z the Z coordinate
*/
public BlockWorldVector2D(LocalWorld world, double x, double z) {
super(world, x, z);
}
/**
* Construct a new instance.
*
* @param world the world
* @param x the X coordinate
* @param z the Z coordinate
*/
public BlockWorldVector2D(LocalWorld world, float x, float z) {
super(world, x, z);
}
/**
* Construct a new instance.
*
* @param world the world
* @param x the X coordinate
* @param z the Z coordinate
*/
public BlockWorldVector2D(LocalWorld world, int x, int z) {
super(world, x, z);
}
/**
* Construct a new instance.
*
* @param world the world
* @param position a position
*/
public BlockWorldVector2D(LocalWorld world, Vector2D position) {
super(world, position);
}
/**
* Construct a new instance with X and Z set to (0, 0).
*
* @param world the world
*/
public BlockWorldVector2D(LocalWorld world) {
super(world);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof WorldVector2D)) {
return false;
}
WorldVector2D other = (WorldVector2D) obj;
return other.getWorld().equals(world)
&& (int) other.getX() == (int) this.x
&& (int) other.getZ() == (int) this.z;
}
@Override
public int hashCode() {
int result = super.hashCode();
long temp;
result = 31 * result + world.hashCode();
temp = Double.doubleToLongBits(x);
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(z);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
}

View File

@ -0,0 +1,695 @@
/*
* 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;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.schematic.SchematicFormat;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.DataException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The clipboard remembers the state of a cuboid region.
*
* @deprecated This is slowly being replaced with {@link Clipboard}, which is
* far more versatile. Transforms are supported using affine
* transformations and full entity support is provided because
* the clipboard properly implements {@link Extent}. However,
* the new clipboard class is only available in WorldEdit 6.x and
* beyond. We intend on keeping this deprecated class in WorldEdit
* for an extended amount of time so there is no rush to
* switch (but new features will not be supported). To copy between
* a clipboard and a world (or between any two {@code Extent}s),
* one can use {@link ForwardExtentCopy}. See
* {@link ClipboardCommands} and {@link SchematicCommands} for
* more information.
*/
@Deprecated
public class CuboidClipboard {
/**
* An enum of possible flip directions.
*/
public enum FlipDirection {
NORTH_SOUTH,
WEST_EAST,
UP_DOWN
}
private BaseBlock[][][] data;
private Vector offset;
private Vector origin;
private Vector size;
private List<CopiedEntity> entities = new ArrayList<CopiedEntity>();
/**
* Constructs the clipboard.
*
* @param size the dimensions of the clipboard (should be at least 1 on every dimension)
*/
public CuboidClipboard(Vector size) {
checkNotNull(size);
this.size = size;
data = new BaseBlock[size.getBlockX()][size.getBlockY()][size.getBlockZ()];
origin = new Vector();
offset = new Vector();
}
/**
* Constructs the clipboard.
*
* @param size the dimensions of the clipboard (should be at least 1 on every dimension)
* @param origin the origin point where the copy was made, which must be the
* {@link CuboidRegion#getMinimumPoint()} relative to the copy
*/
public CuboidClipboard(Vector size, Vector origin) {
checkNotNull(size);
checkNotNull(origin);
this.size = size;
data = new BaseBlock[size.getBlockX()][size.getBlockY()][size.getBlockZ()];
this.origin = origin;
offset = new Vector();
}
/**
* Constructs the clipboard.
*
* @param size the dimensions of the clipboard (should be at least 1 on every dimension)
* @param origin the origin point where the copy was made, which must be the
* {@link CuboidRegion#getMinimumPoint()} relative to the copy
* @param offset the offset from the minimum point of the copy where the user was
*/
public CuboidClipboard(Vector size, Vector origin, Vector offset) {
checkNotNull(size);
checkNotNull(origin);
checkNotNull(offset);
this.size = size;
data = new BaseBlock[size.getBlockX()][size.getBlockY()][size.getBlockZ()];
this.origin = origin;
this.offset = offset;
}
/**
* Get the width (X-direction) of the clipboard.
*
* @return width
*/
public int getWidth() {
return size.getBlockX();
}
/**
* Get the length (Z-direction) of the clipboard.
*
* @return length
*/
public int getLength() {
return size.getBlockZ();
}
/**
* Get the height (Y-direction) of the clipboard.
*
* @return height
*/
public int getHeight() {
return size.getBlockY();
}
/**
* Rotate the clipboard in 2D. It can only rotate by angles divisible by 90.
*
* @param angle in degrees
*/
@SuppressWarnings("deprecation")
public void rotate2D(int angle) {
angle = angle % 360;
if (angle % 90 != 0) { // Can only rotate 90 degrees at the moment
return;
}
final boolean reverse = angle < 0;
final int numRotations = Math.abs((int) Math.floor(angle / 90.0));
final int width = getWidth();
final int length = getLength();
final int height = getHeight();
final Vector sizeRotated = size.transform2D(angle, 0, 0, 0, 0);
final int shiftX = sizeRotated.getX() < 0 ? -sizeRotated.getBlockX() - 1 : 0;
final int shiftZ = sizeRotated.getZ() < 0 ? -sizeRotated.getBlockZ() - 1 : 0;
final BaseBlock[][][] newData = new BaseBlock
[Math.abs(sizeRotated.getBlockX())]
[Math.abs(sizeRotated.getBlockY())]
[Math.abs(sizeRotated.getBlockZ())];
for (int x = 0; x < width; ++x) {
for (int z = 0; z < length; ++z) {
final Vector2D v = new Vector2D(x, z).transform2D(angle, 0, 0, shiftX, shiftZ);
final int newX = v.getBlockX();
final int newZ = v.getBlockZ();
for (int y = 0; y < height; ++y) {
final BaseBlock block = data[x][y][z];
newData[newX][y][newZ] = block;
if (block == null) {
continue;
}
if (reverse) {
for (int i = 0; i < numRotations; ++i) {
block.rotate90Reverse();
}
} else {
for (int i = 0; i < numRotations; ++i) {
block.rotate90();
}
}
}
}
}
data = newData;
size = new Vector(Math.abs(sizeRotated.getBlockX()),
Math.abs(sizeRotated.getBlockY()),
Math.abs(sizeRotated.getBlockZ()));
offset = offset.transform2D(angle, 0, 0, 0, 0)
.subtract(shiftX, 0, shiftZ);
}
/**
* Flip the clipboard.
*
* @param dir direction to flip
*/
public void flip(FlipDirection dir) {
flip(dir, false);
}
/**
* Flip the clipboard.
*
* @param dir direction to flip
* @param aroundPlayer flip the offset around the player
*/
@SuppressWarnings("deprecation")
public void flip(FlipDirection dir, boolean aroundPlayer) {
checkNotNull(dir);
final int width = getWidth();
final int length = getLength();
final int height = getHeight();
switch (dir) {
case WEST_EAST:
final int wid = (int) Math.ceil(width / 2.0f);
for (int xs = 0; xs < wid; ++xs) {
for (int z = 0; z < length; ++z) {
for (int y = 0; y < height; ++y) {
final BaseBlock block1 = data[xs][y][z];
if (block1 != null) {
block1.flip(dir);
}
// Skip the center plane
if (xs == width - xs - 1) {
continue;
}
final BaseBlock block2 = data[width - xs - 1][y][z];
if (block2 != null) {
block2.flip(dir);
}
data[xs][y][z] = block2;
data[width - xs - 1][y][z] = block1;
}
}
}
if (aroundPlayer) {
offset = offset.setX(1 - offset.getX() - width);
}
break;
case NORTH_SOUTH:
final int len = (int) Math.ceil(length / 2.0f);
for (int zs = 0; zs < len; ++zs) {
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
final BaseBlock block1 = data[x][y][zs];
if (block1 != null) {
block1.flip(dir);
}
// Skip the center plane
if (zs == length - zs - 1) {
continue;
}
final BaseBlock block2 = data[x][y][length - zs - 1];
if (block2 != null) {
block2.flip(dir);
}
data[x][y][zs] = block2;
data[x][y][length - zs - 1] = block1;
}
}
}
if (aroundPlayer) {
offset = offset.setZ(1 - offset.getZ() - length);
}
break;
case UP_DOWN:
final int hei = (int) Math.ceil(height / 2.0f);
for (int ys = 0; ys < hei; ++ys) {
for (int x = 0; x < width; ++x) {
for (int z = 0; z < length; ++z) {
final BaseBlock block1 = data[x][ys][z];
if (block1 != null) {
block1.flip(dir);
}
// Skip the center plane
if (ys == height - ys - 1) {
continue;
}
final BaseBlock block2 = data[x][height - ys - 1][z];
if (block2 != null) {
block2.flip(dir);
}
data[x][ys][z] = block2;
data[x][height - ys - 1][z] = block1;
}
}
}
if (aroundPlayer) {
offset = offset.setY(1 - offset.getY() - height);
}
break;
}
}
/**
* Copies blocks to the clipboard.
*
* @param editSession the EditSession from which to take the blocks
*/
public void copy(EditSession editSession) {
for (int x = 0; x < size.getBlockX(); ++x) {
for (int y = 0; y < size.getBlockY(); ++y) {
for (int z = 0; z < size.getBlockZ(); ++z) {
data[x][y][z] =
editSession.getBlock(new Vector(x, y, z).add(getOrigin()));
}
}
}
}
/**
* Copies blocks to the clipboard.
*
* @param editSession The EditSession from which to take the blocks
* @param region A region that further constrains which blocks to take.
*/
public void copy(EditSession editSession, Region region) {
for (int x = 0; x < size.getBlockX(); ++x) {
for (int y = 0; y < size.getBlockY(); ++y) {
for (int z = 0; z < size.getBlockZ(); ++z) {
final Vector pt = new Vector(x, y, z).add(getOrigin());
if (region.contains(pt)) {
data[x][y][z] = editSession.getBlock(pt);
} else {
data[x][y][z] = null;
}
}
}
}
}
/**
* Paste the clipboard at the given location using the given {@code EditSession}.
*
* <p>This method blocks the server/game until the entire clipboard is
* pasted. In the future, {@link ForwardExtentCopy} will be recommended,
* which, if combined with the proposed operation scheduler framework,
* will not freeze the game/server.</p>
*
* @param editSession the EditSession to which blocks are to be copied to
* @param newOrigin the new origin point (must correspond to the minimum point of the cuboid)
* @param noAir true to not copy air blocks in the source
* @throws MaxChangedBlocksException thrown if too many blocks were changed
*/
public void paste(EditSession editSession, Vector newOrigin, boolean noAir) throws MaxChangedBlocksException {
paste(editSession, newOrigin, noAir, false);
}
/**
* Paste the clipboard at the given location using the given {@code EditSession}.
*
* <p>This method blocks the server/game until the entire clipboard is
* pasted. In the future, {@link ForwardExtentCopy} will be recommended,
* which, if combined with the proposed operation scheduler framework,
* will not freeze the game/server.</p>
*
* @param editSession the EditSession to which blocks are to be copied to
* @param newOrigin the new origin point (must correspond to the minimum point of the cuboid)
* @param noAir true to not copy air blocks in the source
* @param entities true to copy entities
* @throws MaxChangedBlocksException thrown if too many blocks were changed
*/
public void paste(EditSession editSession, Vector newOrigin, boolean noAir, boolean entities) throws MaxChangedBlocksException {
place(editSession, newOrigin.add(offset), noAir);
if (entities) {
pasteEntities(newOrigin.add(offset));
}
}
/**
* Paste the clipboard at the given location using the given {@code EditSession}.
*
* <p>This method blocks the server/game until the entire clipboard is
* pasted. In the future, {@link ForwardExtentCopy} will be recommended,
* which, if combined with the proposed operation scheduler framework,
* will not freeze the game/server.</p>
*
* @param editSession the EditSession to which blocks are to be copied to
* @param newOrigin the new origin point (must correspond to the minimum point of the cuboid)
* @param noAir true to not copy air blocks in the source
* @throws MaxChangedBlocksException thrown if too many blocks were changed
*/
public void place(EditSession editSession, Vector newOrigin, boolean noAir) throws MaxChangedBlocksException {
for (int x = 0; x < size.getBlockX(); ++x) {
for (int y = 0; y < size.getBlockY(); ++y) {
for (int z = 0; z < size.getBlockZ(); ++z) {
final BaseBlock block = data[x][y][z];
if (block == null) {
continue;
}
if (noAir && block.isAir()) {
continue;
}
editSession.setBlock(new Vector(x, y, z).add(newOrigin), block);
}
}
}
}
/**
* Paste the stored entities to the given position.
*
* @param newOrigin the new origin
* @return a list of entities that were pasted
*/
public LocalEntity[] pasteEntities(Vector newOrigin) {
LocalEntity[] entities = new LocalEntity[this.entities.size()];
for (int i = 0; i < this.entities.size(); ++i) {
CopiedEntity copied = this.entities.get(i);
if (copied.entity.spawn(copied.entity.getPosition().setPosition(copied.relativePosition.add(newOrigin)))) {
entities[i] = copied.entity;
}
}
return entities;
}
/**
* Store an entity.
*
* @param entity the entity
*/
public void storeEntity(LocalEntity entity) {
this.entities.add(new CopiedEntity(entity));
}
/**
* Get the block at the given position.
*
* <p>If the position is out of bounds, air will be returned.</p>
*
* @param position the point, relative to the origin of the copy (0, 0, 0) and not to the actual copy origin
* @return air, if this block was outside the (non-cuboid) selection while copying
* @throws ArrayIndexOutOfBoundsException if the position is outside the bounds of the CuboidClipboard
* @deprecated use {@link #getBlock(Vector)} instead
*/
@Deprecated
public BaseBlock getPoint(Vector position) throws ArrayIndexOutOfBoundsException {
final BaseBlock block = getBlock(position);
if (block == null) {
return new BaseBlock(BlockID.AIR);
}
return block;
}
/**
* Get the block at the given position.
*
* <p>If the position is out of bounds, air will be returned.</p>
*
* @param position the point, relative to the origin of the copy (0, 0, 0) and not to the actual copy origin
* @return null, if this block was outside the (non-cuboid) selection while copying
* @throws ArrayIndexOutOfBoundsException if the position is outside the bounds of the CuboidClipboard
*/
public BaseBlock getBlock(Vector position) throws ArrayIndexOutOfBoundsException {
return data[position.getBlockX()][position.getBlockY()][position.getBlockZ()];
}
/**
* Set the block at a position in the clipboard.
*
* @param position the point, relative to the origin of the copy (0, 0, 0) and not to the actual copy origin.
* @param block the block to set
* @throws ArrayIndexOutOfBoundsException if the position is outside the bounds of the CuboidClipboard
*/
public void setBlock(Vector position, BaseBlock block) {
data[position.getBlockX()][position.getBlockY()][position.getBlockZ()] = block;
}
/**
* Get the dimensions of the clipboard.
*
* @return the dimensions, where (1, 1, 1) is 1 wide, 1 across, 1 deep
*/
public Vector getSize() {
return size;
}
/**
* Saves the clipboard data to a .schematic-format file.
*
* @param path the path to the file to save
* @throws IOException thrown on I/O error
* @throws DataException thrown on error writing the data for other reasons
* @deprecated use {@link SchematicFormat#MCEDIT}
*/
@Deprecated
public void saveSchematic(File path) throws IOException, DataException {
checkNotNull(path);
SchematicFormat.MCEDIT.save(this, path);
}
/**
* Load a .schematic file into a clipboard.
*
* @param path the path to the file to load
* @return a clipboard
* @throws IOException thrown on I/O error
* @throws DataException thrown on error writing the data for other reasons
* @deprecated use {@link SchematicFormat#MCEDIT}
*/
@Deprecated
public static CuboidClipboard loadSchematic(File path) throws DataException, IOException {
checkNotNull(path);
return SchematicFormat.MCEDIT.load(path);
}
/**
* Get the origin point, which corresponds to where the copy was
* originally copied from. The origin is the lowest possible X, Y, and
* Z components of the cuboid region that was copied.
*
* @return the origin
*/
public Vector getOrigin() {
return origin;
}
/**
* Set the origin point, which corresponds to where the copy was
* originally copied from. The origin is the lowest possible X, Y, and
* Z components of the cuboid region that was copied.
*
* @param origin the origin to set
*/
public void setOrigin(Vector origin) {
checkNotNull(origin);
this.origin = origin;
}
/**
* Get the offset of the player to the clipboard's minimum point
* (minimum X, Y, Z coordinates).
*
* <p>The offset is inverse (multiplied by -1).</p>
*
* @return the offset the offset
*/
public Vector getOffset() {
return offset;
}
/**
* Set the offset of the player to the clipboard's minimum point
* (minimum X, Y, Z coordinates).
*
* <p>The offset is inverse (multiplied by -1).</p>
*
* @param offset the new offset
*/
public void setOffset(Vector offset) {
this.offset = offset;
}
/**
* Get the block distribution inside a clipboard.
*
* @return a block distribution
*/
public List<Countable<Integer>> getBlockDistribution() {
List<Countable<Integer>> distribution = new ArrayList<Countable<Integer>>();
Map<Integer, Countable<Integer>> map = new HashMap<Integer, Countable<Integer>>();
int maxX = getWidth();
int maxY = getHeight();
int maxZ = getLength();
for (int x = 0; x < maxX; ++x) {
for (int y = 0; y < maxY; ++y) {
for (int z = 0; z < maxZ; ++z) {
final BaseBlock block = data[x][y][z];
if (block == null) {
continue;
}
int id = block.getId();
if (map.containsKey(id)) {
map.get(id).increment();
} else {
Countable<Integer> c = new Countable<Integer>(id, 1);
map.put(id, c);
distribution.add(c);
}
}
}
}
Collections.sort(distribution);
// Collections.reverse(distribution);
return distribution;
}
/**
* Get the block distribution inside a clipboard with data values.
*
* @return a block distribution
*/
// TODO reduce code duplication
public List<Countable<BaseBlock>> getBlockDistributionWithData() {
List<Countable<BaseBlock>> distribution = new ArrayList<Countable<BaseBlock>>();
Map<BaseBlock, Countable<BaseBlock>> map = new HashMap<BaseBlock, Countable<BaseBlock>>();
int maxX = getWidth();
int maxY = getHeight();
int maxZ = getLength();
for (int x = 0; x < maxX; ++x) {
for (int y = 0; y < maxY; ++y) {
for (int z = 0; z < maxZ; ++z) {
final BaseBlock block = data[x][y][z];
if (block == null) {
continue;
}
// Strip the block from metadata that is not part of our key
final BaseBlock bareBlock = new BaseBlock(block.getId(), block.getData());
if (map.containsKey(bareBlock)) {
map.get(bareBlock).increment();
} else {
Countable<BaseBlock> c = new Countable<BaseBlock>(bareBlock, 1);
map.put(bareBlock, c);
distribution.add(c);
}
}
}
}
Collections.sort(distribution);
// Collections.reverse(distribution);
return distribution;
}
/**
* Stores a copied entity.
*/
private class CopiedEntity {
private final LocalEntity entity;
private final Vector relativePosition;
private CopiedEntity(LocalEntity entity) {
this.entity = entity;
this.relativePosition = entity.getPosition().getPosition().subtract(getOrigin());
}
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,234 @@
/*
* 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;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.World;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Creates new {@link EditSession}s. To get an instance of this factory,
* use {@link WorldEdit#getEditSessionFactory()}.
*
* <p>It is no longer possible to replace the instance of this in WorldEdit
* with a custom one. Use {@link EditSessionEvent} to override
* the creation of {@link EditSession}s.</p>
*/
public class EditSessionFactory {
/**
* Construct an edit session with a maximum number of blocks.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @return an instance
*/
public EditSession getEditSession(World world, int maxBlocks) {
// ============ READ ME ============
// This method is actually implemented if you call WorldEdit.getEditSessionFactory()
// as it returns an instance of EditSessionFactoryImpl seen below.
// Previously, other plugins would create their own EditSessionFactory and extend ours and
// then use it to return custom EditSessions so the plugin could log block changes, etc.
// However, that method only allows one plugin to hook into WorldEdit at a time,
// so now we recommend catching the EditSessionEvent and hooking into our
// new(er) Extent framework.
throw new RuntimeException("Method needs to be implemented");
}
/**
* Construct an edit session with a maximum number of blocks.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @param player the player that the {@link EditSession} is for
* @return an instance
*/
public EditSession getEditSession(World world, int maxBlocks, Player player) {
// ============ READ ME ============
// This method is actually implemented if you call WorldEdit.getEditSessionFactory()
// as it returns an instance of EditSessionFactoryImpl seen below.
// Previously, other plugins would create their own EditSessionFactory and extend ours and
// then use it to return custom EditSessions so the plugin could log block changes, etc.
// However, that method only allows one plugin to hook into WorldEdit at a time,
// so now we recommend catching the EditSessionEvent and hooking into our
// new(er) Extent framework.
throw new RuntimeException("Method needs to be implemented");
}
/**
* Construct an edit session with a maximum number of blocks and a block bag.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @param blockBag an optional {@link BlockBag} to use, otherwise null
* @return an instance
*/
public EditSession getEditSession(World world, int maxBlocks, BlockBag blockBag) {
// ============ READ ME ============
// This method is actually implemented if you call WorldEdit.getEditSessionFactory()
// as it returns an instance of EditSessionFactoryImpl seen below.
// Previously, other plugins would create their own EditSessionFactory and extend ours and
// then use it to return custom EditSessions so the plugin could log block changes, etc.
// However, that method only allows one plugin to hook into WorldEdit at a time,
// so now we recommend catching the EditSessionEvent and hooking into our
// new(er) Extent framework.
throw new RuntimeException("Method needs to be implemented");
}
/**
* Construct an edit session with a maximum number of blocks and a block bag.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @param blockBag an optional {@link BlockBag} to use, otherwise null
* @param player the player that the {@link EditSession} is for
* @return an instance
*/
public EditSession getEditSession(World world, int maxBlocks, BlockBag blockBag, Player player) {
// ============ READ ME ============
// This method is actually implemented if you call WorldEdit.getEditSessionFactory()
// as it returns an instance of EditSessionFactoryImpl seen below.
// Previously, other plugins would create their own EditSessionFactory and extend ours and
// then use it to return custom EditSessions so the plugin could log block changes, etc.
// However, that method only allows one plugin to hook into WorldEdit at a time,
// so now we recommend catching the EditSessionEvent and hooking into our
// new(er) Extent framework.
throw new RuntimeException("Method needs to be implemented");
}
// ------------------------------------------------------------------------
// Methods being deprecated
// ------------------------------------------------------------------------
/**
* Construct an edit session.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @return an instance
* @deprecated We are replacing {@link LocalWorld} with {@link World}, so use {@link #getEditSession(World, int)} instead
*/
@Deprecated
public EditSession getEditSession(LocalWorld world, int maxBlocks) {
return getEditSession((World) world, maxBlocks);
}
/**
* Construct an edit session.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @param player the player that the {@link EditSession} is for
* @return an instance
* @deprecated We are replacing {@link LocalWorld} with {@link World}, so use {@link #getEditSession(World, int, Player)} instead
*/
@Deprecated
public EditSession getEditSession(LocalWorld world, int maxBlocks, LocalPlayer player) {
return getEditSession((World) world, maxBlocks, player);
}
/**
* Construct an edit session.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @param blockBag an optional {@link BlockBag} to use, otherwise null
* @return an instance
* @deprecated We are replacing {@link LocalWorld} with {@link World}, so use {@link #getEditSession(World, int, BlockBag)} instead
*/
@Deprecated
public EditSession getEditSession(LocalWorld world, int maxBlocks, BlockBag blockBag) {
return getEditSession((World) world, maxBlocks, blockBag);
}
/**
* Construct an edit session.
*
* @param world the world
* @param maxBlocks the maximum number of blocks that can be changed, or -1 to use no limit
* @param blockBag an optional {@link BlockBag} to use, otherwise null
* @param player the player that the {@link EditSession} is for
* @return an instance
* @deprecated We are replacing {@link LocalWorld} with {@link World}, so use {@link #getEditSession(World, int, BlockBag, Player)} instead
*/
@Deprecated
public EditSession getEditSession(LocalWorld world, int maxBlocks, BlockBag blockBag, LocalPlayer player) {
return getEditSession((World) world, maxBlocks, blockBag, player);
}
/**
* Internal factory for {@link EditSession}s.
*/
static final class EditSessionFactoryImpl extends EditSessionFactory {
private final EventBus eventBus;
/**
* Create a new factory.
*
* @param eventBus the event bus
*/
EditSessionFactoryImpl(EventBus eventBus) {
checkNotNull(eventBus);
this.eventBus = eventBus;
}
@Override
public EditSession getEditSession(World world, int maxBlocks) {
return new EditSession(eventBus, world, maxBlocks, null, new EditSessionEvent(world, null, maxBlocks, null));
}
@Override
public EditSession getEditSession(World world, int maxBlocks, Player player) {
return new EditSession(eventBus, world, maxBlocks, null, new EditSessionEvent(world, player, maxBlocks, null));
}
@Override
public EditSession getEditSession(World world, int maxBlocks, BlockBag blockBag) {
return new EditSession(eventBus, world, maxBlocks, blockBag, new EditSessionEvent(world, null, maxBlocks, null));
}
@Override
public EditSession getEditSession(World world, int maxBlocks, BlockBag blockBag, Player player) {
return new EditSession(eventBus, world, maxBlocks, blockBag, new EditSessionEvent(world, player, maxBlocks, null));
}
}
}

View File

@ -0,0 +1,27 @@
/*
* 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;
/**
* Thrown when there is no clipboard set.
*/
public class EmptyClipboardException extends WorldEditException {
}

View File

@ -0,0 +1,27 @@
/*
* 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;
/**
* Raised when a region is not fully defined.
*/
public class IncompleteRegionException extends WorldEditException {
}

View File

@ -0,0 +1,31 @@
/*
* 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;
/**
* Thrown when an invalid item is specified.
*/
public class InvalidItemException extends DisallowedItemException {
public InvalidItemException(String type, String message) {
super(type, message);
}
}

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.worldedit;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.ItemID;
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
/**
* Represents WorldEdit's configuration.
*/
public abstract class LocalConfiguration {
protected static final int[] defaultDisallowedBlocks = new int[] {
// dangerous stuff (physics/drops items)
BlockID.SAPLING,
BlockID.BED,
BlockID.POWERED_RAIL,
BlockID.DETECTOR_RAIL,
BlockID.LONG_GRASS,
BlockID.DEAD_BUSH,
BlockID.PISTON_EXTENSION,
BlockID.PISTON_MOVING_PIECE,
BlockID.YELLOW_FLOWER,
BlockID.RED_FLOWER,
BlockID.BROWN_MUSHROOM,
BlockID.RED_MUSHROOM,
BlockID.TNT,
BlockID.TORCH,
BlockID.FIRE,
BlockID.REDSTONE_WIRE,
BlockID.CROPS,
BlockID.MINECART_TRACKS,
BlockID.LEVER,
BlockID.REDSTONE_TORCH_OFF,
BlockID.REDSTONE_TORCH_ON,
BlockID.REDSTONE_REPEATER_OFF,
BlockID.REDSTONE_REPEATER_ON,
BlockID.STONE_BUTTON,
BlockID.CACTUS,
BlockID.REED,
// ores and stuff
BlockID.BEDROCK,
BlockID.GOLD_ORE,
BlockID.IRON_ORE,
BlockID.COAL_ORE,
BlockID.DIAMOND_ORE,
// @TODO rethink what should be disallowed by default
// Gold and iron can be legitimately obtained, but were set to disallowed by
// default. Diamond and coal can't be legitimately obtained. Sponges,
// portals, snow, and locked chests also can't, but are allowed. None of
// these blocks poses any immediate threat. Most of the blocks (in the first
// section) are disallowed because people will accidentally set a huge area
// of them, triggering physics and a million item drops, lagging the server.
// Doors also have this effect, but are not disallowed.
};
public boolean profile = false;
public Set<Integer> disallowedBlocks = new HashSet<Integer>();
public int defaultChangeLimit = -1;
public int maxChangeLimit = -1;
public int defaultMaxPolygonalPoints = -1;
public int maxPolygonalPoints = 20;
public int defaultMaxPolyhedronPoints = -1;
public int maxPolyhedronPoints = 20;
public String shellSaveType = "";
public SnapshotRepository snapshotRepo = null;
public int maxRadius = -1;
public int maxSuperPickaxeSize = 5;
public int maxBrushRadius = 6;
public boolean logCommands = false;
public String logFile = "";
public boolean registerHelp = true; // what is the point of this, it's not even used
public int wandItem = ItemID.WOOD_AXE;
public boolean superPickaxeDrop = true;
public boolean superPickaxeManyDrop = true;
public boolean noDoubleSlash = false;
public boolean useInventory = false;
public boolean useInventoryOverride = false;
public boolean useInventoryCreativeOverride = false;
public boolean navigationUseGlass = true;
public int navigationWand = ItemID.COMPASS;
public int navigationWandMaxDistance = 50;
public int scriptTimeout = 3000;
public Set<Integer> allowedDataCycleBlocks = new HashSet<Integer>();
public String saveDir = "schematics";
public String scriptsDir = "craftscripts";
public boolean showHelpInfo = true;
public int butcherDefaultRadius = -1;
public int butcherMaxRadius = -1;
public boolean allowSymlinks = false;
/**
* Load the configuration.
*/
public abstract void load();
/**
* Get the working directory to work from.
*
* @return a working directory
*/
public File getWorkingDirectory() {
return new File(".");
}
}

View File

@ -0,0 +1,49 @@
/*
* 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;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
/**
* Holds an entity.
*
* @deprecated replaced with the new entity API using {@link Entity} and {@link BaseEntity}
*/
@Deprecated
public abstract class LocalEntity {
private final Location position;
protected LocalEntity(Location position) {
this.position = position;
}
public Location getPosition() {
return position;
}
public boolean spawn() {
return spawn(getPosition());
}
public abstract boolean spawn(Location loc);
}

View File

@ -0,0 +1,34 @@
/*
* 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;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
import com.sk89q.worldedit.extension.platform.Actor;
/**
* Represents a player that uses WorldEdit.
*
* @deprecated use {@link Actor} (or {@link Player}, etc.) instead (and {@link AbstractPlayerActor} to extend)
*/
@Deprecated
public abstract class LocalPlayer extends AbstractPlayerActor {
}

View File

@ -0,0 +1,922 @@
/*
* 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;
import com.sk89q.jchronic.Chronic;
import com.sk89q.jchronic.Options;
import com.sk89q.jchronic.utils.Span;
import com.sk89q.jchronic.utils.Time;
import com.sk89q.worldedit.command.tool.BlockTool;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.SinglePickaxe;
import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.internal.cui.CUIRegion;
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.regions.selector.RegionSelectorType;
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 javax.annotation.Nullable;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Stores session information.
*/
public class LocalSession {
public transient static int MAX_HISTORY_SIZE = 15;
// Non-session related fields
private transient LocalConfiguration config;
private transient final AtomicBoolean dirty = new AtomicBoolean();
// Session related
private transient RegionSelector selector = new CuboidRegionSelector();
private transient boolean placeAtPos1 = false;
private transient LinkedList<EditSession> history = new LinkedList<EditSession>();
private transient int historyPointer = 0;
private transient ClipboardHolder clipboard;
private transient boolean toolControl = true;
private transient boolean superPickaxe = false;
private transient BlockTool pickaxeMode = new SinglePickaxe();
private transient Map<Integer, Tool> tools = new HashMap<Integer, Tool>();
private transient int maxBlocksChanged = -1;
private transient boolean useInventory;
private transient Snapshot snapshot;
private transient boolean hasCUISupport = false;
private transient int cuiVersion = -1;
private transient boolean fastMode = false;
private transient Mask mask;
private transient TimeZone timezone = TimeZone.getDefault();
// Saved properties
private String lastScript;
private RegionSelectorType defaultSelector;
/**
* Construct the object.
*
* <p>{@link #setConfiguration(LocalConfiguration)} should be called
* later with configuration.</p>
*/
public LocalSession() {
}
/**
* Construct the object.
*
* @param config the configuration
*/
public LocalSession(@Nullable LocalConfiguration config) {
this.config = config;
}
/**
* Set the configuration.
*
* @param config the configuration
*/
public void setConfiguration(LocalConfiguration config) {
checkNotNull(config);
this.config = config;
}
/**
* Called on post load of the session from persistent storage.
*/
public void postLoad() {
if (defaultSelector != null) {
this.selector = defaultSelector.createSelector();
}
}
/**
* Get whether this session is "dirty" and has changes that needs to
* be committed.
*
* @return true if dirty
*/
public boolean isDirty() {
return dirty.get();
}
/**
* Set this session as dirty.
*/
private void setDirty() {
dirty.set(true);
}
/**
* Get whether this session is "dirty" and has changes that needs to
* be committed, and reset it to {@code false}.
*
* @return true if the dirty value was {@code true}
*/
public boolean compareAndResetDirty() {
return dirty.compareAndSet(true, false);
}
/**
* Get the session's timezone.
*
* @return the timezone
*/
public TimeZone getTimeZone() {
return timezone;
}
/**
* Set the session's timezone.
*
* @param timezone the user's timezone
*/
public void setTimezone(TimeZone timezone) {
checkNotNull(timezone);
this.timezone = timezone;
}
/**
* Clear history.
*/
public void clearHistory() {
history.clear();
historyPointer = 0;
}
/**
* Remember an edit session for the undo history. If the history maximum
* size is reached, old edit sessions will be discarded.
*
* @param editSession the edit session
*/
public void remember(EditSession editSession) {
checkNotNull(editSession);
// Don't store anything if no changes were made
if (editSession.size() == 0) return;
// Destroy any sessions after this undo point
while (historyPointer < history.size()) {
history.remove(historyPointer);
}
history.add(editSession);
while (history.size() > MAX_HISTORY_SIZE) {
history.remove(0);
}
historyPointer = history.size();
}
/**
* Performs an undo.
*
* @param newBlockBag a new block bag
* @param player the player
* @return whether anything was undone
*/
public EditSession undo(@Nullable BlockBag newBlockBag, LocalPlayer player) {
return undo(newBlockBag, (Player) player);
}
/**
* Performs an undo.
*
* @param newBlockBag a new block bag
* @param player the player
* @return whether anything was undone
*/
public EditSession undo(@Nullable BlockBag newBlockBag, Player player) {
checkNotNull(player);
--historyPointer;
if (historyPointer >= 0) {
EditSession editSession = history.get(historyPointer);
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(editSession.getWorld(), -1, newBlockBag, player);
newEditSession.enableQueue();
newEditSession.setFastMode(fastMode);
editSession.undo(newEditSession);
return editSession;
} else {
historyPointer = 0;
return null;
}
}
/**
* Performs a redo
*
* @param newBlockBag a new block bag
* @param player the player
* @return whether anything was redone
*/
public EditSession redo(@Nullable BlockBag newBlockBag, LocalPlayer player) {
return redo(newBlockBag, (Player) player);
}
/**
* Performs a redo
*
* @param newBlockBag a new block bag
* @param player the player
* @return whether anything was redone
*/
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
checkNotNull(player);
if (historyPointer < history.size()) {
EditSession editSession = history.get(historyPointer);
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(editSession.getWorld(), -1, newBlockBag, player);
newEditSession.enableQueue();
newEditSession.setFastMode(fastMode);
editSession.redo(newEditSession);
++historyPointer;
return editSession;
}
return null;
}
/**
* Get the default region selector.
*
* @return the default region selector
*/
public RegionSelectorType getDefaultRegionSelector() {
return defaultSelector;
}
/**
* Set the default region selector.
*
* @param defaultSelector the default region selector
*/
public void setDefaultRegionSelector(RegionSelectorType defaultSelector) {
checkNotNull(defaultSelector);
this.defaultSelector = defaultSelector;
setDirty();
}
/**
* @deprecated Use {@link #getRegionSelector(World)}
*/
@Deprecated
public RegionSelector getRegionSelector(LocalWorld world) {
return getRegionSelector((World) world);
}
/**
* Get the region selector for defining the selection. If the selection
* was defined for a different world, the old selection will be discarded.
*
* @param world the world
* @return position the position
*/
public RegionSelector getRegionSelector(World world) {
checkNotNull(world);
if (selector.getWorld() == null || !selector.getWorld().equals(world)) {
selector.setWorld(world);
selector.clear();
}
return selector;
}
/**
* @deprecated use {@link #getRegionSelector(World)}
*/
@Deprecated
public RegionSelector getRegionSelector() {
return selector;
}
/**
* @deprecated use {@link #setRegionSelector(World, RegionSelector)}
*/
@Deprecated
public void setRegionSelector(LocalWorld world, RegionSelector selector) {
setRegionSelector((World) world, selector);
}
/**
* Set the region selector.
*
* @param world the world
* @param selector the selector
*/
public void setRegionSelector(World world, RegionSelector selector) {
checkNotNull(world);
checkNotNull(selector);
selector.setWorld(world);
this.selector = selector;
}
/**
* Returns true if the region is fully defined.
*
* @return true if a region selection is defined
*/
@Deprecated
public boolean isRegionDefined() {
return selector.isDefined();
}
/**
* @deprecated use {@link #isSelectionDefined(World)}
*/
@Deprecated
public boolean isSelectionDefined(LocalWorld world) {
return isSelectionDefined((World) world);
}
/**
* Returns true if the region is fully defined for the specified world.
*
* @param world the world
* @return true if a region selection is defined
*/
public boolean isSelectionDefined(World world) {
checkNotNull(world);
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
return false;
}
return selector.isDefined();
}
/**
* @deprecated use {@link #getSelection(World)}
*/
@Deprecated
public Region getRegion() throws IncompleteRegionException {
return selector.getRegion();
}
/**
* @deprecated use {@link #getSelection(World)}
*/
@Deprecated
public Region getSelection(LocalWorld world) throws IncompleteRegionException {
return getSelection((World) world);
}
/**
* Get the selection region. If you change the region, you should
* call learnRegionChanges(). If the selection is defined in
* a different world, the {@code IncompleteRegionException}
* exception will be thrown.
*
* @param world the world
* @return a region
* @throws IncompleteRegionException if no region is selected
*/
public Region getSelection(World world) throws IncompleteRegionException {
checkNotNull(world);
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
throw new IncompleteRegionException();
}
return selector.getRegion();
}
/**
* Get the selection world.
*
* @return the the world of the selection
*/
public World getSelectionWorld() {
return selector.getIncompleteRegion().getWorld();
}
/**
* Gets the clipboard.
*
* @return clipboard
* @throws EmptyClipboardException thrown if no clipboard is set
*/
public ClipboardHolder getClipboard() throws EmptyClipboardException {
if (clipboard == null) {
throw new EmptyClipboardException();
}
return clipboard;
}
/**
* Sets the 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(@Nullable ClipboardHolder clipboard) {
this.clipboard = clipboard;
}
/**
* See if tool control is enabled.
*
* @return true if enabled
*/
public boolean isToolControlEnabled() {
return toolControl;
}
/**
* Change tool control setting.
*
* @param toolControl true to enable tool control
*/
public void setToolControl(boolean toolControl) {
this.toolControl = toolControl;
}
/**
* Get the maximum number of blocks that can be changed in an edit session.
*
* @return block change limit
*/
public int getBlockChangeLimit() {
return maxBlocksChanged;
}
/**
* Set the maximum number of blocks that can be changed.
*
* @param maxBlocksChanged the maximum number of blocks changed
*/
public void setBlockChangeLimit(int maxBlocksChanged) {
this.maxBlocksChanged = maxBlocksChanged;
}
/**
* Checks whether the super pick axe is enabled.
*
* @return status
*/
public boolean hasSuperPickAxe() {
return superPickaxe;
}
/**
* Enable super pick axe.
*/
public void enableSuperPickAxe() {
superPickaxe = true;
}
/**
* Disable super pick axe.
*/
public void disableSuperPickAxe() {
superPickaxe = false;
}
/**
* Toggle the super pick axe.
*
* @return whether the super pick axe is now enabled
*/
public boolean toggleSuperPickAxe() {
superPickaxe = !superPickaxe;
return superPickaxe;
}
/**
* Get the position use for commands that take a center point
* (i.e. //forestgen, etc.).
*
* @param player the player
* @return the position to use
* @throws IncompleteRegionException thrown if a region is not fully selected
*/
public Vector getPlacementPosition(Player player) throws IncompleteRegionException {
checkNotNull(player);
if (!placeAtPos1) {
return player.getBlockIn();
}
return selector.getPrimaryPosition();
}
/**
* Toggle placement position.
*
* @return whether "place at position 1" is now enabled
*/
public boolean togglePlacementPosition() {
placeAtPos1 = !placeAtPos1;
return placeAtPos1;
}
/**
* Get a block bag for a player.
*
* @param player the player to get the block bag for
* @return a block bag
*/
@Nullable
public BlockBag getBlockBag(Player player) {
checkNotNull(player);
if (!useInventory) {
return null;
}
return player.getInventoryBlockBag();
}
/**
* Get the snapshot that has been selected.
*
* @return the snapshot
*/
@Nullable
public Snapshot getSnapshot() {
return snapshot;
}
/**
* Select a snapshot.
*
* @param snapshot a snapshot
*/
public void setSnapshot(@Nullable Snapshot snapshot) {
this.snapshot = snapshot;
}
/**
* Get the assigned block tool.
*
* @return the super pickaxe tool mode
*/
public BlockTool getSuperPickaxe() {
return pickaxeMode;
}
/**
* Set the super pick axe tool.
*
* @param tool the tool to set
*/
public void setSuperPickaxe(BlockTool tool) {
checkNotNull(tool);
this.pickaxeMode = tool;
}
/**
* Get the tool assigned to the item.
*
* @param item the item type ID
* @return the tool, which may be {@link null}
*/
@Nullable
public Tool getTool(int item) {
return tools.get(item);
}
/**
* Get the brush tool assigned to the item. If there is no tool assigned
* or the tool is not assigned, the slot will be replaced with the
* brush tool.
*
* @param item the item type ID
* @return the tool, or {@code null}
* @throws InvalidToolBindException if the item can't be bound to that item
*/
@Nullable
public BrushTool getBrushTool(int item) throws InvalidToolBindException {
Tool tool = getTool(item);
if (tool == null || !(tool instanceof BrushTool)) {
tool = new BrushTool("worldedit.brush.sphere");
setTool(item, tool);
}
return (BrushTool) tool;
}
/**
* Set the tool.
*
* @param item the item type ID
* @param tool the tool to set, which can be {@code null}
* @throws InvalidToolBindException if the item can't be bound to that item
*/
public void setTool(int item, @Nullable Tool tool) throws InvalidToolBindException {
if (item > 0 && item < 255) {
throw new InvalidToolBindException(item, "Blocks can't be used");
} else if (item == config.wandItem) {
throw new InvalidToolBindException(item, "Already used for the wand");
} else if (item == config.navigationWand) {
throw new InvalidToolBindException(item, "Already used for the navigation wand");
}
this.tools.put(item, tool);
}
/**
* Returns whether inventory usage is enabled for this session.
*
* @return if inventory is being used
*/
public boolean isUsingInventory() {
return useInventory;
}
/**
* Set the state of inventory usage.
*
* @param useInventory if inventory is to be used
*/
public void setUseInventory(boolean useInventory) {
this.useInventory = useInventory;
}
/**
* Get the last script used.
*
* @return the last script's name
*/
@Nullable
public String getLastScript() {
return lastScript;
}
/**
* Set the last script used.
*
* @param lastScript the last script's name
*/
public void setLastScript(@Nullable String lastScript) {
this.lastScript = lastScript;
setDirty();
}
/**
* Tell the player the WorldEdit version.
*
* @param player the player
*/
public void tellVersion(Actor player) {
}
/**
* Dispatch a CUI event but only if the actor has CUI support.
*
* @param actor the actor
* @param event the event
*/
public void dispatchCUIEvent(Actor actor, CUIEvent event) {
checkNotNull(actor);
checkNotNull(event);
if (hasCUISupport) {
actor.dispatchCUIEvent(event);
}
}
/**
* Dispatch the initial setup CUI messages.
*
* @param actor the actor
*/
public void dispatchCUISetup(Actor actor) {
if (selector != null) {
dispatchCUISelection(actor);
}
}
/**
* Send the selection information.
*
* @param actor the actor
*/
public void dispatchCUISelection(Actor actor) {
checkNotNull(actor);
if (!hasCUISupport) {
return;
}
if (selector instanceof CUIRegion) {
CUIRegion tempSel = (CUIRegion) selector;
if (tempSel.getProtocolVersion() > cuiVersion) {
actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getLegacyTypeID()));
tempSel.describeLegacyCUI(this, actor);
} else {
actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getTypeID()));
tempSel.describeCUI(this, actor);
}
}
}
/**
* Describe the selection to the CUI actor.
*
* @param actor the actor
*/
public void describeCUI(Actor actor) {
checkNotNull(actor);
if (!hasCUISupport) {
return;
}
if (selector instanceof CUIRegion) {
CUIRegion tempSel = (CUIRegion) selector;
if (tempSel.getProtocolVersion() > cuiVersion) {
tempSel.describeLegacyCUI(this, actor);
} else {
tempSel.describeCUI(this, actor);
}
}
}
/**
* Handle a CUI initialization message.
*
* @param text the message
*/
public void handleCUIInitializationMessage(String text) {
checkNotNull(text);
String[] split = text.split("\\|");
if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message
setCUISupport(true);
try {
setCUIVersion(Integer.parseInt(split[1]));
} catch (NumberFormatException e) {
WorldEdit.logger.warning("Error while reading CUI init message: " + e.getMessage());
}
}
}
/**
* Gets the status of CUI support.
*
* @return true if CUI is enabled
*/
public boolean hasCUISupport() {
return hasCUISupport;
}
/**
* Sets the status of CUI support.
*
* @param support true if CUI is enabled
*/
public void setCUISupport(boolean support) {
hasCUISupport = support;
}
/**
* Gets the client's CUI protocol version
*
* @return the CUI version
*/
public int getCUIVersion() {
return cuiVersion;
}
/**
* Sets the client's CUI protocol version
*
* @param cuiVersion the CUI version
*/
public void setCUIVersion(int cuiVersion) {
this.cuiVersion = cuiVersion;
}
/**
* Detect date from a user's input.
*
* @param input the input to parse
* @return a date
*/
@Nullable
public Calendar detectDate(String input) {
checkNotNull(input);
Time.setTimeZone(getTimeZone());
Options opt = new com.sk89q.jchronic.Options();
opt.setNow(Calendar.getInstance(getTimeZone()));
Span date = Chronic.parse(input, opt);
if (date == null) {
return null;
} else {
return date.getBeginCalendar();
}
}
/**
* @deprecated use {@link #createEditSession(Player)}
*/
@Deprecated
public EditSession createEditSession(LocalPlayer player) {
return createEditSession((Player) player);
}
/**
* Construct a new edit session.
*
* @param player the player
* @return an edit session
*/
@SuppressWarnings("deprecation")
public EditSession createEditSession(Player player) {
checkNotNull(player);
BlockBag blockBag = getBlockBag(player);
// Create an edit session
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(player.isPlayer() ? player.getWorld() : null,
getBlockChangeLimit(), blockBag, player);
editSession.setFastMode(fastMode);
Request.request().setEditSession(editSession);
editSession.setMask(mask);
return editSession;
}
/**
* Checks if the session has fast mode enabled.
*
* @return true if fast mode is enabled
*/
public boolean hasFastMode() {
return fastMode;
}
/**
* Set fast mode.
*
* @param fastMode true if fast mode is enabled
*/
public void setFastMode(boolean fastMode) {
this.fastMode = fastMode;
}
/**
* Get the mask.
*
* @return mask, may be null
*/
public Mask getMask() {
return mask;
}
/**
* Set a mask.
*
* @param mask mask or null
*/
public void setMask(Mask mask) {
this.mask = mask;
}
/**
* Set a mask.
*
* @param mask mask or null
*/
@SuppressWarnings("deprecation")
public void setMask(com.sk89q.worldedit.masks.Mask mask) {
setMask(mask != null ? Masks.wrap(mask) : null);
}
}

View File

@ -0,0 +1,83 @@
/*
* 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;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.World;
/**
* A legacy abstract implementation of {@link World}. New implementations
* should use {@link AbstractWorld} when possible.
*
* @deprecated Replace with {@link World} wherever appropriate
*/
@Deprecated
public abstract class LocalWorld extends AbstractWorld {
@Override
public BaseBlock getLazyBlock(Vector position) {
return getBlock(position);
}
@Override
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException {
switch (type) {
case BIG_TREE:
return generateBigTree(editSession, pt);
case BIRCH:
return generateBirchTree(editSession, pt);
case REDWOOD:
return generateRedwoodTree(editSession, pt);
case TALL_REDWOOD:
return generateTallRedwoodTree(editSession, pt);
default:
case TREE:
return generateTree(editSession, pt);
}
}
@Override
public boolean generateTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return false;
}
@Override
public boolean generateBigTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return false;
}
@Override
public boolean generateBirchTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return false;
}
@Override
public boolean generateRedwoodTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return false;
}
@Override
public boolean generateTallRedwoodTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return false;
}
}

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.worldedit;
/**
* @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible
*/
@Deprecated
public class Location {
private final LocalWorld world;
private final Vector position;
private final float yaw;
private final float pitch;
public Location(LocalWorld world, Vector position) {
this(world, position, 0, 0);
}
public Location(LocalWorld world, Vector position, float yaw, float pitch) {
this.world = world;
this.position = position;
this.yaw = yaw;
this.pitch = pitch;
}
public LocalWorld getWorld() {
return world;
}
public Vector getPosition() {
return position;
}
public float getYaw() {
return yaw;
}
public float getPitch() {
return pitch;
}
public Location setAngles(float yaw, float pitch) {
return new Location(world, position, yaw, pitch);
}
public Location setPosition(Vector position) {
return new Location(world, position, yaw, pitch);
}
public Location add(Vector other) {
return setPosition(position.add(other));
}
public Location add(double x, double y, double z) {
return setPosition(position.add(x, y, z));
}
public Vector getDirection() {
final double yawRadians = Math.toRadians(yaw);
final double pitchRadians = Math.toRadians(pitch);
final double y = -Math.sin(pitchRadians);
final double h = Math.cos(pitchRadians);
final double x = -h * Math.sin(yawRadians);
final double z = h * Math.cos(yawRadians);
return new Vector(x, y, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Location))
return false;
Location location = (Location) obj;
if (!world.equals(location.world))
return false;
if (!position.equals(location.position))
return false;
return true;
}
@Override
public int hashCode() {
return position.hashCode() + 19 * world.hashCode();
}
@Override
public String toString() {
return "World: " + world.getName() + ", Coordinates: " + position
+ ", Yaw: " + yaw + ", Pitch: " + pitch;
}
public static Location fromLookAt(LocalWorld world, Vector start, Vector lookAt) {
final Vector diff = lookAt.subtract(start);
return fromEye(world, start, diff);
}
public static Location fromEye(LocalWorld world, Vector start, Vector eye) {
final double eyeX = eye.getX();
final double eyeZ = eye.getZ();
final float yaw = (float) Math.toDegrees(Math.atan2(-eyeX, eyeZ));
final double length = Math.sqrt(eyeX * eyeX + eyeZ * eyeZ);
final float pitch = (float) Math.toDegrees(Math.atan2(-eye.getY(), length));
return new Location(world, start, yaw, pitch);
}
}

View File

@ -0,0 +1,27 @@
/*
* 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;
/**
* Thrown when a maximum radius for a brush is reached.
*/
public class MaxBrushRadiusException extends MaxRadiusException {
}

View File

@ -0,0 +1,48 @@
/*
* 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;
/**
* Thrown when too many blocks are changed (which may be limited
* due to the configuration).
*/
public class MaxChangedBlocksException extends WorldEditException {
int maxBlocks;
/**
* Create a new instance.
*
* @param maxBlocks the maximum number of blocks that can be changed
*/
public MaxChangedBlocksException(int maxBlocks) {
this.maxBlocks = maxBlocks;
}
/**
* Get the limit.
*
* @return the maximum number of blocks that can be changed
*/
public int getBlockLimit() {
return maxBlocks;
}
}

View File

@ -0,0 +1,28 @@
/*
* 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;
/**
* Thrown when a maximum radius is reached, such as, for example,
* in the case of a sphere command.
*/
public class MaxRadiusException extends WorldEditException {
}

View File

@ -0,0 +1,52 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit;
/**
* Raised when an item is used when a block was expected.
*/
public class NotABlockException extends WorldEditException {
/**
* Create a new instance.
*/
public NotABlockException() {
super("This item is not a block.");
}
/**
* Create a new instance.
*
* @param input the input that was used
*/
public NotABlockException(String input) {
super("The item '" + input + "' is not a block.");
}
/**
* Create a new instance.
*
* @param input the input that was used
*/
public NotABlockException(int input) {
super("The item with the ID " + input + " is not a block.");
}
}

View File

@ -0,0 +1,65 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit;
import com.sk89q.worldedit.util.Direction;
/**
* The player's direction.
*
* <p>In the future, this class will be replaced with {@link Direction}.</p>
*/
public enum PlayerDirection {
NORTH(new Vector(0, 0, -1), new Vector(-1, 0, 0), true),
NORTH_EAST((new Vector(1, 0, -1)).normalize(), (new Vector(-1, 0, -1)).normalize(), false),
EAST(new Vector(1, 0, 0), new Vector(0, 0, -1), true),
SOUTH_EAST((new Vector(1, 0, 1)).normalize(), (new Vector(1, 0, -1)).normalize(), false),
SOUTH(new Vector(0, 0, 1), new Vector(1, 0, 0), true),
SOUTH_WEST((new Vector(-1, 0, 1)).normalize(), (new Vector(1, 0, 1)).normalize(), false),
WEST(new Vector(-1, 0, 0), new Vector(0, 0, 1), true),
NORTH_WEST((new Vector(-1, 0, -1)).normalize(), (new Vector(-1, 0, 1)).normalize(), false),
UP(new Vector(0, 1, 0), new Vector(0, 0, 1), true),
DOWN(new Vector(0, -1, 0), new Vector(0, 0, 1), true);
private final Vector dir;
private final Vector leftDir;
private final boolean isOrthogonal;
PlayerDirection(Vector vec, Vector leftDir, boolean isOrthogonal) {
this.dir = vec;
this.leftDir = leftDir;
this.isOrthogonal = isOrthogonal;
}
public Vector vector() {
return dir;
}
@Deprecated
public Vector leftVector() {
return leftDir;
}
public boolean isOrthogonal() {
return isOrthogonal;
}
}

View File

@ -0,0 +1,33 @@
/*
* 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;
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
import com.sk89q.worldedit.extension.platform.Platform;
/**
* A legacy abstract class that is to be replaced with {@link Platform}.
* Extend {@link AbstractPlatform} instead.
*
* @deprecated Use {@link Platform} wherever possible
*/
@Deprecated
public abstract class ServerInterface extends AbstractPlatform {
}

View File

@ -0,0 +1,47 @@
/*
* 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;
/**
* Thrown when an unknown direction is specified or detected.
*/
public class UnknownDirectionException extends WorldEditException {
private String dir;
/**
* Create a new instance.
*
* @param dir the input that was tried
*/
public UnknownDirectionException(String dir) {
this.dir = dir;
}
/**
* Get the direction string that was input.
*
* @return input
*/
public String getDirection() {
return dir;
}
}

View File

@ -0,0 +1,47 @@
/*
* 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;
/**
* Thrown when no item exist by the ID.
*/
public class UnknownItemException extends WorldEditException {
private String type;
/**
* Create a new instance.
*
* @param type the input that was provided
*/
public UnknownItemException(String type) {
this.type = type;
}
/**
* Get the input.
*
* @return the input
*/
public String getID() {
return type;
}
}

View File

@ -0,0 +1,850 @@
/*
* 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;
import com.sk89q.worldedit.math.transform.AffineTransform;
import javax.annotation.Nullable;
/**
* An immutable 3-dimensional vector.
*/
public class Vector implements Comparable<Vector> {
public static final Vector ZERO = new Vector(0, 0, 0);
public static final Vector UNIT_X = new Vector(1, 0, 0);
public static final Vector UNIT_Y = new Vector(0, 1, 0);
public static final Vector UNIT_Z = new Vector(0, 0, 1);
public static final Vector ONE = new Vector(1, 1, 1);
protected final double x, y, z;
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public Vector(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public Vector(int x, int y, int z) {
this.x = (double) x;
this.y = (double) y;
this.z = (double) z;
}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public Vector(float x, float y, float z) {
this.x = (double) x;
this.y = (double) y;
this.z = (double) z;
}
/**
* Copy another vector.
*
* @param other another vector to make a copy of
*/
public Vector(Vector other) {
this.x = other.x;
this.y = other.y;
this.z = other.z;
}
/**
* Construct a new instance with X, Y, and Z coordinates set to 0.
*
* <p>One can also refer to a static {@link #ZERO}.</p>
*/
public Vector() {
this.x = 0;
this.y = 0;
this.z = 0;
}
/**
* Get the X coordinate.
*
* @return the x coordinate
*/
public double getX() {
return x;
}
/**
* Get the X coordinate rounded.
*
* @return the x coordinate
*/
public int getBlockX() {
return (int) Math.round(x);
}
/**
* Set the X coordinate.
*
* @param x the new X
* @return a new vector
*/
public Vector setX(double x) {
return new Vector(x, y, z);
}
/**
* Set the X coordinate.
*
* @param x the X coordinate
* @return new vector
*/
public Vector setX(int x) {
return new Vector(x, y, z);
}
/**
* Get the Y coordinate.
*
* @return the y coordinate
*/
public double getY() {
return y;
}
/**
* Get the Y coordinate rounded.
*
* @return the y coordinate
*/
public int getBlockY() {
return (int) Math.round(y);
}
/**
* Set the Y coordinate.
*
* @param y the new Y
* @return a new vector
*/
public Vector setY(double y) {
return new Vector(x, y, z);
}
/**
* Set the Y coordinate.
*
* @param y the new Y
* @return a new vector
*/
public Vector setY(int y) {
return new Vector(x, y, z);
}
/**
* Get the Z coordinate.
*
* @return the z coordinate
*/
public double getZ() {
return z;
}
/**
* Get the Z coordinate rounded.
*
* @return the z coordinate
*/
public int getBlockZ() {
return (int) Math.round(z);
}
/**
* Set the Z coordinate.
*
* @param z the new Z
* @return a new vector
*/
public Vector setZ(double z) {
return new Vector(x, y, z);
}
/**
* Set the Z coordinate.
*
* @param z the new Z
* @return a new vector
*/
public Vector setZ(int z) {
return new Vector(x, y, z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param other the other vector
* @return a new vector
*/
public Vector add(Vector other) {
return new Vector(x + other.x, y + other.y, z + other.z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param x the value to add
* @param y the value to add
* @param z the value to add
* @return a new vector
*/
public Vector add(double x, double y, double z) {
return new Vector(this.x + x, this.y + y, this.z + z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param x the value to add
* @param y the value to add
* @param z the value to add
* @return a new vector
*/
public Vector add(int x, int y, int z) {
return new Vector(this.x + x, this.y + y, this.z + z);
}
/**
* Add a list of vectors to this vector and return the
* result as a new vector.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector add(Vector... others) {
double newX = x, newY = y, newZ = z;
for (Vector other : others) {
newX += other.x;
newY += other.y;
newZ += other.z;
}
return new Vector(newX, newY, newZ);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param other the other vector
* @return a new vector
*/
public Vector subtract(Vector other) {
return new Vector(x - other.x, y - other.y, z - other.z);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param x the value to subtract
* @param y the value to subtract
* @param z the value to subtract
* @return a new vector
*/
public Vector subtract(double x, double y, double z) {
return new Vector(this.x - x, this.y - y, this.z - z);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param x the value to subtract
* @param y the value to subtract
* @param z the value to subtract
* @return a new vector
*/
public Vector subtract(int x, int y, int z) {
return new Vector(this.x - x, this.y - y, this.z - z);
}
/**
* Subtract a list of vectors from this vector and return the result
* as a new vector.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector subtract(Vector... others) {
double newX = x, newY = y, newZ = z;
for (Vector other : others) {
newX -= other.x;
newY -= other.y;
newZ -= other.z;
}
return new Vector(newX, newY, newZ);
}
/**
* Multiply this vector by another vector on each component.
*
* @param other the other vector
* @return a new vector
*/
public Vector multiply(Vector other) {
return new Vector(x * other.x, y * other.y, z * other.z);
}
/**
* Multiply this vector by another vector on each component.
*
* @param x the value to multiply
* @param y the value to multiply
* @param z the value to multiply
* @return a new vector
*/
public Vector multiply(double x, double y, double z) {
return new Vector(this.x * x, this.y * y, this.z * z);
}
/**
* Multiply this vector by another vector on each component.
*
* @param x the value to multiply
* @param y the value to multiply
* @param z the value to multiply
* @return a new vector
*/
public Vector multiply(int x, int y, int z) {
return new Vector(this.x * x, this.y * y, this.z * z);
}
/**
* Multiply this vector by zero or more vectors on each component.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector multiply(Vector... others) {
double newX = x, newY = y, newZ = z;
for (Vector other : others) {
newX *= other.x;
newY *= other.y;
newZ *= other.z;
}
return new Vector(newX, newY, newZ);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector multiply(double n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector multiply(float n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector multiply(int n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Divide this vector by another vector on each component.
*
* @param other the other vector
* @return a new vector
*/
public Vector divide(Vector other) {
return new Vector(x / other.x, y / other.y, z / other.z);
}
/**
* Divide this vector by another vector on each component.
*
* @param x the value to divide by
* @param y the value to divide by
* @param z the value to divide by
* @return a new vector
*/
public Vector divide(double x, double y, double z) {
return new Vector(this.x / x, this.y / y, this.z / z);
}
/**
* Divide this vector by another vector on each component.
*
* @param x the value to divide by
* @param y the value to divide by
* @param z the value to divide by
* @return a new vector
*/
public Vector divide(int x, int y, int z) {
return new Vector(this.x / x, this.y / y, this.z / z);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector divide(int n) {
return new Vector(x / n, y / n, z / n);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector divide(double n) {
return new Vector(x / n, y / n, z / n);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector divide(float n) {
return new Vector(x / n, y / n, z / n);
}
/**
* Get the length of the vector.
*
* @return length
*/
public double length() {
return Math.sqrt(x * x + y * y + z * z);
}
/**
* Get the length, squared, of the vector.
*
* @return length, squared
*/
public double lengthSq() {
return x * x + y * y + z * z;
}
/**
* Get the distance between this vector and another vector.
*
* @param other the other vector
* @return distance
*/
public double distance(Vector other) {
return Math.sqrt(Math.pow(other.x - x, 2) +
Math.pow(other.y - y, 2) +
Math.pow(other.z - z, 2));
}
/**
* Get the distance between this vector and another vector, squared.
*
* @param other the other vector
* @return distance
*/
public double distanceSq(Vector other) {
return Math.pow(other.x - x, 2) +
Math.pow(other.y - y, 2) +
Math.pow(other.z - z, 2);
}
/**
* Get the normalized vector, which is the vector divided by its
* length, as a new vector.
*
* @return a new vector
*/
public Vector normalize() {
return divide(length());
}
/**
* Gets the dot product of this and another vector.
*
* @param other the other vector
* @return the dot product of this and the other vector
*/
public double dot(Vector other) {
return x * other.x + y * other.y + z * other.z;
}
/**
* Gets the cross product of this and another vector.
*
* @param other the other vector
* @return the cross product of this and the other vector
*/
public Vector cross(Vector other) {
return new Vector(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
);
}
/**
* Checks to see if a vector is contained with another.
*
* @param min the minimum point (X, Y, and Z are the lowest)
* @param max the maximum point (X, Y, and Z are the lowest)
* @return true if the vector is contained
*/
public boolean containedWithin(Vector min, Vector max) {
return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z;
}
/**
* Checks to see if a vector is contained with another, comparing
* using discrete comparisons, inclusively.
*
* @param min the minimum point (X, Y, and Z are the lowest)
* @param max the maximum point (X, Y, and Z are the lowest)
* @return true if the vector is contained
*/
public boolean containedWithinBlock(Vector min, Vector max) {
return getBlockX() >= min.getBlockX() && getBlockX() <= max.getBlockX()
&& getBlockY() >= min.getBlockY() && getBlockY() <= max.getBlockY()
&& getBlockZ() >= min.getBlockZ() && getBlockZ() <= max.getBlockZ();
}
/**
* Clamp the Y component.
*
* @param min the minimum value
* @param max the maximum value
* @return a new vector
*/
public Vector clampY(int min, int max) {
return new Vector(x, Math.max(min, Math.min(max, y)), z);
}
/**
* Floors the values of all components.
*
* @return a new vector
*/
public Vector floor() {
return new Vector(Math.floor(x), Math.floor(y), Math.floor(z));
}
/**
* Rounds all components up.
*
* @return a new vector
*/
public Vector ceil() {
return new Vector(Math.ceil(x), Math.ceil(y), Math.ceil(z));
}
/**
* Rounds all components to the closest integer.
*
* <p>Components &lt; 0.5 are rounded down, otherwise up.</p>
*
* @return a new vector
*/
public Vector round() {
return new Vector(Math.floor(x + 0.5), Math.floor(y + 0.5), Math.floor(z + 0.5));
}
/**
* Returns a vector with the absolute values of the components of
* this vector.
*
* @return a new vector
*/
public Vector positive() {
return new Vector(Math.abs(x), Math.abs(y), Math.abs(z));
}
/**
* Perform a 2D transformation on this vector and return a new one.
*
* @param angle in degrees
* @param aboutX about which x coordinate to rotate
* @param aboutZ about which z coordinate to rotate
* @param translateX what to add after rotation
* @param translateZ what to add after rotation
* @return a new vector
* @see AffineTransform another method to transform vectors
*/
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;
double x2 = x * Math.cos(angle) - z * Math.sin(angle);
double z2 = x * Math.sin(angle) + z * Math.cos(angle);
return new Vector(
x2 + aboutX + translateX,
y,
z2 + aboutZ + translateZ
);
}
/**
* Returns whether this vector is collinear with another vector.
*
* @param other the other vector
* @return true if collinear
*/
public boolean isCollinearWith(Vector other) {
if (x == 0 && y == 0 && z == 0) {
// this is a zero vector
return true;
}
final double otherX = other.x;
final double otherY = other.y;
final double otherZ = other.z;
if (otherX == 0 && otherY == 0 && otherZ == 0) {
// other is a zero vector
return true;
}
if ((x == 0) != (otherX == 0)) return false;
if ((y == 0) != (otherY == 0)) return false;
if ((z == 0) != (otherZ == 0)) return false;
final double quotientX = otherX / x;
if (!Double.isNaN(quotientX)) {
return other.equals(multiply(quotientX));
}
final double quotientY = otherY / y;
if (!Double.isNaN(quotientY)) {
return other.equals(multiply(quotientY));
}
final double quotientZ = otherZ / z;
if (!Double.isNaN(quotientZ)) {
return other.equals(multiply(quotientZ));
}
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));
}
/**
* Create a new {@code BlockVector} using the given components.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return a new {@code BlockVector}
*/
public static BlockVector toBlockPoint(double x, double y, double z) {
return new BlockVector(
Math.floor(x),
Math.floor(y),
Math.floor(z)
);
}
/**
* Create a new {@code BlockVector} from this vector.
*
* @return a new {@code BlockVector}
*/
public BlockVector toBlockPoint() {
return new BlockVector(
Math.floor(x),
Math.floor(y),
Math.floor(z)
);
}
/**
* Create a new {@code BlockVector} from this vector.
*
* @return a new {@code BlockVector}
*/
public BlockVector toBlockVector() {
return new BlockVector(this);
}
/**
* Creates a 2D vector by dropping the Y component from this vector.
*
* @return a new {@code Vector2D}
*/
public Vector2D toVector2D() {
return new Vector2D(x, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector)) {
return false;
}
Vector other = (Vector) obj;
return other.x == this.x && other.y == this.y && other.z == this.z;
}
@Override
public int compareTo(@Nullable Vector other) {
if (other == null) {
throw new IllegalArgumentException("null not supported");
}
if (y != other.y) return Double.compare(y, other.y);
if (z != other.z) return Double.compare(z, other.z);
if (x != other.x) return Double.compare(x, other.x);
return 0;
}
@Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32));
return hash;
}
@Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
}
/**
* Gets the minimum components of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return minimum
*/
public static Vector getMinimum(Vector v1, Vector v2) {
return new Vector(
Math.min(v1.x, v2.x),
Math.min(v1.y, v2.y),
Math.min(v1.z, v2.z)
);
}
/**
* Gets the maximum components of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return maximum
*/
public static Vector getMaximum(Vector v1, Vector v2) {
return new Vector(
Math.max(v1.x, v2.x),
Math.max(v1.y, v2.y),
Math.max(v1.z, v2.z)
);
}
/**
* Gets the midpoint of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return maximum
*/
public static Vector getMidpoint(Vector v1, Vector v2) {
return new Vector(
(v1.x + v2.x) / 2,
(v1.y + v2.y) / 2,
(v1.z + v2.z) / 2
);
}
}

View File

@ -0,0 +1,667 @@
/*
* 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;
import com.sk89q.worldedit.math.transform.AffineTransform;
/**
* An immutable 2-dimensional vector.
*/
public class Vector2D {
public static final Vector2D ZERO = new Vector2D(0, 0);
public static final Vector2D UNIT_X = new Vector2D(1, 0);
public static final Vector2D UNIT_Z = new Vector2D(0, 1);
public static final Vector2D ONE = new Vector2D(1, 1);
protected final double x, z;
/**
* Construct an instance.
*
* @param x the X coordinate
* @param z the Z coordinate
*/
public Vector2D(double x, double z) {
this.x = x;
this.z = z;
}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param z the Z coordinate
*/
public Vector2D(int x, int z) {
this.x = (double) x;
this.z = (double) z;
}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param z the Z coordinate
*/
public Vector2D(float x, float z) {
this.x = (double) x;
this.z = (double) z;
}
/**
* Copy another vector.
*
* @param other the other vector
*/
public Vector2D(Vector2D other) {
this.x = other.x;
this.z = other.z;
}
/**
* Construct a new instance with X and Z coordinates set to 0.
*
* <p>One can also refer to a static {@link #ZERO}.</p>
*/
public Vector2D() {
this.x = 0;
this.z = 0;
}
/**
* Get the X coordinate.
*
* @return the x coordinate
*/
public double getX() {
return x;
}
/**
* Get the X coordinate rounded.
*
* @return the x coordinate
*/
public int getBlockX() {
return (int) Math.round(x);
}
/**
* Set the X coordinate.
*
* @param x the new X
* @return a new vector
*/
public Vector2D setX(double x) {
return new Vector2D(x, z);
}
/**
* Set the X coordinate.
*
* @param x the new X
* @return a new vector
*/
public Vector2D setX(int x) {
return new Vector2D(x, z);
}
/**
* Get the Z coordinate.
*
* @return the z coordinate
*/
public double getZ() {
return z;
}
/**
* Get the Z coordinate rounded.
*
* @return the z coordinate
*/
public int getBlockZ() {
return (int) Math.round(z);
}
/**
* Set the Z coordinate.
*
* @param z the new Z
* @return a new vector
*/
public Vector2D setZ(double z) {
return new Vector2D(x, z);
}
/**
* Set the Z coordinate.
*
* @param z the new Z
* @return a new vector
*/
public Vector2D setZ(int z) {
return new Vector2D(x, z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param other the other vector
* @return a new vector
*/
public Vector2D add(Vector2D other) {
return new Vector2D(x + other.x, z + other.z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param x the value to add
* @param z the value to add
* @return a new vector
*/
public Vector2D add(double x, double z) {
return new Vector2D(this.x + x, this.z + z);
}
/**
* Add another vector to this vector and return the result as a new vector.
*
* @param x the value to add
* @param z the value to add
* @return a new vector
*/
public Vector2D add(int x, int z) {
return new Vector2D(this.x + x, this.z + z);
}
/**
* Add a list of vectors to this vector and return the
* result as a new vector.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector2D add(Vector2D... others) {
double newX = x, newZ = z;
for (Vector2D other : others) {
newX += other.x;
newZ += other.z;
}
return new Vector2D(newX, newZ);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param other the other vector
* @return a new vector
*/
public Vector2D subtract(Vector2D other) {
return new Vector2D(x - other.x, z - other.z);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param x the value to subtract
* @param z the value to subtract
* @return a new vector
*/
public Vector2D subtract(double x, double z) {
return new Vector2D(this.x - x, this.z - z);
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
*
* @param x the value to subtract
* @param z the value to subtract
* @return a new vector
*/
public Vector2D subtract(int x, int z) {
return new Vector2D(this.x - x, this.z - z);
}
/**
* Subtract a list of vectors from this vector and return the result
* as a new vector.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector2D subtract(Vector2D... others) {
double newX = x, newZ = z;
for (Vector2D other : others) {
newX -= other.x;
newZ -= other.z;
}
return new Vector2D(newX, newZ);
}
/**
* Multiply this vector by another vector on each component.
*
* @param other the other vector
* @return a new vector
*/
public Vector2D multiply(Vector2D other) {
return new Vector2D(x * other.x, z * other.z);
}
/**
* Multiply this vector by another vector on each component.
*
* @param x the value to multiply
* @param z the value to multiply
* @return a new vector
*/
public Vector2D multiply(double x, double z) {
return new Vector2D(this.x * x, this.z * z);
}
/**
* Multiply this vector by another vector on each component.
*
* @param x the value to multiply
* @param z the value to multiply
* @return a new vector
*/
public Vector2D multiply(int x, int z) {
return new Vector2D(this.x * x, this.z * z);
}
/**
* Multiply this vector by zero or more vectors on each component.
*
* @param others an array of vectors
* @return a new vector
*/
public Vector2D multiply(Vector2D... others) {
double newX = x, newZ = z;
for (Vector2D other : others) {
newX *= other.x;
newZ *= other.z;
}
return new Vector2D(newX, newZ);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector2D multiply(double n) {
return new Vector2D(this.x * n, this.z * n);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector2D multiply(float n) {
return new Vector2D(this.x * n, this.z * n);
}
/**
* Perform scalar multiplication and return a new vector.
*
* @param n the value to multiply
* @return a new vector
*/
public Vector2D multiply(int n) {
return new Vector2D(this.x * n, this.z * n);
}
/**
* Divide this vector by another vector on each component.
*
* @param other the other vector
* @return a new vector
*/
public Vector2D divide(Vector2D other) {
return new Vector2D(x / other.x, z / other.z);
}
/**
* Divide this vector by another vector on each component.
*
* @param x the value to divide by
* @param z the value to divide by
* @return a new vector
*/
public Vector2D divide(double x, double z) {
return new Vector2D(this.x / x, this.z / z);
}
/**
* Divide this vector by another vector on each component.
*
* @param x the value to divide by
* @param z the value to divide by
* @return a new vector
*/
public Vector2D divide(int x, int z) {
return new Vector2D(this.x / x, this.z / z);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector2D divide(int n) {
return new Vector2D(x / n, z / n);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector2D divide(double n) {
return new Vector2D(x / n, z / n);
}
/**
* Perform scalar division and return a new vector.
*
* @param n the value to divide by
* @return a new vector
*/
public Vector2D divide(float n) {
return new Vector2D(x / n, z / n);
}
/**
* Get the length of the vector.
*
* @return length
*/
public double length() {
return Math.sqrt(x * x + z * z);
}
/**
* Get the length, squared, of the vector.
*
* @return length, squared
*/
public double lengthSq() {
return x * x + z * z;
}
/**
* Get the distance between this vector and another vector.
*
* @param other the other vector
* @return distance
*/
public double distance(Vector2D other) {
return Math.sqrt(Math.pow(other.x - x, 2) + Math.pow(other.z - z, 2));
}
/**
* Get the distance between this vector and another vector, squared.
*
* @param other the other vector
* @return distance
*/
public double distanceSq(Vector2D other) {
return Math.pow(other.x - x, 2) +
Math.pow(other.z - z, 2);
}
/**
* Get the normalized vector, which is the vector divided by its
* length, as a new vector.
*
* @return a new vector
*/
public Vector2D normalize() {
return divide(length());
}
/**
* Gets the dot product of this and another vector.
*
* @param other the other vector
* @return the dot product of this and the other vector
*/
public double dot(Vector2D other) {
return x * other.x + z * other.z;
}
/**
* Checks to see if a vector is contained with another.
*
* @param min the minimum point (X, Y, and Z are the lowest)
* @param max the maximum point (X, Y, and Z are the lowest)
* @return true if the vector is contained
*/
public boolean containedWithin(Vector2D min, Vector2D max) {
return x >= min.x && x <= max.x
&& z >= min.z && z <= max.z;
}
/**
* Checks to see if a vector is contained with another.
*
* @param min the minimum point (X, Y, and Z are the lowest)
* @param max the maximum point (X, Y, and Z are the lowest)
* @return true if the vector is contained
*/
public boolean containedWithinBlock(Vector2D min, Vector2D max) {
return getBlockX() >= min.getBlockX() && getBlockX() <= max.getBlockX()
&& getBlockZ() >= min.getBlockZ() && getBlockZ() <= max.getBlockZ();
}
/**
* Floors the values of all components.
*
* @return a new vector
*/
public Vector2D floor() {
return new Vector2D(Math.floor(x), Math.floor(z));
}
/**
* Rounds all components up.
*
* @return a new vector
*/
public Vector2D ceil() {
return new Vector2D(Math.ceil(x), Math.ceil(z));
}
/**
* Rounds all components to the closest integer.
*
* <p>Components &lt; 0.5 are rounded down, otherwise up.</p>
*
* @return a new vector
*/
public Vector2D round() {
return new Vector2D(Math.floor(x + 0.5), Math.floor(z + 0.5));
}
/**
* Returns a vector with the absolute values of the components of
* this vector.
*
* @return a new vector
*/
public Vector2D positive() {
return new Vector2D(Math.abs(x), Math.abs(z));
}
/**
* Perform a 2D transformation on this vector and return a new one.
*
* @param angle in degrees
* @param aboutX about which x coordinate to rotate
* @param aboutZ about which z coordinate to rotate
* @param translateX what to add after rotation
* @param translateZ what to add after rotation
* @return a new vector
* @see AffineTransform another method to transform vectors
*/
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;
double x2 = x * Math.cos(angle) - z * Math.sin(angle);
double z2 = x * Math.sin(angle) + z * Math.cos(angle);
return new Vector2D(
x2 + aboutX + translateX,
z2 + aboutZ + translateZ
);
}
/**
* Returns whether this vector is collinear with another vector.
*
* @param other the other vector
* @return true if collinear
*/
public boolean isCollinearWith(Vector2D other) {
if (x == 0 && z == 0) {
// this is a zero vector
return true;
}
final double otherX = other.x;
final double otherZ = other.z;
if (otherX == 0 && otherZ == 0) {
// other is a zero vector
return true;
}
if ((x == 0) != (otherX == 0)) return false;
if ((z == 0) != (otherZ == 0)) return false;
final double quotientX = otherX / x;
if (!Double.isNaN(quotientX)) {
return other.equals(multiply(quotientX));
}
final double quotientZ = otherZ / z;
if (!Double.isNaN(quotientZ)) {
return other.equals(multiply(quotientZ));
}
throw new RuntimeException("This should not happen");
}
/**
* Create a new {@code BlockVector2D} from this vector.
*
* @return a new {@code BlockVector2D}
*/
public BlockVector2D toBlockVector2D() {
return new BlockVector2D(this);
}
/**
* Creates a 3D vector by adding a zero Y component to this vector.
*
* @return a new vector
*/
public Vector toVector() {
return new Vector(x, 0, z);
}
/**
* Creates a 3D vector by adding the specified Y component to this vector.
*
* @param y the Y component
* @return a new vector
*/
public Vector toVector(double y) {
return new Vector(x, y, z);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Vector2D)) {
return false;
}
Vector2D other = (Vector2D) obj;
return other.x == this.x && other.z == this.z;
}
@Override
public int hashCode() {
return ((new Double(x)).hashCode() >> 13) ^
(new Double(z)).hashCode();
}
@Override
public String toString() {
return "(" + x + ", " + z + ")";
}
/**
* Gets the minimum components of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return minimum
*/
public static Vector2D getMinimum(Vector2D v1, Vector2D v2) {
return new Vector2D(
Math.min(v1.x, v2.x),
Math.min(v1.z, v2.z)
);
}
/**
* Gets the maximum components of two vectors.
*
* @param v1 the first vector
* @param v2 the second vector
* @return maximum
*/
public static Vector2D getMaximum(Vector2D v1, Vector2D v2) {
return new Vector2D(
Math.max(v1.x, v2.x),
Math.max(v1.z, v2.z)
);
}
}

View File

@ -0,0 +1,90 @@
/*
* 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;
import com.sk89q.worldedit.util.Direction;
/**
* Represents the adjacency of one vector to another. Works similarly to
* Bukkit's BlockFace class.
*
* @deprecated to be replaced with {@link Direction}
*/
@Deprecated
public enum VectorFace {
NORTH(-1, 0, 0),
EAST(0, 0, -1),
SOUTH(1, 0, 0),
WEST(0, 0, 1),
UP(0, 1, 0),
DOWN(0, -1, 0),
NORTH_EAST(NORTH, EAST),
NORTH_WEST(NORTH, WEST),
SOUTH_EAST(SOUTH, EAST),
SOUTH_WEST(SOUTH, WEST),
ABOVE_NORTH(UP, NORTH),
BELOW_NORTH(DOWN, NORTH),
ABOVE_SOUTH(UP, SOUTH),
BELOW_SOUTH(DOWN, SOUTH),
ABOVE_WEST(UP, WEST),
BELOW_WEST(DOWN, WEST),
ABOVE_EAST(UP, EAST),
BELOW_EAST(DOWN, EAST),
SELF(0, 0, 0);
private final int modX;
private final int modY;
private final int modZ;
private VectorFace(final int modX, final int modY, final int modZ) {
this.modX = modX;
this.modY = modY;
this.modZ = modZ;
}
private VectorFace(VectorFace face1, VectorFace face2) {
this.modX = face1.getModX() + face2.getModX();
this.modY = face1.getModY() + face2.getModY();
this.modZ = face1.getModZ() + face2.getModZ();
}
public int getModX() {
return modX;
}
public int getModZ() {
return modZ;
}
public int getModY() {
return modY;
}
public static VectorFace fromMods(int modX2, int modY2, int modZ2) {
for (VectorFace face : values()) {
if (face.getModX() == modX2
&& face.getModY() == modY2
&& face.getModZ() == modZ2) {
return face;
}
}
return VectorFace.SELF;
}
}

View File

@ -0,0 +1,857 @@
/*
* 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;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player;
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.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.pattern.Patterns;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.scripting.CraftScriptContext;
import com.sk89q.worldedit.scripting.CraftScriptEngine;
import com.sk89q.worldedit.scripting.RhinoCraftScriptEngine;
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.io.file.FileSelectionAbortedException;
import com.sk89q.worldedit.util.io.file.FilenameException;
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import javax.script.ScriptException;
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;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.event.platform.Interaction.HIT;
import static com.sk89q.worldedit.event.platform.Interaction.OPEN;
/**
* The entry point and container for a working implementation of WorldEdit.
*
* <p>An instance handles event handling; block, mask, pattern, etc. registration;
* the management of sessions; the creation of {@link EditSession}s; and more.
* In order to use WorldEdit, at least one {@link Platform} must be registered
* with WorldEdit using {@link PlatformManager#register(Platform)} on the
* manager retrieved using {@link WorldEdit#getPlatformManager()}.</p>
*
* <p>An instance of WorldEdit can be retrieved using the static
* method {@link WorldEdit#getInstance()}, which is shared among all
* platforms within the same classloader hierarchy.</p>
*/
public class WorldEdit {
public static final Logger logger = Logger.getLogger(WorldEdit.class.getCanonicalName());
private final static WorldEdit instance = new WorldEdit();
private static String version;
private final EventBus eventBus = new EventBus();
private final PlatformManager platformManager = new PlatformManager(this);
private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
private final SessionManager sessions = new SessionManager(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() {
}
/**
* Gets the current instance of this class.
*
* <p>An instance will always be available, but no platform may yet be
* registered with WorldEdit, meaning that a number of operations
* may fail. However, event handlers can be registered.</p>
*
* @return an instance of WorldEdit.
*/
public static WorldEdit getInstance() {
return instance;
}
/**
* Get the platform manager, where platforms (that implement WorldEdit)
* can be registered and information about registered platforms can
* be queried.
*
* @return the platform manager
*/
public PlatformManager getPlatformManager() {
return platformManager;
}
/**
* Get the event bus for WorldEdit.
*
* <p>Event handlers can be registered on the event bus.</p>
*
* @return the event bus
*/
public EventBus getEventBus() {
return eventBus;
}
/**
* Get the block factory from which new {@link BaseBlock}s can be
* constructed.
*
* @return the block factory
*/
public BlockFactory getBlockFactory() {
return blockFactory;
}
/**
* Get the mask factory from which new {@link com.sk89q.worldedit.function.mask.Mask}s
* can be constructed.
*
* @return the mask factory
*/
public MaskFactory getMaskFactory() {
return maskFactory;
}
/**
* Get the pattern factory from which new {@link com.sk89q.worldedit.function.pattern.Pattern}s
* can be constructed.
*
* @return the pattern factory
*/
public PatternFactory getPatternFactory() {
return patternFactory;
}
/**
* Return the session manager.
*
* @return the session manager
*/
public SessionManager getSessionManager() {
return sessions;
}
/**
* @deprecated Use {@link #getSessionManager()}
*/
@Deprecated
public LocalSession getSession(String player) {
return sessions.findByName(player);
}
/**
* @deprecated use {@link #getSessionManager()}
*/
@Deprecated
public LocalSession getSession(Player player) {
return sessions.get(player);
}
/**
* @deprecated use {@link #getSessionManager()}
*/
@Deprecated
public void removeSession(Player player) {
sessions.remove(player);
}
/**
* @deprecated use {@link #getSessionManager()}
*/
@Deprecated
public void clearSessions() {
sessions.clear();
}
/**
* @deprecated use {@link #getSessionManager()}
*/
@Deprecated
public boolean hasSession(Player player) {
return sessions.contains(player);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@SuppressWarnings("deprecation")
@Deprecated
public BaseBlock getBlock(Player player, String arg, boolean allAllowed) throws WorldEditException {
return getBlock(player, arg, allAllowed, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@SuppressWarnings("deprecation")
@Deprecated
public BaseBlock getBlock(Player player, String arg, boolean allAllowed, boolean allowNoData) throws WorldEditException {
ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(getSession(player));
context.setRestricted(!allAllowed);
context.setPreferringWildcard(allowNoData);
return getBlockFactory().parseFromInput(arg, context);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@SuppressWarnings("deprecation")
@Deprecated
public BaseBlock getBlock(Player player, String id) throws WorldEditException {
return getBlock(player, id, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/
@Deprecated
@SuppressWarnings("deprecation")
public Set<BaseBlock> getBlocks(Player player, String list, boolean allAllowed, boolean allowNoData) throws WorldEditException {
String[] items = list.split(",");
Set<BaseBlock> blocks = new HashSet<BaseBlock>();
for (String id : items) {
blocks.add(getBlock(player, id, allAllowed, allowNoData));
}
return blocks;
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
@SuppressWarnings("deprecation")
public Set<BaseBlock> getBlocks(Player player, String list, boolean allAllowed) throws WorldEditException {
return getBlocks(player, list, allAllowed, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/
@Deprecated
@SuppressWarnings("deprecation")
public Set<BaseBlock> getBlocks(Player player, String list) throws WorldEditException {
return getBlocks(player, list, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/
@Deprecated
@SuppressWarnings("deprecation")
public Set<Integer> getBlockIDs(Player player, String list, boolean allBlocksAllowed) throws WorldEditException {
String[] items = list.split(",");
Set<Integer> blocks = new HashSet<Integer>();
for (String s : items) {
blocks.add(getBlock(player, s, allBlocksAllowed).getType());
}
return blocks;
}
/**
* @deprecated Use {@link #getPatternFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
@SuppressWarnings("deprecation")
public Pattern getBlockPattern(Player player, String input) throws WorldEditException {
ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(getSession(player));
return Patterns.wrap(getPatternFactory().parseFromInput(input, context));
}
/**
* @deprecated Use {@link #getMaskFactory()} ()} and {@link MaskFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
@SuppressWarnings("deprecation")
public Mask getBlockMask(Player player, LocalSession session, String input) throws WorldEditException {
ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(session);
return Masks.wrap(getMaskFactory().parseFromInput(input, context));
}
/**
* Gets the path to a file. This method will check to see if the filename
* has valid characters and has an extension. It also prevents directory
* traversal exploits by checking the root directory and the file directory.
* On success, a {@code java.io.File} object will be returned.
*
* @param player the player
* @param dir sub-directory to look in
* @param filename filename (user-submitted)
* @param defaultExt append an extension if missing one, null to not use
* @param extensions list of extensions, null for any
* @return a file
* @throws FilenameException thrown if the filename is invalid
*/
public File getSafeSaveFile(Player player, File dir, String filename, String defaultExt, String... extensions) throws FilenameException {
return getSafeFile(player, dir, filename, defaultExt, extensions, true);
}
/**
* Gets the path to a file. This method will check to see if the filename
* has valid characters and has an extension. It also prevents directory
* traversal exploits by checking the root directory and the file directory.
* On success, a {@code java.io.File} object will be returned.
*
* @param player the player
* @param dir sub-directory to look in
* @param filename filename (user-submitted)
* @param defaultExt append an extension if missing one, null to not use
* @param extensions list of extensions, null for any
* @return a file
* @throws FilenameException thrown if the filename is invalid
*/
public File getSafeOpenFile(Player player, File dir, String filename, String defaultExt, String... extensions) throws FilenameException {
return getSafeFile(player, dir, filename, defaultExt, extensions, false);
}
/**
* Get a safe path to a file.
*
* @param player the player
* @param dir sub-directory to look in
* @param filename filename (user-submitted)
* @param defaultExt append an extension if missing one, null to not use
* @param extensions list of extensions, null for any
* @param isSave true if the purpose is for saving
* @return a file
* @throws FilenameException thrown if the filename is invalid
*/
private File getSafeFile(Player player, File dir, String filename, String defaultExt, String[] extensions, boolean isSave) throws FilenameException {
if (extensions != null && (extensions.length == 1 && extensions[0] == null)) extensions = null;
File f;
if (filename.equals("#")) {
if (isSave) {
f = player.openFileSaveDialog(extensions);
} else {
f = player.openFileOpenDialog(extensions);
}
if (f == null) {
throw new FileSelectionAbortedException("No file selected");
}
} else {
if (defaultExt != null && filename.lastIndexOf('.') == -1) {
filename += "." + defaultExt;
}
if (!filename.matches("^[A-Za-z0-9_\\- \\./\\\\'\\$@~!%\\^\\*\\(\\)\\[\\]\\+\\{\\},\\?]+\\.[A-Za-z0-9]+$")) {
throw new InvalidFilenameException(filename, "Invalid characters or extension missing");
}
f = new File(dir, filename);
}
try {
String filePath = f.getCanonicalPath();
String dirPath = dir.getCanonicalPath();
if (!filePath.substring(0, dirPath.length()).equals(dirPath) && !getConfiguration().allowSymlinks) {
throw new FilenameResolutionException(filename,
"Path is outside allowable root");
}
return f;
} catch (IOException e) {
throw new FilenameResolutionException(filename,
"Failed to resolve path");
}
}
/**
* Checks to see if the specified radius is within bounds.
*
* @param radius the radius
* @throws MaxRadiusException
*/
public void checkMaxRadius(double radius) throws MaxRadiusException {
if (getConfiguration().maxRadius > 0 && radius > getConfiguration().maxRadius) {
throw new MaxRadiusException();
}
}
/**
* Checks to see if the specified brush radius is within bounds.
*
* @param radius the radius
* @throws MaxBrushRadiusException
*/
public void checkMaxBrushRadius(double radius) throws MaxBrushRadiusException {
if (getConfiguration().maxBrushRadius > 0 && radius > getConfiguration().maxBrushRadius) {
throw new MaxBrushRadiusException();
}
}
/**
* Get a file relative to the defined working directory. If the specified
* path is absolute, then the working directory is not used.
*
* @param path the subpath under the working directory
* @return a working directory
*/
public File getWorkingDirectoryFile(String path) {
File f = new File(path);
if (f.isAbsolute()) {
return f;
}
return new File(getConfiguration().getWorkingDirectory(), path);
}
/**
* Get the direction vector for a player's direction. May return
* null if a direction could not be found.
*
* @param player the player
* @param dirStr the direction string
* @return a direction vector
* @throws UnknownDirectionException thrown if the direction is not known
*/
public Vector getDirection(Player player, String dirStr) throws UnknownDirectionException {
dirStr = dirStr.toLowerCase();
final PlayerDirection dir = getPlayerDirection(player, dirStr);
switch (dir) {
case WEST:
case EAST:
case SOUTH:
case NORTH:
case UP:
case DOWN:
return dir.vector();
default:
throw new UnknownDirectionException(dir.name());
}
}
/**
* Get the direction vector for a player's direction. May return
* null if a direction could not be found.
*
* @param player the player
* @param dirStr the direction string
* @return a direction enum value
* @throws UnknownDirectionException thrown if the direction is not known
*/
private PlayerDirection getPlayerDirection(Player player, String dirStr) throws UnknownDirectionException {
final PlayerDirection dir;
switch (dirStr.charAt(0)) {
case 'w':
dir = PlayerDirection.WEST;
break;
case 'e':
dir = PlayerDirection.EAST;
break;
case 's':
if (dirStr.indexOf('w') > 0) {
return PlayerDirection.SOUTH_WEST;
}
if (dirStr.indexOf('e') > 0) {
return PlayerDirection.SOUTH_EAST;
}
dir = PlayerDirection.SOUTH;
break;
case 'n':
if (dirStr.indexOf('w') > 0) {
return PlayerDirection.NORTH_WEST;
}
if (dirStr.indexOf('e') > 0) {
return PlayerDirection.NORTH_EAST;
}
dir = PlayerDirection.NORTH;
break;
case 'u':
dir = PlayerDirection.UP;
break;
case 'd':
dir = PlayerDirection.DOWN;
break;
case 'm': // me
case 'f': // forward
dir = player.getCardinalDirection(0);
break;
case 'b': // back
dir = player.getCardinalDirection(180);
break;
case 'l': // left
dir = player.getCardinalDirection(-90);
break;
case 'r': // right
dir = player.getCardinalDirection(90);
break;
default:
throw new UnknownDirectionException(dirStr);
}
return dir;
}
/**
* Get diagonal direction vector for a player's direction. May return
* null if a direction could not be found.
*
* @param player the player
* @param dirStr the direction string
* @return a direction vector
* @throws UnknownDirectionException thrown if the direction is not known
*/
public Vector getDiagonalDirection(Player player, String dirStr) throws UnknownDirectionException {
return getPlayerDirection(player, dirStr.toLowerCase()).vector();
}
/**
* Get the flip direction for a player's direction.
*
* @param player the player
* @param dirStr the direction string
* @return a direction vector
* @throws UnknownDirectionException thrown if the direction is not known
*/
public FlipDirection getFlipDirection(Player player, String dirStr) throws UnknownDirectionException {
final PlayerDirection dir = getPlayerDirection(player, dirStr);
switch (dir) {
case WEST:
case EAST:
return FlipDirection.WEST_EAST;
case NORTH:
case SOUTH:
return FlipDirection.NORTH_SOUTH;
case UP:
case DOWN:
return FlipDirection.UP_DOWN;
default:
throw new UnknownDirectionException(dir.name());
}
}
/**
* Flush a block bag's changes to a player.
*
* @param actor the actor
* @param editSession the edit session
*/
public void flushBlockBag(Actor actor, EditSession editSession) {
BlockBag blockBag = editSession.getBlockBag();
if (blockBag != null) {
blockBag.flushChanges();
}
Map<Integer, Integer> missingBlocks = editSession.popMissingBlocks();
if (!missingBlocks.isEmpty()) {
StringBuilder str = new StringBuilder();
str.append("Missing these blocks: ");
int size = missingBlocks.size();
int i = 0;
for (Integer id : missingBlocks.keySet()) {
BlockType type = BlockType.fromID(id);
str.append(type != null
? type.getName() + " (" + id + ")"
: id.toString());
str.append(" [Amt: ").append(missingBlocks.get(id)).append("]");
++i;
if (i != size) {
str.append(", ");
}
}
actor.printError(str.toString());
}
}
/**
* Called on arm swing.
*
* @param player the player
* @return true if the swing was handled
*/
public boolean handleArmSwing(Player player) {
PlayerInputEvent event = new PlayerInputEvent(player, InputType.PRIMARY);
getEventBus().post(event);
return event.isCancelled();
}
/**
* Called on right click (not on a block).
*
* @param player the player
* @return true if the right click was handled
*/
public boolean handleRightClick(Player player) {
PlayerInputEvent event = new PlayerInputEvent(player, InputType.SECONDARY);
getEventBus().post(event);
return event.isCancelled();
}
/**
* Called on right click.
*
* @param player the player
* @param clicked the clicked block
* @return false if you want the action to go through
*/
public boolean handleBlockRightClick(Player player, WorldVector clicked) {
BlockInteractEvent event = new BlockInteractEvent(player, clicked.toLocation(), OPEN);
getEventBus().post(event);
return event.isCancelled();
}
/**
* Called on left click.
*
* @param player the player
* @param clicked the clicked block
* @return false if you want the action to go through
*/
public boolean handleBlockLeftClick(Player player, WorldVector clicked) {
BlockInteractEvent event = new BlockInteractEvent(player, clicked.toLocation(), HIT);
getEventBus().post(event);
return event.isCancelled();
}
/**
* Executes a WorldEdit script.
*
* @param player the player
* @param f the script file to execute
* @param args arguments for the script
* @throws WorldEditException
*/
public void runScript(Player player, File f, String[] args) throws WorldEditException {
Request.reset();
String filename = f.getPath();
int index = filename.lastIndexOf(".");
String ext = filename.substring(index + 1, filename.length());
if (!ext.equalsIgnoreCase("js")) {
player.printError("Only .js scripts are currently supported");
return;
}
String script;
try {
InputStream file;
if (!f.exists()) {
file = WorldEdit.class.getResourceAsStream("craftscripts/" + filename);
if (file == null) {
player.printError("Script does not exist: " + filename);
return;
}
} else {
file = new FileInputStream(f);
}
DataInputStream in = new DataInputStream(file);
byte[] data = new byte[in.available()];
in.readFully(data);
in.close();
script = new String(data, 0, data.length, "utf-8");
} catch (IOException e) {
player.printError("Script read error: " + e.getMessage());
return;
}
LocalSession session = getSessionManager().get(player);
CraftScriptContext scriptContext = new CraftScriptContext(this, getServer(), getConfiguration(), session, player, args);
CraftScriptEngine engine = null;
try {
engine = new RhinoCraftScriptEngine();
} catch (NoClassDefFoundError e) {
player.printError("Failed to find an installed script engine.");
player.printError("Please see http://wiki.sk89q.com/wiki/WorldEdit/Installation");
return;
}
engine.setTimeLimit(getConfiguration().scriptTimeout);
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("argv", args);
vars.put("context", scriptContext);
vars.put("player", player);
try {
engine.evaluate(script, filename, vars);
} catch (ScriptException e) {
player.printError("Failed to execute:");
player.printRaw(e.getMessage());
logger.log(Level.WARNING, "Failed to execute script", e);
} catch (NumberFormatException e) {
throw e;
} catch (WorldEditException e) {
throw e;
} catch (Throwable e) {
player.printError("Failed to execute (see console):");
player.printRaw(e.getClass().getCanonicalName());
logger.log(Level.WARNING, "Failed to execute script", e);
} finally {
for (EditSession editSession : scriptContext.getEditSessions()) {
editSession.flushQueue();
session.remember(editSession);
}
}
}
/**
* Get Worldedit's configuration.
*
* @return a configuration
*/
public LocalConfiguration getConfiguration() {
return getPlatformManager().getConfiguration();
}
/**
* Get the server interface.
*
* @return the server interface
*/
public ServerInterface getServer() {
return getPlatformManager().getServerInterface();
}
/**
* Get a factory for {@link EditSession}s.
*/
public EditSessionFactory getEditSessionFactory() {
return editSessionFactory;
}
/**
* @deprecated EditSessionFactories are no longer used. Please register an {@link EditSessionEvent} event
* with the event bus in order to override or catch changes to the world
*/
@Deprecated
public void setEditSessionFactory(EditSessionFactory factory) {
checkNotNull(factory);
logger.severe("Got request to set EditSessionFactory of type " +
factory.getClass().getName() + " from " + factory.getClass().getPackage().getName() +
" but EditSessionFactories have been removed in favor of extending EditSession's extents.\n\n" +
"This may mean that any block logger / intercepters addons/plugins/mods that you have installed will not " +
"intercept WorldEdit's changes! Please notify the maintainer of the other addon about this.");
}
/**
* Get the version.
*
* @return the version of WorldEdit
*/
public static String getVersion() {
if (version != null) {
return version;
}
Package p = WorldEdit.class.getPackage();
if (p == null) {
p = Package.getPackage("com.sk89q.worldedit");
}
if (p == null) {
version = "(unknown)";
} else {
version = p.getImplementationVersion();
if (version == null) {
version = "(unknown)";
}
}
return version;
}
/**
* @deprecated Declare your platform version with {@link Platform#getPlatformVersion()}
*/
@Deprecated
public static void setVersion(String version) {
}
}

View File

@ -0,0 +1,60 @@
/*
* 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;
/**
* Parent for all WorldEdit exceptions.
*/
public abstract class WorldEditException extends Exception {
/**
* Create a new exception.
*/
protected WorldEditException() {
}
/**
* Create a new exception with a message.
*
* @param message the message
*/
protected WorldEditException(String message) {
super(message);
}
/**
* Create a new exception with a message and a cause.
*
* @param message the message
* @param cause the cause
*/
protected WorldEditException(String message, Throwable cause) {
super(message, cause);
}
/**
* Create a new exception with a cause.
*
* @param cause the cause
*/
protected WorldEditException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,33 @@
/*
* 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;
/**
* Represents a WorldEdit operation.
*
* @deprecated This will be removed with no direct replacement. Please use the
* WorldEdit API.
*/
@Deprecated
public abstract class WorldEditOperation {
public abstract void run(LocalSession session, LocalPlayer player, EditSession editSession) throws Throwable;
}

View File

@ -0,0 +1,147 @@
/*
* 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;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.world.World;
/**
* @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible
*/
@SuppressWarnings("deprecation")
@Deprecated
public class WorldVector extends Vector {
private LocalWorld world;
/**
* Construct the Vector object.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public WorldVector(LocalWorld world, double x, double y, double z) {
super(x, y, z);
this.world = world;
}
/**
* Construct the Vector object.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public WorldVector(LocalWorld world, int x, int y, int z) {
super(x, y, z);
this.world = world;
}
/**
* Construct the Vector object.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
public WorldVector(LocalWorld world, float x, float y, float z) {
super(x, y, z);
this.world = world;
}
/**
* Construct the Vector object.
*
* @param world a world
* @param other the position to copy
*/
public WorldVector(LocalWorld world, Vector other) {
super(other);
this.world = world;
}
/**
* Construct the Vector object.
*
* @param world a world
*/
public WorldVector(LocalWorld world) {
super();
this.world = world;
}
/**
* Construct the Vector object.
*
* @param location the location
*/
public WorldVector(com.sk89q.worldedit.util.Location location) {
this(LocalWorldAdapter.adapt((World) location.getExtent()), location.getX(), location.getY(), location.getZ());
}
/**
* Get the world.
*
* @return the world
*/
public LocalWorld getWorld() {
return world;
}
/**
* Get a block point from a point.
*
* @param world a world
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return point
*/
public static WorldVector toBlockPoint(LocalWorld world, double x, double y,
double z) {
return new WorldVector(world, (int) Math.floor(x),
(int) Math.floor(y),
(int) Math.floor(z));
}
/**
* Gets a BlockVector version.
*
* @return BlockWorldVector
*/
public BlockWorldVector toWorldBlockVector() {
return new BlockWorldVector(this);
}
/**
* Return this object as a new preferred {@code Location}
* object.
*
* @return a new location object
*/
public com.sk89q.worldedit.util.Location toLocation() {
return new com.sk89q.worldedit.util.Location(getWorld(), this);
}
}

View File

@ -0,0 +1,81 @@
/*
* 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;
/**
* @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible
*/
@Deprecated
public class WorldVector2D extends Vector2D {
protected LocalWorld world;
public WorldVector2D(LocalWorld world) {
super();
this.world = world;
}
public WorldVector2D(LocalWorld world, double x, double z) {
super(x, z);
this.world = world;
}
public WorldVector2D(LocalWorld world, float x, float z) {
super(x, z);
this.world = world;
}
public WorldVector2D(LocalWorld world, int x, int z) {
super(x, z);
this.world = world;
}
public WorldVector2D(LocalWorld world, Vector2D pt) {
super(pt);
this.world = world;
}
public LocalWorld getWorld() {
return world;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof WorldVector2D)) {
return false;
}
WorldVector2D other = (WorldVector2D) obj;
return other.world.equals(world) && other.x == this.x
&& other.z == this.z;
}
/**
* Gets the hash code.
*
* @return hash code
*/
@Override
public int hashCode() {
return (world.hashCode() >> 7) ^
((int) (Double.doubleToLongBits(x) ^ (Double.doubleToLongBits(x) >>> 32)) >> 13) ^
(int) (Double.doubleToLongBits(z) ^ (Double.doubleToLongBits(z) >>> 32));
}
}

View File

@ -0,0 +1,108 @@
/*
* 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;
/**
* @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible
*/
@SuppressWarnings("deprecation")
@Deprecated
public class WorldVectorFace extends WorldVector {
private VectorFace face;
public WorldVectorFace(LocalWorld world, double x, double y, double z, VectorFace face) {
super(world, x, y, z);
this.face = face;
}
public WorldVectorFace(LocalWorld world, int x, int y, int z, VectorFace face) {
super(world, x, y, z);
this.face = face;
}
public WorldVectorFace(LocalWorld world, float x, float y, float z, VectorFace face) {
super(world, x, y, z);
this.face = face;
}
public WorldVectorFace(LocalWorld world, Vector pt, VectorFace face) {
super(world, pt);
this.face = face;
}
public WorldVectorFace(LocalWorld world, VectorFace face) {
super(world);
this.face = face;
}
/**
* Get the face.
*
* @return the face
*/
public VectorFace getFace() {
return face;
}
/**
* Get the WorldVector adjacent to this WorldVectorFace.
*
* @return the face vector
*/
public WorldVector getFaceVector() {
return new WorldVector(getWorld(),
getBlockX() - face.getModX(),
getBlockY() - face.getModY(),
getBlockZ() - face.getModZ());
}
/**
* Get a WorldVectorFace by comparing two vectors. Note that they need not be
* adjacent, as only the directions, not distance, will be taken into account.
*
* @param world the world in which the resulting vector should lie
* @param vector the original vector
* @param face the direction in which the face should lie
* @return a face
*/
public static WorldVectorFace getWorldVectorFace(LocalWorld world, Vector vector, Vector face) {
if (vector == null || face == null) return null;
// check which direction the face is from the vector
final int x1 = vector.getBlockX();
final int y1 = vector.getBlockY();
final int z1 = vector.getBlockZ();
int modX = x1 - face.getBlockX();
int modY = y1 - face.getBlockY();
int modZ = z1 - face.getBlockZ();
if (modX > 0) modX = 1;
else if (modX < 0) modX = -1;
else modX = 0;
if (modY > 0) modY = 1;
else if (modY < 0) modY = -1;
else modY = 0;
if (modZ > 0) modZ = 1;
else if (modZ < 0) modZ = -1;
else modZ = 0;
// construct new vector
return new WorldVectorFace(world, x1, y1, z1, VectorFace.fromMods(modX, modY, modZ));
}
}

View File

@ -0,0 +1,410 @@
/*
* 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.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.foundation.Block;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.world.registry.WorldData;
import javax.annotation.Nullable;
import java.util.Collection;
/**
* Represents a mutable "snapshot" of a block.
*
* <p>An instance of this block contains all the information needed to
* accurately reproduce the block, provided that the instance was
* made correctly. In some implementations, it may not be possible to get a
* snapshot of blocks correctly, so, for example, the NBT data for a block
* may be missing.</p>
*
* <p>This class identifies blocks using an integer ID. However, IDs for
* a given block may differ between worlds so it is important that users of
* this class convert the ID from one "world space" to another "world space,"
* a task that that is assisted with by working with the source and
* destination {@link WorldData} instances. Numeric IDs are utilized because
* they are more space efficient to store, and it also implies that internal
* uses of this class (i.e. history, etc.) do not need to worry about
* interning block string IDs.</p>
*
* <p>A peculiar detail of this class is that it accepts {@code -1} as a
* valid data value. This is due to legacy reasons: WorldEdit uses -1
* as a "wildcard" block value, even though a {@link Mask} would be
* more appropriate.</p>
*/
@SuppressWarnings("deprecation")
public class BaseBlock extends Block implements TileEntityBlock {
/**
* Indicates the highest possible block ID (inclusive) that can be used.
* This value is subject to change depending on the implementation, but
* internally this class only supports a range of 4096 IDs (for space
* reasons), which coincides with the number of possible IDs that official
* Minecraft supports as of version 1.7.
*/
public static final int MAX_ID = 4095;
/**
* Indicates the maximum data value (inclusive) that can be used. A future
* version of Minecraft may abolish block data values.
*/
public static final int MAX_DATA = 15;
// Instances of this class should be _as small as possible_ because there will
// be millions of instances of this object.
private short id;
private short data;
@Nullable
private CompoundTag nbtData;
/**
* Construct a block with the given ID and a data value of 0.
*
* @param id ID value
* @see #setId(int)
*/
public BaseBlock(int id) {
internalSetId(id);
internalSetData(0);
}
/**
* Construct a block with the given ID and data value.
*
* @param id ID value
* @param data data value
* @see #setId(int)
* @see #setData(int)
*/
public BaseBlock(int id, int data) {
internalSetId(id);
internalSetData(data);
}
/**
* Construct a block with the given ID, data value and NBT data structure.
*
* @param id ID value
* @param data data value
* @param nbtData NBT data, which may be null
*/
public BaseBlock(int id, int data, @Nullable 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;
}
/**
* Set the block ID.
*
* @param id block id (between 0 and {@link #MAX_ID}).
*/
protected final void internalSetId(int id) {
if (id > MAX_ID) {
throw new IllegalArgumentException("Can't have a block ID above "
+ MAX_ID + " (" + id + " given)");
}
if (id < 0) {
throw new IllegalArgumentException("Can't have a block ID below 0");
}
this.id = (short) id;
}
/**
* Set the block ID.
*
* @param id block id (between 0 and {@link #MAX_ID}).
*/
@Override
public void setId(int id) {
internalSetId(id);
}
/**
* Get the block's data value.
*
* @return data value (0-15)
*/
@Override
public int getData() {
return data;
}
/**
* Set the block's data value.
*
* @param data block data value (between 0 and {@link #MAX_DATA}).
*/
protected final void internalSetData(int data) {
if (data > MAX_DATA) {
throw new IllegalArgumentException(
"Can't have a block data value above " + MAX_DATA + " ("
+ data + " given)");
}
if (data < -1) {
throw new IllegalArgumentException("Can't have a block data value below -1");
}
this.data = (short) data;
}
/**
* Set the block's data value.
*
* @param data block data value (between 0 and {@link #MAX_DATA}).
*/
@Override
public void setData(int data) {
internalSetData(data);
}
/**
* Set both the block's ID and data value.
*
* @param id ID value
* @param data data value
* @see #setId(int)
* @see #setData(int)
*/
@Override
public void setIdAndData(int id, int data) {
setId(id);
setData(data);
}
/**
* Returns whether the data value is -1, indicating that this block is to be
* used as a wildcard matching block.
*
* @return true if the data value is -1
*/
@Override
public boolean hasWildcardData() {
return getData() == -1;
}
@Override
public boolean hasNbtData() {
return getNbtData() != null;
}
@Override
public String getNbtId() {
CompoundTag nbtData = getNbtData();
if (nbtData == null) {
return "";
}
Tag idTag = nbtData.getValue().get("id");
if (idTag != null && idTag instanceof StringTag) {
return ((StringTag) idTag).getValue();
} else {
return "";
}
}
@Nullable
@Override
public CompoundTag getNbtData() {
return nbtData;
}
@Override
public void setNbtData(@Nullable CompoundTag nbtData) {
this.nbtData = nbtData;
}
/**
* Get the type of block.
*
* @return the type
*/
public int getType() {
return getId();
}
/**
* Set the type of block.
*
* @param type the type to set
*/
public void setType(int type) {
setId(type);
}
/**
* Returns true if it's air.
*
* @return if air
*/
public boolean isAir() {
return getType() == BlockID.AIR;
}
/**
* Rotate this block 90 degrees.
*
* @return new data value
* @deprecated Use {@link BlockData#rotate90(int, int)}
*/
@Deprecated
public int rotate90() {
int newData = BlockData.rotate90(getType(), getData());
setData(newData);
return newData;
}
/**
* Rotate this block -90 degrees.
*
* @return new data value
* @deprecated Use {@link BlockData#rotate90Reverse(int, int)}
*/
@Deprecated
public int rotate90Reverse() {
int newData = BlockData.rotate90Reverse(getType(), getData());
setData((short) newData);
return newData;
}
/**
* Cycle the damage value of the block forward or backward
*
* @param increment 1 for forward, -1 for backward
* @return new data value
* @deprecated Use {@link BlockData#cycle(int, int, int)}
*/
@Deprecated
public int cycleData(int increment) {
int newData = BlockData.cycle(getType(), getData(), increment);
setData((short) newData);
return newData;
}
/**
* Flip this block.
*
* @return this block
* @deprecated Use {@link BlockData#flip(int, int)}
*/
@Deprecated
public BaseBlock flip() {
setData((short) BlockData.flip(getType(), getData()));
return this;
}
/**
* Flip this block.
*
* @param direction direction to flip in
* @return this block
* @deprecated Use {@link BlockData#flip(int, int, FlipDirection)}
*/
@Deprecated
public BaseBlock flip(FlipDirection direction) {
setData((short) BlockData.flip(getType(), getData(), direction));
return this;
}
/**
* Checks whether the type ID and data value are equal.
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof BaseBlock)) {
return false;
}
final BaseBlock otherBlock = (BaseBlock) o;
return getType() == otherBlock.getType() && getData() == otherBlock.getData();
}
/**
* Checks if the type is the same, and if data is the same if only data != -1.
*
* @param o other block
* @return true if equal
*/
public boolean equalsFuzzy(BaseBlock o) {
return (getType() == o.getType()) && (getData() == o.getData() || getData() == -1 || o.getData() == -1);
}
/**
* @deprecated This method is silly, use {@link #containsFuzzy(java.util.Collection, BaseBlock)} instead.
*/
@Deprecated
public boolean inIterable(Iterable<BaseBlock> iter) {
for (BaseBlock block : iter) {
if (block.equalsFuzzy(this)) {
return true;
}
}
return false;
}
/**
* @deprecated Use {@link Blocks#containsFuzzy(Collection, BaseBlock)}
*/
@Deprecated
public static boolean containsFuzzy(Collection<BaseBlock> collection, BaseBlock o) {
return Blocks.containsFuzzy(collection, o);
}
@Override
public int hashCode() {
int ret = getId() << 3;
if (getData() != (byte) -1) ret |= getData();
return ret;
}
@Override
public String toString() {
return "Block{ID:" + getId() + ", Data: " + getData() + "}";
}
}

View File

@ -0,0 +1,122 @@
/*
* 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;
/**
* Represents an item, without an amount value. See {@link BaseItemStack}
* for an instance with stack amount information.
*
* <p>This class may be removed in the future.</p>
*/
public class BaseItem {
private int id;
private short data;
private final Map<Integer, Integer> enchantments = new HashMap<Integer, Integer>();
/**
* Construct the object.
*
* @param id ID of the item
*/
public BaseItem(int id) {
this.id = id;
this.data = 0;
}
/**
* Construct the object.
*
* @param id ID of the item
* @param data data value of the item
*/
public BaseItem(int id, short data) {
this.id = id;
this.data = data;
}
/**
* Get the type of item.
*
* @return the id
*/
public int getType() {
return id;
}
/**
* Get the type of item.
*
* @param id the id to set
*/
public void setType(int id) {
this.id = id;
}
/**
* Get the damage value.
*
* @return the damage
*/
@Deprecated
public short getDamage() {
return data;
}
/**
* Get the data value.
*
* @return the data
*/
public short getData() {
return data;
}
/**
* Set the data value.
*
* @param data the damage to set
*/
@Deprecated
public void setDamage(short data) {
this.data = data;
}
/**
* Set the data value.
*
* @param data the damage to set
*/
public void setData(short data) {
this.data = data;
}
/**
* Get the map of enchantments.
*
* @return map of enchantments
*/
public Map<Integer, Integer> getEnchantments() {
return enchantments;
}
}

View File

@ -0,0 +1,80 @@
/*
* 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;
/**
* Represents a stack of BaseItems.
*
* <p>This class may be removed in the future.</p>
*/
public class BaseItemStack extends BaseItem {
private int amount = 1;
/**
* Construct the object with default stack size of one, with data value of 0.
*
* @param id with data value of 0.
*/
public BaseItemStack(int id) {
super(id);
}
/**
* Construct the object.
*
* @param id type ID
* @param amount amount in the stack
*/
public BaseItemStack(int id, int amount) {
super(id);
this.amount = amount;
}
/**
* Construct the object.
*
* @param id type ID
* @param amount amount in the stack
* @param data data value
*/
public BaseItemStack(int id, int amount, short data) {
super(id, data);
this.amount = amount;
}
/**
* Get the number of items in the stack.
*
* @return the amount
*/
public int getAmount() {
return amount;
}
/**
* Set the amount of items in the stack.
*
* @param amount the amount to set
*/
public void setAmount(int amount) {
this.amount = amount;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
/*
* 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;
/**
* List of block IDs.
*/
public final class BlockID {
public static final int AIR = 0;
public static final int STONE = 1;
public static final int GRASS = 2;
public static final int DIRT = 3;
public static final int COBBLESTONE = 4;
public static final int WOOD = 5; // PLANKS
public static final int SAPLING = 6;
public static final int BEDROCK = 7;
public static final int WATER = 8; // FLOWING_WATER
public static final int STATIONARY_WATER = 9; // WATER
public static final int LAVA = 10; // FLOWING_LAVA
public static final int STATIONARY_LAVA = 11; // LAVA
public static final int SAND = 12;
public static final int GRAVEL = 13;
public static final int GOLD_ORE = 14;
public static final int IRON_ORE = 15;
public static final int COAL_ORE = 16;
public static final int LOG = 17;
public static final int LEAVES = 18;
public static final int SPONGE = 19;
public static final int GLASS = 20;
public static final int LAPIS_LAZULI_ORE = 21; // LAPIS_ORE
public static final int LAPIS_LAZULI_BLOCK = 22; // LAPIS_BLOCK
public static final int DISPENSER = 23;
public static final int SANDSTONE = 24;
public static final int NOTE_BLOCK = 25; // NOTEBLOCK
public static final int BED = 26;
public static final int POWERED_RAIL = 27; // GOLDEN_RAIL
public static final int DETECTOR_RAIL = 28;
public static final int PISTON_STICKY_BASE = 29; // STICKY_PISTON
public static final int WEB = 30;
public static final int LONG_GRASS = 31; // TALLGRASS
public static final int DEAD_BUSH = 32; // DEADBUSH
public static final int PISTON_BASE = 33; // PISTON
public static final int PISTON_EXTENSION = 34; // PISTON_HEAD
public static final int CLOTH = 35; // WOOL
public static final int PISTON_MOVING_PIECE = 36; // PISTON_EXTENSION
public static final int YELLOW_FLOWER = 37;
public static final int RED_FLOWER = 38;
public static final int BROWN_MUSHROOM = 39;
public static final int RED_MUSHROOM = 40;
public static final int GOLD_BLOCK = 41;
public static final int IRON_BLOCK = 42;
public static final int DOUBLE_STEP = 43; // DOUBLE_STONE_SLAB
public static final int STEP = 44; // STONE_SLAB
public static final int BRICK = 45; // BRICK_BLOCK
public static final int TNT = 46;
public static final int BOOKCASE = 47; // BOOKSHELF
public static final int MOSSY_COBBLESTONE = 48;
public static final int OBSIDIAN = 49;
public static final int TORCH = 50;
public static final int FIRE = 51;
public static final int MOB_SPAWNER = 52;
@Deprecated
public static final int WOODEN_STAIRS = 53;
public static final int OAK_WOOD_STAIRS = 53; // OAK_STAIRS
public static final int CHEST = 54;
public static final int REDSTONE_WIRE = 55;
public static final int DIAMOND_ORE = 56;
public static final int DIAMOND_BLOCK = 57;
public static final int WORKBENCH = 58; // CRAFTING_TABLE
public static final int CROPS = 59; // WHEAT
public static final int SOIL = 60; // FARMLAND
public static final int FURNACE = 61;
public static final int BURNING_FURNACE = 62; // LIT_FURNACE
public static final int SIGN_POST = 63; // STANDING_SIGN
public static final int WOODEN_DOOR = 64; // WOODEN_DOOR
public static final int LADDER = 65;
public static final int MINECART_TRACKS = 66; // RAIL
public static final int COBBLESTONE_STAIRS = 67; // STONE_STAIRS
public static final int WALL_SIGN = 68;
public static final int LEVER = 69;
public static final int STONE_PRESSURE_PLATE = 70;
public static final int IRON_DOOR = 71;
public static final int WOODEN_PRESSURE_PLATE = 72;
public static final int REDSTONE_ORE = 73; // LIT_REDSTONE_ORE
public static final int GLOWING_REDSTONE_ORE = 74; // UNLIT_REDSTONE_ORE
public static final int REDSTONE_TORCH_OFF = 75; // UNLIT_REDSTONE_TORCH
public static final int REDSTONE_TORCH_ON = 76; // LIT_REDSTONE_TORCH
public static final int STONE_BUTTON = 77;
public static final int SNOW = 78; // SNOW_LAYER
public static final int ICE = 79;
public static final int SNOW_BLOCK = 80; // SNOW
public static final int CACTUS = 81;
public static final int CLAY = 82;
public static final int REED = 83; // REEDS
public static final int JUKEBOX = 84;
public static final int FENCE = 85;
public static final int PUMPKIN = 86;
@Deprecated
public static final int NETHERSTONE = 87;
public static final int NETHERRACK = 87;
public static final int SLOW_SAND = 88; // SOUL_SAND
public static final int LIGHTSTONE = 89; // GLOWSTONE
public static final int PORTAL = 90;
public static final int JACKOLANTERN = 91; // LIT_PUMPKIN
public static final int CAKE_BLOCK = 92; // CAKE
public static final int REDSTONE_REPEATER_OFF = 93; // UNPOWERED_REPEATER
public static final int REDSTONE_REPEATER_ON = 94; // POWERED_REPEATER
@Deprecated
public static final int LOCKED_CHEST = 95;
public static final int STAINED_GLASS = 95;
public static final int TRAP_DOOR = 96; // TRAPDOOR
public static final int SILVERFISH_BLOCK = 97; // MONSTER_EGG
public static final int STONE_BRICK = 98; // STONEBRICK
public static final int BROWN_MUSHROOM_CAP = 99; // BROWN_MUSHROOM_BLOCK
public static final int RED_MUSHROOM_CAP = 100; // RED_MUSHROOM_BLOCK
public static final int IRON_BARS = 101;
public static final int GLASS_PANE = 102;
public static final int MELON_BLOCK = 103;
public static final int PUMPKIN_STEM = 104;
public static final int MELON_STEM = 105;
public static final int VINE = 106;
public static final int FENCE_GATE = 107;
public static final int BRICK_STAIRS = 108;
public static final int STONE_BRICK_STAIRS = 109;
public static final int MYCELIUM = 110;
public static final int LILY_PAD = 111; // WATERLILY
public static final int NETHER_BRICK = 112;
public static final int NETHER_BRICK_FENCE = 113;
public static final int NETHER_BRICK_STAIRS = 114;
public static final int NETHER_WART = 115;
public static final int ENCHANTMENT_TABLE = 116; // ENCHANTING_TABLE
public static final int BREWING_STAND = 117;
public static final int CAULDRON = 118;
public static final int END_PORTAL = 119;
public static final int END_PORTAL_FRAME = 120;
public static final int END_STONE = 121;
public static final int DRAGON_EGG = 122;
public static final int REDSTONE_LAMP_OFF = 123; // REDSTONE_LAMP
public static final int REDSTONE_LAMP_ON = 124; // LIT_REDSTONE_LAMP
public static final int DOUBLE_WOODEN_STEP = 125; // DOUBLE_WOODEN_SLAB
public static final int WOODEN_STEP = 126; // WOODEN_SLAB
public static final int COCOA_PLANT = 127; // COCOA
public static final int SANDSTONE_STAIRS = 128;
public static final int EMERALD_ORE = 129;
public static final int ENDER_CHEST = 130;
public static final int TRIPWIRE_HOOK = 131;
public static final int TRIPWIRE = 132;
public static final int EMERALD_BLOCK = 133;
public static final int SPRUCE_WOOD_STAIRS = 134; // SPRUCE_STAIRS
public static final int BIRCH_WOOD_STAIRS = 135; // BRUCE_STAIRS
public static final int JUNGLE_WOOD_STAIRS = 136; // JUNGLE_STAIRS
public static final int COMMAND_BLOCK = 137;
public static final int BEACON = 138;
public static final int COBBLESTONE_WALL = 139;
public static final int FLOWER_POT = 140;
public static final int CARROTS = 141;
public static final int POTATOES = 142;
public static final int WOODEN_BUTTON = 143;
public static final int HEAD = 144; // SKULL
public static final int ANVIL = 145;
public static final int TRAPPED_CHEST = 146;
public static final int PRESSURE_PLATE_LIGHT = 147; // LIGHT_WEIGHTED_PRESSURE_PLATE
public static final int PRESSURE_PLATE_HEAVY = 148; // HEAVY_WEIGHTED_PRESSURE_PLATE
public static final int COMPARATOR_OFF = 149; // UNPOWERED_COMPARATOR
public static final int COMPARATOR_ON = 150; // COMPARATOR
public static final int DAYLIGHT_SENSOR = 151; // DAYLIGHT_DETECTOR
public static final int REDSTONE_BLOCK = 152;
public static final int QUARTZ_ORE = 153;
public static final int HOPPER = 154;
public static final int QUARTZ_BLOCK = 155;
public static final int QUARTZ_STAIRS = 156;
public static final int ACTIVATOR_RAIL = 157;
public static final int DROPPER = 158;
public static final int STAINED_CLAY = 159; // STAINED_HARDENED_CLAY
public static final int STAINED_GLASS_PANE = 160;
public static final int LEAVES2 = 161;
public static final int LOG2 = 162;
public static final int ACACIA_STAIRS = 163;
public static final int DARK_OAK_STAIRS = 164;
public static final int HAY_BLOCK = 170;
public static final int CARPET = 171;
public static final int HARDENED_CLAY = 172;
public static final int COAL_BLOCK = 173;
public static final int PACKED_ICE = 174;
public static final int DOUBLE_PLANT = 175;
private BlockID() {
}
}

View File

@ -0,0 +1,183 @@
/*
* 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 {
/**
* Get whether this block is rendered like a normal block.
*
* @return the value of the test
*/
boolean isRenderedAsNormalBlock();
/**
* Get whether this block is a full sized cube.
*
* @return the value of the test
*/
boolean isFullCube();
/**
* Get whether this block is opaque.
*
* @return the value of the test
*/
boolean isOpaque();
/**
* Get whether this block emits a Redstone signal.
*
* @return the value of the test
*/
boolean isPowerSource();
/**
* Get whether this block is a liquid.
*
* @return the value of the test
*/
boolean isLiquid();
/**
* Get whether this block is a solid.
*
* @return the value of the test
*/
boolean isSolid();
/**
* Get the hardness factor for this block.
*
* @return the hardness factor
*/
float getHardness();
/**
* Get the resistance factor for this block.
*
* @return the resistance factor
*/
float getResistance();
/**
* Get the slipperiness factor for this block.
*
* @return the slipperiness factor
*/
float getSlipperiness();
/**
* Get whether this block blocks grass from growing.
*
* @return whether this block blocks grass
*/
boolean isGrassBlocking();
/**
* Get the ambient occlusion light value.
*
* @return the ambient occlusion light value
*/
float getAmbientOcclusionLightValue();
/**
* Get the opacity of this block for light to pass through.
*
* @return the opacity
*/
int getLightOpacity();
/**
* Get the light value for this block.
*
* @return the light value
*/
int getLightValue();
/**
* Get whether this block breaks when it is pushed by a piston.
*
* @return true if the block breaks
*/
boolean isFragileWhenPushed();
/**
* Get whether this block can be pushed by a piston.
*
* @return true if the block cannot be pushed
*/
boolean isUnpushable();
/**
* Get whether this block can be used in adventure mode.
*
* @return true if the block can be used in adventure mode
*/
boolean isAdventureModeExempt();
/**
* Get whether this block is ticked randomly.
*
* @return true if this block is ticked randomly
*/
boolean isTicksRandomly();
/**
* Gets whether this block uses a neighbor's light value.
*
* @return true if this block does
*/
boolean isUsingNeighborLight();
/**
* Get whether this block prevents movement.
*
* @return true if this block blocks movement
*/
boolean isMovementBlocker();
/**
* Get whether this block will burn.
*
* @return true if this block will burn
*/
boolean isBurnable();
/**
* Get whether this block needs to be broken by a tool for maximum
* speed.
*
* @return true if a tool is required
*/
boolean isToolRequired();
/**
* Get whether this block is replaced when a block is placed over it
* (for example, tall grass).
*
* @return true if the block is replaced
*/
boolean isReplacedDuringPlacement();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/*
* 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.Collection;
/**
* Block-related utility methods.
*/
public final class Blocks {
private Blocks() {
}
/**
* Checks whether a given block is in a list of base blocks.
*
* @param collection the collection
* @param o the block
* @return true if the collection contains the given block
*/
public static boolean containsFuzzy(Collection<? extends BaseBlock> collection, BaseBlock o) {
// Allow masked data in the searchBlocks to match various types
for (BaseBlock b : collection) {
if (b.equalsFuzzy(o)) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,162 @@
/*
* 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 javax.annotation.Nullable;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumSet;
/**
* The colors for wool.
*
* <p>This class may be removed in the future.</p>
*/
public enum ClothColor {
WHITE(ID.WHITE, "White", "white"),
ORANGE(ID.ORANGE, "Orange", "orange"),
MAGENTA(ID.MAGENTA, "Magenta", "magenta"),
LIGHT_BLUE(ID.LIGHT_BLUE, "Light blue", "lightblue"),
YELLOW(ID.YELLOW, "Yellow", "yellow"),
LIGHT_GREEN(ID.LIGHT_GREEN, "Light green", "lightgreen"),
PINK(ID.PINK, "Pink", new String[] { "pink", "lightred" }),
GRAY(ID.GRAY, "Gray", new String[] { "grey", "gray" }),
LIGHT_GRAY(ID.LIGHT_GRAY, "Light gray", new String[] { "lightgrey", "lightgray" }),
CYAN(ID.CYAN, "Cyan", new String[] { "cyan", "turquoise" }),
PURPLE(ID.PURPLE, "Purple", new String[] { "purple", "violet" }),
BLUE(ID.BLUE, "Blue", "blue"),
BROWN(ID.BROWN, "Brown", new String[] { "brown", "cocoa", "coffee" }),
DARK_GREEN(ID.DARK_GREEN, "Dark green", new String[] { "green", "darkgreen", "cactusgreen", "cactigreen" }),
RED(ID.RED, "Red", "red"),
BLACK(ID.BLACK, "Black", "black");
public static final class ID {
public static final int WHITE = 0;
public static final int ORANGE = 1;
public static final int MAGENTA = 2;
public static final int LIGHT_BLUE = 3;
public static final int YELLOW = 4;
public static final int LIGHT_GREEN = 5;
public static final int PINK = 6;
public static final int GRAY = 7;
public static final int LIGHT_GRAY = 8;
public static final int CYAN = 9;
public static final int PURPLE = 10;
public static final int BLUE = 11;
public static final int BROWN = 12;
public static final int DARK_GREEN = 13;
public static final int RED = 14;
public static final int BLACK = 15;
private ID() {
}
}
/**
* Stores a map of the IDs for fast access.
*/
private static final Map<Integer, ClothColor> ids = new HashMap<Integer, ClothColor>();
/**
* Stores a map of the names for fast access.
*/
private static final Map<String, ClothColor> lookup = new HashMap<String, ClothColor>();
private final int id;
private final String name;
private final String[] lookupKeys;
static {
for (ClothColor type : EnumSet.allOf(ClothColor.class)) {
ids.put(type.id, type);
for (String key : type.lookupKeys) {
lookup.put(key, type);
}
}
}
/**
* Construct the type.
*
* @param id the ID of the color
* @param name the name of the color
* @param lookupKey a name to refer to the color by
*/
ClothColor(int id, String name, String lookupKey) {
this.id = id;
this.name = name;
this.lookupKeys = new String[] { lookupKey };
}
/**
* Construct the type.
*
* @param id the ID of the color
* @param name the name of the color
* @param lookupKeys an array of lookup keys
*/
ClothColor(int id, String name, String[] lookupKeys) {
this.id = id;
this.name = name;
this.lookupKeys = lookupKeys;
}
/**
* Return type from ID. May return null.
*
* @param id the ID
* @return a color or null
*/
@Nullable
public static ClothColor fromID(int id) {
return ids.get(id);
}
/**
* Return type from name. May return null.
*
* @param name the name of the color
* @return a color or null
*/
@Nullable
public static ClothColor lookup(String name) {
return lookup.get(name.toLowerCase());
}
/**
* Get item numeric ID.
*
* @return the ID
*/
public int getID() {
return id;
}
/**
* Get user-friendly item name.
*
* @return the name
*/
public String getName() {
return name;
}
}

View File

@ -0,0 +1,205 @@
/*
* 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;
/**
* List of item IDs.
*/
public final class ItemID {
public static final int IRON_SHOVEL = 256;
public static final int IRON_PICK = 257;
public static final int IRON_AXE = 258;
public static final int FLINT_AND_TINDER = 259;
public static final int RED_APPLE = 260;
public static final int BOW = 261;
public static final int ARROW = 262;
public static final int COAL = 263;
public static final int DIAMOND = 264;
public static final int IRON_BAR = 265;
public static final int GOLD_BAR = 266;
public static final int IRON_SWORD = 267;
public static final int WOOD_SWORD = 268;
public static final int WOOD_SHOVEL = 269;
public static final int WOOD_PICKAXE = 270;
public static final int WOOD_AXE = 271;
public static final int STONE_SWORD = 272;
public static final int STONE_SHOVEL = 273;
public static final int STONE_PICKAXE = 274;
public static final int STONE_AXE = 275;
public static final int DIAMOND_SWORD = 276;
public static final int DIAMOND_SHOVEL = 277;
public static final int DIAMOND_PICKAXE = 278;
public static final int DIAMOND_AXE = 279;
public static final int STICK = 280;
public static final int BOWL = 281;
public static final int MUSHROOM_SOUP = 282;
public static final int GOLD_SWORD = 283;
public static final int GOLD_SHOVEL = 284;
public static final int GOLD_PICKAXE = 285;
public static final int GOLD_AXE = 286;
public static final int STRING = 287;
public static final int FEATHER = 288;
public static final int SULPHUR = 289;
public static final int WOOD_HOE = 290;
public static final int STONE_HOE = 291;
public static final int IRON_HOE = 292;
public static final int DIAMOND_HOE = 293;
public static final int GOLD_HOE = 294;
public static final int SEEDS = 295;
public static final int WHEAT = 296;
public static final int BREAD = 297;
public static final int LEATHER_HELMET = 298;
public static final int LEATHER_CHEST = 299;
public static final int LEATHER_PANTS = 300;
public static final int LEATHER_BOOTS = 301;
public static final int CHAINMAIL_HELMET = 302;
public static final int CHAINMAIL_CHEST = 303;
public static final int CHAINMAIL_PANTS = 304;
public static final int CHAINMAIL_BOOTS = 305;
public static final int IRON_HELMET = 306;
public static final int IRON_CHEST = 307;
public static final int IRON_PANTS = 308;
public static final int IRON_BOOTS = 309;
public static final int DIAMOND_HELMET = 310;
public static final int DIAMOND_CHEST = 311;
public static final int DIAMOND_PANTS = 312;
public static final int DIAMOND_BOOTS = 313;
public static final int GOLD_HELMET = 314;
public static final int GOLD_CHEST = 315;
public static final int GOLD_PANTS = 316;
public static final int GOLD_BOOTS = 317;
public static final int FLINT = 318;
public static final int RAW_PORKCHOP = 319;
public static final int COOKED_PORKCHOP = 320;
public static final int PAINTING = 321;
public static final int GOLD_APPLE = 322;
public static final int SIGN = 323;
public static final int WOODEN_DOOR_ITEM = 324;
public static final int BUCKET = 325;
public static final int WATER_BUCKET = 326;
public static final int LAVA_BUCKET = 327;
public static final int MINECART = 328;
public static final int SADDLE = 329;
public static final int IRON_DOOR_ITEM = 330;
public static final int REDSTONE_DUST = 331;
public static final int SNOWBALL = 332;
public static final int WOOD_BOAT = 333;
public static final int LEATHER = 334;
public static final int MILK_BUCKET = 335;
public static final int BRICK_BAR = 336;
public static final int CLAY_BALL = 337;
public static final int SUGAR_CANE_ITEM = 338;
public static final int PAPER = 339;
public static final int BOOK = 340;
public static final int SLIME_BALL = 341;
public static final int STORAGE_MINECART = 342;
public static final int POWERED_MINECART = 343;
public static final int EGG = 344;
public static final int COMPASS = 345;
public static final int FISHING_ROD = 346;
public static final int WATCH = 347;
public static final int LIGHTSTONE_DUST = 348;
public static final int RAW_FISH = 349;
public static final int COOKED_FISH = 350;
public static final int INK_SACK = 351;
public static final int BONE = 352;
public static final int SUGAR = 353;
public static final int CAKE_ITEM = 354;
public static final int BED_ITEM = 355;
public static final int REDSTONE_REPEATER = 356;
public static final int COOKIE = 357;
public static final int MAP = 358;
public static final int SHEARS = 359;
public static final int MELON = 360;
public static final int PUMPKIN_SEEDS = 361;
public static final int MELON_SEEDS = 362;
public static final int RAW_BEEF = 363;
public static final int COOKED_BEEF = 364;
public static final int RAW_CHICKEN = 365;
public static final int COOKED_CHICKEN = 366;
public static final int ROTTEN_FLESH = 367;
public static final int ENDER_PEARL = 368;
public static final int BLAZE_ROD = 369;
public static final int GHAST_TEAR = 370;
public static final int GOLD_NUGGET = 371;
public static final int NETHER_WART_SEED = 372;
public static final int POTION = 373;
public static final int GLASS_BOTTLE = 374;
public static final int SPIDER_EYE = 375;
public static final int FERMENTED_SPIDER_EYE = 376;
public static final int BLAZE_POWDER = 377;
public static final int MAGMA_CREAM = 378;
public static final int BREWING_STAND = 379;
public static final int CAULDRON = 380;
public static final int EYE_OF_ENDER = 381;
public static final int GLISTERING_MELON = 382;
public static final int SPAWN_EGG = 383;
public static final int BOTTLE_O_ENCHANTING = 384;
public static final int FIRE_CHARGE = 385;
public static final int BOOK_AND_QUILL = 386;
public static final int WRITTEN_BOOK = 387;
public static final int EMERALD = 388;
public static final int ITEM_FRAME = 389;
public static final int FLOWER_POT = 390;
public static final int CARROT = 391;
public static final int POTATO = 392;
public static final int BAKED_POTATO = 393;
public static final int POISONOUS_POTATO = 394;
public static final int BLANK_MAP = 395;
public static final int GOLDEN_CARROT = 396;
public static final int HEAD = 397;
public static final int CARROT_ON_A_STICK = 398;
public static final int NETHER_STAR = 399;
public static final int PUMPKIN_PIE = 400;
public static final int FIREWORK_ROCKET = 401;
public static final int FIREWORK_STAR = 402;
public static final int ENCHANTED_BOOK = 403;
public static final int COMPARATOR = 404;
public static final int NETHER_BRICK = 405;
public static final int NETHER_QUARTZ = 406;
public static final int TNT_MINECART = 407;
public static final int HOPPER_MINECART = 408;
public static final int HORSE_ARMOR_IRON = 417;
public static final int HORSE_ARMOR_GOLD = 418;
public static final int HORSE_ARMOR_DIAMOND = 419;
public static final int LEAD = 420;
public static final int NAME_TAG = 421;
public static final int COMMAND_BLOCK_MINECART = 422;
@Deprecated public static final int GOLD_RECORD = 2256; // deprecated, but leave it there
@Deprecated public static final int GREEN_RECORD = 2257; // deprecated, but leave it there
public static final int DISC_13 = 2256;
public static final int DISC_CAT = 2257;
public static final int DISC_BLOCKS = 2258;
public static final int DISC_CHIRP = 2259;
public static final int DISC_FAR = 2260;
public static final int DISC_MALL = 2261;
public static final int DISC_MELLOHI = 2262;
public static final int DISC_STAL = 2263;
public static final int DISC_STRAD = 2264;
public static final int DISC_WARD = 2265;
public static final int DISC_11 = 2266;
public static final int DISC_WAIT = 2267;
private ItemID() {
}
}

View File

@ -0,0 +1,687 @@
/*
* 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.util.StringUtil;
import javax.annotation.Nullable;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* An enum of types of items.
*/
public enum ItemType {
// Blocks
AIR(BlockID.AIR, "Air", "air"),
STONE(BlockID.STONE, "Stone", "stone", "rock"),
GRASS(BlockID.GRASS, "Grass", "grass"),
DIRT(BlockID.DIRT, "Dirt", "dirt"),
COBBLESTONE(BlockID.COBBLESTONE, "Cobblestone", "cobblestone", "cobble"),
WOOD(BlockID.WOOD, "Wood", "wood", "woodplank", "plank", "woodplanks", "planks"),
SAPLING(BlockID.SAPLING, "Sapling", "sapling", "seedling"),
BEDROCK(BlockID.BEDROCK, "Bedrock", "adminium", "bedrock"),
WATER(BlockID.WATER, "Water", "watermoving", "movingwater", "flowingwater", "waterflowing"),
STATIONARY_WATER(BlockID.STATIONARY_WATER, "Water (stationary)", "water", "waterstationary", "stationarywater", "stillwater"),
LAVA(BlockID.LAVA, "Lava", "lavamoving", "movinglava", "flowinglava", "lavaflowing"),
STATIONARY_LAVA(BlockID.STATIONARY_LAVA, "Lava (stationary)", "lava", "lavastationary", "stationarylava", "stilllava"),
SAND(BlockID.SAND, "Sand", "sand"),
GRAVEL(BlockID.GRAVEL, "Gravel", "gravel"),
GOLD_ORE(BlockID.GOLD_ORE, "Gold ore", "goldore"),
IRON_ORE(BlockID.IRON_ORE, "Iron ore", "ironore"),
COAL_ORE(BlockID.COAL_ORE, "Coal ore", "coalore"),
LOG(BlockID.LOG, "Log", "log", "tree", "pine", "oak", "birch", "redwood"),
LEAVES(BlockID.LEAVES, "Leaves", "leaves", "leaf"),
SPONGE(BlockID.SPONGE, "Sponge", "sponge"),
GLASS(BlockID.GLASS, "Glass", "glass"),
LAPIS_LAZULI_ORE(BlockID.LAPIS_LAZULI_ORE, "Lapis lazuli ore", "lapislazuliore", "blueore", "lapisore"),
LAPIS_LAZULI(BlockID.LAPIS_LAZULI_BLOCK, "Lapis lazuli", "lapislazuli", "lapislazuliblock", "bluerock"),
DISPENSER(BlockID.DISPENSER, "Dispenser", "dispenser"),
SANDSTONE(BlockID.SANDSTONE, "Sandstone", "sandstone"),
NOTE_BLOCK(BlockID.NOTE_BLOCK, "Note block", "musicblock", "noteblock", "note", "music", "instrument"),
BED(BlockID.BED, "Bed", "bed"),
POWERED_RAIL(BlockID.POWERED_RAIL, "Powered Rail", "poweredrail", "boosterrail", "poweredtrack", "boostertrack", "booster"),
DETECTOR_RAIL(BlockID.DETECTOR_RAIL, "Detector Rail", "detectorrail", "detector"),
PISTON_STICKY_BASE(BlockID.PISTON_STICKY_BASE, "Sticky Piston", "stickypiston"),
WEB(BlockID.WEB, "Web", "web", "spiderweb"),
LONG_GRASS(BlockID.LONG_GRASS, "Long grass", "longgrass", "tallgrass"),
DEAD_BUSH(BlockID.DEAD_BUSH, "Shrub", "deadbush", "shrub", "deadshrub", "tumbleweed"),
PISTON_BASE(BlockID.PISTON_BASE, "Piston", "piston"),
PISTON_EXTENSION(BlockID.PISTON_EXTENSION, "Piston extension", "pistonextendsion", "pistonhead"),
CLOTH(BlockID.CLOTH, "Wool", "cloth", "wool"),
PISTON_MOVING_PIECE(BlockID.PISTON_MOVING_PIECE, "Piston moving piece", "movingpiston"),
YELLOW_FLOWER(BlockID.YELLOW_FLOWER, "Yellow flower", "yellowflower", "flower"),
RED_FLOWER(BlockID.RED_FLOWER, "Red rose", "redflower", "redrose", "rose"),
BROWN_MUSHROOM(BlockID.BROWN_MUSHROOM, "Brown mushroom", "brownmushroom", "mushroom"),
RED_MUSHROOM(BlockID.RED_MUSHROOM, "Red mushroom", "redmushroom"),
GOLD_BLOCK(BlockID.GOLD_BLOCK, "Gold block", "gold", "goldblock"),
IRON_BLOCK(BlockID.IRON_BLOCK, "Iron block", "iron", "ironblock"),
DOUBLE_STEP(BlockID.DOUBLE_STEP, "Double step", "doubleslab", "doublestoneslab", "doublestep"),
STEP(BlockID.STEP, "Step", "slab", "stoneslab", "step", "halfstep"),
BRICK(BlockID.BRICK, "Brick", "brick", "brickblock"),
TNT(BlockID.TNT, "TNT", "tnt", "c4", "explosive"),
BOOKCASE(BlockID.BOOKCASE, "Bookcase", "bookshelf", "bookshelves", "bookcase", "bookcases"),
MOSSY_COBBLESTONE(BlockID.MOSSY_COBBLESTONE, "Cobblestone (mossy)", "mossycobblestone", "mossstone", "mossystone", "mosscobble", "mossycobble", "moss", "mossy", "sossymobblecone"),
OBSIDIAN(BlockID.OBSIDIAN, "Obsidian", "obsidian"),
TORCH(BlockID.TORCH, "Torch", "torch", "light", "candle"),
FIRE(BlockID.FIRE, "Fire", "fire", "flame", "flames"),
MOB_SPAWNER(BlockID.MOB_SPAWNER, "Mob spawner", "mobspawner", "spawner"),
WOODEN_STAIRS(BlockID.OAK_WOOD_STAIRS, "Wooden stairs", "woodstair", "woodstairs", "woodenstair", "woodenstairs"),
CHEST(BlockID.CHEST, "Chest", "chest", "storage", "storagechest"),
REDSTONE_WIRE(BlockID.REDSTONE_WIRE, "Redstone wire", "redstone", "redstoneblock"),
DIAMOND_ORE(BlockID.DIAMOND_ORE, "Diamond ore", "diamondore"),
DIAMOND_BLOCK(BlockID.DIAMOND_BLOCK, "Diamond block", "diamond", "diamondblock"),
WORKBENCH(BlockID.WORKBENCH, "Workbench", "workbench", "table", "craftingtable", "crafting"),
CROPS(BlockID.CROPS, "Crops", "crops", "crop", "plant", "plants"),
SOIL(BlockID.SOIL, "Soil", "soil", "farmland"),
FURNACE(BlockID.FURNACE, "Furnace", "furnace"),
BURNING_FURNACE(BlockID.BURNING_FURNACE, "Furnace (burning)", "burningfurnace", "litfurnace"),
SIGN_POST(BlockID.SIGN_POST, "Sign post", "sign", "signpost"),
WOODEN_DOOR(BlockID.WOODEN_DOOR, "Wooden door", "wooddoor", "woodendoor", "door"),
LADDER(BlockID.LADDER, "Ladder", "ladder"),
MINECART_TRACKS(BlockID.MINECART_TRACKS, "Minecart tracks", "track", "tracks", "minecrattrack", "minecarttracks", "rails", "rail"),
COBBLESTONE_STAIRS(BlockID.COBBLESTONE_STAIRS, "Cobblestone stairs", "cobblestonestair", "cobblestonestairs", "cobblestair", "cobblestairs"),
WALL_SIGN(BlockID.WALL_SIGN, "Wall sign", "wallsign"),
LEVER(BlockID.LEVER, "Lever", "lever", "switch", "stonelever", "stoneswitch"),
STONE_PRESSURE_PLATE(BlockID.STONE_PRESSURE_PLATE, "Stone pressure plate", "stonepressureplate", "stoneplate"),
IRON_DOOR(BlockID.IRON_DOOR, "Iron Door", "irondoor"),
WOODEN_PRESSURE_PLATE(BlockID.WOODEN_PRESSURE_PLATE, "Wooden pressure plate", "woodpressureplate", "woodplate", "woodenpressureplate", "woodenplate", "plate", "pressureplate"),
REDSTONE_ORE(BlockID.REDSTONE_ORE, "Redstone ore", "redstoneore"),
GLOWING_REDSTONE_ORE(BlockID.GLOWING_REDSTONE_ORE, "Glowing redstone ore", "glowingredstoneore"),
REDSTONE_TORCH_OFF(BlockID.REDSTONE_TORCH_OFF, "Redstone torch (off)", "redstonetorchoff", "rstorchoff"),
REDSTONE_TORCH_ON(BlockID.REDSTONE_TORCH_ON, "Redstone torch (on)", "redstonetorch", "redstonetorchon", "rstorchon", "redtorch"),
STONE_BUTTON(BlockID.STONE_BUTTON, "Stone Button", "stonebutton", "button"),
SNOW(BlockID.SNOW, "Snow", "snow"),
ICE(BlockID.ICE, "Ice", "ice"),
SNOW_BLOCK(BlockID.SNOW_BLOCK, "Snow block", "snowblock"),
CACTUS(BlockID.CACTUS, "Cactus", "cactus", "cacti"),
CLAY(BlockID.CLAY, "Clay", "clay"),
SUGAR_CANE(BlockID.REED, "Reed", "reed", "cane", "sugarcane", "sugarcanes", "vine", "vines"),
JUKEBOX(BlockID.JUKEBOX, "Jukebox", "jukebox", "stereo", "recordplayer"),
FENCE(BlockID.FENCE, "Fence", "fence"),
PUMPKIN(BlockID.PUMPKIN, "Pumpkin", "pumpkin"),
NETHERRACK(BlockID.NETHERRACK, "Netherrack", "redmossycobblestone", "redcobblestone", "redmosstone", "redcobble", "netherstone", "netherrack", "nether", "hellstone"),
SOUL_SAND(BlockID.SLOW_SAND, "Soul sand", "slowmud", "mud", "soulsand", "hellmud"),
GLOWSTONE(BlockID.LIGHTSTONE, "Glowstone", "brittlegold", "glowstone", "lightstone", "brimstone", "australium"),
PORTAL(BlockID.PORTAL, "Portal", "portal"),
JACK_O_LANTERN(BlockID.JACKOLANTERN, "Pumpkin (on)", "pumpkinlighted", "pumpkinon", "litpumpkin", "jackolantern"),
CAKE(BlockID.CAKE_BLOCK, "Cake", "cake", "cakeblock"),
REDSTONE_REPEATER_OFF(BlockID.REDSTONE_REPEATER_OFF, "Redstone repeater (off)", "diodeoff", "redstonerepeater", "repeateroff", "delayeroff"),
REDSTONE_REPEATER_ON(BlockID.REDSTONE_REPEATER_ON, "Redstone repeater (on)", "diodeon", "redstonerepeateron", "repeateron", "delayeron"),
@Deprecated LOCKED_CHEST(BlockID.LOCKED_CHEST, "thisblockisinvalidusedstainedglassinstead"),
STAINED_GLASS(BlockID.STAINED_GLASS, "Stained Glass", "stainedglass"),
TRAP_DOOR(BlockID.TRAP_DOOR, "Trap door", "trapdoor", "hatch", "floordoor"),
SILVERFISH_BLOCK(BlockID.SILVERFISH_BLOCK, "Silverfish block", "silverfish", "silver"),
STONE_BRICK(BlockID.STONE_BRICK, "Stone brick", "stonebrick", "sbrick", "smoothstonebrick"),
RED_MUSHROOM_CAP(BlockID.RED_MUSHROOM_CAP, "Red mushroom cap", "giantmushroomred", "redgiantmushroom", "redmushroomcap"),
BROWN_MUSHROOM_CAP(BlockID.BROWN_MUSHROOM_CAP, "Brown mushroom cap", "giantmushroombrown", "browngiantmushoom", "brownmushroomcap"),
IRON_BARS(BlockID.IRON_BARS, "Iron bars", "ironbars", "ironfence"),
GLASS_PANE(BlockID.GLASS_PANE, "Glass pane", "window", "glasspane", "glasswindow"),
MELON_BLOCK(BlockID.MELON_BLOCK, "Melon (block)", "melonblock"),
PUMPKIN_STEM(BlockID.PUMPKIN_STEM, "Pumpkin stem", "pumpkinstem"),
MELON_STEM(BlockID.MELON_STEM, "Melon stem", "melonstem"),
VINE(BlockID.VINE, "Vine", "vine", "vines", "creepers"),
FENCE_GATE(BlockID.FENCE_GATE, "Fence gate", "fencegate", "gate"),
BRICK_STAIRS(BlockID.BRICK_STAIRS, "Brick stairs", "brickstairs", "bricksteps"),
STONE_BRICK_STAIRS(BlockID.STONE_BRICK_STAIRS, "Stone brick stairs", "stonebrickstairs", "smoothstonebrickstairs"),
MYCELIUM(BlockID.MYCELIUM, "Mycelium", "mycelium", "fungus", "mycel"),
LILY_PAD(BlockID.LILY_PAD, "Lily pad", "lilypad", "waterlily"),
NETHER_BRICK(BlockID.NETHER_BRICK, "Nether brick", "netherbrick"),
NETHER_BRICK_FENCE(BlockID.NETHER_BRICK_FENCE, "Nether brick fence", "netherbrickfence", "netherfence"),
NETHER_BRICK_STAIRS(BlockID.NETHER_BRICK_STAIRS, "Nether brick stairs", "netherbrickstairs", "netherbricksteps", "netherstairs", "nethersteps"),
NETHER_WART(BlockID.NETHER_WART, "Nether wart", "netherwart", "netherstalk"),
ENCHANTMENT_TABLE(BlockID.ENCHANTMENT_TABLE, "Enchantment table", "enchantmenttable", "enchanttable"),
BREWING_STAND(BlockID.BREWING_STAND, "Brewing Stand", "brewingstand"),
CAULDRON(BlockID.CAULDRON, "Cauldron"),
END_PORTAL(BlockID.END_PORTAL, "End Portal", "endportal", "blackstuff", "airportal", "weirdblackstuff"),
END_PORTAL_FRAME(BlockID.END_PORTAL_FRAME, "End Portal Frame", "endportalframe", "airportalframe", "crystalblock"),
END_STONE(BlockID.END_STONE, "End Stone", "endstone", "enderstone", "endersand"),
DRAGON_EGG(BlockID.DRAGON_EGG, "Dragon Egg", "dragonegg", "dragons"),
REDSTONE_LAMP_OFF(BlockID.REDSTONE_LAMP_OFF, "Redstone lamp (off)", "redstonelamp", "redstonelampoff", "rslamp", "rslampoff", "rsglow", "rsglowoff"),
REDSTONE_LAMP_ON(BlockID.REDSTONE_LAMP_ON, "Redstone lamp (on)", "redstonelampon", "rslampon", "rsglowon"),
DOUBLE_WOODEN_STEP(BlockID.DOUBLE_WOODEN_STEP, "Double wood step", "doublewoodslab", "doublewoodstep"),
WOODEN_STEP(BlockID.WOODEN_STEP, "Wood step", "woodenslab", "woodslab", "woodstep", "woodhalfstep"),
COCOA_PLANT(BlockID.COCOA_PLANT, "Cocoa plant", "cocoplant", "cocoaplant"),
SANDSTONE_STAIRS(BlockID.SANDSTONE_STAIRS, "Sandstone stairs", "sandstairs", "sandstonestairs"),
EMERALD_ORE(BlockID.EMERALD_ORE, "Emerald ore", "emeraldore"),
ENDER_CHEST(BlockID.ENDER_CHEST, "Ender chest", "enderchest"),
TRIPWIRE_HOOK(BlockID.TRIPWIRE_HOOK, "Tripwire hook", "tripwirehook"),
TRIPWIRE(BlockID.TRIPWIRE, "Tripwire", "tripwire", "string"),
EMERALD_BLOCK(BlockID.EMERALD_BLOCK, "Emerald block", "emeraldblock", "emerald"),
SPRUCE_WOOD_STAIRS(BlockID.SPRUCE_WOOD_STAIRS, "Spruce wood stairs", "sprucestairs", "sprucewoodstairs"),
BIRCH_WOOD_STAIRS(BlockID.BIRCH_WOOD_STAIRS, "Birch wood stairs", "birchstairs", "birchwoodstairs"),
JUNGLE_WOOD_STAIRS(BlockID.JUNGLE_WOOD_STAIRS, "Jungle wood stairs", "junglestairs", "junglewoodstairs"),
COMMAND_BLOCK(BlockID.COMMAND_BLOCK, "Command block", "commandblock", "cmdblock", "command", "cmd"),
BEACON(BlockID.BEACON, "Beacon", "beacon", "beaconblock"),
COBBLESTONE_WALL(BlockID.COBBLESTONE_WALL, "Cobblestone wall", "cobblestonewall", "cobblewall"),
FLOWER_POT_BLOCK(BlockID.FLOWER_POT, "Flower pot", "flowerpot", "plantpot", "pot"),
CARROTS(BlockID.CARROTS, "Carrots", "carrots", "carrotsplant", "carrotsblock"),
POTATOES(BlockID.POTATOES, "Potatoes", "potatoes", "potatoesblock"),
WOODEN_BUTTON(BlockID.WOODEN_BUTTON, "Wooden button", "woodbutton", "woodenbutton"),
HEAD_BLOCK(BlockID.HEAD, "Head", "head", "skull"),
ANVIL(BlockID.ANVIL, "Anvil", "anvil", "blacksmith"),
TRAPPED_CHEST(BlockID.TRAPPED_CHEST, "Trapped Chest", "trappedchest", "redstonechest"),
PRESSURE_PLATE_LIGHT(BlockID.PRESSURE_PLATE_LIGHT, "Weighted Pressure Plate (Light)", "lightpressureplate"),
PRESSURE_PLATE_HEAVY(BlockID.PRESSURE_PLATE_HEAVY, "Weighted Pressure Plate (Heavy)", "heavypressureplate"),
COMPARATOR_OFF(BlockID.COMPARATOR_OFF, "Redstone Comparator (inactive)", "redstonecomparator", "comparator"),
COMPARATOR_ON(BlockID.COMPARATOR_ON, "Redstone Comparator (active)", "redstonecomparatoron", "comparatoron"),
DAYLIGHT_SENSOR(BlockID.DAYLIGHT_SENSOR, "Daylight Sensor", "daylightsensor", "lightsensor", "daylightdetector"),
REDSTONE_BLOCK(BlockID.REDSTONE_BLOCK, "Block of Redstone", "redstoneblock", "blockofredstone"),
QUARTZ_ORE(BlockID.QUARTZ_ORE, "Nether Quartz Ore", "quartzore", "netherquartzore"),
HOPPER(BlockID.HOPPER, "Hopper", "hopper"),
QUARTZ_BLOCK(BlockID.QUARTZ_BLOCK, "Block of Quartz", "quartzblock", "quartz"),
QUARTZ_STAIRS(BlockID.QUARTZ_STAIRS, "Quartz Stairs", "quartzstairs"),
ACTIVATOR_RAIL(BlockID.ACTIVATOR_RAIL, "Activator Rail", "activatorrail", "tntrail", "activatortrack"),
DROPPER(BlockID.DROPPER, "Dropper", "dropper"),
STAINED_CLAY(BlockID.STAINED_CLAY, "Stained Clay", "stainedclay", "stainedhardenedclay"),
STAINED_GLASS_PANE(BlockID.STAINED_GLASS_PANE, "Stained Glass Pane", "stainedglasspane"),
LEAVES2(BlockID.LEAVES2, "Leaves", "leaves2", "acacialeaves", "darkoakleaves"),
LOG2(BlockID.LOG2, "Log", "log2", "acacia", "darkoak"),
ACACIA_STAIRS(BlockID.ACACIA_STAIRS, "Acacia Wood Stairs", "acaciawoodstairs", "acaciastairs"),
DARK_OAK_STAIRS(BlockID.DARK_OAK_STAIRS, "Dark Oak Wood Stairs", "darkoakwoodstairs", "darkoakstairs"),
HAY_BLOCK(BlockID.HAY_BLOCK, "Hay Block", "hayblock", "haybale", "wheatbale"),
CARPET(BlockID.CARPET, "Carpet", "carpet"),
HARDENED_CLAY(BlockID.HARDENED_CLAY, "Hardened Clay", "hardenedclay", "hardclay"),
COAL_BLOCK(BlockID.COAL_BLOCK, "Block of Coal", "coalblock", "blockofcoal"),
PACKED_ICE(BlockID.PACKED_ICE, "Packed Ice", "packedice", "hardice"),
DOUBLE_PLANT(BlockID.DOUBLE_PLANT, "Large Flowers", "largeflowers", "doubleflowers"),
// Items
IRON_SHOVEL(ItemID.IRON_SHOVEL, "Iron shovel", "ironshovel"),
IRON_PICK(ItemID.IRON_PICK, "Iron pick", "ironpick", "ironpickaxe"),
IRON_AXE(ItemID.IRON_AXE, "Iron axe", "ironaxe"),
FLINT_AND_TINDER(ItemID.FLINT_AND_TINDER, "Flint and tinder", "flintandtinder", "lighter", "flintandsteel", "flintsteel", "flintandiron", "flintnsteel", "flintniron", "flintntinder"),
RED_APPLE(ItemID.RED_APPLE, "Red apple", "redapple", "apple"),
BOW(ItemID.BOW, "Bow", "bow"),
ARROW(ItemID.ARROW, "Arrow", "arrow"),
COAL(ItemID.COAL, "Coal", "coal"),
DIAMOND(ItemID.DIAMOND, "Diamond", "diamond"),
IRON_BAR(ItemID.IRON_BAR, "Iron bar", "ironbar", "iron"),
GOLD_BAR(ItemID.GOLD_BAR, "Gold bar", "goldbar", "gold"),
IRON_SWORD(ItemID.IRON_SWORD, "Iron sword", "ironsword"),
WOOD_SWORD(ItemID.WOOD_SWORD, "Wooden sword", "woodsword"),
WOOD_SHOVEL(ItemID.WOOD_SHOVEL, "Wooden shovel", "woodshovel"),
WOOD_PICKAXE(ItemID.WOOD_PICKAXE, "Wooden pickaxe", "woodpick", "woodpickaxe"),
WOOD_AXE(ItemID.WOOD_AXE, "Wooden axe", "woodaxe"),
STONE_SWORD(ItemID.STONE_SWORD, "Stone sword", "stonesword"),
STONE_SHOVEL(ItemID.STONE_SHOVEL, "Stone shovel", "stoneshovel"),
STONE_PICKAXE(ItemID.STONE_PICKAXE, "Stone pickaxe", "stonepick", "stonepickaxe"),
STONE_AXE(ItemID.STONE_AXE, "Stone pickaxe", "stoneaxe"),
DIAMOND_SWORD(ItemID.DIAMOND_SWORD, "Diamond sword", "diamondsword"),
DIAMOND_SHOVEL(ItemID.DIAMOND_SHOVEL, "Diamond shovel", "diamondshovel"),
DIAMOND_PICKAXE(ItemID.DIAMOND_PICKAXE, "Diamond pickaxe", "diamondpick", "diamondpickaxe"),
DIAMOND_AXE(ItemID.DIAMOND_AXE, "Diamond axe", "diamondaxe"),
STICK(ItemID.STICK, "Stick", "stick"),
BOWL(ItemID.BOWL, "Bowl", "bowl"),
MUSHROOM_SOUP(ItemID.MUSHROOM_SOUP, "Mushroom soup", "mushroomsoup", "soup", "brbsoup"),
GOLD_SWORD(ItemID.GOLD_SWORD, "Golden sword", "goldsword"),
GOLD_SHOVEL(ItemID.GOLD_SHOVEL, "Golden shovel", "goldshovel"),
GOLD_PICKAXE(ItemID.GOLD_PICKAXE, "Golden pickaxe", "goldpick", "goldpickaxe"),
GOLD_AXE(ItemID.GOLD_AXE, "Golden axe", "goldaxe"),
STRING(ItemID.STRING, "String", "string"),
FEATHER(ItemID.FEATHER, "Feather", "feather"),
SULPHUR(ItemID.SULPHUR, "Sulphur", "sulphur", "sulfur", "gunpowder"),
WOOD_HOE(ItemID.WOOD_HOE, "Wooden hoe", "woodhoe"),
STONE_HOE(ItemID.STONE_HOE, "Stone hoe", "stonehoe"),
IRON_HOE(ItemID.IRON_HOE, "Iron hoe", "ironhoe"),
DIAMOND_HOE(ItemID.DIAMOND_HOE, "Diamond hoe", "diamondhoe"),
GOLD_HOE(ItemID.GOLD_HOE, "Golden hoe", "goldhoe"),
SEEDS(ItemID.SEEDS, "Seeds", "seeds", "seed"),
WHEAT(ItemID.WHEAT, "Wheat", "wheat"),
BREAD(ItemID.BREAD, "Bread", "bread"),
LEATHER_HELMET(ItemID.LEATHER_HELMET, "Leather helmet", "leatherhelmet", "leatherhat"),
LEATHER_CHEST(ItemID.LEATHER_CHEST, "Leather chestplate", "leatherchest", "leatherchestplate", "leathervest", "leatherbreastplate", "leatherplate", "leathercplate", "leatherbody"),
LEATHER_PANTS(ItemID.LEATHER_PANTS, "Leather pants", "leatherpants", "leathergreaves", "leatherlegs", "leatherleggings", "leatherstockings", "leatherbreeches"),
LEATHER_BOOTS(ItemID.LEATHER_BOOTS, "Leather boots", "leatherboots", "leathershoes", "leatherfoot", "leatherfeet"),
CHAINMAIL_HELMET(ItemID.CHAINMAIL_HELMET, "Chainmail helmet", "chainmailhelmet", "chainmailhat"),
CHAINMAIL_CHEST(ItemID.CHAINMAIL_CHEST, "Chainmail chestplate", "chainmailchest", "chainmailchestplate", "chainmailvest", "chainmailbreastplate", "chainmailplate", "chainmailcplate", "chainmailbody"),
CHAINMAIL_PANTS(ItemID.CHAINMAIL_PANTS, "Chainmail pants", "chainmailpants", "chainmailgreaves", "chainmaillegs", "chainmailleggings", "chainmailstockings", "chainmailbreeches"),
CHAINMAIL_BOOTS(ItemID.CHAINMAIL_BOOTS, "Chainmail boots", "chainmailboots", "chainmailshoes", "chainmailfoot", "chainmailfeet"),
IRON_HELMET(ItemID.IRON_HELMET, "Iron helmet", "ironhelmet", "ironhat"),
IRON_CHEST(ItemID.IRON_CHEST, "Iron chestplate", "ironchest", "ironchestplate", "ironvest", "ironbreastplate", "ironplate", "ironcplate", "ironbody"),
IRON_PANTS(ItemID.IRON_PANTS, "Iron pants", "ironpants", "irongreaves", "ironlegs", "ironleggings", "ironstockings", "ironbreeches"),
IRON_BOOTS(ItemID.IRON_BOOTS, "Iron boots", "ironboots", "ironshoes", "ironfoot", "ironfeet"),
DIAMOND_HELMET(ItemID.DIAMOND_HELMET, "Diamond helmet", "diamondhelmet", "diamondhat"),
DIAMOND_CHEST(ItemID.DIAMOND_CHEST, "Diamond chestplate", "diamondchest", "diamondchestplate", "diamondvest", "diamondbreastplate", "diamondplate", "diamondcplate", "diamondbody"),
DIAMOND_PANTS(ItemID.DIAMOND_PANTS, "Diamond pants", "diamondpants", "diamondgreaves", "diamondlegs", "diamondleggings", "diamondstockings", "diamondbreeches"),
DIAMOND_BOOTS(ItemID.DIAMOND_BOOTS, "Diamond boots", "diamondboots", "diamondshoes", "diamondfoot", "diamondfeet"),
GOLD_HELMET(ItemID.GOLD_HELMET, "Gold helmet", "goldhelmet", "goldhat"),
GOLD_CHEST(ItemID.GOLD_CHEST, "Gold chestplate", "goldchest", "goldchestplate", "goldvest", "goldbreastplate", "goldplate", "goldcplate", "goldbody"),
GOLD_PANTS(ItemID.GOLD_PANTS, "Gold pants", "goldpants", "goldgreaves", "goldlegs", "goldleggings", "goldstockings", "goldbreeches"),
GOLD_BOOTS(ItemID.GOLD_BOOTS, "Gold boots", "goldboots", "goldshoes", "goldfoot", "goldfeet"),
FLINT(ItemID.FLINT, "Flint", "flint"),
RAW_PORKCHOP(ItemID.RAW_PORKCHOP, "Raw porkchop", "rawpork", "rawporkchop", "rawbacon", "baconstrips", "rawmeat"),
COOKED_PORKCHOP(ItemID.COOKED_PORKCHOP, "Cooked porkchop", "pork", "cookedpork", "cookedporkchop", "cookedbacon", "bacon", "meat"),
PAINTING(ItemID.PAINTING, "Painting", "painting"),
GOLD_APPLE(ItemID.GOLD_APPLE, "Golden apple", "goldapple", "goldenapple"),
SIGN(ItemID.SIGN, "Wooden sign", "sign"),
WOODEN_DOOR_ITEM(ItemID.WOODEN_DOOR_ITEM, "Wooden door", "wooddoor", "door"),
BUCKET(ItemID.BUCKET, "Bucket", "bucket", "bukkit"),
WATER_BUCKET(ItemID.WATER_BUCKET, "Water bucket", "waterbucket", "waterbukkit"),
LAVA_BUCKET(ItemID.LAVA_BUCKET, "Lava bucket", "lavabucket", "lavabukkit"),
MINECART(ItemID.MINECART, "Minecart", "minecart", "cart"),
SADDLE(ItemID.SADDLE, "Saddle", "saddle"),
IRON_DOOR_ITEM(ItemID.IRON_DOOR_ITEM, "Iron door", "irondoor"),
REDSTONE_DUST(ItemID.REDSTONE_DUST, "Redstone dust", "redstonedust", "reddust", "redstone", "dust", "wire"),
SNOWBALL(ItemID.SNOWBALL, "Snowball", "snowball"),
WOOD_BOAT(ItemID.WOOD_BOAT, "Wooden boat", "woodboat", "woodenboat", "boat"),
LEATHER(ItemID.LEATHER, "Leather", "leather", "cowhide"),
MILK_BUCKET(ItemID.MILK_BUCKET, "Milk bucket", "milkbucket", "milk", "milkbukkit"),
BRICK_BAR(ItemID.BRICK_BAR, "Brick", "brickbar"),
CLAY_BALL(ItemID.CLAY_BALL, "Clay", "clay"),
SUGAR_CANE_ITEM(ItemID.SUGAR_CANE_ITEM, "Sugar cane", "sugarcane", "reed", "reeds"),
PAPER(ItemID.PAPER, "Paper", "paper"),
BOOK(ItemID.BOOK, "Book", "book"),
SLIME_BALL(ItemID.SLIME_BALL, "Slime ball", "slimeball", "slime"),
STORAGE_MINECART(ItemID.STORAGE_MINECART, "Minecart with Chest", "storageminecart", "storagecart", "minecartwithchest", "minecartchest", "chestminecart"),
POWERED_MINECART(ItemID.POWERED_MINECART, "Minecart with Furnace", "poweredminecart", "poweredcart", "minecartwithfurnace", "minecartfurnace", "furnaceminecart"),
EGG(ItemID.EGG, "Egg", "egg"),
COMPASS(ItemID.COMPASS, "Compass", "compass"),
FISHING_ROD(ItemID.FISHING_ROD, "Fishing rod", "fishingrod", "fishingpole"),
WATCH(ItemID.WATCH, "Watch", "watch", "clock", "timer"),
LIGHTSTONE_DUST(ItemID.LIGHTSTONE_DUST, "Glowstone dust", "lightstonedust", "glowstonedone", "brightstonedust", "brittlegolddust", "brimstonedust"),
RAW_FISH(ItemID.RAW_FISH, "Raw fish", "rawfish", "fish"),
COOKED_FISH(ItemID.COOKED_FISH, "Cooked fish", "cookedfish"),
INK_SACK(ItemID.INK_SACK, "Ink sac", "inksac", "ink", "dye", "inksack"),
BONE(ItemID.BONE, "Bone", "bone"),
SUGAR(ItemID.SUGAR, "Sugar", "sugar"),
CAKE_ITEM(ItemID.CAKE_ITEM, "Cake", "cake"),
BED_ITEM(ItemID.BED_ITEM, "Bed", "bed"),
REDSTONE_REPEATER(ItemID.REDSTONE_REPEATER, "Redstone repeater", "redstonerepeater", "diode", "delayer", "repeater"),
COOKIE(ItemID.COOKIE, "Cookie", "cookie"),
MAP(ItemID.MAP, "Map", "map"),
SHEARS(ItemID.SHEARS, "Shears", "shears", "scissors"),
MELON(ItemID.MELON, "Melon Slice", "melon", "melonslice"),
PUMPKIN_SEEDS(ItemID.PUMPKIN_SEEDS, "Pumpkin seeds", "pumpkinseed", "pumpkinseeds"),
MELON_SEEDS(ItemID.MELON_SEEDS, "Melon seeds", "melonseed", "melonseeds"),
RAW_BEEF(ItemID.RAW_BEEF, "Raw beef", "rawbeef", "rawcow", "beef"),
COOKED_BEEF(ItemID.COOKED_BEEF, "Steak", "steak", "cookedbeef", "cookedcow"),
RAW_CHICKEN(ItemID.RAW_CHICKEN, "Raw chicken", "rawchicken"),
COOKED_CHICKEN(ItemID.COOKED_CHICKEN, "Cooked chicken", "cookedchicken", "chicken", "grilledchicken"),
ROTTEN_FLESH(ItemID.ROTTEN_FLESH, "Rotten flesh", "rottenflesh", "zombiemeat", "flesh"),
ENDER_PEARL(ItemID.ENDER_PEARL, "Ender pearl", "pearl", "enderpearl"),
BLAZE_ROD(ItemID.BLAZE_ROD, "Blaze rod", "blazerod"),
GHAST_TEAR(ItemID.GHAST_TEAR, "Ghast tear", "ghasttear"),
GOLD_NUGGET(ItemID.GOLD_NUGGET, "Gold nuggest", "goldnugget"),
NETHER_WART_ITEM(ItemID.NETHER_WART_SEED, "Nether wart", "netherwart", "netherwartseed"),
POTION(ItemID.POTION, "Potion", "potion"),
GLASS_BOTTLE(ItemID.GLASS_BOTTLE, "Glass bottle", "glassbottle"),
SPIDER_EYE(ItemID.SPIDER_EYE, "Spider eye", "spidereye"),
FERMENTED_SPIDER_EYE(ItemID.FERMENTED_SPIDER_EYE, "Fermented spider eye", "fermentedspidereye", "fermentedeye"),
BLAZE_POWDER(ItemID.BLAZE_POWDER, "Blaze powder", "blazepowder"),
MAGMA_CREAM(ItemID.MAGMA_CREAM, "Magma cream", "magmacream"),
BREWING_STAND_ITEM(ItemID.BREWING_STAND, "Brewing stand", "brewingstand"),
CAULDRON_ITEM(ItemID.CAULDRON, "Cauldron", "cauldron"),
EYE_OF_ENDER(ItemID.EYE_OF_ENDER, "Eye of Ender", "eyeofender", "endereye"),
GLISTERING_MELON(ItemID.GLISTERING_MELON, "Glistering Melon", "glisteringmelon", "goldmelon"),
SPAWN_EGG(ItemID.SPAWN_EGG, "Spawn Egg", "spawnegg", "spawn", "mobspawnegg"),
BOTTLE_O_ENCHANTING(ItemID.BOTTLE_O_ENCHANTING, "Bottle o' Enchanting", "expbottle", "bottleoenchanting", "experiencebottle", "exppotion", "experiencepotion"),
FIRE_CHARGE(ItemID.FIRE_CHARGE, "Fire Charge", "firecharge", "firestarter", "firerock"),
BOOK_AND_QUILL(ItemID.BOOK_AND_QUILL, "Book and Quill", "bookandquill", "quill", "writingbook"),
WRITTEN_BOOK(ItemID.WRITTEN_BOOK, "Written Book", "writtenbook"),
EMERALD(ItemID.EMERALD, "Emerald", "emeraldingot", "emerald"),
ITEM_FRAME(ItemID.ITEM_FRAME, "Item frame", "itemframe", "frame", "itempainting"),
FLOWER_POT(ItemID.FLOWER_POT, "Flower pot", "flowerpot", "plantpot", "pot"),
CARROT(ItemID.CARROT, "Carrot", "carrot"),
POTATO(ItemID.POTATO, "Potato", "potato"),
BAKED_POTATO(ItemID.BAKED_POTATO, "Baked potato", "bakedpotato", "potatobaked"),
POISONOUS_POTATO(ItemID.POISONOUS_POTATO, "Poisonous potato", "poisonpotato", "poisonouspotato"),
BLANK_MAP(ItemID.BLANK_MAP, "Blank map", "blankmap", "emptymap"),
GOLDEN_CARROT(ItemID.GOLDEN_CARROT, "Golden carrot", "goldencarrot", "goldcarrot"),
HEAD(ItemID.HEAD, "Head", "skull", "head", "headmount", "mount"),
CARROT_ON_A_STICK(ItemID.CARROT_ON_A_STICK, "Carrot on a stick", "carrotonastick", "carrotonstick", "stickcarrot", "carrotstick"),
NETHER_STAR(ItemID.NETHER_STAR, "Nether star", "netherstar", "starnether"),
PUMPKIN_PIE(ItemID.PUMPKIN_PIE, "Pumpkin pie", "pumpkinpie"),
FIREWORK_ROCKET(ItemID.FIREWORK_ROCKET, "Firework rocket", "firework", "rocket"),
FIREWORK_STAR(ItemID.FIREWORK_STAR, "Firework star", "fireworkstar", "fireworkcharge"),
ENCHANTED_BOOK(ItemID.ENCHANTED_BOOK, "Enchanted book", "enchantedbook", "spellbook", "enchantedtome", "tome"),
COMPARATOR(ItemID.COMPARATOR, "Comparator", "comparator", "capacitor"),
NETHER_BRICK_ITEM(ItemID.NETHER_BRICK, "Nether Brick (item)", "netherbrickitem"),
NETHER_QUARTZ(ItemID.NETHER_QUARTZ, "Nether Quartz", "netherquartz", "quartz"),
TNT_MINECART(ItemID.TNT_MINECART, "Minecart with TNT", "minecraftwithtnt", "tntminecart", "minecarttnt"),
HOPPER_MINECART(ItemID.HOPPER_MINECART, "Minecart with Hopper", "minecraftwithhopper", "hopperminecart", "minecarthopper"),
HORSE_ARMOR_IRON(ItemID.HORSE_ARMOR_IRON, "Iron Horse Armor", "ironhorsearmor", "ironbarding"),
HORSE_ARMOR_GOLD(ItemID.HORSE_ARMOR_GOLD, "Gold Horse Armor", "goldhorsearmor", "goldbarding"),
HORSE_ARMOR_DIAMOND(ItemID.HORSE_ARMOR_DIAMOND, "Diamond Horse Armor", "diamondhorsearmor", "diamondbarding"),
LEAD(ItemID.LEAD, "Lead", "lead", "leash"),
NAME_TAG(ItemID.NAME_TAG, "Name Tag", "nametag"),
COMMAND_BLOCK_MINECART(ItemID.COMMAND_BLOCK_MINECART, "Minecart with Command Block"),
DISC_13(ItemID.DISC_13, "Music Disc - 13", "disc_13"),
DISC_CAT(ItemID.DISC_CAT, "Music Disc - Cat", "disc_cat"),
DISC_BLOCKS(ItemID.DISC_BLOCKS, "Music Disc - blocks", "disc_blocks"),
DISC_CHIRP(ItemID.DISC_CHIRP, "Music Disc - chirp", "disc_chirp"),
DISC_FAR(ItemID.DISC_FAR, "Music Disc - far", "disc_far"),
DISC_MALL(ItemID.DISC_MALL, "Music Disc - mall", "disc_mall"),
DISC_MELLOHI(ItemID.DISC_MELLOHI, "Music Disc - mellohi", "disc_mellohi"),
DISC_STAL(ItemID.DISC_STAL, "Music Disc - stal", "disc_stal"),
DISC_STRAD(ItemID.DISC_STRAD, "Music Disc - strad", "disc_strad"),
DISC_WARD(ItemID.DISC_WARD, "Music Disc - ward", "disc_ward"),
DISC_11(ItemID.DISC_11, "Music Disc - 11", "disc_11"),
DISC_WAIT(ItemID.DISC_WAIT, "Music Disc - wait", "disc_wait"),
// deprecated
@Deprecated GOLD_RECORD(ItemID.GOLD_RECORD, "Gold Record", "goldrecord", "golddisc"),
@Deprecated GREEN_RECORD(ItemID.GREEN_RECORD, "Green Record", "greenrecord", "greenddisc");
/**
* Stores a map of the IDs for fast access.
*/
private static final Map<Integer, ItemType> ids = new HashMap<Integer, ItemType>();
/**
* Stores a map of the names for fast access.
*/
private static final Map<String, ItemType> lookup = new LinkedHashMap<String, ItemType>();
private final int id;
private final String name;
private final String[] lookupKeys;
static {
for (ItemType type : EnumSet.allOf(ItemType.class)) {
ids.put(type.id, type);
for (String key : type.lookupKeys) {
lookup.put(key, type);
}
}
}
/**
* Construct the type.
*
* @param id the type ID of the item
* @param name the name of the item
* @param lookupKey a name to refer to the item type by
*/
ItemType(int id, String name, String lookupKey) {
this.id = id;
this.name = name;
this.lookupKeys = new String[] { lookupKey };
}
/**
* Construct the type.
*
* @param id the type ID of the item
* @param name the name of the item
* @param lookupKeys a list of names to refer to the item type by
*/
ItemType(int id, String name, String... lookupKeys) {
this.id = id;
this.name = name;
this.lookupKeys = lookupKeys;
}
/**
* Return type from ID. May return null.
*
* @param id the type ID of the item
* @return an item type or null
*/
@Nullable
public static ItemType fromID(int id) {
return ids.get(id);
}
/**
* Get a name for the item.
*
* <p>If the item type is not null, the numeric ID will be returned.</p>
*
* @param id the type ID of the item
* @return a name for the item
*/
public static String toName(int id) {
ItemType type = ids.get(id);
if (type != null) {
return type.getName();
} else {
return "#" + id;
}
}
/**
* Get a name for a held item.
*
* <p>If the item type is not null, the numeric ID will be returned.</p>
*
* @param id the type ID of the item
* @return the name of the item
*/
public static String toHeldName(int id) {
if (id == 0) {
return "Hand";
}
ItemType type = ids.get(id);
if (type != null) {
return type.getName();
} else {
return "#" + id;
}
}
/**
* Return type from name. May return null.
*
* @param name the name
* @return the type or null
*/
@Nullable
public static ItemType lookup(String name) {
return lookup(name, true);
}
/**
* Return type from name. May return null.
*
* @param name the name
* @param fuzzy true to do a fuzzy string search
* @return the type or null
*/
@Nullable
public static ItemType lookup(String name, boolean fuzzy) {
try {
return fromID(Integer.parseInt(name));
} catch (NumberFormatException e) {
return StringUtil.lookup(lookup, name, fuzzy);
}
}
/**
* Get item numeric ID.
*
* @return the type ID of this item
*/
public int getID() {
return id;
}
/**
* Get user-friendly item name.
*
* @return a name of this item
*/
public String getName() {
return name;
}
/**
* Get a list of aliases.
*
* @return a list of aliases
*/
public String[] getAliases() {
return lookupKeys;
}
private static final Set<Integer> shouldNotStack = new HashSet<Integer>();
static {
shouldNotStack.add(ItemID.IRON_SHOVEL);
shouldNotStack.add(ItemID.IRON_PICK);
shouldNotStack.add(ItemID.IRON_AXE);
shouldNotStack.add(ItemID.FLINT_AND_TINDER);
shouldNotStack.add(ItemID.BOW);
shouldNotStack.add(ItemID.IRON_SWORD);
shouldNotStack.add(ItemID.WOOD_SWORD);
shouldNotStack.add(ItemID.WOOD_SHOVEL);
shouldNotStack.add(ItemID.WOOD_PICKAXE);
shouldNotStack.add(ItemID.WOOD_AXE);
shouldNotStack.add(ItemID.STONE_SWORD);
shouldNotStack.add(ItemID.STONE_SHOVEL);
shouldNotStack.add(ItemID.STONE_PICKAXE);
shouldNotStack.add(ItemID.STONE_AXE);
shouldNotStack.add(ItemID.DIAMOND_SWORD);
shouldNotStack.add(ItemID.DIAMOND_SHOVEL);
shouldNotStack.add(ItemID.DIAMOND_PICKAXE);
shouldNotStack.add(ItemID.DIAMOND_AXE);
shouldNotStack.add(ItemID.BOWL);
shouldNotStack.add(ItemID.GOLD_SWORD);
shouldNotStack.add(ItemID.GOLD_SHOVEL);
shouldNotStack.add(ItemID.GOLD_PICKAXE);
shouldNotStack.add(ItemID.GOLD_AXE);
shouldNotStack.add(ItemID.WOOD_HOE);
shouldNotStack.add(ItemID.STONE_HOE);
shouldNotStack.add(ItemID.IRON_HOE);
shouldNotStack.add(ItemID.DIAMOND_HOE);
shouldNotStack.add(ItemID.GOLD_HOE);
shouldNotStack.add(ItemID.LEATHER_HELMET);
shouldNotStack.add(ItemID.LEATHER_CHEST);
shouldNotStack.add(ItemID.LEATHER_PANTS);
shouldNotStack.add(ItemID.LEATHER_BOOTS);
shouldNotStack.add(ItemID.CHAINMAIL_CHEST);
shouldNotStack.add(ItemID.CHAINMAIL_HELMET);
shouldNotStack.add(ItemID.CHAINMAIL_BOOTS);
shouldNotStack.add(ItemID.CHAINMAIL_PANTS);
shouldNotStack.add(ItemID.IRON_HELMET);
shouldNotStack.add(ItemID.IRON_CHEST);
shouldNotStack.add(ItemID.IRON_PANTS);
shouldNotStack.add(ItemID.IRON_BOOTS);
shouldNotStack.add(ItemID.DIAMOND_HELMET);
shouldNotStack.add(ItemID.DIAMOND_PANTS);
shouldNotStack.add(ItemID.DIAMOND_CHEST);
shouldNotStack.add(ItemID.DIAMOND_BOOTS);
shouldNotStack.add(ItemID.GOLD_HELMET);
shouldNotStack.add(ItemID.GOLD_CHEST);
shouldNotStack.add(ItemID.GOLD_PANTS);
shouldNotStack.add(ItemID.GOLD_BOOTS);
shouldNotStack.add(ItemID.WOODEN_DOOR_ITEM);
shouldNotStack.add(ItemID.WATER_BUCKET);
shouldNotStack.add(ItemID.LAVA_BUCKET);
shouldNotStack.add(ItemID.MINECART);
shouldNotStack.add(ItemID.SADDLE);
shouldNotStack.add(ItemID.IRON_DOOR_ITEM);
shouldNotStack.add(ItemID.WOOD_BOAT);
shouldNotStack.add(ItemID.MILK_BUCKET);
shouldNotStack.add(ItemID.STORAGE_MINECART);
shouldNotStack.add(ItemID.POWERED_MINECART);
shouldNotStack.add(ItemID.WATCH);
shouldNotStack.add(ItemID.CAKE_ITEM);
shouldNotStack.add(ItemID.BED_ITEM);
shouldNotStack.add(ItemID.MAP);
shouldNotStack.add(ItemID.SHEARS);
shouldNotStack.add(ItemID.HEAD);
shouldNotStack.add(ItemID.FIREWORK_ROCKET);
shouldNotStack.add(ItemID.FIREWORK_STAR);
shouldNotStack.add(ItemID.ENCHANTED_BOOK);
shouldNotStack.add(ItemID.TNT_MINECART);
shouldNotStack.add(ItemID.HOPPER_MINECART);
shouldNotStack.add(ItemID.HORSE_ARMOR_IRON);
shouldNotStack.add(ItemID.HORSE_ARMOR_GOLD);
shouldNotStack.add(ItemID.HORSE_ARMOR_DIAMOND);
shouldNotStack.add(ItemID.COMMAND_BLOCK_MINECART);
shouldNotStack.add(ItemID.DISC_13);
shouldNotStack.add(ItemID.DISC_CAT);
shouldNotStack.add(ItemID.DISC_BLOCKS);
shouldNotStack.add(ItemID.DISC_CHIRP);
shouldNotStack.add(ItemID.DISC_FAR);
shouldNotStack.add(ItemID.DISC_MALL);
shouldNotStack.add(ItemID.DISC_MELLOHI);
shouldNotStack.add(ItemID.DISC_STAL);
shouldNotStack.add(ItemID.DISC_STRAD);
shouldNotStack.add(ItemID.DISC_WARD);
shouldNotStack.add(ItemID.DISC_11);
shouldNotStack.add(ItemID.DISC_WAIT);
}
/**
* Returns true if an item should not be stacked.
*
* @param id the type ID of the item
* @return true if the item should not stack
*/
public static boolean shouldNotStack(int id) {
return shouldNotStack.contains(id);
}
private static final Set<Integer> usesDamageValue = new HashSet<Integer>();
static {
usesDamageValue.add(BlockID.DIRT);
usesDamageValue.add(BlockID.WOOD);
usesDamageValue.add(BlockID.SAPLING);
usesDamageValue.add(BlockID.SAND);
usesDamageValue.add(BlockID.LOG);
usesDamageValue.add(BlockID.LEAVES);
usesDamageValue.add(BlockID.SANDSTONE);
usesDamageValue.add(BlockID.LONG_GRASS);
usesDamageValue.add(BlockID.CLOTH);
usesDamageValue.add(BlockID.RED_FLOWER);
usesDamageValue.add(BlockID.DOUBLE_STEP);
usesDamageValue.add(BlockID.STEP);
usesDamageValue.add(BlockID.SILVERFISH_BLOCK);
usesDamageValue.add(BlockID.STONE_BRICK);
usesDamageValue.add(BlockID.BROWN_MUSHROOM_CAP);
usesDamageValue.add(BlockID.RED_MUSHROOM_CAP);
usesDamageValue.add(BlockID.DOUBLE_WOODEN_STEP);
usesDamageValue.add(BlockID.WOODEN_STEP);
usesDamageValue.add(BlockID.COBBLESTONE_WALL);
usesDamageValue.add(BlockID.ANVIL);
usesDamageValue.add(BlockID.QUARTZ_BLOCK);
usesDamageValue.add(BlockID.STAINED_CLAY);
usesDamageValue.add(BlockID.CARPET);
usesDamageValue.add(ItemID.COAL);
usesDamageValue.add(ItemID.INK_SACK);
usesDamageValue.add(ItemID.POTION);
usesDamageValue.add(ItemID.SPAWN_EGG);
usesDamageValue.add(ItemID.MAP);
usesDamageValue.add(ItemID.HEAD);
usesDamageValue.add(ItemID.GOLD_APPLE);
usesDamageValue.add(ItemID.RAW_FISH);
usesDamageValue.add(ItemID.COOKED_FISH);
}
/**
* Returns true if an item uses its damage value for something
* other than damage.
*
* @param id the type ID of the item
* @return true if the item uses its damage value
*/
public static boolean usesDamageValue(int id) {
return usesDamageValue.contains(id);
}
}

View File

@ -0,0 +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.blocks;
import com.sk89q.worldedit.world.NbtValued;
/**
* Indicates a block that contains extra data identified as an NBT structure.
* Compared to a {@link NbtValued}, tile entity blocks also contain an ID.
*
* @see NbtValued
*/
public interface TileEntityBlock extends NbtValued {
/**
* Return the name of the title entity ID.
*
* @return tile entity ID, non-null string
*/
String getNbtId();
}

View File

@ -0,0 +1,66 @@
/*
* 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.metadata;
/**
* Represents the possible types of mobs.
*/
public enum MobType {
BAT("Bat"),
BLAZE("Blaze"),
CAVE_SPIDER("CaveSpider"),
CHICKEN("Chicken"),
COW("Cow"),
CREEPER("Creeper"),
ENDERDRAGON("EnderDragon"),
ENDERMAN("Enderman"),
GHAST("Ghast"),
GIANT("Giant"),
VILLAGER_GOLEM("VillagerGolem"),
HORSE("EntityHorse"),
MAGMA_CUBE("LavaSlime"),
MOOSHROOM("MushroomCow"),
OCELOT("Ozelot"),
PIG("Pig"),
PIG_ZOMBIE("PigZombie"),
SHEEP("Sheep"),
SILVERFISH("Silverfish"),
SKELETON("Skeleton"),
SLIME("Slime"),
SNOWMAN("SnowMan"),
SPIDER("Spider"),
SQUID("Squid"),
VILLAGER("Villager"),
WITCH("Witch"),
WITHER("WitherBoss"),
WOLF("Wolf"),
ZOMBIE("Zombie");
private final String name;
private MobType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,209 @@
/*
* 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.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.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.function.FlatRegionFunction;
import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
import com.sk89q.worldedit.function.biome.BiomeReplace;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.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;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/**
* Implements biome-related commands such as "/biomelist".
*/
public class BiomeCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public BiomeCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "biomelist", "biomels" },
usage = "[page]",
desc = "Gets all biomes available.",
max = 1
)
@CommandPermissions("worldedit.biome.list")
public void biomeList(Player player, CommandContext args) throws WorldEditException {
int page;
int offset;
int count = 0;
if (args.argsLength() == 0 || (page = args.getInteger(0)) < 2) {
page = 1;
offset = 0;
} else {
offset = (page - 1) * 19;
}
BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
List<BaseBiome> biomes = biomeRegistry.getBiomes();
int totalPages = biomes.size() / 19 + 1;
player.print("Available Biomes (page " + page + "/" + totalPages + ") :");
for (BaseBiome biome : biomes) {
if (offset > 0) {
offset--;
} else {
BiomeData data = biomeRegistry.getData(biome);
if (data != null) {
player.print(" " + data.getName());
if (++count == 19) {
break;
}
} else {
player.print(" <unknown #" + biome.getId() + ">");
}
}
}
}
@Command(
aliases = { "biomeinfo" },
flags = "pt",
desc = "Get the biome of the targeted block.",
help =
"Get the biome of the block.\n" +
"By default use all the blocks contained in your selection.\n" +
"-t use the block you are looking at.\n" +
"-p use the block you are currently in",
max = 0
)
@CommandPermissions("worldedit.biome.info")
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) {
player.printError("No block in sight!");
return;
}
BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
biomes.add(biome);
qualifier = "at line of sight point";
} else if (args.hasFlag('p')) {
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);
if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
biomes.add(world.getBiome(pt));
}
} else {
for (Vector pt : region) {
biomes.add(world.getBiome(pt.toVector2D()));
}
}
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() + ">");
}
}
}
@Command(
aliases = { "/setbiome" },
usage = "<biome>",
flags = "p",
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"
)
@Logging(REGION)
@CommandPermissions("worldedit.biome.set")
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();
Mask2D mask2d = mask != null ? mask.toMask2D() : null;
if (atPosition) {
region = new CuboidRegion(player.getPosition(), player.getPosition());
} else {
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

@ -0,0 +1,273 @@
/*
* 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.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.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.tool.BrushTool;
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;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands to set brush shape.
*/
public class BrushCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public BrushCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "sphere", "s" },
usage = "<pattern> [radius]",
flags = "h",
desc = "Choose the sphere brush",
help =
"Chooses the sphere brush.\n" +
"The -h flag creates hollow spheres instead.",
min = 1,
max = 2
)
@CommandPermissions("worldedit.brush.sphere")
public void sphereBrush(Player player, LocalSession session, EditSession editSession, Pattern fill,
@Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setFill(fill);
tool.setSize(radius);
if (hollow) {
tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere");
} else {
tool.setBrush(new SphereBrush(), "worldedit.brush.sphere");
}
player.print(String.format("Sphere brush shape equipped (%.0f).", radius));
}
@Command(
aliases = { "cylinder", "cyl", "c" },
usage = "<block> [radius] [height]",
flags = "h",
desc = "Choose the cylinder brush",
help =
"Chooses the cylinder brush.\n" +
"The -h flag creates hollow cylinders instead.",
min = 1,
max = 3
)
@CommandPermissions("worldedit.brush.cylinder")
public void cylinderBrush(Player player, LocalSession session, EditSession editSession, Pattern fill,
@Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
worldEdit.checkMaxBrushRadius(height);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setFill(fill);
tool.setSize(radius);
if (hollow) {
tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder");
} else {
tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder");
}
player.print(String.format("Cylinder brush shape equipped (%.0f by %d).", radius, height));
}
@Command(
aliases = { "clipboard", "copy" },
usage = "",
desc = "Choose the clipboard brush",
help =
"Chooses the clipboard brush.\n" +
"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, @Switch('p') boolean usingOrigin) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
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(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard");
player.print("Clipboard brush shape equipped.");
}
@Command(
aliases = { "smooth" },
usage = "[size] [iterations]",
flags = "n",
desc = "Choose the terrain softener brush",
help =
"Chooses the terrain softener brush.\n" +
"The -n flag makes it only consider naturally occurring blocks.",
min = 0,
max = 2
)
@CommandPermissions("worldedit.brush.smooth")
public void smoothBrush(Player player, LocalSession session, EditSession editSession,
@Optional("2") double radius, @Optional("4") int iterations, @Switch('n')
boolean naturalBlocksOnly) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth");
player.print(String.format("Smooth brush equipped (%.0f x %dx, using " + (naturalBlocksOnly ? "natural blocks only" : "any block") + ").",
radius, iterations));
}
@Command(
aliases = { "ex", "extinguish" },
usage = "[radius]",
desc = "Shortcut fire extinguisher brush",
min = 0,
max = 1
)
@CommandPermissions("worldedit.brush.ex")
public void extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
Pattern fill = new BlockPattern(new BaseBlock(0));
tool.setFill(fill);
tool.setSize(radius);
tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
tool.setBrush(new SphereBrush(), "worldedit.brush.ex");
player.print(String.format("Extinguisher equipped (%.0f).", radius));
}
@Command(
aliases = { "gravity", "grav" },
usage = "[radius]",
flags = "h",
desc = "Gravity brush",
help =
"This brush simulates the affect of gravity.\n" +
"The -h flag makes it affect blocks starting at the world's max y, " +
"instead of the clicked block's y + radius.",
min = 0,
max = 1
)
@CommandPermissions("worldedit.brush.gravity")
public void gravityBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity");
player.print(String.format("Gravity brush equipped (%.0f).",
radius));
}
@Command(
aliases = { "butcher", "kill" },
usage = "[radius]",
flags = "plangbtf",
desc = "Butcher brush",
help = "Kills nearby mobs within the specified radius.\n" +
"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 = 1
)
@CommandPermissions("worldedit.brush.butcher")
public void butcherBrush(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
LocalConfiguration config = worldEdit.getConfiguration();
double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
double maxRadius = config.maxBrushRadius;
// hmmmm not horribly worried about this because -1 is still rather efficient,
// the problem arises when butcherMaxRadius is some really high number but not infinite
// - original idea taken from https://github.com/sk89q/worldedit/pull/198#issuecomment-6463108
if (player.hasPermission("worldedit.butcher")) {
maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius);
}
if (radius > maxRadius) {
player.printError("Maximum allowed brush radius: " + maxRadius);
return;
}
CreatureButcher flags = new CreatureButcher(player);
flags.fromCommand(args);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");
player.print(String.format("Butcher brush equipped (%.0f).", radius));
}
}

View File

@ -0,0 +1,179 @@
/*
* 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.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.entity.Player;
import com.sk89q.worldedit.math.MathUtils;
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/**
* Commands for working with chunks.
*/
public class ChunkCommands {
private final WorldEdit worldEdit;
public ChunkCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "chunkinfo" },
usage = "",
desc = "Get information about the chunk that you are inside",
min = 0,
max = 0
)
@CommandPermissions("worldedit.chunkinfo")
public void chunkInfo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Vector pos = player.getBlockIn();
int chunkX = (int) Math.floor(pos.getBlockX() / 16.0);
int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0);
String folder1 = Integer.toString(MathUtils.divisorMod(chunkX, 64), 36);
String folder2 = Integer.toString(MathUtils.divisorMod(chunkZ, 64), 36);
String filename = "c." + Integer.toString(chunkX, 36)
+ "." + Integer.toString(chunkZ, 36) + ".dat";
player.print("Chunk: " + chunkX + ", " + chunkZ);
player.print("Old format: " + folder1 + "/" + folder2 + "/" + filename);
player.print("McRegion: region/" + McRegionChunkStore.getFilename(
new Vector2D(chunkX, chunkZ)));
}
@Command(
aliases = { "listchunks" },
usage = "",
desc = "List chunks that your selection includes",
min = 0,
max = 0
)
@CommandPermissions("worldedit.listchunks")
public void listChunks(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
for (Vector2D chunk : chunks) {
player.print(LegacyChunkStore.getFilename(chunk));
}
}
@Command(
aliases = { "delchunks" },
usage = "",
desc = "Delete chunks that your selection includes",
min = 0,
max = 0
)
@CommandPermissions("worldedit.delchunks")
@Logging(REGION)
public void deleteChunks(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
player.print("Note that this command does not yet support the mcregion format.");
LocalConfiguration config = worldEdit.getConfiguration();
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
FileOutputStream out = null;
if (config.shellSaveType == null) {
player.printError("Shell script type must be configured: 'bat' or 'bash' expected.");
} else if (config.shellSaveType.equalsIgnoreCase("bat")) {
try {
out = new FileOutputStream("worldedit-delchunks.bat");
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
writer.write("@ECHO off\r\n");
writer.write("ECHO This batch file was generated by WorldEdit.\r\n");
writer.write("ECHO It contains a list of chunks that were in the selected region\r\n");
writer.write("ECHO at the time that the /delchunks command was used. Run this file\r\n");
writer.write("ECHO in order to delete the chunk files listed in this file.\r\n");
writer.write("ECHO.\r\n");
writer.write("PAUSE\r\n");
for (Vector2D chunk : chunks) {
String filename = LegacyChunkStore.getFilename(chunk);
writer.write("ECHO " + filename + "\r\n");
writer.write("DEL \"world/" + filename + "\"\r\n");
}
writer.write("ECHO Complete.\r\n");
writer.write("PAUSE\r\n");
writer.close();
player.print("worldedit-delchunks.bat written. Run it when no one is near the region.");
} catch (IOException e) {
player.printError("Error occurred: " + e.getMessage());
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ignored) { }
}
}
} else if (config.shellSaveType.equalsIgnoreCase("bash")) {
try {
out = new FileOutputStream("worldedit-delchunks.sh");
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
writer.write("#!/bin/bash\n");
writer.write("echo This shell file was generated by WorldEdit.\n");
writer.write("echo It contains a list of chunks that were in the selected region\n");
writer.write("echo at the time that the /delchunks command was used. Run this file\n");
writer.write("echo in order to delete the chunk files listed in this file.\n");
writer.write("echo\n");
writer.write("read -p \"Press any key to continue...\"\n");
for (Vector2D chunk : chunks) {
String filename = LegacyChunkStore.getFilename(chunk);
writer.write("echo " + filename + "\n");
writer.write("rm \"world/" + filename + "\"\n");
}
writer.write("echo Complete.\n");
writer.write("read -p \"Press any key to continue...\"\n");
writer.close();
player.print("worldedit-delchunks.sh written. Run it when no one is near the region.");
player.print("You will have to chmod it to be executable.");
} catch (IOException e) {
player.printError("Error occurred: " + e.getMessage());
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ignored) {
}
}
}
} else {
player.printError("Shell script type must be configured: 'bat' or 'bash' expected.");
}
}
}

View File

@ -0,0 +1,258 @@
/*
* 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.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
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.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 static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/**
* Clipboard commands.
*/
public class ClipboardCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public ClipboardCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/copy" },
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,
@Selection Region region, @Switch('e') boolean copyEntities,
@Switch('m') Mask mask) throws WorldEditException {
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()));
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!",
min = 0,
max = 1
)
@CommandPermissions("worldedit.clipboard.cut")
@Logging(REGION)
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 {
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()));
player.print(region.getArea() + " block(s) were copied.");
}
@Command(
aliases = { "/paste" },
usage = "",
flags = "sao",
desc = "Paste the clipboard's contents",
help =
"Pastes the clipboard's contents.\n" +
"Flags:\n" +
" -a skips air blocks\n" +
" -o pastes at the original position\n" +
" -s selects the region after pasting",
min = 0,
max = 0
)
@CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT)
public void paste(Player player, LocalSession session, EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
Operation operation = holder
.createPaste(editSession, editSession.getWorld().getWorldData())
.to(to)
.ignoreAirBlocks(ignoreAirBlocks)
.build();
Operations.completeLegacy(operation);
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);
}
player.print("The clipboard has been pasted at " + to);
}
@Command(
aliases = { "/rotate" },
usage = "<y-axis> [<x-axis>] [<z-axis>]",
desc = "Rotate the contents of the clipboard",
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, 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 = "[<direction>]",
desc = "Flip the contents of the clipboard",
help =
"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,
@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(
aliases = { "/load" },
usage = "<filename>",
desc = "Load a schematic into your clipboard",
min = 0,
max = 1
)
@Deprecated
@CommandPermissions("worldedit.clipboard.load")
public void load(Actor actor) {
actor.printError("This command is no longer used. See //schematic load.");
}
@Command(
aliases = { "/save" },
usage = "<filename>",
desc = "Save a schematic into your clipboard",
min = 0,
max = 1
)
@Deprecated
@CommandPermissions("worldedit.clipboard.save")
public void save(Actor actor) {
actor.printError("This command is no longer used. See //schematic save.");
}
@Command(
aliases = { "clearclipboard" },
usage = "",
desc = "Clear your clipboard",
min = 0,
max = 0
)
@CommandPermissions("worldedit.clipboard.clear")
public void clearClipboard(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
session.setClipboard(null);
player.print("Clipboard cleared.");
}
}

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

@ -0,0 +1,225 @@
/*
* 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.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.blocks.ItemType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.util.command.parametric.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* General WorldEdit commands.
*/
public class GeneralCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public GeneralCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/limit" },
usage = "<limit>",
desc = "Modify block change limit",
min = 1,
max = 1
)
@CommandPermissions("worldedit.limit")
public void limit(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
LocalConfiguration config = worldEdit.getConfiguration();
boolean mayDisable = player.hasPermission("worldedit.limit.unrestricted");
int limit = Math.max(-1, args.getInteger(0));
if (!mayDisable && config.maxChangeLimit > -1) {
if (limit > config.maxChangeLimit) {
player.printError("Your maximum allowable limit is " + config.maxChangeLimit + ".");
return;
}
}
session.setBlockChangeLimit(limit);
if (limit != -1) {
player.print("Block change limit set to " + limit + ". (Use //limit -1 to go back to the default.)");
} else {
player.print("Block change limit set to " + limit + ".");
}
}
@Command(
aliases = { "/fast" },
usage = "[on|off]",
desc = "Toggle fast mode",
min = 0,
max = 1
)
@CommandPermissions("worldedit.fast")
public void fast(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
String newState = args.getString(0, null);
if (session.hasFastMode()) {
if ("on".equals(newState)) {
player.printError("Fast mode already enabled.");
return;
}
session.setFastMode(false);
player.print("Fast mode disabled.");
} else {
if ("off".equals(newState)) {
player.printError("Fast mode already disabled.");
return;
}
session.setFastMode(true);
player.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.");
}
}
@Command(
aliases = { "/gmask", "gmask" },
usage = "[mask]",
desc = "Set the global mask",
min = 0,
max = -1
)
@CommandPermissions("worldedit.global-mask")
public void gmask(Player player, LocalSession session, EditSession editSession, @Optional Mask mask) throws WorldEditException {
if (mask == null) {
session.setMask((Mask) null);
player.print("Global mask disabled.");
} else {
session.setMask(mask);
player.print("Global mask set.");
}
}
@Command(
aliases = { "/toggleplace", "toggleplace" },
usage = "",
desc = "Switch between your position and pos1 for placement",
min = 0,
max = 0
)
public void togglePlace(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
if (session.togglePlacementPosition()) {
player.print("Now placing at pos #1.");
} else {
player.print("Now placing at the block you stand in.");
}
}
@Command(
aliases = { "/searchitem", "/l", "/search", "searchitem" },
usage = "<query>",
flags = "bi",
desc = "Search for an item",
help =
"Searches for an item.\n" +
"Flags:\n" +
" -b only search for blocks\n" +
" -i only search for items",
min = 1,
max = 1
)
public void searchItem(Actor actor, CommandContext args) throws WorldEditException {
String query = args.getString(0).trim().toLowerCase();
boolean blocksOnly = args.hasFlag('b');
boolean itemsOnly = args.hasFlag('i');
try {
int id = Integer.parseInt(query);
ItemType type = ItemType.fromID(id);
if (type != null) {
actor.print("#" + type.getID() + " (" + type.getName() + ")");
} else {
actor.printError("No item found by ID " + id);
}
return;
} catch (NumberFormatException ignored) {
}
if (query.length() <= 2) {
actor.printError("Enter a longer search string (len > 2).");
return;
}
if (!blocksOnly && !itemsOnly) {
actor.print("Searching for: " + query);
} else if (blocksOnly && itemsOnly) {
actor.printError("You cannot use both the 'b' and 'i' flags simultaneously.");
return;
} else if (blocksOnly) {
actor.print("Searching for blocks: " + query);
} else {
actor.print("Searching for items: " + query);
}
int found = 0;
for (ItemType type : ItemType.values()) {
if (found >= 15) {
actor.print("Too many results!");
break;
}
if (blocksOnly && type.getID() > 255) {
continue;
}
if (itemsOnly && type.getID() <= 255) {
continue;
}
for (String alias : type.getAliases()) {
if (alias.contains(query)) {
actor.print("#" + type.getID() + " (" + type.getName() + ")");
++found;
break;
}
}
}
if (found == 0) {
actor.printError("No items found.");
}
}
}

View File

@ -0,0 +1,382 @@
/*
* 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.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
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;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
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.*;
/**
* Commands for the generation of shapes and other objects.
*/
public class GenerationCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public GenerationCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/hcyl" },
usage = "<pattern> <radius>[,<radius>] [height]",
desc = "Generates a hollow cylinder.",
help =
"Generates a hollow cylinder.\n" +
"By specifying 2 radii, separated by a comma,\n" +
"you can generate elliptical cylinders.\n" +
"The 1st radius is north/south, the 2nd radius is east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT)
public void hcyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height) throws WorldEditException {
cyl(player, session, editSession, pattern, radiusString, height, true);
}
@Command(
aliases = { "/cyl" },
usage = "<block> <radius>[,<radius>] [height]",
flags = "h",
desc = "Generates a cylinder.",
help =
"Generates a cylinder.\n" +
"By specifying 2 radii, separated by a comma,\n" +
"you can generate elliptical cylinders.\n" +
"The 1st radius is north/south, the 2nd radius is east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT)
public void cyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
String[] radii = radiusString.split(",");
final double radiusX, radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusZ = Math.max(1, Double.parseDouble(radii[0]));
break;
case 2:
radiusX = Math.max(1, Double.parseDouble(radii[0]));
radiusZ = Math.max(1, Double.parseDouble(radii[1]));
break;
default:
player.printError("You must either specify 1 or 2 radius values.");
return;
}
worldEdit.checkMaxRadius(radiusX);
worldEdit.checkMaxRadius(radiusZ);
worldEdit.checkMaxRadius(height);
Vector pos = session.getPlacementPosition(player);
int affected = editSession.makeCylinder(pos, Patterns.wrap(pattern), radiusX, radiusZ, height, !hollow);
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/hsphere" },
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
desc = "Generates a hollow sphere.",
help =
"Generates a hollow sphere.\n" +
"By specifying 3 radii, separated by commas,\n" +
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
"is north/south, up/down, east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.sphere")
@Logging(PLACEMENT)
public void hsphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised) throws WorldEditException {
sphere(player, session, editSession, pattern, radiusString, raised, true);
}
@Command(
aliases = { "/sphere" },
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
flags = "h",
desc = "Generates a filled sphere.",
help =
"Generates a filled sphere.\n" +
"By specifying 3 radii, separated by commas,\n" +
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
"is north/south, up/down, east/west.",
min = 2,
max = 3
)
@CommandPermissions("worldedit.generation.sphere")
@Logging(PLACEMENT)
public void sphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised, @Switch('h') boolean hollow) throws WorldEditException {
String[] radii = radiusString.split(",");
final double radiusX, radiusY, radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radii[0]));
break;
case 3:
radiusX = Math.max(1, Double.parseDouble(radii[0]));
radiusY = Math.max(1, Double.parseDouble(radii[1]));
radiusZ = Math.max(1, Double.parseDouble(radii[2]));
break;
default:
player.printError("You must either specify 1 or 3 radius values.");
return;
}
worldEdit.checkMaxRadius(radiusX);
worldEdit.checkMaxRadius(radiusY);
worldEdit.checkMaxRadius(radiusZ);
Vector pos = session.getPlacementPosition(player);
if (raised) {
pos = pos.add(0, radiusY, 0);
}
int affected = editSession.makeSphere(pos, Patterns.wrap(pattern), radiusX, radiusY, radiusZ, !hollow);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "forestgen" },
usage = "[size] [type] [density]",
desc = "Generate a forest",
min = 0,
max = 3
)
@CommandPermissions("worldedit.generation.forest")
@Logging(POSITION)
@SuppressWarnings("deprecation")
public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size, @Optional("tree") TreeType type, @Optional("5") double density) throws WorldEditException {
density = density / 100;
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, new TreeGenerator(type));
player.print(affected + " trees created.");
}
@Command(
aliases = { "pumpkins" },
usage = "[size]",
desc = "Generate pumpkin patches",
min = 0,
max = 1
)
@CommandPermissions("worldedit.generation.pumpkins")
@Logging(POSITION)
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException {
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem);
player.print(affected + " pumpkin patches created.");
}
@Command(
aliases = { "/hpyramid" },
usage = "<block> <size>",
desc = "Generate a hollow pyramid",
min = 2,
max = 2
)
@CommandPermissions("worldedit.generation.pyramid")
@Logging(PLACEMENT)
public void hollowPyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size) throws WorldEditException {
pyramid(player, session, editSession, pattern, size, true);
}
@Command(
aliases = { "/pyramid" },
usage = "<block> <size>",
flags = "h",
desc = "Generate a filled pyramid",
min = 2,
max = 2
)
@CommandPermissions("worldedit.generation.pyramid")
@Logging(PLACEMENT)
public void pyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size, @Switch('h') boolean hollow) throws WorldEditException {
Vector pos = session.getPlacementPosition(player);
worldEdit.checkMaxRadius(size);
int affected = editSession.makePyramid(pos, Patterns.wrap(pattern), size, !hollow);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = { "/generate", "/gen", "/g" },
usage = "<block> <expression>",
desc = "Generates a shape according to a formula.",
help =
"Generates a shape according to a formula that is expected to\n" +
"return positive numbers (true) if the point is inside the shape\n" +
"Optionally set type/data to the desired block.\n" +
"Flags:\n" +
" -h to generate a hollow shape\n" +
" -r to use raw minecraft coordinates\n" +
" -o is like -r, except offset from placement.\n" +
" -c is like -r, except offset selection center.\n" +
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
"See also tinyurl.com/wesyntax.",
flags = "hroc",
min = 2,
max = -1
)
@CommandPermissions("worldedit.generation.shape")
@Logging(ALL)
public void generate(Player player, LocalSession session, EditSession editSession,
@Selection Region region,
Pattern pattern,
@Text String expression,
@Switch('h') boolean hollow,
@Switch('r') boolean useRawCoords,
@Switch('o') boolean offset,
@Switch('c') boolean offsetCenter) throws WorldEditException {
final Vector zero;
Vector unit;
if (useRawCoords) {
zero = Vector.ZERO;
unit = Vector.ONE;
} else if (offset) {
zero = session.getPlacementPosition(player);
unit = Vector.ONE;
} else if (offsetCenter) {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = Vector.ONE;
} else {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);
if (unit.getX() == 0) unit = unit.setX(1.0);
if (unit.getY() == 0) unit = unit.setY(1.0);
if (unit.getZ() == 0) unit = unit.setZ(1.0);
}
try {
final int affected = editSession.makeShape(region, zero, unit, Patterns.wrap(pattern), expression, hollow);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
} catch (ExpressionException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/generatebiome", "/genbiome", "/gb" },
usage = "<block> <expression>",
desc = "Sets biome according to a formula.",
help =
"Generates a shape according to a formula that is expected to\n" +
"return positive numbers (true) if the point is inside the shape\n" +
"Optionally set type/data to the desired block.\n" +
"Flags:\n" +
" -h to generate a hollow shape\n" +
" -r to use raw minecraft coordinates\n" +
" -o is like -r, except offset from placement.\n" +
" -c is like -r, except offset selection center.\n" +
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
"See also tinyurl.com/wesyntax.",
flags = "hroc",
min = 2,
max = -1
)
@CommandPermissions({"worldedit.generation.shape", "worldedit.biome.set"})
@Logging(ALL)
public void generateBiome(Player player, LocalSession session, EditSession editSession,
@Selection Region region,
BaseBiome target,
@Text String expression,
@Switch('h') boolean hollow,
@Switch('r') boolean useRawCoords,
@Switch('o') boolean offset,
@Switch('c') boolean offsetCenter) throws WorldEditException {
final Vector zero;
Vector unit;
if (useRawCoords) {
zero = Vector.ZERO;
unit = Vector.ONE;
} else if (offset) {
zero = session.getPlacementPosition(player);
unit = Vector.ONE;
} else if (offsetCenter) {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = Vector.ONE;
} else {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);
if (unit.getX() == 0) unit = unit.setX(1.0);
if (unit.getY() == 0) unit = unit.setY(1.0);
if (unit.getZ() == 0) unit = unit.setZ(1.0);
}
try {
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow);
player.findFreePosition();
player.print("" + affected + " columns affected.");
} catch (ExpressionException e) {
player.printError(e.getMessage());
}
}
}

View File

@ -0,0 +1,127 @@
/*
* 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.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.entity.Player;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands to undo, redo, and clear history.
*/
public class HistoryCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public HistoryCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/undo", "undo" },
usage = "[times] [player]",
desc = "Undoes the last action",
min = 0,
max = 2
)
@CommandPermissions("worldedit.history.undo")
public void undo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int times = Math.max(1, args.getInteger(0, 1));
for (int i = 0; i < times; ++i) {
EditSession undone;
if (args.argsLength() < 2) {
undone = session.undo(session.getBlockBag(player), player);
} else {
player.checkPermission("worldedit.history.undo.other");
LocalSession sess = worldEdit.getSession(args.getString(1));
if (sess == null) {
player.printError("Unable to find session for " + args.getString(1));
break;
}
undone = sess.undo(session.getBlockBag(player), player);
}
if (undone != null) {
player.print("Undo successful.");
worldEdit.flushBlockBag(player, undone);
} else {
player.printError("Nothing left to undo.");
break;
}
}
}
@Command(
aliases = { "/redo", "redo" },
usage = "[times] [player]",
desc = "Redoes the last action (from history)",
min = 0,
max = 2
)
@CommandPermissions("worldedit.history.redo")
public void redo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int times = Math.max(1, args.getInteger(0, 1));
for (int i = 0; i < times; ++i) {
EditSession redone;
if (args.argsLength() < 2) {
redone = session.redo(session.getBlockBag(player), player);
} else {
player.checkPermission("worldedit.history.redo.other");
LocalSession sess = worldEdit.getSession(args.getString(1));
if (sess == null) {
player.printError("Unable to find session for " + args.getString(1));
break;
}
redone = sess.redo(session.getBlockBag(player), player);
}
if (redone != null) {
player.print("Redo successful.");
worldEdit.flushBlockBag(player, redone);
} else {
player.printError("Nothing left to redo.");
}
}
}
@Command(
aliases = { "/clearhistory", "clearhistory" },
usage = "",
desc = "Clear your history",
min = 0,
max = 0
)
@CommandPermissions("worldedit.history.clear")
public void clearHistory(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
session.clearHistory();
player.print("History cleared.");
}
}

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