mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-06-13 21:13:53 +00:00
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:
34
worldedit-core/src/main/assembly/default.xml
Normal file
34
worldedit-core/src/main/assembly/default.xml
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
65
worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java
Normal file
65
worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
436
worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java
Normal file
436
worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
66
worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java
Normal file
66
worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
44
worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java
Normal file
44
worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java
Normal 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";
|
||||
}
|
||||
|
||||
}
|
65
worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java
Normal file
65
worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
77
worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java
Normal file
77
worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
65
worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java
Normal file
65
worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
450
worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java
Normal file
450
worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
129
worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java
Normal file
129
worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
66
worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java
Normal file
66
worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
171
worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java
Normal file
171
worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
289
worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java
Normal file
289
worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
189
worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java
Normal file
189
worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
65
worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java
Normal file
65
worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
69
worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java
Normal file
69
worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
64
worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java
Normal file
64
worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java
Normal 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();
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
44
worldedit-core/src/main/java/com/sk89q/util/ArrayUtil.java
Normal file
44
worldedit-core/src/main/java/com/sk89q/util/ArrayUtil.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
304
worldedit-core/src/main/java/com/sk89q/util/StringUtil.java
Normal file
304
worldedit-core/src/main/java/com/sk89q/util/StringUtil.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
804
worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLNode.java
Normal file
804
worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLNode.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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, "");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
2336
worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
Normal file
2336
worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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(".");
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
129
worldedit-core/src/main/java/com/sk89q/worldedit/Location.java
Normal file
129
worldedit-core/src/main/java/com/sk89q/worldedit/Location.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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.");
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
850
worldedit-core/src/main/java/com/sk89q/worldedit/Vector.java
Normal file
850
worldedit-core/src/main/java/com/sk89q/worldedit/Vector.java
Normal 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 < 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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
667
worldedit-core/src/main/java/com/sk89q/worldedit/Vector2D.java
Normal file
667
worldedit-core/src/main/java/com/sk89q/worldedit/Vector2D.java
Normal 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 < 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)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
857
worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java
Normal file
857
worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java
Normal 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) {
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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() + "}";
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
@ -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() {
|
||||
}
|
||||
}
|
@ -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
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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.");
|
||||
}
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
Reference in New Issue
Block a user