Updated Gradle

This commit is contained in:
Matt
2016-02-22 23:11:28 -05:00
parent 7b15d50674
commit b69e31129d
407 changed files with 15242 additions and 15248 deletions

2
Core/build.gradle Normal file
View File

@ -0,0 +1,2 @@
apply plugin: 'eclipse'
apply plugin: 'idea'

View File

@ -0,0 +1,84 @@
package com.intellectualcrafters.configuration;
import java.util.Map;
/**
* Represents a source of configurable options and settings
*/
public interface Configuration extends ConfigurationSection {
/**
* Sets the default value of the given path as provided.
* <p>
* If no source {@link Configuration} was provided as a default
* collection, then a new {@link MemoryConfiguration} will be created to
* hold the new default value.
* <p>
* If value is null, the value will be removed from the default
* Configuration source.
*
* @param path Path of the value to set.
* @param value Value to set the default to.
* @throws IllegalArgumentException Thrown if path is null.
*/
@Override void addDefault(final String path, final Object value);
/**
* Sets the default values of the given paths as provided.
* <p>
* If no source {@link Configuration} was provided as a default
* collection, then a new {@link MemoryConfiguration} will be created to
* hold the new default values.
*
* @param defaults A map of Path->Values to add to defaults.
* @throws IllegalArgumentException Thrown if defaults is null.
*/
void addDefaults(final Map<String, Object> defaults);
/**
* Sets the default values of the given paths as provided.
* <p>
* If no source {@link Configuration} was provided as a default
* collection, then a new {@link MemoryConfiguration} will be created to
* hold the new default value.
* <p>
* This method will not hold a reference to the specified Configuration,
* nor will it automatically update if that Configuration ever changes. If
* you require this, you should set the default source with {@link
* #setDefaults(com.intellectualcrafters.configuration.Configuration)}.
*
* @param defaults A configuration holding a list of defaults to copy.
* @throws IllegalArgumentException Thrown if defaults is null or this.
*/
void addDefaults(final Configuration defaults);
/**
* Sets the source of all default values for this {@link Configuration}.
* <p>
* If a previous source was set, or previous default values were defined,
* then they will not be copied to the new source.
*
* @param defaults New source of default values for this configuration.
* @throws IllegalArgumentException Thrown if defaults is null or this.
*/
void setDefaults(final Configuration defaults);
/**
* Gets the source {@link Configuration} for this configuration.
* <p>
* If no configuration source was set, but default values were added, then
* a {@link MemoryConfiguration} will be returned. If no source was set
* and no defaults were set, then this method will return null.
*
* @return Configuration source for default values, or null if none exist.
*/
Configuration getDefaults();
/**
* Gets the {@link ConfigurationOptions} for this {@link Configuration}.
* <p>
* All setters through this method are chainable.
*
* @return Options for this configuration
*/
ConfigurationOptions options();
}

View File

@ -0,0 +1,90 @@
package com.intellectualcrafters.configuration;
/**
* Various settings for controlling the input and output of a {@link
* Configuration}
*/
public class ConfigurationOptions {
private char pathSeparator = '.';
private boolean copyDefaults = false;
private final Configuration configuration;
protected ConfigurationOptions(final Configuration configuration) {
this.configuration = configuration;
}
/**
* Returns the {@link Configuration} that this object is responsible for.
*
* @return Parent configuration
*/
public Configuration configuration() {
return configuration;
}
/**
* Gets the char that will be used to separate {@link
* ConfigurationSection}s
* <p>
* This value does not affect how the {@link Configuration} is stored,
* only in how you access the data. The default value is '.'.
*
* @return Path separator
*/
public char pathSeparator() {
return pathSeparator;
}
/**
* Sets the char that will be used to separate {@link
* ConfigurationSection}s
* <p>
* This value does not affect how the {@link Configuration} is stored,
* only in how you access the data. The default value is '.'.
*
* @param value Path separator
* @return This object, for chaining
*/
public ConfigurationOptions pathSeparator(final char value) {
pathSeparator = value;
return this;
}
/**
* Checks if the {@link Configuration} should copy values from its default
* {@link Configuration} directly.
* <p>
* If this is true, all values in the default Configuration will be
* directly copied, making it impossible to distinguish between values
* that were set and values that are provided by default. As a result,
* {@link ConfigurationSection#contains(java.lang.String)} will always
* return the same value as {@link
* ConfigurationSection#isSet(java.lang.String)}. The default value is
* false.
*
* @return Whether or not defaults are directly copied
*/
public boolean copyDefaults() {
return copyDefaults;
}
/**
* Sets if the {@link Configuration} should copy values from its default
* {@link Configuration} directly.
* <p>
* If this is true, all values in the default Configuration will be
* directly copied, making it impossible to distinguish between values
* that were set and values that are provided by default. As a result,
* {@link ConfigurationSection#contains(java.lang.String)} will always
* return the same value as {@link
* ConfigurationSection#isSet(java.lang.String)}. The default value is
* false.
*
* @param value Whether or not defaults are directly copied
* @return This object, for chaining
*/
public ConfigurationOptions copyDefaults(final boolean value) {
copyDefaults = value;
return this;
}
}

View File

@ -0,0 +1,642 @@
package com.intellectualcrafters.configuration;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Represents a section of a {@link Configuration}
*/
public interface ConfigurationSection {
/**
* Gets a set containing all keys in this section.
* <p>
* If deep is set to true, then this will contain all the keys within any
* child {@link ConfigurationSection}s (and their children, etc). These
* will be in a valid path notation for you to use.
* <p>
* If deep is set to false, then this will contain only the keys of any
* direct children, and not their own children.
*
* @param deep Whether or not to get a deep list, as opposed to a shallow
* list.
* @return Set of keys contained within this ConfigurationSection.
*/
Set<String> getKeys(final boolean deep);
/**
* Gets a Map containing all keys and their values for this section.
* <p>
* If deep is set to true, then this will contain all the keys and values
* within any child {@link ConfigurationSection}s (and their children,
* etc). These keys will be in a valid path notation for you to use.
* <p>
* If deep is set to false, then this will contain only the keys and
* values of any direct children, and not their own children.
*
* @param deep Whether or not to get a deep list, as opposed to a shallow
* list.
* @return Map of keys and values of this section.
*/
Map<String, Object> getValues(final boolean deep);
/**
* Checks if this {@link ConfigurationSection} contains the given path.
* <p>
* If the value for the requested path does not exist but a default value
* has been specified, this will return true.
*
* @param path Path to check for existence.
* @return True if this section contains the requested path, either via
* default or being set.
* @throws IllegalArgumentException Thrown when path is null.
*/
boolean contains(final String path);
/**
* Checks if this {@link ConfigurationSection} has a value set for the
* given path.
* <p>
* If the value for the requested path does not exist but a default value
* has been specified, this will still return false.
*
* @param path Path to check for existence.
* @return True if this section contains the requested path, regardless of
* having a default.
* @throws IllegalArgumentException Thrown when path is null.
*/
boolean isSet(final String path);
/**
* Gets the path of this {@link ConfigurationSection} from its root {@link
* Configuration}
* <p>
* For any {@link Configuration} themselves, this will return an empty
* string.
* <p>
* If the section is no longer contained within its root for any reason,
* such as being replaced with a different value, this may return null.
* <p>
* To retrieve the single name of this section, that is, the final part of
* the path returned by this method, you may use {@link #getName()}.
*
* @return Path of this section relative to its root
*/
String getCurrentPath();
/**
* Gets the name of this individual {@link ConfigurationSection}, in the
* path.
* <p>
* This will always be the final part of {@link #getCurrentPath()}, unless
* the section is orphaned.
*
* @return Name of this section
*/
String getName();
/**
* Gets the root {@link Configuration} that contains this {@link
* ConfigurationSection}
* <p>
* For any {@link Configuration} themselves, this will return its own
* object.
* <p>
* If the section is no longer contained within its root for any reason,
* such as being replaced with a different value, this may return null.
*
* @return Root configuration containing this section.
*/
Configuration getRoot();
/**
* Gets the parent {@link ConfigurationSection} that directly contains
* this {@link ConfigurationSection}.
* <p>
* For any {@link Configuration} themselves, this will return null.
* <p>
* If the section is no longer contained within its parent for any reason,
* such as being replaced with a different value, this may return null.
*
* @return Parent section containing this section.
*/
ConfigurationSection getParent();
/**
* Gets the requested Object by path.
* <p>
* If the Object does not exist but a default value has been specified,
* this will return the default value. If the Object does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the Object to get.
* @return Requested Object.
*/
Object get(final String path);
/**
* Gets the requested Object by path, returning a default value if not
* found.
* <p>
* If the Object does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the Object to get.
* @param def The default value to return if the path is not found.
* @return Requested Object.
*/
Object get(final String path, final Object def);
/**
* Sets the specified path to the given value.
* <p>
* If value is null, the entry will be removed. Any existing entry will be
* replaced, regardless of what the new value is.
* <p>
* Some implementations may have limitations on what you may store. See
* their individual javadoc for details. No implementations should allow
* you to store {@link Configuration}s or {@link ConfigurationSection}s,
* please use {@link #createSection(String)} for that.
*
* @param path Path of the object to set.
* @param value New value to set the path to.
*/
void set(final String path, final Object value);
/**
* Creates an empty {@link ConfigurationSection} at the specified path.
* <p>
* Any value that was previously set at this path will be overwritten. If
* the previous value was itself a {@link ConfigurationSection}, it will
* be orphaned.
*
* @param path Path to create the section at.
* @return Newly created section
*/
ConfigurationSection createSection(final String path);
/**
* Creates a {@link ConfigurationSection} at the specified path, with
* specified values.
* <p>
* Any value that was previously set at this path will be overwritten. If
* the previous value was itself a {@link ConfigurationSection}, it will
* be orphaned.
*
* @param path Path to create the section at.
* @param map The values to used.
* @return Newly created section
*/
ConfigurationSection createSection(final String path, final Map<?, ?> map);
// Primitives
/**
* Gets the requested String by path.
* <p>
* If the String does not exist but a default value has been specified,
* this will return the default value. If the String does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the String to get.
* @return Requested String.
*/
String getString(final String path);
/**
* Gets the requested String by path, returning a default value if not
* found.
* <p>
* If the String does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the String to get.
* @param def The default value to return if the path is not found or is
* not a String.
* @return Requested String.
*/
String getString(final String path, final String def);
/**
* Checks if the specified path is a String.
* <p>
* If the path exists but is not a String, this will return false. If the
* path does not exist, this will return false. If the path does not exist
* but a default value has been specified, this will check if that default
* value is a String and return appropriately.
*
* @param path Path of the String to check.
* @return Whether or not the specified path is a String.
*/
boolean isString(final String path);
/**
* Gets the requested int by path.
* <p>
* If the int does not exist but a default value has been specified, this
* will return the default value. If the int does not exist and no default
* value was specified, this will return 0.
*
* @param path Path of the int to get.
* @return Requested int.
*/
int getInt(final String path);
/**
* Gets the requested int by path, returning a default value if not found.
* <p>
* If the int does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the int to get.
* @param def The default value to return if the path is not found or is
* not an int.
* @return Requested int.
*/
int getInt(final String path, final int def);
/**
* Checks if the specified path is an int.
* <p>
* If the path exists but is not a int, this will return false. If the
* path does not exist, this will return false. If the path does not exist
* but a default value has been specified, this will check if that default
* value is a int and return appropriately.
*
* @param path Path of the int to check.
* @return Whether or not the specified path is an int.
*/
boolean isInt(final String path);
/**
* Gets the requested boolean by path.
* <p>
* If the boolean does not exist but a default value has been specified,
* this will return the default value. If the boolean does not exist and
* no default value was specified, this will return false.
*
* @param path Path of the boolean to get.
* @return Requested boolean.
*/
boolean getBoolean(final String path);
/**
* Gets the requested boolean by path, returning a default value if not
* found.
* <p>
* If the boolean does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the boolean to get.
* @param def The default value to return if the path is not found or is
* not a boolean.
* @return Requested boolean.
*/
boolean getBoolean(final String path, final boolean def);
/**
* Checks if the specified path is a boolean.
* <p>
* If the path exists but is not a boolean, this will return false. If the
* path does not exist, this will return false. If the path does not exist
* but a default value has been specified, this will check if that default
* value is a boolean and return appropriately.
*
* @param path Path of the boolean to check.
* @return Whether or not the specified path is a boolean.
*/
boolean isBoolean(final String path);
/**
* Gets the requested double by path.
* <p>
* If the double does not exist but a default value has been specified,
* this will return the default value. If the double does not exist and no
* default value was specified, this will return 0.
*
* @param path Path of the double to get.
* @return Requested double.
*/
double getDouble(final String path);
/**
* Gets the requested double by path, returning a default value if not
* found.
* <p>
* If the double does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the double to get.
* @param def The default value to return if the path is not found or is
* not a double.
* @return Requested double.
*/
double getDouble(final String path, final double def);
/**
* Checks if the specified path is a double.
* <p>
* If the path exists but is not a double, this will return false. If the
* path does not exist, this will return false. If the path does not exist
* but a default value has been specified, this will check if that default
* value is a double and return appropriately.
*
* @param path Path of the double to check.
* @return Whether or not the specified path is a double.
*/
boolean isDouble(final String path);
/**
* Gets the requested long by path.
* <p>
* If the long does not exist but a default value has been specified, this
* will return the default value. If the long does not exist and no
* default value was specified, this will return 0.
*
* @param path Path of the long to get.
* @return Requested long.
*/
long getLong(final String path);
/**
* Gets the requested long by path, returning a default value if not
* found.
* <p>
* If the long does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the long to get.
* @param def The default value to return if the path is not found or is
* not a long.
* @return Requested long.
*/
long getLong(final String path, final long def);
/**
* Checks if the specified path is a long.
* <p>
* If the path exists but is not a long, this will return false. If the
* path does not exist, this will return false. If the path does not exist
* but a default value has been specified, this will check if that default
* value is a long and return appropriately.
*
* @param path Path of the long to check.
* @return Whether or not the specified path is a long.
*/
boolean isLong(final String path);
// Java
/**
* Gets the requested List by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the List to get.
* @return Requested List.
*/
List<?> getList(final String path);
/**
* Gets the requested List by path, returning a default value if not
* found.
* <p>
* If the List does not exist then the specified default value will
* returned regardless of if a default has been identified in the root
* {@link Configuration}.
*
* @param path Path of the List to get.
* @param def The default value to return if the path is not found or is
* not a List.
* @return Requested List.
*/
List<?> getList(final String path, final List<?> def);
/**
* Checks if the specified path is a List.
* <p>
* If the path exists but is not a List, this will return false. If the
* path does not exist, this will return false. If the path does not exist
* but a default value has been specified, this will check if that default
* value is a List and return appropriately.
*
* @param path Path of the List to check.
* @return Whether or not the specified path is a List.
*/
boolean isList(final String path);
/**
* Gets the requested List of String by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a String if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of String.
*/
List<String> getStringList(final String path);
/**
* Gets the requested List of Integer by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Integer if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Integer.
*/
List<Integer> getIntegerList(final String path);
/**
* Gets the requested List of Boolean by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Boolean if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Boolean.
*/
List<Boolean> getBooleanList(final String path);
/**
* Gets the requested List of Double by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Double if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Double.
*/
List<Double> getDoubleList(final String path);
/**
* Gets the requested List of Float by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Float if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Float.
*/
List<Float> getFloatList(final String path);
/**
* Gets the requested List of Long by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Long if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Long.
*/
List<Long> getLongList(final String path);
/**
* Gets the requested List of Byte by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Byte if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Byte.
*/
List<Byte> getByteList(final String path);
/**
* Gets the requested List of Character by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Character if
* possible, but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Character.
*/
List<Character> getCharacterList(final String path);
/**
* Gets the requested List of Short by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Short if possible,
* but may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Short.
*/
List<Short> getShortList(final String path);
/**
* Gets the requested List of Maps by path.
* <p>
* If the List does not exist but a default value has been specified, this
* will return the default value. If the List does not exist and no
* default value was specified, this will return an empty List.
* <p>
* This method will attempt to cast any values into a Map if possible, but
* may miss any values out if they are not compatible.
*
* @param path Path of the List to get.
* @return Requested List of Maps.
*/
List<Map<?, ?>> getMapList(final String path);
/**
* Gets the requested ConfigurationSection by path.
* <p>
* If the ConfigurationSection does not exist but a default value has been
* specified, this will return the default value. If the
* ConfigurationSection does not exist and no default value was specified,
* this will return null.
*
* @param path Path of the ConfigurationSection to get.
* @return Requested ConfigurationSection.
*/
ConfigurationSection getConfigurationSection(final String path);
/**
* Checks if the specified path is a ConfigurationSection.
* <p>
* If the path exists but is not a ConfigurationSection, this will return
* false. If the path does not exist, this will return false. If the path
* does not exist but a default value has been specified, this will check
* if that default value is a ConfigurationSection and return
* appropriately.
*
* @param path Path of the ConfigurationSection to check.
* @return Whether or not the specified path is a ConfigurationSection.
*/
boolean isConfigurationSection(final String path);
/**
* Gets the equivalent {@link ConfigurationSection} from the default
* {@link Configuration} defined in {@link #getRoot()}.
* <p>
* If the root contains no defaults, or the defaults doesn't contain a
* value for this path, or the value at this path is not a {@link
* ConfigurationSection} then this will return null.
*
* @return Equivalent section in root configuration
*/
ConfigurationSection getDefaultSection();
/**
* Sets the default value in the root at the given path as provided.
* <p>
* If no source {@link Configuration} was provided as a default
* collection, then a new {@link MemoryConfiguration} will be created to
* hold the new default value.
* <p>
* If value is null, the value will be removed from the default
* Configuration source.
* <p>
* If the value as returned by {@link #getDefaultSection()} is null, then
* this will create a new section at the path, replacing anything that may
* have existed there previously.
*
* @param path Path of the value to set.
* @param value Value to set the default to.
* @throws IllegalArgumentException Thrown if path is null.
*/
void addDefault(final String path, final Object value);
}

View File

@ -0,0 +1,45 @@
package com.intellectualcrafters.configuration;
/**
* Exception thrown when attempting to load an invalid {@link Configuration}
*/
@SuppressWarnings("serial")
public class InvalidConfigurationException extends Exception {
/**
* Creates a new instance of InvalidConfigurationException without a
* message or cause.
*/
public InvalidConfigurationException() {}
/**
* Constructs an instance of InvalidConfigurationException with the
* specified message.
*
* @param msg The details of the exception.
*/
public InvalidConfigurationException(final String msg) {
super(msg);
}
/**
* Constructs an instance of InvalidConfigurationException with the
* specified cause.
*
* @param cause The cause of the exception.
*/
public InvalidConfigurationException(final Throwable cause) {
super(cause);
}
/**
* Constructs an instance of InvalidConfigurationException with the
* specified message and cause.
*
* @param cause The cause of the exception.
* @param msg The details of the exception.
*/
public InvalidConfigurationException(final String msg, final Throwable cause) {
super(msg, cause);
}
}

View File

@ -0,0 +1,89 @@
package com.intellectualcrafters.configuration;
import java.util.Map;
/**
* This is a {@link Configuration} implementation that does not save or load
* from any source, and stores all values in memory only.
* This is useful for temporary Configurations for providing defaults.
*/
public class MemoryConfiguration extends MemorySection implements Configuration {
protected Configuration defaults;
protected MemoryConfigurationOptions options;
/**
* Creates an empty {@link MemoryConfiguration} with no default values.
*/
public MemoryConfiguration() {}
/**
* Creates an empty {@link MemoryConfiguration} using the specified {@link
* Configuration} as a source for all default values.
*
* @param defaults Default value provider
* @throws IllegalArgumentException Thrown if defaults is null
*/
public MemoryConfiguration(final Configuration defaults) {
this.defaults = defaults;
}
@Override
public void addDefault(final String path, final Object value) {
if (path == null) {
throw new NullPointerException("Path may not be null");
}
if (defaults == null) {
defaults = new MemoryConfiguration();
}
defaults.set(path, value);
}
@Override
public void addDefaults(final Map<String, Object> defaults) {
if (defaults == null) {
throw new NullPointerException("Defaults may not be null");
}
for (final Map.Entry<String, Object> entry : defaults.entrySet()) {
addDefault(entry.getKey(), entry.getValue());
}
}
@Override
public void addDefaults(final Configuration defaults) {
if (defaults == null) {
throw new NullPointerException("Defaults may not be null");
}
addDefaults(defaults.getValues(true));
}
@Override
public void setDefaults(final Configuration defaults) {
if (defaults == null) {
throw new NullPointerException("Defaults may not be null");
}
this.defaults = defaults;
}
@Override
public Configuration getDefaults() {
return defaults;
}
@Override
public ConfigurationSection getParent() {
return null;
}
@Override
public MemoryConfigurationOptions options() {
if (options == null) {
options = new MemoryConfigurationOptions(this);
}
return options;
}
}

View File

@ -0,0 +1,28 @@
package com.intellectualcrafters.configuration;
/**
* Various settings for controlling the input and output of a {@link
* MemoryConfiguration}
*/
public class MemoryConfigurationOptions extends ConfigurationOptions {
protected MemoryConfigurationOptions(final MemoryConfiguration configuration) {
super(configuration);
}
@Override
public MemoryConfiguration configuration() {
return (MemoryConfiguration) super.configuration();
}
@Override
public MemoryConfigurationOptions copyDefaults(final boolean value) {
super.copyDefaults(value);
return this;
}
@Override
public MemoryConfigurationOptions pathSeparator(final char value) {
super.pathSeparator(value);
return this;
}
}

View File

@ -0,0 +1,864 @@
package com.intellectualcrafters.configuration;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A type of {@link ConfigurationSection} that is stored in memory.
*/
public class MemorySection implements ConfigurationSection {
protected final Map<String, Object> map = new LinkedHashMap<>();
private final Configuration root;
private final ConfigurationSection parent;
private final String path;
private final String fullPath;
/**
* Creates an empty MemorySection for use as a root {@link Configuration}
* section.
* <p>
* Note that calling this without being yourself a {@link Configuration}
* will throw an exception!
*
* @throws IllegalStateException Thrown if this is not a {@link
* Configuration} root.
*/
protected MemorySection() {
if (!(this instanceof Configuration)) {
throw new IllegalStateException("Cannot construct a root MemorySection when not a Configuration");
}
path = "";
fullPath = "";
parent = null;
root = (Configuration) this;
}
/**
* Creates an empty MemorySection with the specified parent and path.
*
* @param parent Parent section that contains this own section.
* @param path Path that you may access this section from via the root
* {@link Configuration}.
* @throws IllegalArgumentException Thrown is parent or path is null, or
* if parent contains no root Configuration.
*/
protected MemorySection(final ConfigurationSection parent, final String path) {
if (parent == null) {
throw new NullPointerException("Parent may not be null");
}
if (path == null) {
throw new NullPointerException("Path may not be null");
}
this.path = path;
this.parent = parent;
root = parent.getRoot();
if (root == null) {
throw new NullPointerException("Path may not be orphaned");
}
fullPath = createPath(parent, path);
}
public static double toDouble(final Object obj, final double def) {
if (obj instanceof Number) {
return ((Number) obj).doubleValue();
}
if (obj instanceof String) {
try {
return Double.parseDouble((String) obj);
} catch (NumberFormatException ignored) {
}
} else if (obj instanceof List) {
final List<?> val = ((List<?>) obj);
if (!val.isEmpty()) {
return toDouble(val.get(0), def);
}
}
return def;
}
public static int toInt(final Object obj, final int def) {
if (obj instanceof Number) {
return ((Number) obj).intValue();
}
if (obj instanceof String) {
try {
return Integer.parseInt((String) obj);
} catch (NumberFormatException ignored) {
}
} else if (obj instanceof List) {
final List<?> val = ((List<?>) obj);
if (!val.isEmpty()) {
return toInt(val.get(0), def);
}
}
return def;
}
public static long toLong(final Object obj, final long def) {
if (obj instanceof Number) {
return ((Number) obj).longValue();
}
if (obj instanceof String) {
try {
return Long.parseLong((String) obj);
} catch (NumberFormatException ignored) {
}
} else if (obj instanceof List) {
final List<?> val = ((List<?>) obj);
if (!val.isEmpty()) {
return toLong(val.get(0), def);
}
}
return def;
}
/**
* Creates a full path to the given {@link ConfigurationSection} from its
* root {@link Configuration}.
* <p>
* You may use this method for any given {@link ConfigurationSection}, not
* only {@link MemorySection}.
*
* @param section Section to create a path for.
* @param key Name of the specified section.
* @return Full path of the section from its root.
*/
public static String createPath(final ConfigurationSection section, final String key) {
return createPath(section, key, (section == null) ? null : section.getRoot());
}
/**
* Creates a relative path to the given {@link ConfigurationSection} from
* the given relative section.
* <p>
* You may use this method for any given {@link ConfigurationSection}, not
* only {@link MemorySection}.
*
* @param section Section to create a path for.
* @param key Name of the specified section.
* @param relativeTo Section to create the path relative to.
* @return Full path of the section from its root.
*/
public static String createPath(final ConfigurationSection section, final String key, final ConfigurationSection relativeTo) {
if (section == null) {
throw new NullPointerException("Cannot create path without a section");
}
final Configuration root = section.getRoot();
if (root == null) {
throw new IllegalStateException("Cannot create path without a root");
}
final char separator = root.options().pathSeparator();
final StringBuilder builder = new StringBuilder();
for (ConfigurationSection parent = section; (parent != null) && (parent != relativeTo); parent = parent.getParent()) {
if (builder.length() > 0) {
builder.insert(0, separator);
}
builder.insert(0, parent.getName());
}
if ((key != null) && (!key.isEmpty())) {
if (builder.length() > 0) {
builder.append(separator);
}
builder.append(key);
}
return builder.toString();
}
@Override
public Set<String> getKeys(final boolean deep) {
final Set<String> result = new LinkedHashSet<>();
final Configuration root = getRoot();
if ((root != null) && root.options().copyDefaults()) {
final ConfigurationSection defaults = getDefaultSection();
if (defaults != null) {
result.addAll(defaults.getKeys(deep));
}
}
mapChildrenKeys(result, this, deep);
return result;
}
@Override
public Map<String, Object> getValues(final boolean deep) {
final Map<String, Object> result = new LinkedHashMap<>();
final Configuration root = getRoot();
if ((root != null) && root.options().copyDefaults()) {
final ConfigurationSection defaults = getDefaultSection();
if (defaults != null) {
result.putAll(defaults.getValues(deep));
}
}
mapChildrenValues(result, this, deep);
return result;
}
@Override
public boolean contains(final String path) {
return get(path) != null;
}
@Override
public boolean isSet(final String path) {
final Configuration root = getRoot();
if (root == null) {
return false;
}
if (root.options().copyDefaults()) {
return contains(path);
}
return get(path, null) != null;
}
@Override
public String getCurrentPath() {
return fullPath;
}
@Override
public String getName() {
return path;
}
@Override
public Configuration getRoot() {
return root;
}
@Override
public ConfigurationSection getParent() {
return parent;
}
@Override
public void addDefault(final String path, final Object value) {
if (path == null) {
throw new NullPointerException("Path cannot be null");
}
final Configuration root = getRoot();
if (root == null) {
throw new IllegalStateException("Cannot add default without root");
}
if (root == this) {
throw new UnsupportedOperationException("Unsupported addDefault(String, Object) implementation");
}
root.addDefault(createPath(this, path), value);
}
@Override
public ConfigurationSection getDefaultSection() {
final Configuration root = getRoot();
final Configuration defaults = root == null ? null : root.getDefaults();
if (defaults != null) {
if (defaults.isConfigurationSection(getCurrentPath())) {
return defaults.getConfigurationSection(getCurrentPath());
}
}
return null;
}
@Override
public void set(final String path, final Object value) {
if (path == null) {
throw new NullPointerException("Cannot set to an empty path");
}
final Configuration root = getRoot();
if (root == null) {
throw new IllegalStateException("Cannot use section without a root");
}
final char separator = root.options().pathSeparator();
// i1 is the leading (higher) index
// i2 is the trailing (lower) index
int i1 = -1, i2;
ConfigurationSection section = this;
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
final String node = path.substring(i2, i1);
final ConfigurationSection subSection = section.getConfigurationSection(node);
if (subSection == null) {
section = section.createSection(node);
} else {
section = subSection;
}
}
final String key = path.substring(i2);
if (section == this) {
if (value == null) {
map.remove(key);
} else {
map.put(key, value);
}
} else {
section.set(key, value);
}
}
@Override
public Object get(final String path) {
return get(path, getDefault(path));
}
@Override
public Object get(final String path, final Object def) {
if (path == null) {
throw new NullPointerException("Path cannot be null");
}
if (path.isEmpty()) {
return this;
}
final Configuration root = getRoot();
if (root == null) {
throw new IllegalStateException("Cannot access section without a root");
}
final char separator = root.options().pathSeparator();
// i1 is the leading (higher) index
// i2 is the trailing (lower) index
int i1 = -1, i2;
ConfigurationSection section = this;
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
section = section.getConfigurationSection(path.substring(i2, i1));
if (section == null) {
return def;
}
}
final String key = path.substring(i2);
if (section == this) {
final Object result = map.get(key);
return (result == null) ? def : result;
}
return section.get(key, def);
}
@Override
public ConfigurationSection createSection(final String path) {
if (path == null) {
throw new NullPointerException("Cannot create section at empty path");
}
final Configuration root = getRoot();
if (root == null) {
throw new IllegalStateException("Cannot create section without a root");
}
final char separator = root.options().pathSeparator();
// i1 is the leading (higher) index
// i2 is the trailing (lower) index
int i1 = -1, i2;
ConfigurationSection section = this;
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
final String node = path.substring(i2, i1);
final ConfigurationSection subSection = section.getConfigurationSection(node);
if (subSection == null) {
section = section.createSection(node);
} else {
section = subSection;
}
}
final String key = path.substring(i2);
if (section == this) {
final ConfigurationSection result = new MemorySection(this, key);
map.put(key, result);
return result;
}
return section.createSection(key);
}
@Override
public ConfigurationSection createSection(final String path, final Map<?, ?> map) {
final ConfigurationSection section = createSection(path);
for (final Map.Entry<?, ?> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
section.createSection(entry.getKey().toString(), (Map<?, ?>) entry.getValue());
} else {
section.set(entry.getKey().toString(), entry.getValue());
}
}
return section;
}
// Primitives
@Override
public String getString(final String path) {
final Object def = getDefault(path);
return getString(path, def != null ? def.toString() : null);
}
@Override
public String getString(final String path, final String def) {
final Object val = get(path, def);
return (val != null) ? val.toString() : def;
}
@Override
public boolean isString(final String path) {
final Object val = get(path);
return val instanceof String;
}
@Override
public int getInt(final String path) {
final Object def = getDefault(path);
return getInt(path, toInt(def, 0));
}
@Override
public int getInt(final String path, final int def) {
final Object val = get(path, def);
return toInt(val, def);
}
@Override
public boolean isInt(final String path) {
final Object val = get(path);
return val instanceof Integer;
}
@Override
public boolean getBoolean(final String path) {
final Object def = getDefault(path);
return getBoolean(path, (def instanceof Boolean) ? (Boolean) def : false);
}
@Override
public boolean getBoolean(final String path, final boolean def) {
final Object val = get(path, def);
return (val instanceof Boolean) ? (Boolean) val : def;
}
@Override
public boolean isBoolean(final String path) {
final Object val = get(path);
return val instanceof Boolean;
}
@Override
public double getDouble(final String path) {
final Object def = getDefault(path);
return getDouble(path, toDouble(def, 0));
}
@Override
public double getDouble(final String path, final double def) {
final Object val = get(path, def);
return toDouble(val, def);
}
@Override
public boolean isDouble(final String path) {
final Object val = get(path);
return val instanceof Double;
}
@Override
public long getLong(final String path) {
final Object def = getDefault(path);
return getLong(path, toLong(def, 0));
}
@Override
public long getLong(final String path, final long def) {
final Object val = get(path, def);
return toLong(val, def);
}
@Override
public boolean isLong(final String path) {
final Object val = get(path);
return val instanceof Long;
}
// Java
@Override
public List<?> getList(final String path) {
final Object def = getDefault(path);
return getList(path, (def instanceof List) ? (List<?>) def : null);
}
@Override
public List<?> getList(final String path, final List<?> def) {
final Object val = get(path, def);
return (List<?>) ((val instanceof List) ? val : def);
}
@Override
public boolean isList(final String path) {
final Object val = get(path);
return val instanceof List;
}
@Override
public List<String> getStringList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<String> result = new ArrayList<>();
for (final Object object : list) {
if ((object instanceof String) || (isPrimitiveWrapper(object))) {
result.add(String.valueOf(object));
}
}
return result;
}
@Override
public List<Integer> getIntegerList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Integer> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Integer) {
result.add((Integer) object);
} else if (object instanceof String) {
try {
result.add(Integer.valueOf((String) object));
} catch (NumberFormatException ignored) {
}
} else if (object instanceof Character) {
result.add((int) (Character) object);
} else if (object instanceof Number) {
result.add(((Number) object).intValue());
}
}
return result;
}
@Override
public List<Boolean> getBooleanList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Boolean> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Boolean) {
result.add((Boolean) object);
} else if (object instanceof String) {
if (Boolean.TRUE.toString().equals(object)) {
result.add(true);
} else if (Boolean.FALSE.toString().equals(object)) {
result.add(false);
}
}
}
return result;
}
@Override
public List<Double> getDoubleList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Double> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Double) {
result.add((Double) object);
} else if (object instanceof String) {
try {
result.add(Double.valueOf((String) object));
} catch (NumberFormatException ignored) {
}
} else if (object instanceof Character) {
result.add((double) (Character) object);
} else if (object instanceof Number) {
result.add(((Number) object).doubleValue());
}
}
return result;
}
@Override
public List<Float> getFloatList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Float> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Float) {
result.add((Float) object);
} else if (object instanceof String) {
try {
result.add(Float.valueOf((String) object));
} catch (NumberFormatException ignored) {
}
} else if (object instanceof Character) {
result.add((float) (Character) object);
} else if (object instanceof Number) {
result.add(((Number) object).floatValue());
}
}
return result;
}
@Override
public List<Long> getLongList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Long> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Long) {
result.add((Long) object);
} else if (object instanceof String) {
try {
result.add(Long.valueOf((String) object));
} catch (NumberFormatException ignored) {
}
} else if (object instanceof Character) {
result.add((long) (Character) object);
} else if (object instanceof Number) {
result.add(((Number) object).longValue());
}
}
return result;
}
@Override
public List<Byte> getByteList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Byte> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Byte) {
result.add((Byte) object);
} else if (object instanceof String) {
try {
result.add(Byte.valueOf((String) object));
} catch (NumberFormatException ignored) {
}
} else if (object instanceof Character) {
result.add((byte) ((Character) object).charValue());
} else if (object instanceof Number) {
result.add(((Number) object).byteValue());
}
}
return result;
}
@Override
public List<Character> getCharacterList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Character> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Character) {
result.add((Character) object);
} else if (object instanceof String) {
final String str = (String) object;
if (str.length() == 1) {
result.add(str.charAt(0));
}
} else if (object instanceof Number) {
result.add((char) ((Number) object).intValue());
}
}
return result;
}
@Override
public List<Short> getShortList(final String path) {
final List<?> list = getList(path);
if (list == null) {
return new ArrayList<>(0);
}
final List<Short> result = new ArrayList<>();
for (final Object object : list) {
if (object instanceof Short) {
result.add((Short) object);
} else if (object instanceof String) {
try {
result.add(Short.valueOf((String) object));
} catch (NumberFormatException ignored) {
}
} else if (object instanceof Character) {
result.add((short) ((Character) object).charValue());
} else if (object instanceof Number) {
result.add(((Number) object).shortValue());
}
}
return result;
}
@Override
public List<Map<?, ?>> getMapList(final String path) {
final List<?> list = getList(path);
final List<Map<?, ?>> result = new ArrayList<>();
if (list == null) {
return result;
}
for (final Object object : list) {
if (object instanceof Map) {
result.add((Map<?, ?>) object);
}
}
return result;
}
@Override
public ConfigurationSection getConfigurationSection(final String path) {
Object val = get(path, null);
if (val != null) {
return (val instanceof ConfigurationSection) ? (ConfigurationSection) val : null;
}
val = get(path, getDefault(path));
return (val instanceof ConfigurationSection) ? createSection(path) : null;
}
@Override
public boolean isConfigurationSection(final String path) {
final Object val = get(path);
return val instanceof ConfigurationSection;
}
protected boolean isPrimitiveWrapper(final Object input) {
return (input instanceof Integer)
|| (input instanceof Boolean)
|| (input instanceof Character)
|| (input instanceof Byte)
|| (input instanceof Short)
|| (input instanceof Double)
|| (input instanceof Long)
|| (input instanceof Float);
}
protected Object getDefault(final String path) {
if (path == null) {
throw new NullPointerException("Path may not be null");
}
final Configuration root = getRoot();
final Configuration defaults = root == null ? null : root.getDefaults();
return (defaults == null) ? null : defaults.get(createPath(this, path));
}
protected void mapChildrenKeys(final Set<String> output, final ConfigurationSection section, final boolean deep) {
if (section instanceof MemorySection) {
final MemorySection sec = (MemorySection) section;
for (final Map.Entry<String, Object> entry : sec.map.entrySet()) {
output.add(createPath(section, entry.getKey(), this));
if ((deep) && (entry.getValue() instanceof ConfigurationSection)) {
final ConfigurationSection subsection = (ConfigurationSection) entry.getValue();
mapChildrenKeys(output, subsection, deep);
}
}
} else {
final Set<String> keys = section.getKeys(deep);
for (final String key : keys) {
output.add(createPath(section, key, this));
}
}
}
protected void mapChildrenValues(final Map<String, Object> output, final ConfigurationSection section, final boolean deep) {
if (section instanceof MemorySection) {
final MemorySection sec = (MemorySection) section;
for (final Map.Entry<String, Object> entry : sec.map.entrySet()) {
output.put(createPath(section, entry.getKey(), this), entry.getValue());
if (entry.getValue() instanceof ConfigurationSection) {
if (deep) {
mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep);
}
}
}
} else {
final Map<String, Object> values = section.getValues(deep);
for (final Map.Entry<String, Object> entry : values.entrySet()) {
output.put(createPath(section, entry.getKey(), this), entry.getValue());
}
}
}
@Override
public String toString() {
final Configuration root = getRoot();
return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + (root == null ? null : root.getClass().getSimpleName()) +
"']";
}
}

View File

@ -0,0 +1,221 @@
package com.intellectualcrafters.configuration.file;
import com.intellectualcrafters.configuration.Configuration;
import com.intellectualcrafters.configuration.InvalidConfigurationException;
import com.intellectualcrafters.configuration.MemoryConfiguration;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
/**
* This is a base class for all File based implementations of {@link
* Configuration}
*/
public abstract class FileConfiguration extends MemoryConfiguration {
/**
* Creates an empty {@link FileConfiguration} with no default values.
*/
public FileConfiguration() {
super();
}
/**
* Creates an empty {@link FileConfiguration} using the specified {@link
* Configuration} as a source for all default values.
*
* @param defaults Default value provider
*/
public FileConfiguration(final Configuration defaults) {
super(defaults);
}
/**
* Saves this {@link FileConfiguration} to the specified location.
* <p>
* If the file does not exist, it will be created. If already exists, it
* will be overwritten. If it cannot be overwritten or created, an
* exception will be thrown.
* <p>
* This method will save using the system default encoding, or possibly
* using UTF8.
*
* @param file File to save to.
* @throws IOException Thrown when the given file cannot be written to for
* any reason.
* @throws IllegalArgumentException Thrown when file is null.
*/
public void save(final File file) throws IOException {
if (file == null) {
throw new NullPointerException("File cannot be null");
}
file.getParentFile().mkdirs();
final String data = saveToString();
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
writer.write(data);
}
}
/**
* Saves this {@link FileConfiguration} to the specified location.
* <p>
* If the file does not exist, it will be created. If already exists, it
* will be overwritten. If it cannot be overwritten or created, an
* exception will be thrown.
* <p>
* This method will save using the system default encoding, or possibly
* using UTF8.
*
* @param file File to save to.
* @throws IOException Thrown when the given file cannot be written to for
* any reason.
* @throws IllegalArgumentException Thrown when file is null.
*/
public void save(final String file) throws IOException {
if (file == null) {
throw new NullPointerException("File cannot be null");
}
save(new File(file));
}
/**
* Saves this {@link FileConfiguration} to a string, and returns it.
*
* @return String containing this configuration.
*/
public abstract String saveToString();
/**
* Loads this {@link FileConfiguration} from the specified location.
* <p>
* All the values contained within this configuration will be removed,
* leaving only settings and defaults, and the new values will be loaded
* from the given file.
* <p>
* If the file cannot be loaded for any reason, an exception will be
* thrown.
* <p>
*
* @param file File to load from.
* @throws FileNotFoundException Thrown when the given file cannot be
* opened.
* @throws IOException Thrown when the given file cannot be read.
* @throws InvalidConfigurationException Thrown when the given file is not
* a valid Configuration.
* @throws IllegalArgumentException Thrown when file is null.
*/
public void load(final File file) throws IOException, InvalidConfigurationException {
if (file == null) {
throw new NullPointerException("File cannot be null");
}
final FileInputStream stream = new FileInputStream(file);
load(new InputStreamReader(stream, StandardCharsets.UTF_8));
}
/**
* Loads this {@link FileConfiguration} from the specified reader.
* <p>
* All the values contained within this configuration will be removed,
* leaving only settings and defaults, and the new values will be loaded
* from the given stream.
*
* @param reader the reader to load from
* @throws IOException thrown when underlying reader throws an IOException
* @throws InvalidConfigurationException thrown when the reader does not
* represent a valid Configuration
* @throws IllegalArgumentException thrown when reader is null
*/
public void load(final Reader reader) throws IOException, InvalidConfigurationException {
final StringBuilder builder = new StringBuilder();
try (BufferedReader input = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader)) {
String line;
while ((line = input.readLine()) != null) {
builder.append(line);
builder.append('\n');
}
}
loadFromString(builder.toString());
}
/**
* Loads this {@link FileConfiguration} from the specified location.
* <p>
* All the values contained within this configuration will be removed,
* leaving only settings and defaults, and the new values will be loaded
* from the given file.
* <p>
* If the file cannot be loaded for any reason, an exception will be
* thrown.
*
* @param file File to load from.
* @throws FileNotFoundException Thrown when the given file cannot be
* opened.
* @throws IOException Thrown when the given file cannot be read.
* @throws InvalidConfigurationException Thrown when the given file is not
* a valid Configuration.
* @throws IllegalArgumentException Thrown when file is null.
*/
public void load(final String file) throws IOException, InvalidConfigurationException {
if (file == null) {
throw new NullPointerException("File cannot be null");
}
load(new File(file));
}
/**
* Loads this {@link FileConfiguration} from the specified string, as
* opposed to from file.
* <p>
* All the values contained within this configuration will be removed,
* leaving only settings and defaults, and the new values will be loaded
* from the given string.
* <p>
* If the string is invalid in any way, an exception will be thrown.
*
* @param contents Contents of a Configuration to load.
* @throws InvalidConfigurationException Thrown if the specified string is
* invalid.
* @throws IllegalArgumentException Thrown if contents is null.
*/
public abstract void loadFromString(final String contents) throws InvalidConfigurationException;
/**
* Compiles the header for this {@link FileConfiguration} and returns the
* result.
* <p>
* This will use the header from {@link #options()} -> {@link
* FileConfigurationOptions#header()}, respecting the rules of {@link
* FileConfigurationOptions#copyHeader()} if set.
*
* @return Compiled header
*/
protected abstract String buildHeader();
@Override
public FileConfigurationOptions options() {
if (options == null) {
options = new FileConfigurationOptions(this);
}
return (FileConfigurationOptions) options;
}
}

View File

@ -0,0 +1,119 @@
package com.intellectualcrafters.configuration.file;
import com.intellectualcrafters.configuration.MemoryConfiguration;
import com.intellectualcrafters.configuration.MemoryConfigurationOptions;
/**
* Various settings for controlling the input and output of a {@link
* FileConfiguration}
*/
public class FileConfigurationOptions extends MemoryConfigurationOptions {
private String header = null;
private boolean copyHeader = true;
protected FileConfigurationOptions(final MemoryConfiguration configuration) {
super(configuration);
}
@Override
public FileConfiguration configuration() {
return (FileConfiguration) super.configuration();
}
@Override
public FileConfigurationOptions copyDefaults(final boolean value) {
super.copyDefaults(value);
return this;
}
@Override
public FileConfigurationOptions pathSeparator(final char value) {
super.pathSeparator(value);
return this;
}
/**
* Gets the header that will be applied to the top of the saved output.
* <p>
* This header will be commented out and applied directly at the top of
* the generated output of the {@link FileConfiguration}. It is not
* required to include a newline at the end of the header as it will
* automatically be applied, but you may include one if you wish for extra
* spacing.
* <p>
* Null is a valid value which will indicate that no header is to be
* applied. The default value is null.
*
* @return Header
*/
public String header() {
return header;
}
/**
* Sets the header that will be applied to the top of the saved output.
* <p>
* This header will be commented out and applied directly at the top of
* the generated output of the {@link FileConfiguration}. It is not
* required to include a newline at the end of the header as it will
* automatically be applied, but you may include one if you wish for extra
* spacing.
* <p>
* Null is a valid value which will indicate that no header is to be
* applied.
*
* @param value New header
* @return This object, for chaining
*/
public FileConfigurationOptions header(final String value) {
header = value;
return this;
}
/**
* Gets whether or not the header should be copied from a default source.
* <p>
* If this is true, if a default {@link FileConfiguration} is passed to
* {@link
* FileConfiguration#setDefaults(com.intellectualcrafters.configuration.Configuration)}
* then upon saving it will use the header from that config, instead of
* the one provided here.
* <p>
* If no default is set on the configuration, or the default is not of
* type FileConfiguration, or that config has no header ({@link #header()}
* returns null) then the header specified in this configuration will be
* used.
* <p>
* Defaults to true.
*
* @return Whether or not to copy the header
*/
public boolean copyHeader() {
return copyHeader;
}
/**
* Sets whether or not the header should be copied from a default source.
* <p>
* If this is true, if a default {@link FileConfiguration} is passed to
* {@link
* FileConfiguration#setDefaults(com.intellectualcrafters.configuration.Configuration)}
* then upon saving it will use the header from that config, instead of
* the one provided here.
* <p>
* If no default is set on the configuration, or the default is not of
* type FileConfiguration, or that config has no header ({@link #header()}
* returns null) then the header specified in this configuration will be
* used.
* <p>
* Defaults to true.
*
* @param value Whether or not to copy the header
* @return This object, for chaining
*/
public FileConfigurationOptions copyHeader(final boolean value) {
copyHeader = value;
return this;
}
}

View File

@ -0,0 +1,231 @@
package com.intellectualcrafters.configuration.file;
import com.intellectualcrafters.configuration.Configuration;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.configuration.InvalidConfigurationException;
import com.intellectualcrafters.plot.PS;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Map;
/**
* An implementation of {@link Configuration} which saves all files in Yaml.
* Note that this implementation is not synchronized.
*/
public class YamlConfiguration extends FileConfiguration {
protected static final String COMMENT_PREFIX = "# ";
protected static final String BLANK_CONFIG = "{}\n";
private final DumperOptions yamlOptions = new DumperOptions();
private final Representer yamlRepresenter = new YamlRepresenter();
private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions);
/**
* Creates a new {@link YamlConfiguration}, loading from the given file.
* <p>
* Any errors loading the Configuration will be logged and then ignored.
* If the specified input is not a valid config, a blank config will be
* returned.
* <p>
* The encoding used may follow the system dependent default.
*
* @param file Input file
* @return Resulting configuration
* @throws IllegalArgumentException Thrown if file is null
*/
public static YamlConfiguration loadConfiguration(final File file) {
if (file == null) {
throw new NullPointerException("File cannot be null");
}
final YamlConfiguration config = new YamlConfiguration();
try {
config.load(file);
} catch (InvalidConfigurationException | IOException ex) {
try {
file.getAbsolutePath();
File dest = new File(file.getAbsolutePath() + "_broken");
int i = 0;
while (dest.exists()) {
dest = new File(file.getAbsolutePath() + "_broken_" + i++);
}
Files.copy(file.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
PS.debug("&dCould not read: &7" + file);
PS.debug("&dRenamed to: &7" + dest.getName());
PS.debug("&c============ Full stacktrace ============");
ex.printStackTrace();
PS.debug("&c=========================================");
} catch (final IOException e) {
e.printStackTrace();
}
}
return config;
}
/**
* Creates a new {@link YamlConfiguration}, loading from the given reader.
* <p>
* Any errors loading the Configuration will be logged and then ignored.
* If the specified input is not a valid config, a blank config will be
* returned.
*
* @param reader input
* @return resulting configuration
* @throws IllegalArgumentException Thrown if stream is null
*/
public static YamlConfiguration loadConfiguration(final Reader reader) {
if (reader == null) {
throw new NullPointerException("Reader cannot be null");
}
final YamlConfiguration config = new YamlConfiguration();
try {
config.load(reader);
} catch (final IOException | InvalidConfigurationException ex) {
PS.debug("Cannot load configuration from stream");
ex.printStackTrace();
}
return config;
}
@Override
public String saveToString() {
yamlOptions.setIndent(options().indent());
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
final String header = buildHeader();
String dump = yaml.dump(getValues(false));
if (dump.equals(BLANK_CONFIG)) {
dump = "";
}
return header + dump;
}
@Override
public void loadFromString(final String contents) throws InvalidConfigurationException {
if (contents == null) {
throw new NullPointerException("Contents cannot be null");
}
Map<?, ?> input;
try {
input = (Map<?, ?>) yaml.load(contents);
} catch (final YAMLException e) {
throw new InvalidConfigurationException(e);
} catch (final ClassCastException e) {
throw new InvalidConfigurationException("Top level is not a Map.");
}
final String header = parseHeader(contents);
if (!header.isEmpty()) {
options().header(header);
}
if (input != null) {
convertMapsToSections(input, this);
}
}
protected void convertMapsToSections(final Map<?, ?> input, final ConfigurationSection section) {
for (final Map.Entry<?, ?> entry : input.entrySet()) {
final String key = entry.getKey().toString();
final Object value = entry.getValue();
if (value instanceof Map) {
convertMapsToSections((Map<?, ?>) value, section.createSection(key));
} else {
section.set(key, value);
}
}
}
protected String parseHeader(final String input) {
final String[] lines = input.split("\r?\n", -1);
final StringBuilder result = new StringBuilder();
boolean readingHeader = true;
boolean foundHeader = false;
for (int i = 0; (i < lines.length) && (readingHeader); i++) {
final String line = lines[i];
if (line.startsWith(COMMENT_PREFIX)) {
if (i > 0) {
result.append("\n");
}
if (line.length() > COMMENT_PREFIX.length()) {
result.append(line.substring(COMMENT_PREFIX.length()));
}
foundHeader = true;
} else if ((foundHeader) && (line.isEmpty())) {
result.append("\n");
} else if (foundHeader) {
readingHeader = false;
}
}
return result.toString();
}
@Override
protected String buildHeader() {
final String header = options().header();
if (options().copyHeader()) {
final Configuration def = getDefaults();
if ((def != null) && (def instanceof FileConfiguration)) {
final FileConfiguration filedefaults = (FileConfiguration) def;
final String defaultsHeader = filedefaults.buildHeader();
if ((defaultsHeader != null) && (!defaultsHeader.isEmpty())) {
return defaultsHeader;
}
}
}
if (header == null) {
return "";
}
final StringBuilder builder = new StringBuilder();
final String[] lines = header.split("\r?\n", -1);
boolean startedHeader = false;
for (int i = lines.length - 1; i >= 0; i--) {
builder.insert(0, "\n");
if ((startedHeader) || (!lines[i].isEmpty())) {
builder.insert(0, lines[i]);
builder.insert(0, COMMENT_PREFIX);
startedHeader = true;
}
}
return builder.toString();
}
@Override
public YamlConfigurationOptions options() {
if (options == null) {
options = new YamlConfigurationOptions(this);
}
return (YamlConfigurationOptions) options;
}
}

View File

@ -0,0 +1,73 @@
package com.intellectualcrafters.configuration.file;
/**
* Various settings for controlling the input and output of a {@link
* YamlConfiguration}
*/
public class YamlConfigurationOptions extends FileConfigurationOptions {
private int indent = 2;
protected YamlConfigurationOptions(final YamlConfiguration configuration) {
super(configuration);
}
@Override
public YamlConfiguration configuration() {
return (YamlConfiguration) super.configuration();
}
@Override
public YamlConfigurationOptions copyDefaults(final boolean value) {
super.copyDefaults(value);
return this;
}
@Override
public YamlConfigurationOptions pathSeparator(final char value) {
super.pathSeparator(value);
return this;
}
@Override
public YamlConfigurationOptions header(final String value) {
super.header(value);
return this;
}
@Override
public YamlConfigurationOptions copyHeader(final boolean value) {
super.copyHeader(value);
return this;
}
/**
* Gets how much spaces should be used to indent each line.
* <p>
* The minimum value this may be is 2, and the maximum is 9.
*
* @return How much to indent by
*/
public int indent() {
return indent;
}
/**
* Sets how much spaces should be used to indent each line.
* <p>
* The minimum value this may be is 2, and the maximum is 9.
*
* @param value New indent
* @return This object, for chaining
*/
public YamlConfigurationOptions indent(final int value) {
if (value < 2) {
throw new IllegalArgumentException("Indent must be at least 2 characters");
}
if (value > 9) {
throw new IllegalArgumentException("Indent cannot be greater than 9 characters");
}
indent = value;
return this;
}
}

View File

@ -0,0 +1,48 @@
package com.intellectualcrafters.configuration.file;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import java.util.LinkedHashMap;
import java.util.Map;
public class YamlConstructor extends SafeConstructor {
public YamlConstructor() {
yamlConstructors.put(Tag.MAP, new ConstructCustomObject());
}
private class ConstructCustomObject extends ConstructYamlMap {
@Override
public Object construct(final Node node) {
if (node.isTwoStepsConstruction()) {
throw new YAMLException("Unexpected referential mapping structure. Node: " + node);
}
final Map<?, ?> raw = (Map<?, ?>) super.construct(node);
if (raw.containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY)) {
final Map<String, Object> typed = new LinkedHashMap<>(raw.size());
for (final Map.Entry<?, ?> entry : raw.entrySet()) {
typed.put(entry.getKey().toString(), entry.getValue());
}
try {
return ConfigurationSerialization.deserializeObject(typed);
} catch (final IllegalArgumentException ex) {
throw new YAMLException("Could not deserialize object", ex);
}
}
return raw;
}
@Override
public void construct2ndStep(final Node node, final Object object) {
throw new YAMLException("Unexpected referential mapping structure. Node: " + node);
}
}
}

View File

@ -0,0 +1,38 @@
package com.intellectualcrafters.configuration.file;
import java.util.LinkedHashMap;
import java.util.Map;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.representer.Representer;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
public class YamlRepresenter extends Representer {
public YamlRepresenter() {
multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection());
multiRepresenters.put(ConfigurationSerializable.class, new RepresentConfigurationSerializable());
}
private class RepresentConfigurationSection extends RepresentMap {
@Override
public Node representData(final Object data) {
return super.representData(((ConfigurationSection) data).getValues(false));
}
}
private class RepresentConfigurationSerializable extends RepresentMap {
@Override
public Node representData(final Object data) {
final ConfigurationSerializable serializable = (ConfigurationSerializable) data;
final Map<String, Object> values = new LinkedHashMap<>();
values.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY, ConfigurationSerialization.getAlias(serializable.getClass()));
values.putAll(serializable.serialize());
return super.representData(values);
}
}
}

View File

@ -0,0 +1,35 @@
package com.intellectualcrafters.configuration.serialization;
import java.util.Map;
/**
* Represents an object that may be serialized.
* <p>
* These objects MUST implement one of the following, in addition to the
* methods as defined by this interface:
* <ul>
* <li>A static method "deserialize" that accepts a single {@link Map}&lt;
* {@link String}, {@link Object}> and returns the class.</li>
* <li>A static method "valueOf" that accepts a single {@link Map}&lt;{@link
* String}, {@link Object}> and returns the class.</li>
* <li>A constructor that accepts a single {@link Map}&lt;{@link String},
* {@link Object}>.</li>
* </ul>
* In addition to implementing this interface, you must register the class
* with {@link ConfigurationSerialization#registerClass(Class)}.
*
* @see DelegateDeserialization
* @see SerializableAs
*/
public interface ConfigurationSerializable {
/**
* Creates a Map representation of this class.
* <p>
* This class must provide a method to restore this class, as defined in
* the {@link ConfigurationSerializable} interface javadoc.
*
* @return Map containing the current state of this class
*/
Map<String, Object> serialize();
}

View File

@ -0,0 +1,255 @@
package com.intellectualcrafters.configuration.serialization;
import com.intellectualcrafters.configuration.Configuration;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Utility class for storing and retrieving classes for {@link Configuration}.
*/
public class ConfigurationSerialization {
public static final String SERIALIZED_TYPE_KEY = "==";
private final Class<? extends ConfigurationSerializable> clazz;
private static Map<String, Class<? extends ConfigurationSerializable>> aliases = new HashMap<String, Class<? extends ConfigurationSerializable>>();
protected ConfigurationSerialization(final Class<? extends ConfigurationSerializable> clazz) {
this.clazz = clazz;
}
protected Method getMethod(final String name, final boolean isStatic) {
try {
final Method method = clazz.getDeclaredMethod(name, Map.class);
if (!ConfigurationSerializable.class.isAssignableFrom(method.getReturnType())) {
return null;
}
if (Modifier.isStatic(method.getModifiers()) != isStatic) {
return null;
}
return method;
} catch (final NoSuchMethodException ex) {
return null;
} catch (final SecurityException ex) {
return null;
}
}
protected Constructor<? extends ConfigurationSerializable> getConstructor() {
try {
return clazz.getConstructor(Map.class);
} catch (final NoSuchMethodException ex) {
return null;
} catch (final SecurityException ex) {
return null;
}
}
protected ConfigurationSerializable deserializeViaMethod(final Method method, final Map<String, ?> args) {
try {
final ConfigurationSerializable result = (ConfigurationSerializable) method.invoke(null, args);
if (result == null) {
Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE,
"Could not call method '" + method.toString() + "' of " + clazz + " for deserialization: method returned null");
} else {
return result;
}
} catch (final Throwable ex) {
Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE, "Could not call method '" + method.toString() + "' of " + clazz + " for deserialization",
ex instanceof InvocationTargetException ? ex.getCause() : ex);
}
return null;
}
protected ConfigurationSerializable deserializeViaCtor(final Constructor<? extends ConfigurationSerializable> ctor, final Map<String, ?> args) {
try {
return ctor.newInstance(args);
} catch (final Throwable ex) {
Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE, "Could not call constructor '" + ctor.toString() + "' of " + clazz + " for deserialization",
ex instanceof InvocationTargetException ? ex.getCause() : ex);
}
return null;
}
public ConfigurationSerializable deserialize(final Map<String, ?> args) {
if (args == null) {
throw new NullPointerException("Args must not be null");
}
ConfigurationSerializable result = null;
Method method = getMethod("deserialize", true);
if (method != null) {
result = deserializeViaMethod(method, args);
}
if (result == null) {
method = getMethod("valueOf", true);
if (method != null) {
result = deserializeViaMethod(method, args);
}
}
if (result == null) {
final Constructor<? extends ConfigurationSerializable> constructor = getConstructor();
if (constructor != null) {
result = deserializeViaCtor(constructor, args);
}
}
return result;
}
/**
* Attempts to deserialize the given arguments into a new instance of the
* given class.
* <p>
* The class must implement {@link ConfigurationSerializable}, including
* the extra methods as specified in the javadoc of
* ConfigurationSerializable.
* <p>
* If a new instance could not be made, an example being the class not
* fully implementing the interface, null will be returned.
*
* @param args Arguments for deserialization
* @param clazz Class to deserialize into
* @return New instance of the specified class
*/
public static ConfigurationSerializable deserializeObject(final Map<String, ?> args, final Class<? extends ConfigurationSerializable> clazz) {
return new ConfigurationSerialization(clazz).deserialize(args);
}
/**
* Attempts to deserialize the given arguments into a new instance of the
* given class.
* <p>
* The class must implement {@link ConfigurationSerializable}, including
* the extra methods as specified in the javadoc of
* ConfigurationSerializable.
* <p>
* If a new instance could not be made, an example being the class not
* fully implementing the interface, null will be returned.
*
* @param args Arguments for deserialization
* @return New instance of the specified class
*/
public static ConfigurationSerializable deserializeObject(final Map<String, ?> args) {
Class<? extends ConfigurationSerializable> clazz = null;
if (args.containsKey(SERIALIZED_TYPE_KEY)) {
try {
final String alias = (String) args.get(SERIALIZED_TYPE_KEY);
if (alias == null) {
throw new IllegalArgumentException("Cannot have null alias");
}
clazz = getClassByAlias(alias);
if (clazz == null) {
throw new IllegalArgumentException("Specified class does not exist ('" + alias + "')");
}
} catch (final ClassCastException ex) {
ex.fillInStackTrace();
throw ex;
}
} else {
throw new IllegalArgumentException("Args doesn't contain type key ('" + SERIALIZED_TYPE_KEY + "')");
}
return new ConfigurationSerialization(clazz).deserialize(args);
}
/**
* Registers the given {@link ConfigurationSerializable} class by its
* alias
*
* @param clazz Class to register
*/
public static void registerClass(final Class<? extends ConfigurationSerializable> clazz) {
final DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
if (delegate == null) {
registerClass(clazz, getAlias(clazz));
registerClass(clazz, clazz.getName());
}
}
/**
* Registers the given alias to the specified {@link
* ConfigurationSerializable} class
*
* @param clazz Class to register
* @param alias Alias to register as
* @see SerializableAs
*/
public static void registerClass(final Class<? extends ConfigurationSerializable> clazz, final String alias) {
aliases.put(alias, clazz);
}
/**
* Unregisters the specified alias to a {@link ConfigurationSerializable}
*
* @param alias Alias to unregister
*/
public static void unregisterClass(final String alias) {
aliases.remove(alias);
}
/**
* Unregisters any aliases for the specified {@link
* ConfigurationSerializable} class
*
* @param clazz Class to unregister
*/
public static void unregisterClass(final Class<? extends ConfigurationSerializable> clazz) {
while (aliases.values().remove(clazz)) {}
}
/**
* Attempts to get a registered {@link ConfigurationSerializable} class by
* its alias
*
* @param alias Alias of the serializable
* @return Registered class, or null if not found
*/
public static Class<? extends ConfigurationSerializable> getClassByAlias(final String alias) {
return aliases.get(alias);
}
/**
* Gets the correct alias for the given {@link ConfigurationSerializable}
* class
*
* @param clazz Class to get alias for
* @return Alias to use for the class
*/
public static String getAlias(final Class<? extends ConfigurationSerializable> clazz) {
DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
if (delegate != null) {
if ((delegate.value() == null) || (delegate.value() == clazz)) {
delegate = null;
} else {
return getAlias(delegate.value());
}
}
final SerializableAs alias = clazz.getAnnotation(SerializableAs.class);
if ((alias != null) && (alias.value() != null)) {
return alias.value();
}
return clazz.getName();
}
}

View File

@ -0,0 +1,22 @@
package com.intellectualcrafters.configuration.serialization;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Applies to a {@link ConfigurationSerializable} that will delegate all
* deserialization to another {@link ConfigurationSerializable}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DelegateDeserialization {
/**
* Which class should be used as a delegate for this classes
* deserialization
*
* @return Delegate class
*/
Class<? extends ConfigurationSerializable> value();
}

View File

@ -0,0 +1,34 @@
package com.intellectualcrafters.configuration.serialization;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Represents an "alias" that a {@link ConfigurationSerializable} may be
* stored as.
* If this is not present on a {@link ConfigurationSerializable} class, it
* will use the fully qualified name of the class.
* <p>
* This value will be stored in the configuration so that the configuration
* deserialization can determine what type it is.
* <p>
* Using this annotation on any other class than a {@link
* ConfigurationSerializable} will have no effect.
*
* @see ConfigurationSerialization#registerClass(Class, String)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SerializableAs {
/**
* This is the name your class will be stored and retrieved as.
* <p>
* This name MUST be unique. We recommend using names such as
* "MyPluginThing" instead of "Thing".
*
* @return Name to serialize the class as.
*/
String value();
}

View File

@ -0,0 +1,52 @@
package com.intellectualcrafters.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(final 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(final String name, final byte[] value) {
super(name);
this.value = value;
}
@Override
public byte[] getValue() {
return value;
}
@Override
public String toString() {
final StringBuilder hex = new StringBuilder();
for (final byte b : value) {
final String hexDigits = Integer.toHexString(b).toUpperCase();
if (hexDigits.length() == 1) {
hex.append("0");
}
hex.append(hexDigits).append(" ");
}
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Byte_Array" + append + ": " + hex;
}
}

View File

@ -0,0 +1,44 @@
package com.intellectualcrafters.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(final 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(final String name, final byte value) {
super(name);
this.value = value;
}
@Override
public Byte getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Byte" + append + ": " + value;
}
}

View File

@ -0,0 +1,380 @@
package com.intellectualcrafters.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(final 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(final String name, final 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(final 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(final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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
* @param <T> the type of list
*
* @return a list of tags
*/
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(final String key, final Class<T> listType) {
final Tag tag = value.get(key);
if (tag instanceof ListTag) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final 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(final String key) {
final Tag tag = value.get(key);
if (tag instanceof StringTag) {
return ((StringTag) tag).getValue();
} else {
return "";
}
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
final StringBuilder bldr = new StringBuilder();
bldr.append("TAG_Compound").append(append).append(": ").append(value.size()).append(" entries\r\n{\r\n");
for (final Map.Entry<String, Tag> entry : value.entrySet()) {
bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
}
bldr.append("}");
return bldr.toString();
}
}

View File

@ -0,0 +1,197 @@
package com.intellectualcrafters.jnbt;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.HashMap;
import java.util.Map;
/**
* Helps create compound tags.
*/
public class CompoundTagBuilder {
private final Map<String, Tag> entries;
/**
* Create a new instance.
*/
CompoundTagBuilder() {
entries = new HashMap<String, Tag>();
}
/**
* Create a new instance and use the given map (which will be modified).
*
* @param value the value
*/
CompoundTagBuilder(final Map<String, Tag> value) {
checkNotNull(value);
entries = value;
}
/**
* Create a new builder instance.
*
* @return a new builder
*/
public static CompoundTagBuilder create() {
return new CompoundTagBuilder();
}
/**
* Put the given key and tag into the compound tag.
*
* @param key they key
* @param value the value
*
* @return this object
*/
public CompoundTagBuilder put(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final String key, final 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(final Map<String, ? extends Tag> value) {
checkNotNull(value);
for (final 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(final String name) {
return new CompoundTag(name, new HashMap<String, Tag>(entries));
}
}

View File

@ -0,0 +1,44 @@
package com.intellectualcrafters.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(final 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(final String name, final double value) {
super(name);
this.value = value;
}
@Override
public Double getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Double" + append + ": " + value;
}
}

View File

@ -0,0 +1,23 @@
package com.intellectualcrafters.jnbt;
/**
* The {@code TAG_End} tag.
*/
public final class EndTag extends Tag {
/**
* Creates the tag.
*/
public EndTag() {
super();
}
@Override
public Object getValue() {
return null;
}
@Override
public String toString() {
return "TAG_End";
}
}

View File

@ -0,0 +1,44 @@
package com.intellectualcrafters.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(final 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(final String name, final float value) {
super(name);
this.value = value;
}
@Override
public Float getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Float" + append + ": " + value;
}
}

View File

@ -0,0 +1,56 @@
package com.intellectualcrafters.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(final 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(final String name, final int[] value) {
super(name);
checkNotNull(value);
this.value = value;
}
@Override
public int[] getValue() {
return value;
}
@Override
public String toString() {
final StringBuilder hex = new StringBuilder();
for (final int b : value) {
final String hexDigits = Integer.toHexString(b).toUpperCase();
if (hexDigits.length() == 1) {
hex.append("0");
}
hex.append(hexDigits).append(" ");
}
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Int_Array" + append + ": " + hex;
}
}

View File

@ -0,0 +1,44 @@
package com.intellectualcrafters.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(final 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(final String name, final int value) {
super(name);
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Int" + append + ": " + value;
}
}

View File

@ -0,0 +1,392 @@
package com.intellectualcrafters.jnbt;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
/**
* 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(final Class<? extends Tag> type, final 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(final String name, final Class<? extends Tag> type, final 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(final 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
*/
public Tag getIfExists(final int index) {
try {
return value.get(index);
} catch (final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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
* @param <T> the NBT type
*
* @return a list of tags
*/
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(final int index, final Class<T> listType) {
final Tag tag = getIfExists(index);
if (tag instanceof ListTag) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final 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(final int index) {
final Tag tag = getIfExists(index);
if (tag instanceof StringTag) {
return ((StringTag) tag).getValue();
} else {
return "";
}
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
final 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 (final Tag t : value) {
bldr.append(" ").append(t.toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
}
bldr.append("}");
return bldr.toString();
}
}

View File

@ -0,0 +1,114 @@
package com.intellectualcrafters.jnbt;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* 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(final Class<? extends Tag> type) {
checkNotNull(type);
this.type = type;
entries = new ArrayList<Tag>();
}
/**
* Create a new builder instance.
*
* @param type
*
* @return a new builder
*/
public static ListTagBuilder create(final Class<? extends Tag> type) {
return new ListTagBuilder(type);
}
/**
* Create a new builder instance.
*
* @param entries
* @param <T>
*
* @return a new builder
*/
@SafeVarargs
public static <T extends Tag> ListTagBuilder createWith(final T... entries) {
checkNotNull(entries);
if (entries.length == 0) {
throw new IllegalArgumentException("This method needs an array of at least one entry");
}
final 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");
}
}
final ListTagBuilder builder = new ListTagBuilder(type);
builder.addAll(Arrays.asList(entries));
return builder;
}
/**
* Add the given tag.
*
* @param value the tag
*
* @return this object
*/
public ListTagBuilder add(final 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(final Collection<? extends Tag> value) {
checkNotNull(value);
for (final 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(final String name) {
return new ListTag(name, type, new ArrayList<Tag>(entries));
}
}

View File

@ -0,0 +1,44 @@
package com.intellectualcrafters.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(final 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(final String name, final long value) {
super(name);
this.value = value;
}
@Override
public Long getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Long" + append + ": " + value;
}
}

View File

@ -0,0 +1,79 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.jnbt;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* A class which holds constant values.
*/
public final class NBTConstants {
public static final Charset CHARSET = StandardCharsets.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(final int id) {
switch (id) {
case TYPE_END:
return EndTag.class;
case TYPE_BYTE:
return ByteTag.class;
case TYPE_SHORT:
return ShortTag.class;
case TYPE_INT:
return IntTag.class;
case TYPE_LONG:
return LongTag.class;
case TYPE_FLOAT:
return FloatTag.class;
case TYPE_DOUBLE:
return DoubleTag.class;
case TYPE_BYTE_ARRAY:
return ByteArrayTag.class;
case TYPE_STRING:
return StringTag.class;
case TYPE_LIST:
return ListTag.class;
case TYPE_COMPOUND:
return CompoundTag.class;
case TYPE_INT_ARRAY:
return IntArrayTag.class;
default:
throw new IllegalArgumentException("Unknown tag type ID of " + id);
}
}
}

View File

@ -0,0 +1,191 @@
package com.intellectualcrafters.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. The NBT format was created by Markus Persson, and the specification
* may be found at @linktourl http://www.minecraft.net/docs/NBT.txt"> http://www.minecraft.net/docs/NBT.txt.
*/
public final class NBTInputStream implements Closeable {
private final DataInputStream is;
private int count;
/**
* 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(final InputStream is) {
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, Integer.MAX_VALUE);
}
/**
* Reads an NBT tag from the stream.
*
* @return The tag that was read.
*
* @throws IOException if an I/O error occurs.
*/
public Tag readTag(final int maxDepth) throws IOException {
return readTag(0, maxDepth);
}
/**
* 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(final int depth, final int maxDepth) throws IOException {
if ((count++) > maxDepth) {
throw new IOException("Exceeds max depth: " + count);
}
final int type = is.readByte() & 0xFF;
String name;
if (type != NBTConstants.TYPE_END) {
final int nameLength = is.readShort() & 0xFFFF;
final byte[] nameBytes = new byte[nameLength];
is.readFully(nameBytes);
name = new String(nameBytes, NBTConstants.CHARSET);
} else {
name = "";
}
return readTagPayload(type, name, depth, maxDepth);
}
/**
* 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(final int type, final String name, final int depth, final int maxDepth) throws IOException {
if ((count++) > maxDepth) {
throw new IOException("Exceeds max depth: " + count);
}
count++;
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();
// Max depth
if ((count += length) > maxDepth) {
throw new IOException("Exceeds max depth: " + count);
//
}
byte[] bytes = new byte[length];
is.readFully(bytes);
return new ByteArrayTag(name, bytes);
case NBTConstants.TYPE_STRING:
length = is.readShort();
// Max depth
if ((count += length) > maxDepth) {
throw new IOException("Exceeds max depth: " + count);
//
}
bytes = new byte[length];
is.readFully(bytes);
return new StringTag(name, new String(bytes, NBTConstants.CHARSET));
case NBTConstants.TYPE_LIST:
final int childType = is.readByte();
length = is.readInt();
// Max depth
if ((count += length) > maxDepth) {
throw new IOException("Exceeds max depth: " + count);
//
}
final List<Tag> tagList = new ArrayList<Tag>();
for (int i = 0; i < length; ++i) {
final Tag tag = readTagPayload(childType, "", depth + 1, maxDepth);
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:
final Map<String, Tag> tagMap = new HashMap<String, Tag>();
while (true) {
final Tag tag = readTag(depth + 1, maxDepth);
if (tag instanceof EndTag) {
break;
} else {
tagMap.put(tag.getName(), tag);
}
}
return new CompoundTag(name, tagMap);
case NBTConstants.TYPE_INT_ARRAY:
length = is.readInt();
// Max depth
if ((count += length) > maxDepth) {
throw new IOException("Exceeds max depth: " + count);
}
//
final int[] data = new int[length];
for (int i = 0; i < length; i++) {
data[i] = is.readInt();
}
return new IntArrayTag(name, data);
default:
throw new IOException("Invalid tag type: " + type + ".");
}
}
@Override
public void close() throws IOException {
is.close();
}
}

View File

@ -0,0 +1,281 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.jnbt;
import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
/**
* <p> This class writes <strong>NBT</strong>, or <strong>Named Binary Tag</strong> <code>Tag</code> objects to an
* underlying <code>OutputStream</code>. </p> <p> The NBT format was created by Markus Persson, and the
* specification may be found at
* @linktourl http://www.minecraft.net/docs/NBT.txt
* </p>
*
* @author Graham Edgecombe
*/
public final class NBTOutputStream implements Closeable {
/**
* The output stream.
*/
private final DataOutputStream os;
/**
* Creates a new <code>NBTOutputStream</code>, 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(final OutputStream os) {
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(final Tag tag) throws IOException {
final int type = NBTUtils.getTypeCode(tag.getClass());
final String name = tag.getName();
final 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(final Tag tag) throws IOException {
final 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</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeByteTagPayload(final ByteTag tag) throws IOException {
os.writeByte(tag.getValue());
}
/**
* Writes a <code>TAG_Byte_Array</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeByteArrayTagPayload(final ByteArrayTag tag) throws IOException {
final byte[] bytes = tag.getValue();
os.writeInt(bytes.length);
os.write(bytes);
}
/**
* Writes a <code>TAG_Compound</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeCompoundTagPayload(final CompoundTag tag) throws IOException {
for (final Tag childTag : tag.getValue().values()) {
writeTag(childTag);
}
os.writeByte((byte) 0); // end tag - better way?
}
/**
* Writes a <code>TAG_List</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeListTagPayload(final ListTag tag) throws IOException {
final Class<? extends Tag> clazz = tag.getType();
final List<Tag> tags = tag.getValue();
final int size = tags.size();
os.writeByte(NBTUtils.getTypeCode(clazz));
os.writeInt(size);
for (final Tag tag1 : tags) {
writeTagPayload(tag1);
}
}
/**
* Writes a <code>TAG_String</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeStringTagPayload(final StringTag tag) throws IOException {
final byte[] bytes = tag.getValue().getBytes(NBTConstants.CHARSET);
os.writeShort(bytes.length);
os.write(bytes);
}
/**
* Writes a <code>TAG_Double</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeDoubleTagPayload(final DoubleTag tag) throws IOException {
os.writeDouble(tag.getValue());
}
/**
* Writes a <code>TAG_Float</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeFloatTagPayload(final FloatTag tag) throws IOException {
os.writeFloat(tag.getValue());
}
/**
* Writes a <code>TAG_Long</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeLongTagPayload(final LongTag tag) throws IOException {
os.writeLong(tag.getValue());
}
/**
* Writes a <code>TAG_Int</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeIntTagPayload(final IntTag tag) throws IOException {
os.writeInt(tag.getValue());
}
/**
* Writes a <code>TAG_Short</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeShortTagPayload(final ShortTag tag) throws IOException {
os.writeShort(tag.getValue());
}
/**
* Writes a <code>TAG_Empty</code> tag.
*
* @param tag The tag.
*
* @throws IOException if an I/O error occurs.
*/
private void writeEndTagPayload(final EndTag tag) {
/* empty */
}
private void writeIntArrayTagPayload(final IntArrayTag tag) throws IOException {
final int[] data = tag.getValue();
os.writeInt(data.length);
for (final int element : data) {
os.writeInt(element);
}
}
@Override
public void close() throws IOException {
os.close();
}
/**
* Flush output
* @throws IOException
*/
public void flush() throws IOException {
os.flush();
}
}

View File

@ -0,0 +1,150 @@
package com.intellectualcrafters.jnbt;
import java.util.Map;
/**
* 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(final 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 class (" + 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(final 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 class (" + 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(final 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 + ".");
}
}
/**
* 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
* @param <T>
*
* @return child tag
*/
public static <T extends Tag> T getChildTag(final Map<String, Tag> items, final String key, final Class<T> expected) throws IllegalArgumentException {
if (!items.containsKey(key)) {
throw new IllegalArgumentException("Missing a \"" + key + "\" tag");
}
final Tag tag = items.get(key);
if (!expected.isInstance(tag)) {
throw new IllegalArgumentException(key + " tag is not of tag type " + expected.getName());
}
return expected.cast(tag);
}
}

View File

@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.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(final 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(final String name, final short value) {
super(name);
this.value = value;
}
@Override
public Short getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_Short" + append + ": " + value;
}
}

View File

@ -0,0 +1,48 @@
package com.intellectualcrafters.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(final 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(final String name, final String value) {
super(name);
checkNotNull(value);
this.value = value;
}
@Override
public String getValue() {
return value;
}
@Override
public String toString() {
final String name = getName();
String append = "";
if ((name != null) && !name.equals("")) {
append = "(\"" + getName() + "\")";
}
return "TAG_String" + append + ": " + value;
}
}

View File

@ -0,0 +1,63 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.jnbt;
/**
* Represents a NBT tag.
*/
public abstract class Tag {
private final String name;
/**
* Create a new tag with an empty name.
*/
Tag() {
this("");
}
/**
* Creates the tag with the specified name.
*
* @param name the name
*/
Tag(String name) {
if (name == null) {
name = "";
}
this.name = name;
}
/**
* Gets the name of this tag.
*
* @return the name of this tag
*/
public final String getName() {
return name;
}
/**
* Gets the value of this tag.
*
* @return the value
*/
public abstract Object getValue();
}

View File

@ -0,0 +1,266 @@
package com.intellectualcrafters.json;
/**
* This provides static methods to convert comma delimited text into a JSONArray, and to covert a JSONArray into comma
* delimited text. Comma delimited text is a very popular format for data interchange. It is understood by most
* database, spreadsheet, and organizer programs.
*
* Each row of text represents a row in a table or a data record. Each row ends with a NEWLINE character. Each row
* contains one or more values. Values are separated by commas. A value can contain any character except for comma,
* unless is is wrapped in single quotes or double quotes.
*
* The first row usually contains the names of the columns.
*
* A comma delimited list can be converted into a JSONArray of JSONObjects. The names for the elements in the
* JSONObjects can be taken from the names in the first row.
*
* @author JSON.org
* @version 2014-05-03
*/
public class CDL {
/**
* Get the next value. The value can be wrapped in quotes. The value can be empty.
*
* @param x A JSONTokener of the source text.
*
* @return The value string, or null if empty.
*
* @throws JSONException if the quoted string is badly formed.
*/
private static String getValue(final JSONTokener x) throws JSONException {
char c;
char q;
StringBuffer sb;
do {
c = x.next();
} while ((c == ' ') || (c == '\t'));
switch (c) {
case 0:
return null;
case '"':
case '\'':
q = c;
sb = new StringBuffer();
for (;;) {
c = x.next();
if (c == q) {
break;
}
if ((c == 0) || (c == '\n') || (c == '\r')) {
throw x.syntaxError("Missing close quote '" + q + "'.");
}
sb.append(c);
}
return sb.toString();
case ',':
x.back();
return "";
default:
x.back();
return x.nextTo(',');
}
}
/**
* Produce a JSONArray of strings from a row of comma delimited values.
*
* @param x A JSONTokener of the source text.
*
* @return A JSONArray of strings.
*
* @throws JSONException
*/
public static JSONArray rowToJSONArray(final JSONTokener x) throws JSONException {
final JSONArray ja = new JSONArray();
for (;;) {
final String value = getValue(x);
char c = x.next();
if ((value == null) || ((ja.length() == 0) && (value.isEmpty()) && (c != ','))) {
return null;
}
ja.put(value);
for (;;) {
if (c == ',') {
break;
}
if (c != ' ') {
if ((c == '\n') || (c == '\r') || (c == 0)) {
return ja;
}
throw x.syntaxError("Bad character '" + c + "' (" + (int) c + ").");
}
c = x.next();
}
}
}
/**
* Produce a JSONObject from a row of comma delimited text, using a parallel JSONArray of strings to provides the
* names of the elements.
*
* @param names A JSONArray of names. This is commonly obtained from the first row of a comma delimited text file
* using the rowToJSONArray method.
* @param x A JSONTokener of the source text.
*
* @return A JSONObject combining the names and values.
*
* @throws JSONException
*/
public static JSONObject rowToJSONObject(final JSONArray names, final JSONTokener x) throws JSONException {
final JSONArray ja = rowToJSONArray(x);
return ja != null ? ja.toJSONObject(names) : null;
}
/**
* Produce a comma delimited text row from a JSONArray. Values containing the comma character will be quoted.
* Troublesome characters may be removed.
*
* @param ja A JSONArray of strings.
*
* @return A string ending in NEWLINE.
*/
public static String rowToString(final JSONArray ja) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < ja.length(); i += 1) {
if (i > 0) {
sb.append(',');
}
final Object object = ja.opt(i);
if (object != null) {
final String string = object.toString();
if ((!string.isEmpty()) && ((string.indexOf(',') >= 0) || (string.indexOf('\n') >= 0) || (string.indexOf('\r') >= 0) || (
string.indexOf(0) >= 0) || (string.charAt(0) == '"'))) {
sb.append('"');
final int length = string.length();
for (int j = 0; j < length; j += 1) {
final char c = string.charAt(j);
if ((c >= ' ') && (c != '"')) {
sb.append(c);
}
}
sb.append('"');
} else {
sb.append(string);
}
}
}
sb.append('\n');
return sb.toString();
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string, using the first row as a source of names.
*
* @param string The comma delimited text.
*
* @return A JSONArray of JSONObjects.
*
* @throws JSONException
*/
public static JSONArray toJSONArray(final String string) throws JSONException {
return toJSONArray(new JSONTokener(string));
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string, using the first row as a source of names.
*
* @param x The JSONTokener containing the comma delimited text.
*
* @return A JSONArray of JSONObjects.
*
* @throws JSONException
*/
public static JSONArray toJSONArray(final JSONTokener x) throws JSONException {
return toJSONArray(rowToJSONArray(x), x);
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string using a supplied JSONArray as the source of
* element names.
*
* @param names A JSONArray of strings.
* @param string The comma delimited text.
*
* @return A JSONArray of JSONObjects.
*
* @throws JSONException
*/
public static JSONArray toJSONArray(final JSONArray names, final String string) throws JSONException {
return toJSONArray(names, new JSONTokener(string));
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string using a supplied JSONArray as the source of
* element names.
*
* @param names A JSONArray of strings.
* @param x A JSONTokener of the source text.
*
* @return A JSONArray of JSONObjects.
*
* @throws JSONException
*/
public static JSONArray toJSONArray(final JSONArray names, final JSONTokener x) throws JSONException {
if ((names == null) || (names.length() == 0)) {
return null;
}
final JSONArray ja = new JSONArray();
for (;;) {
final JSONObject jo = rowToJSONObject(names, x);
if (jo == null) {
break;
}
ja.put(jo);
}
if (ja.length() == 0) {
return null;
}
return ja;
}
/**
* Produce a comma delimited text from a JSONArray of JSONObjects. The first row will be a list of names obtained by
* inspecting the first JSONObject.
*
* @param ja A JSONArray of JSONObjects.
*
* @return A comma delimited text.
*
* @throws JSONException
*/
public static String toString(final JSONArray ja) throws JSONException {
final JSONObject jo = ja.optJSONObject(0);
if (jo != null) {
final JSONArray names = jo.names();
if (names != null) {
return rowToString(names) + toString(names, ja);
}
}
return null;
}
/**
* Produce a comma delimited text from a JSONArray of JSONObjects using a provided list of names. The list of names
* is not included in the output.
*
* @param names A JSONArray of strings.
* @param ja A JSONArray of JSONObjects.
*
* @return A comma delimited text.
*
* @throws JSONException
*/
public static String toString(final JSONArray names, final JSONArray ja) throws JSONException {
if ((names == null) || (names.length() == 0)) {
return null;
}
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < ja.length(); i += 1) {
final JSONObject jo = ja.optJSONObject(i);
if (jo != null) {
sb.append(rowToString(jo.toJSONArray(names)));
}
}
return sb.toString();
}
}

View File

@ -0,0 +1,161 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.json;
/**
* Convert a web browser cookie specification to a JSONObject and back. JSON and Cookies are both notations for
* name/value pairs.
*
* @author JSON.org
* @version 2014-05-03
*/
public class Cookie {
/**
* Produce a copy of a string in which the characters '+', '%', '=', ';' and control characters are replaced with
* "%hh". This is a gentle form of URL encoding, attempting to cause as little distortion to the string as possible.
* The characters '=' and ';' are meta characters in cookies. By convention, they are escaped using the
* URL-encoding. This is only a convention, not a standard. Often, cookies are expected to have encoded values. We
* encode '=' and ';' because we must. We encode '%' and '+' because they are meta characters in URL encoding.
*
* @param string The source string.
*
* @return The escaped result.
*/
public static String escape(final String string) {
char c;
final String s = string.trim();
final int length = s.length();
final StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i += 1) {
c = s.charAt(i);
if ((c < ' ') || (c == '+') || (c == '%') || (c == '=') || (c == ';')) {
sb.append('%');
sb.append(Character.forDigit((char) ((c >>> 4) & 0x0f), 16));
sb.append(Character.forDigit((char) (c & 0x0f), 16));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Convert a cookie specification string into a JSONObject. The string will contain a name value pair separated by
* '='. The name and the value will be unescaped, possibly converting '+' and '%' sequences. The cookie properties
* may follow, separated by ';', also represented as name=value (except the secure property, which does not have a
* value). The name will be stored under the key "name", and the value will be stored under the key "value". This
* method does not do checking or validation of the parameters. It only converts the cookie string into a
* JSONObject.
*
* @param string The cookie specification string.
*
* @return A JSONObject containing "name", "value", and possibly other members.
*
* @throws JSONException
*/
public static JSONObject toJSONObject(final String string) throws JSONException {
String name;
final JSONObject jo = new JSONObject();
Object value;
final JSONTokener x = new JSONTokener(string);
jo.put("name", x.nextTo('='));
x.next('=');
jo.put("value", x.nextTo(';'));
x.next();
while (x.more()) {
name = unescape(x.nextTo("=;"));
if (x.next() != '=') {
if (name.equals("secure")) {
value = Boolean.TRUE;
} else {
throw x.syntaxError("Missing '=' in cookie parameter.");
}
} else {
value = unescape(x.nextTo(';'));
x.next();
}
jo.put(name, value);
}
return jo;
}
/**
* Convert a JSONObject into a cookie specification string. The JSONObject must contain "name" and "value" members.
* If the JSONObject contains "expires", "domain", "path", or "secure" members, they will be appended to the cookie
* specification string. All other members are ignored.
*
* @param jo A JSONObject
*
* @return A cookie specification string
*
* @throws JSONException
*/
public static String toString(final JSONObject jo) throws JSONException {
final StringBuilder sb = new StringBuilder();
sb.append(escape(jo.getString("name")));
sb.append("=");
sb.append(escape(jo.getString("value")));
if (jo.has("expires")) {
sb.append(";expires=");
sb.append(jo.getString("expires"));
}
if (jo.has("domain")) {
sb.append(";domain=");
sb.append(escape(jo.getString("domain")));
}
if (jo.has("path")) {
sb.append(";path=");
sb.append(escape(jo.getString("path")));
}
if (jo.optBoolean("secure")) {
sb.append(";secure");
}
return sb.toString();
}
/**
* Convert <code>%</code><i>hh</i> sequences to single characters, and convert plus to space.
*
* @param string A string that may contain <code>+</code> &nbsp;<small>(plus)</small> and <code>%</code><i>hh</i>
* sequences.
*
* @return The unescaped string.
*/
public static String unescape(final String string) {
final int length = string.length();
final StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; ++i) {
char c = string.charAt(i);
if (c == '+') {
c = ' ';
} else if ((c == '%') && ((i + 2) < length)) {
final int d = JSONTokener.dehexchar(string.charAt(i + 1));
final int e = JSONTokener.dehexchar(string.charAt(i + 2));
if ((d >= 0) && (e >= 0)) {
c = (char) ((d * 16) + e);
i += 2;
}
}
sb.append(c);
}
return sb.toString();
}
}

View File

@ -0,0 +1,68 @@
package com.intellectualcrafters.json;
import java.util.Iterator;
/**
* Convert a web browser cookie list string to a JSONObject and back.
*
* @author JSON.org
* @version 2014-05-03
*/
public class CookieList {
/**
* Convert a cookie list into a JSONObject. A cookie list is a sequence of name/value pairs. The names are separated
* from the values by '='. The pairs are separated by ';'. The names and the values will be unescaped, possibly
* converting '+' and '%' sequences.
*
* To add a cookie to a cooklist, cookielistJSONObject.put(cookieJSONObject.getString("name"),
* cookieJSONObject.getString("value"));
*
* @param string A cookie list string
*
* @return A JSONObject
*
* @throws JSONException
*/
public static JSONObject toJSONObject(final String string) throws JSONException {
final JSONObject jo = new JSONObject();
final JSONTokener x = new JSONTokener(string);
while (x.more()) {
final String name = Cookie.unescape(x.nextTo('='));
x.next('=');
jo.put(name, Cookie.unescape(x.nextTo(';')));
x.next();
}
return jo;
}
/**
* Convert a JSONObject into a cookie list. A cookie list is a sequence of name/value pairs. The names are separated
* from the values by '='. The pairs are separated by ';'. The characters '%', '+', '=', and ';' in the names and
* values are replaced by "%hh".
*
* @param jo A JSONObject
*
* @return A cookie list string
*
* @throws JSONException
*/
public static String toString(final JSONObject jo) throws JSONException {
boolean b = false;
final Iterator<String> keys = jo.keys();
String string;
final StringBuilder sb = new StringBuilder();
while (keys.hasNext()) {
string = keys.next();
if (!jo.isNull(string)) {
if (b) {
sb.append(';');
}
sb.append(Cookie.escape(string));
sb.append("=");
sb.append(Cookie.escape(jo.getString(string)));
b = true;
}
}
return sb.toString();
}
}

View File

@ -0,0 +1,129 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.json;
import java.util.Iterator;
/**
* Convert an HTTP header to a JSONObject and back.
*
* @author JSON.org
* @version 2014-05-03
*/
public class HTTP {
/**
* Carriage return/line feed.
*/
public static final String CRLF = "\r\n";
public static JSONObject toJSONObject(final String string) throws JSONException {
final JSONObject jo = new JSONObject();
final HTTPTokener x = new HTTPTokener(string);
String token;
token = x.nextToken();
if (token.toUpperCase().startsWith("HTTP")) {
// Response
jo.put("HTTP-Version", token);
jo.put("Status-Code", x.nextToken());
jo.put("Reason-Phrase", x.nextTo('\0'));
x.next();
} else {
// Request
jo.put("Method", token);
jo.put("Request-URI", x.nextToken());
jo.put("HTTP-Version", x.nextToken());
}
// Fields
while (x.more()) {
final String name = x.nextTo(':');
x.next(':');
jo.put(name, x.nextTo('\0'));
x.next();
}
return jo;
}
/**
* Convert a JSONObject into an HTTP header. A request header must contain
*
*
* <pre>
* {
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }
* </pre>
*
* A response header must contain
*
*
* <pre>
* {
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }
* </pre>
*
* Any other members of the JSONObject will be output as HTTP fields. The result will end with two CRLF pairs.
*
* @param jo A JSONObject
*
* @return An HTTP header string.
*
* @throws JSONException if the object does not contain enough information.
*/
public static String toString(final JSONObject jo) throws JSONException {
final Iterator<String> keys = jo.keys();
String string;
final StringBuilder sb = new StringBuilder();
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
sb.append(jo.getString("HTTP-Version"));
sb.append(' ');
sb.append(jo.getString("Status-Code"));
sb.append(' ');
sb.append(jo.getString("Reason-Phrase"));
} else if (jo.has("Method") && jo.has("Request-URI")) {
sb.append(jo.getString("Method"));
sb.append(' ');
sb.append('"');
sb.append(jo.getString("Request-URI"));
sb.append('"');
sb.append(' ');
sb.append(jo.getString("HTTP-Version"));
} else {
throw new JSONException("Not enough material for an HTTP header.");
}
sb.append(CRLF);
while (keys.hasNext()) {
string = keys.next();
if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && !"Reason-Phrase".equals(string) && !"Method".equals(string) && !"Request-URI".equals(string) && !jo.isNull(string)) {
sb.append(string);
sb.append(": ");
sb.append(jo.getString(string));
sb.append(CRLF);
}
}
sb.append(CRLF);
return sb.toString();
}
}

View File

@ -0,0 +1,54 @@
package com.intellectualcrafters.json;
/**
* The HTTPTokener extends the JSONTokener to provide additional methods for the parsing of HTTP headers.
*
* @author JSON.org
* @version 2014-05-03
*/
public class HTTPTokener extends JSONTokener {
/**
* Construct an HTTPTokener from a string.
*
* @param string A source string.
*/
public HTTPTokener(final String string) {
super(string);
}
/**
* Get the next token or string. This is used in parsing HTTP headers.
*
* @return A String.
*
* @throws JSONException
*/
public String nextToken() throws JSONException {
char c;
char q;
final StringBuilder sb = new StringBuilder();
do {
c = next();
} while (Character.isWhitespace(c));
if ((c == '"') || (c == '\'')) {
q = c;
for (;;) {
c = next();
if (c < ' ') {
throw syntaxError("Unterminated string.");
}
if (c == q) {
return sb.toString();
}
sb.append(c);
}
}
for (;;) {
if ((c == 0) || Character.isWhitespace(c)) {
return sb.toString();
}
sb.append(c);
c = next();
}
}
}

View File

@ -0,0 +1,881 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.json;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
/**
* A JSONArray is an ordered sequence of values. Its external text form is a string wrapped in square brackets with
* commas separating the values. The internal form is an object having <code>get</code> and <code>opt</code> methods for
* accessing the values by index, and <code>put</code> methods for adding or replacing values. The values can be any of
* these types: <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>, <code>Number</code>,
* <code>String</code>, or the <code>JSONObject.NULL object</code>.
*
* The constructor can convert a JSON text into a Java object. The <code>toString</code> method converts to JSON text.
*
* A <code>get</code> method returns a value if one can be found, and throws an exception if one cannot be found. An
* <code>opt</code> method returns a default value instead of throwing an exception, and so is useful for obtaining
* optional values.
*
* The generic <code>get()</code> and <code>opt()</code> methods return an object which you can cast or query for type.
* There are also typed <code>get</code> and <code>opt</code> methods that do type checking and type coercion for you.
*
* The texts produced by the <code>toString</code> methods strictly conform to JSON syntax rules. The constructors are
* more forgiving in the texts they will accept: <ul> <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear
* just before the closing bracket.</li> <li>The <code>null</code> value will be inserted when there is <code>,</code>
* &nbsp;<small>(comma)</small> elision.</li> <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
* quote)</small>.</li> <li>Strings do not need to be quoted at all if they do not begin with a quote or single quote,
* and if they do not contain leading or trailing spaces, and if they do not contain any of these characters: <code>{ }
* [ ] / \ : , #</code> and if they do not look like numbers and if they are not the reserved words <code>true</code>,
* <code>false</code>, or <code>null</code>.</li> </ul>
*
* @author JSON.org
* @version 2014-05-03
*/
public class JSONArray {
/**
* The arrayList where the JSONArray's properties are kept.
*/
private final ArrayList<Object> myArrayList;
/**
* Construct an empty JSONArray.
*/
public JSONArray() {
myArrayList = new ArrayList<Object>();
}
/**
* Construct a JSONArray from a JSONTokener.
*
* @param x A JSONTokener
*
* @throws JSONException If there is a syntax error.
*/
public JSONArray(final JSONTokener x) throws JSONException {
this();
if (x.nextClean() != '[') {
throw x.syntaxError("A JSONArray text must start with '['");
}
if (x.nextClean() != ']') {
x.back();
for (;;) {
if (x.nextClean() == ',') {
x.back();
myArrayList.add(JSONObject.NULL);
} else {
x.back();
myArrayList.add(x.nextValue());
}
switch (x.nextClean()) {
case ',':
if (x.nextClean() == ']') {
return;
}
x.back();
break;
case ']':
return;
default:
throw x.syntaxError("Expected a ',' or ']'");
}
}
}
}
/**
* Construct a JSONArray from a source JSON text.
*
* @param source A string that begins with <code>[</code>&nbsp;<small>(left bracket)</small> and ends with
* <code>]</code> &nbsp;<small>(right bracket)</small>.
*
* @throws JSONException If there is a syntax error.
*/
public JSONArray(final String source) throws JSONException {
this(new JSONTokener(source));
}
/**
* Construct a JSONArray from a Collection.
*
* @param collection A Collection.
*/
public JSONArray(final Collection<Object> collection) {
myArrayList = new ArrayList<Object>();
if (collection != null) {
for (final Object aCollection : collection) {
myArrayList.add(JSONObject.wrap(aCollection));
}
}
}
/**
* Construct a JSONArray from an array
*
* @throws JSONException If not an array.
*/
public JSONArray(final Object array) throws JSONException {
this();
if (array.getClass().isArray()) {
final int length = Array.getLength(array);
for (int i = 0; i < length; i += 1) {
this.put(JSONObject.wrap(Array.get(array, i)));
}
} else {
throw new JSONException("JSONArray initial value should be a string or collection or array.");
}
}
/**
* Get the object value associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return An object value.
*
* @throws JSONException If there is no value for the index.
*/
public Object get(final int index) throws JSONException {
final Object object = opt(index);
if (object == null) {
throw new JSONException("JSONArray[" + index + "] not found.");
}
return object;
}
/**
* Get the boolean value associated with an index. The string values "true" and "false" are converted to boolean.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The truth.
*
* @throws JSONException If there is no value for the index or if the value is not convertible to boolean.
*/
public boolean getBoolean(final int index) throws JSONException {
final Object object = get(index);
if (object.equals(Boolean.FALSE) || ((object instanceof String) && ((String) object).equalsIgnoreCase("false"))) {
return false;
} else if (object.equals(Boolean.TRUE) || ((object instanceof String) && ((String) object).equalsIgnoreCase("true"))) {
return true;
}
throw new JSONException("JSONArray[" + index + "] is not a boolean.");
}
/**
* Get the double value associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The value.
*
* @throws JSONException If the key is not found or if the value cannot be converted to a number.
*/
public double getDouble(final int index) throws JSONException {
final Object object = get(index);
try {
return object instanceof Number ? ((Number) object).doubleValue() : Double.parseDouble((String) object);
} catch (NumberFormatException e) {
throw new JSONException("JSONArray[" + index + "] is not a number.");
}
}
/**
* Get the int value associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The value.
*
* @throws JSONException If the key is not found or if the value is not a number.
*/
public int getInt(final int index) throws JSONException {
final Object object = get(index);
try {
return object instanceof Number ? ((Number) object).intValue() : Integer.parseInt((String) object);
} catch (NumberFormatException e) {
throw new JSONException("JSONArray[" + index + "] is not a number.");
}
}
/**
* Get the JSONArray associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return A JSONArray value.
*
* @throws JSONException If there is no value for the index. or if the value is not a JSONArray
*/
public JSONArray getJSONArray(final int index) throws JSONException {
final Object object = get(index);
if (object instanceof JSONArray) {
return (JSONArray) object;
}
throw new JSONException("JSONArray[" + index + "] is not a JSONArray.");
}
/**
* Get the JSONObject associated with an index.
*
* @param index subscript
*
* @return A JSONObject value.
*
* @throws JSONException If there is no value for the index or if the value is not a JSONObject
*/
public JSONObject getJSONObject(final int index) throws JSONException {
final Object object = get(index);
if (object instanceof JSONObject) {
return (JSONObject) object;
}
throw new JSONException("JSONArray[" + index + "] is not a JSONObject.");
}
/**
* Get the long value associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The value.
*
* @throws JSONException If the key is not found or if the value cannot be converted to a number.
*/
public long getLong(final int index) throws JSONException {
final Object object = get(index);
try {
return object instanceof Number ? ((Number) object).longValue() : Long.parseLong((String) object);
} catch (NumberFormatException e) {
throw new JSONException("JSONArray[" + index + "] is not a number.");
}
}
/**
* Get the string associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return A string value.
*
* @throws JSONException If there is no string value for the index.
*/
public String getString(final int index) throws JSONException {
final Object object = get(index);
if (object instanceof String) {
return (String) object;
}
throw new JSONException("JSONArray[" + index + "] not a string.");
}
/**
* Determine if the value is null.
*
* @param index The index must be between 0 and length() - 1.
*
* @return true if the value at the index is null, or if there is no value.
*/
public boolean isNull(final int index) {
return JSONObject.NULL.equals(opt(index));
}
/**
* Make a string from the contents of this JSONArray. The <code>separator</code> string is inserted between each
* element. Warning: This method assumes that the data structure is acyclical.
*
* @param separator A string that will be inserted between the elements.
*
* @return a string.
*
* @throws JSONException If the array contains an invalid number.
*/
public String join(final String separator) throws JSONException {
final int len = length();
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i += 1) {
if (i > 0) {
sb.append(separator);
}
sb.append(JSONObject.valueToString(myArrayList.get(i)));
}
return sb.toString();
}
/**
* Get the number of elements in the JSONArray, included nulls.
*
* @return The length (or size).
*/
public int length() {
return myArrayList.size();
}
/**
* Get the optional object value associated with an index.
*
* @param index The index must be between 0 and length() - 1.
*
* @return An object value, or null if there is no object at that index.
*/
public Object opt(final int index) {
return ((index < 0) || (index >= length())) ? null : myArrayList.get(index);
}
/**
* Get the optional boolean value associated with an index. It returns false if there is no value at that index, or
* if the value is not Boolean.TRUE or the String "true".
*
* @param index The index must be between 0 and length() - 1.
*
* @return The truth.
*/
public boolean optBoolean(final int index) {
return this.optBoolean(index, false);
}
/**
* Get the optional boolean value associated with an index. It returns the defaultValue if there is no value at that
* index or if it is not a Boolean or the String "true" or "false" (case insensitive).
*
* @param index The index must be between 0 and length() - 1.
* @param defaultValue A boolean default.
*
* @return The truth.
*/
public boolean optBoolean(final int index, final boolean defaultValue) {
try {
return getBoolean(index);
} catch (JSONException e) {
return defaultValue;
}
}
/**
* Get the optional double value associated with an index. NaN is returned if there is no value for the index, or if
* the value is not a number and cannot be converted to a number.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The value.
*/
public double optDouble(final int index) {
return this.optDouble(index, Double.NaN);
}
/**
* Get the optional double value associated with an index. The defaultValue is returned if there is no value for the
* index, or if the value is not a number and cannot be converted to a number.
*
* @param index subscript
* @param defaultValue The default value.
*
* @return The value.
*/
public double optDouble(final int index, final double defaultValue) {
try {
return getDouble(index);
} catch (JSONException e) {
return defaultValue;
}
}
/**
* Get the optional int value associated with an index. Zero is returned if there is no value for the index, or if
* the value is not a number and cannot be converted to a number.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The value.
*/
public int optInt(final int index) {
return this.optInt(index, 0);
}
/**
* Get the optional int value associated with an index. The defaultValue is returned if there is no value for the
* index, or if the value is not a number and cannot be converted to a number.
*
* @param index The index must be between 0 and length() - 1.
* @param defaultValue The default value.
*
* @return The value.
*/
public int optInt(final int index, final int defaultValue) {
try {
return getInt(index);
} catch (JSONException e) {
return defaultValue;
}
}
/**
* Get the optional JSONArray associated with an index.
*
* @param index subscript
*
* @return A JSONArray value, or null if the index has no value, or if the value is not a JSONArray.
*/
public JSONArray optJSONArray(final int index) {
final Object o = opt(index);
return o instanceof JSONArray ? (JSONArray) o : null;
}
/**
* Get the optional JSONObject associated with an index. Null is returned if the key is not found, or null if the
* index has no value, or if the value is not a JSONObject.
*
* @param index The index must be between 0 and length() - 1.
*
* @return A JSONObject value.
*/
public JSONObject optJSONObject(final int index) {
final Object o = opt(index);
return o instanceof JSONObject ? (JSONObject) o : null;
}
/**
* Get the optional long value associated with an index. Zero is returned if there is no value for the index, or if
* the value is not a number and cannot be converted to a number.
*
* @param index The index must be between 0 and length() - 1.
*
* @return The value.
*/
public long optLong(final int index) {
return this.optLong(index, 0);
}
/**
* Get the optional long value associated with an index. The defaultValue is returned if there is no value for the
* index, or if the value is not a number and cannot be converted to a number.
*
* @param index The index must be between 0 and length() - 1.
* @param defaultValue The default value.
*
* @return The value.
*/
public long optLong(final int index, final long defaultValue) {
try {
return getLong(index);
} catch (JSONException e) {
return defaultValue;
}
}
/**
* Get the optional string value associated with an index. It returns an empty string if there is no value at that
* index. If the value is not a string and is not null, then it is coverted to a string.
*
* @param index The index must be between 0 and length() - 1.
*
* @return A String value.
*/
public String optString(final int index) {
return this.optString(index, "");
}
/**
* Get the optional string associated with an index. The defaultValue is returned if the key is not found.
*
* @param index The index must be between 0 and length() - 1.
* @param defaultValue The default value.
*
* @return A String value.
*/
public String optString(final int index, final String defaultValue) {
final Object object = opt(index);
return JSONObject.NULL.equals(object) ? defaultValue : object.toString();
}
/**
* Append a boolean value. This increases the array's length by one.
*
* @param value A boolean value.
*
* @return this.
*/
public JSONArray put(final boolean value) {
this.put(value ? Boolean.TRUE : Boolean.FALSE);
return this;
}
/**
* Put a value in the JSONArray, where the value will be a JSONArray which is produced from a Collection.
*
* @param value A Collection value.
*
* @return this.
*/
public JSONArray put(final Collection<Object> value) {
this.put(new JSONArray(value));
return this;
}
/**
* Append a double value. This increases the array's length by one.
*
* @param value A double value.
*
* @return this.
*
* @throws JSONException if the value is not finite.
*/
public JSONArray put(final double value) throws JSONException {
final Double d = value;
JSONObject.testValidity(d);
this.put(d);
return this;
}
/**
* Append an int value. This increases the array's length by one.
*
* @param value An int value.
*
* @return this.
*/
public JSONArray put(final int value) {
this.put(new Integer(value));
return this;
}
/**
* Append an long value. This increases the array's length by one.
*
* @param value A long value.
*
* @return this.
*/
public JSONArray put(final long value) {
this.put(new Long(value));
return this;
}
/**
* Put a value in the JSONArray, where the value will be a JSONObject which is produced from a Map.
*
* @param value A Map value.
*
* @return this.
*/
public JSONArray put(final Map<String, Object> value) {
this.put(new JSONObject(value));
return this;
}
/**
* Append an object value. This increases the array's length by one.
*
* @param value An object value. The value should be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or
* String, or the JSONObject.NULL object.
*
* @return this.
*/
public JSONArray put(final Object value) {
myArrayList.add(value);
return this;
}
/**
* Put or replace a boolean value in the JSONArray. If the index is greater than the length of the JSONArray, then
* null elements will be added as necessary to pad it out.
*
* @param index The subscript.
* @param value A boolean value.
*
* @return this.
*
* @throws JSONException If the index is negative.
*/
public JSONArray put(final int index, final boolean value) throws JSONException {
this.put(index, value ? Boolean.TRUE : Boolean.FALSE);
return this;
}
/**
* Put a value in the JSONArray, where the value will be a JSONArray which is produced from a Collection.
*
* @param index The subscript.
* @param value A Collection value.
*
* @return this.
*
* @throws JSONException If the index is negative or if the value is not finite.
*/
public JSONArray put(final int index, final Collection<Object> value) throws JSONException {
this.put(index, new JSONArray(value));
return this;
}
/**
* Put or replace a double value. If the index is greater than the length of the JSONArray, then null elements will
* be added as necessary to pad it out.
*
* @param index The subscript.
* @param value A double value.
*
* @return this.
*
* @throws JSONException If the index is negative or if the value is not finite.
*/
public JSONArray put(final int index, final double value) throws JSONException {
this.put(index, new Double(value));
return this;
}
/**
* Put or replace an int value. If the index is greater than the length of the JSONArray, then null elements will be
* added as necessary to pad it out.
*
* @param index The subscript.
* @param value An int value.
*
* @return this.
*
* @throws JSONException If the index is negative.
*/
public JSONArray put(final int index, final int value) throws JSONException {
this.put(index, new Integer(value));
return this;
}
/**
* Put or replace a long value. If the index is greater than the length of the JSONArray, then null elements will be
* added as necessary to pad it out.
*
* @param index The subscript.
* @param value A long value.
*
* @return this.
*
* @throws JSONException If the index is negative.
*/
public JSONArray put(final int index, final long value) throws JSONException {
this.put(index, new Long(value));
return this;
}
/**
* Put a value in the JSONArray, where the value will be a JSONObject that is produced from a Map.
*
* @param index The subscript.
* @param value The Map value.
*
* @return this.
*
* @throws JSONException If the index is negative or if the the value is an invalid number.
*/
public JSONArray put(final int index, final Map<String, Object> value) throws JSONException {
this.put(index, new JSONObject(value));
return this;
}
/**
* Put or replace an object value in the JSONArray. If the index is greater than the length of the JSONArray, then
* null elements will be added as necessary to pad it out.
*
* @param index The subscript.
* @param value The value to put into the array. The value should be a Boolean, Double, Integer, JSONArray,
* JSONObject, Long, or String, or the JSONObject.NULL object.
*
* @return this.
*
* @throws JSONException If the index is negative or if the the value is an invalid number.
*/
public JSONArray put(final int index, final Object value) throws JSONException {
JSONObject.testValidity(value);
if (index < 0) {
throw new JSONException("JSONArray[" + index + "] not found.");
}
if (index < length()) {
myArrayList.set(index, value);
} else {
while (index != length()) {
this.put(JSONObject.NULL);
}
this.put(value);
}
return this;
}
/**
* Remove an index and close the hole.
*
* @param index The index of the element to be removed.
*
* @return The value that was associated with the index, or null if there was no value.
*/
public Object remove(final int index) {
return (index >= 0) && (index < length()) ? myArrayList.remove(index) : null;
}
/**
* Determine if two JSONArrays are similar. They must contain similar sequences.
*
* @param other The other JSONArray
*
* @return true if they are equal
*/
public boolean similar(final Object other) {
if (!(other instanceof JSONArray)) {
return false;
}
final int len = length();
if (len != ((JSONArray) other).length()) {
return false;
}
for (int i = 0; i < len; i += 1) {
final Object valueThis = get(i);
final Object valueOther = ((JSONArray) other).get(i);
if (valueThis instanceof JSONObject) {
if (!((JSONObject) valueThis).similar(valueOther)) {
return false;
}
} else if (valueThis instanceof JSONArray) {
if (!((JSONArray) valueThis).similar(valueOther)) {
return false;
}
} else if (!valueThis.equals(valueOther)) {
return false;
}
}
return true;
}
/**
* Produce a JSONObject by combining a JSONArray of names with the values of this JSONArray.
*
* @param names A JSONArray containing a list of key strings. These will be paired with the values.
*
* @return A JSONObject, or null if there are no names or if this JSONArray has no values.
*
* @throws JSONException If any of the names are null.
*/
public JSONObject toJSONObject(final JSONArray names) throws JSONException {
if ((names == null) || (names.length() == 0) || (length() == 0)) {
return null;
}
final JSONObject jo = new JSONObject();
for (int i = 0; i < names.length(); i += 1) {
jo.put(names.getString(i), opt(i));
}
return jo;
}
/**
* Make a JSON text of this JSONArray. For compactness, no unnecessary whitespace is added. If it is not possible to
* produce a syntactically correct JSON text then null will be returned instead. This could occur if the array
* contains an invalid number.
*
* Warning: This method assumes that the data structure is acyclical.
*
* @return a printable, displayable, transmittable representation of the array.
*/
@Override
public String toString() {
try {
return this.toString(0);
} catch (JSONException e) {
return null;
}
}
/**
* Make a prettyprinted JSON text of this JSONArray. Warning: This method assumes that the data structure is
* acyclical.
*
* @param indentFactor The number of spaces to add to each level of indentation.
*
* @return a printable, displayable, transmittable representation of the object, beginning with
* <code>[</code>&nbsp;<small>(left bracket)</small> and ending with <code>]</code> &nbsp;<small>(right
* bracket)</small>.
*
* @throws JSONException
*/
public String toString(final int indentFactor) throws JSONException {
final StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0).toString();
}
}
/**
* Write the contents of the JSONArray as JSON text to a writer. For compactness, no whitespace is added.
*
* Warning: This method assumes that the data structure is acyclical.
*
* @return The writer.
*
* @throws JSONException
*/
public Writer write(final Writer writer) throws JSONException {
return this.write(writer, 0, 0);
}
/**
* Write the contents of the JSONArray as JSON text to a writer. For compactness, no whitespace is added.
*
* Warning: This method assumes that the data structure is acyclical.
*
* @param indentFactor The number of spaces to add to each level of indentation.
* @param indent The indention of the top level.
*
* @return The writer.
*
* @throws JSONException
*/
Writer write(final Writer writer, final int indentFactor, final int indent) throws JSONException {
try {
boolean commanate = false;
final int length = length();
writer.write('[');
if (length == 1) {
JSONObject.writeValue(writer, myArrayList.get(0), indentFactor, indent);
} else if (length != 0) {
final int newindent = indent + indentFactor;
for (int i = 0; i < length; i += 1) {
if (commanate) {
writer.write(',');
}
if (indentFactor > 0) {
writer.write('\n');
}
JSONObject.indent(writer, newindent);
JSONObject.writeValue(writer, myArrayList.get(i), indentFactor, newindent);
commanate = true;
}
if (indentFactor > 0) {
writer.write('\n');
}
JSONObject.indent(writer, indent);
}
writer.write(']');
return writer;
} catch (final IOException e) {
throw new JSONException(e);
}
}
}

View File

@ -0,0 +1,41 @@
package com.intellectualcrafters.json;
/**
* The JSONException is thrown by the JSON.org classes when things are amiss.
*
* @author JSON.org
* @version 2014-05-03
*/
public class JSONException extends RuntimeException {
private static final long serialVersionUID = 0;
private Throwable cause;
/**
* Constructs a JSONException with an explanatory message.
*
* @param message Detail about the reason for the exception.
*/
public JSONException(final String message) {
super(message);
}
/**
* Constructs a new JSONException with the specified cause.
*
* @param cause The cause.
*/
public JSONException(final Throwable cause) {
super(cause.getMessage());
this.cause = cause;
}
/**
* Returns the cause of this exception or null if the cause is nonexistent or unknown.
*
* @return the cause of this exception or null if the cause is nonexistent or unknown.
*/
@Override
public Throwable getCause() {
return cause;
}
}

View File

@ -0,0 +1,406 @@
package com.intellectualcrafters.json;
import java.util.Iterator;
/**
* This provides static methods to convert an XML text into a JSONArray or JSONObject, and to covert a JSONArray or
* JSONObject into an XML text using the JsonML transform.
*
* @author JSON.org
* @version 2014-05-03
*/
public class JSONML {
/**
* Parse XML values and store them in a JSONArray.
*
* @param x The XMLTokener containing the source string.
* @param arrayForm true if array form, false if object form.
* @param ja The JSONArray that is containing the current tag or null if we are at the outermost level.
*
* @return A JSONArray if the value is the outermost tag, otherwise null.
*
* @throws JSONException
*/
private static Object parse(final XMLTokener x, final boolean arrayForm, final JSONArray ja) throws JSONException {
String attribute;
char c;
String closeTag = null;
int i;
JSONArray newja = null;
JSONObject newjo = null;
Object token;
String tagName = null;
// Test for and skip past these forms:
// <!-- ... -->
// <![ ... ]]>
// <! ... >
// <? ... ?>
while (true) {
if (!x.more()) {
throw x.syntaxError("Bad XML");
}
token = x.nextContent();
if (token == XML.LT) {
token = x.nextToken();
if (token instanceof Character) {
if (token == XML.SLASH) {
// Close tag </
token = x.nextToken();
if (!(token instanceof String)) {
throw new JSONException("Expected a closing name instead of '" + token + "'.");
}
if (x.nextToken() != XML.GT) {
throw x.syntaxError("Misshaped close tag");
}
return token;
} else if (token == XML.BANG) {
// <!
c = x.next();
if (c == '-') {
if (x.next() == '-') {
x.skipPast("-->");
} else {
x.back();
}
} else if (c == '[') {
token = x.nextToken();
if (token.equals("CDATA") && (x.next() == '[')) {
if (ja != null) {
ja.put(x.nextCDATA());
}
} else {
throw x.syntaxError("Expected 'CDATA['");
}
} else {
i = 1;
do {
token = x.nextMeta();
if (token == null) {
throw x.syntaxError("Missing '>' after '<!'.");
} else if (token == XML.LT) {
i += 1;
} else if (token == XML.GT) {
i -= 1;
}
} while (i > 0);
}
} else if (token == XML.QUEST) {
// <?
x.skipPast("?>");
} else {
throw x.syntaxError("Misshaped tag");
}
// Open tag <
} else {
if (!(token instanceof String)) {
throw x.syntaxError("Bad tagName '" + token + "'.");
}
tagName = (String) token;
newja = new JSONArray();
newjo = new JSONObject();
if (arrayForm) {
newja.put(tagName);
if (ja != null) {
ja.put(newja);
}
} else {
newjo.put("tagName", tagName);
if (ja != null) {
ja.put(newjo);
}
}
token = null;
for (;;) {
if (token == null) {
token = x.nextToken();
}
if (token == null) {
throw x.syntaxError("Misshaped tag");
}
if (!(token instanceof String)) {
break;
}
// attribute = value
attribute = (String) token;
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
throw x.syntaxError("Reserved attribute.");
}
token = x.nextToken();
if (token == XML.EQ) {
token = x.nextToken();
if (!(token instanceof String)) {
throw x.syntaxError("Missing value");
}
newjo.accumulate(attribute, XML.stringToValue((String) token));
token = null;
} else {
newjo.accumulate(attribute, "");
}
}
if (arrayForm && (newjo.length() > 0)) {
newja.put(newjo);
}
// Empty tag <.../>
if (token == XML.SLASH) {
if (x.nextToken() != XML.GT) {
throw x.syntaxError("Misshaped tag");
}
if (ja == null) {
if (arrayForm) {
return newja;
} else {
return newjo;
}
}
// Content, between <...> and </...>
} else {
if (token != XML.GT) {
throw x.syntaxError("Misshaped tag");
}
closeTag = (String) parse(x, arrayForm, newja);
if (closeTag != null) {
if (!closeTag.equals(tagName)) {
throw x.syntaxError("Mismatched '" + tagName + "' and '" + closeTag + "'");
}
tagName = null;
if (!arrayForm && (newja.length() > 0)) {
newjo.put("childNodes", newja);
}
if (ja == null) {
if (arrayForm) {
return newja;
} else {
return newjo;
}
}
}
}
}
} else {
if (ja != null) {
ja.put(token instanceof String ? XML.stringToValue((String) token) : token);
}
}
}
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the JsonML transform. Each
* XML tag is represented as a JSONArray in which the first element is the tag name. If the tag has attributes, then
* the second element will be JSONObject containing the name/value pairs. If the tag contains children, then strings
*
* @param string The source string.
*
* @return A JSONArray containing the structured data from the XML string.
*
* @throws JSONException
*/
public static JSONArray toJSONArray(final String string) throws JSONException {
return toJSONArray(new XMLTokener(string));
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the JsonML transform. Each
* XML tag is represented as a JSONArray in which the first element is the tag name. If the tag has attributes, then
* the second element will be JSONObject containing the name/value pairs. If the tag contains children, then strings
* and JSONArrays will represent the child content and tags. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* are ignored.
*
* @param x An XMLTokener.
*
* @return A JSONArray containing the structured data from the XML string.
*
* @throws JSONException
*/
public static JSONArray toJSONArray(final XMLTokener x) throws JSONException {
return (JSONArray) parse(x, true, null);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the JsonML transform. Each
* XML tag is represented as a JSONObject with a "tagName" property. If the tag has attributes, then the attributes
* will be in the JSONObject as properties. If the tag contains children, the object will have a "childNodes"
* property which will be an array of strings and JsonML JSONObjects.
*
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
*
* @param x An XMLTokener of the XML source text.
*
* @return A JSONObject containing the structured data from the XML string.
*
* @throws JSONException
*/
public static JSONObject toJSONObject(final XMLTokener x) throws JSONException {
return (JSONObject) parse(x, false, null);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the JsonML transform. Each
* XML tag is represented as a JSONObject with a "tagName" property. If the tag has attributes, then the attributes
* will be in the JSONObject as properties. If the tag contains children, the object will have a "childNodes"
* property which will be an array of strings and JsonML JSONObjects.
*
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
*
* @param string The XML source text.
*
* @return A JSONObject containing the structured data from the XML string.
*
* @throws JSONException
*/
public static JSONObject toJSONObject(final String string) throws JSONException {
return toJSONObject(new XMLTokener(string));
}
/**
* Reverse the JSONML transformation, making an XML text from a JSONArray.
*
* @param ja A JSONArray.
*
* @return An XML string.
*
* @throws JSONException
*/
public static String toString(final JSONArray ja) throws JSONException {
int i;
JSONObject jo;
String key;
Iterator<String> keys;
int length;
Object object;
final StringBuilder sb = new StringBuilder();
String tagName;
String value;
// Emit <tagName
tagName = ja.getString(0);
XML.noSpace(tagName);
tagName = XML.escape(tagName);
sb.append('<');
sb.append(tagName);
object = ja.opt(1);
if (object instanceof JSONObject) {
i = 2;
jo = (JSONObject) object;
// Emit the attributes
keys = jo.keys();
while (keys.hasNext()) {
key = keys.next();
XML.noSpace(key);
value = jo.optString(key);
if (value != null) {
sb.append(' ');
sb.append(XML.escape(key));
sb.append('=');
sb.append('"');
sb.append(XML.escape(value));
sb.append('"');
}
}
} else {
i = 1;
}
// Emit content in body
length = ja.length();
if (i >= length) {
sb.append('/');
sb.append('>');
} else {
sb.append('>');
do {
object = ja.get(i);
i += 1;
if (object != null) {
if (object instanceof String) {
sb.append(XML.escape(object.toString()));
} else if (object instanceof JSONObject) {
sb.append(toString((JSONObject) object));
} else if (object instanceof JSONArray) {
sb.append(toString((JSONArray) object));
}
}
} while (i < length);
sb.append('<');
sb.append('/');
sb.append(tagName);
sb.append('>');
}
return sb.toString();
}
/**
* Reverse the JSONML transformation, making an XML text from a JSONObject. The JSONObject must contain a "tagName"
* property. If it has children, then it must have a "childNodes" property containing an array of objects. The other
* properties are attributes with string values.
*
* @param jo A JSONObject.
*
* @return An XML string.
*
* @throws JSONException
*/
public static String toString(final JSONObject jo) throws JSONException {
final StringBuilder sb = new StringBuilder();
int i;
JSONArray ja;
String key;
Iterator<String> keys;
int length;
Object object;
String tagName;
String value;
// Emit <tagName
tagName = jo.optString("tagName");
if (tagName == null) {
return XML.escape(jo.toString());
}
XML.noSpace(tagName);
tagName = XML.escape(tagName);
sb.append('<');
sb.append(tagName);
// Emit the attributes
keys = jo.keys();
while (keys.hasNext()) {
key = keys.next();
if (!"tagName".equals(key) && !"childNodes".equals(key)) {
XML.noSpace(key);
value = jo.optString(key);
if (value != null) {
sb.append(' ');
sb.append(XML.escape(key));
sb.append('=');
sb.append('"');
sb.append(XML.escape(value));
sb.append('"');
}
}
}
// Emit content in body
ja = jo.optJSONArray("childNodes");
if (ja == null) {
sb.append('/');
sb.append('>');
} else {
sb.append('>');
length = ja.length();
for (i = 0; i < length; i += 1) {
object = ja.get(i);
if (object != null) {
if (object instanceof String) {
sb.append(XML.escape(object.toString()));
} else if (object instanceof JSONObject) {
sb.append(toString((JSONObject) object));
} else if (object instanceof JSONArray) {
sb.append(toString((JSONArray) object));
} else {
sb.append(object.toString());
}
}
}
sb.append('<');
sb.append('/');
sb.append(tagName);
sb.append('>');
}
return sb.toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
package com.intellectualcrafters.json;
/**
* The <code>JSONString</code> interface allows a <code>toJSONString()</code> method so that a class can change the
* behavior of <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>, and
* <code>JSONWriter.value(</code>Object<code>)</code>. The <code>toJSONString</code> method will be used instead of the
* default behavior of using the Object's <code>toString()</code> method and quoting the result.
*/
public interface JSONString {
/**
* The <code>toJSONString</code> method allows a class to produce its own JSON serialization.
*
* @return A strictly syntactically correct JSON text.
*/
public String toJSONString();
}

View File

@ -0,0 +1,55 @@
package com.intellectualcrafters.json;
import java.io.StringWriter;
/**
* JSONStringer provides a quick and convenient way of producing JSON text. The texts produced strictly conform to JSON
* syntax rules. No whitespace is added, so the results are ready for transmission or storage. Each instance of
* JSONStringer can produce one JSON text.
*
* A JSONStringer instance provides a <code>value</code> method for appending values to the text, and a <code>key</code>
* method for adding keys before values in objects. There are <code>array</code> and <code>endArray</code> methods that
* make and bound array values, and <code>object</code> and <code>endObject</code> methods which make and bound object
* values. All of these methods return the JSONWriter instance, permitting cascade style. For example,
*
*
* <pre>
* myString = new JSONStringer().object().key(&quot;JSON&quot;).value(&quot;Hello,
* World!&quot;).endObject().toString();
* </pre>
*
* which produces the string
*
*
* <pre>
* {"JSON":"Hello, World!"}
* </pre>
*
* The first method called must be <code>array</code> or <code>object</code>. There are no methods for adding commas or
* colons. JSONStringer adds them for you. Objects and arrays can be nested up to 20 levels deep.
*
* This can sometimes be easier than using a JSONObject to build a string.
*
* @author JSON.org
* @version 2008-09-18
*/
public class JSONStringer extends JSONWriter {
/**
* Make a fresh JSONStringer. It can be used to build one JSON text.
*/
public JSONStringer() {
super(new StringWriter());
}
/**
* Return the JSON text. This method is used to obtain the product of the JSONStringer instance. It will return
* <code>null</code> if there was a problem in the construction of the JSON text (such as the calls to
* <code>array</code> were not properly balanced with calls to <code>endArray</code>).
*
* @return The JSON text.
*/
@Override
public String toString() {
return mode == 'd' ? writer.toString() : null;
}
}

View File

@ -0,0 +1,403 @@
package com.intellectualcrafters.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
/**
* A JSONTokener takes a source string and extracts characters and tokens from it. It is used by the JSONObject and
* JSONArray constructors to parse JSON source strings.
*
* @author JSON.org
* @version 2014-05-03
*/
public class JSONTokener {
private final Reader reader;
private long character;
private boolean eof;
private long index;
private long line;
private char previous;
private boolean usePrevious;
/**
* Construct a JSONTokener from a Reader.
*
* @param reader A reader.
*/
public JSONTokener(final Reader reader) {
this.reader = reader.markSupported() ? reader : new BufferedReader(reader);
eof = false;
usePrevious = false;
previous = 0;
index = 0;
character = 1;
line = 1;
}
/**
* Construct a JSONTokener from an InputStream.
*
* @param inputStream The source.
*/
public JSONTokener(final InputStream inputStream) throws JSONException {
this(new InputStreamReader(inputStream));
}
/**
* Construct a JSONTokener from a string.
*
* @param s A source string.
*/
public JSONTokener(final String s) {
this(new StringReader(s));
}
/**
* Get the hex value of a character (base16).
*
* @param c A character between '0' and '9' or between 'A' and 'F' or between 'a' and 'f'.
*
* @return An int between 0 and 15, or -1 if c was not a hex digit.
*/
public static int dehexchar(final char c) {
if ((c >= '0') && (c <= '9')) {
return c - '0';
}
if ((c >= 'A') && (c <= 'F')) {
return c - ('A' - 10);
}
if ((c >= 'a') && (c <= 'f')) {
return c - ('a' - 10);
}
return -1;
}
/**
* Back up one character. This provides a sort of lookahead capability, so that you can test for a digit or letter
* before attempting to parse the next number or identifier.
*/
public void back() throws JSONException {
if (usePrevious || (index <= 0)) {
throw new JSONException("Stepping back two steps is not supported");
}
index -= 1;
character -= 1;
usePrevious = true;
eof = false;
}
public boolean end() {
return eof && !usePrevious;
}
/**
* Determine if the source string still contains characters that next() can consume.
*
* @return true if not yet at the end of the source.
*/
public boolean more() throws JSONException {
this.next();
if (end()) {
return false;
}
back();
return true;
}
/**
* Get the next character in the source string.
*
* @return The next character, or 0 if past the end of the source string.
*/
public char next() throws JSONException {
int c;
if (usePrevious) {
usePrevious = false;
c = previous;
} else {
try {
c = reader.read();
} catch (final IOException exception) {
throw new JSONException(exception);
}
if (c <= 0) { // End of stream
eof = true;
c = 0;
}
}
index += 1;
if (previous == '\r') {
line += 1;
character = c == '\n' ? 0 : 1;
} else if (c == '\n') {
line += 1;
character = 0;
} else {
character += 1;
}
previous = (char) c;
return previous;
}
/**
* Consume the next character, and check that it matches a specified character.
*
* @param c The character to match.
*
* @return The character.
*
* @throws JSONException if the character does not match.
*/
public char next(final char c) throws JSONException {
final char n = this.next();
if (n != c) {
throw syntaxError("Expected '" + c + "' and instead saw '" + n + "'");
}
return n;
}
/**
* Get the next n characters.
*
* @param n The number of characters to take.
*
* @return A string of n characters.
*
* @throws JSONException Substring bounds error if there are not n characters remaining in the source string.
*/
public String next(final int n) throws JSONException {
if (n == 0) {
return "";
}
final char[] chars = new char[n];
int pos = 0;
while (pos < n) {
chars[pos] = this.next();
if (end()) {
throw syntaxError("Substring bounds error");
}
pos += 1;
}
return new String(chars);
}
/**
* Get the next char in the string, skipping whitespace.
*
* @return A character, or 0 if there are no more characters.
*
* @throws JSONException
*/
public char nextClean() throws JSONException {
for (;;) {
final char c = this.next();
if ((c == 0) || (c > ' ')) {
return c;
}
}
}
/**
* Return the characters up to the next close quote character. Backslash processing is done. The formal JSON format
* does not allow strings in single quotes, but an implementation is allowed to accept them.
*
* @param quote The quoting character, either <code>"</code> &nbsp;<small>(double quote)</small> or <code>'</code>
* &nbsp;<small>(single quote)</small>.
*
* @return A String.
*
* @throws JSONException Unterminated string.
*/
public String nextString(final char quote) throws JSONException {
char c;
final StringBuilder sb = new StringBuilder();
for (;;) {
c = this.next();
switch (c) {
case 0:
case '\n':
case '\r':
throw syntaxError("Unterminated string");
case '\\':
c = this.next();
switch (c) {
case 'b':
sb.append('\b');
break;
case 't':
sb.append('\t');
break;
case 'n':
sb.append('\n');
break;
case 'f':
sb.append('\f');
break;
case 'r':
sb.append('\r');
break;
case 'u':
sb.append((char) Integer.parseInt(this.next(4), 16));
break;
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
default:
throw syntaxError("Illegal escape.");
}
break;
default:
if (c == quote) {
return sb.toString();
}
sb.append(c);
}
}
}
/**
* Get the text up but not including the specified character or the end of line, whichever comes first.
*
* @param delimiter A delimiter character.
*
* @return A string.
*/
public String nextTo(final char delimiter) throws JSONException {
final StringBuilder sb = new StringBuilder();
for (;;) {
final char c = this.next();
if ((c == delimiter) || (c == 0) || (c == '\n') || (c == '\r')) {
if (c != 0) {
back();
}
return sb.toString().trim();
}
sb.append(c);
}
}
/**
* Get the text up but not including one of the specified delimiter characters or the end of line, whichever comes
* first.
*
* @param delimiters A set of delimiter characters.
*
* @return A string, trimmed.
*/
public String nextTo(final String delimiters) throws JSONException {
char c;
final StringBuilder sb = new StringBuilder();
for (;;) {
c = this.next();
if ((delimiters.indexOf(c) >= 0) || (c == 0) || (c == '\n') || (c == '\r')) {
if (c != 0) {
back();
}
return sb.toString().trim();
}
sb.append(c);
}
}
/**
* Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
* JSONObject.NULL object.
*
* @return An object.
*
* @throws JSONException If syntax error.
*/
public Object nextValue() throws JSONException {
char c = nextClean();
String string;
switch (c) {
case '"':
case '\'':
return nextString(c);
case '{':
back();
return new JSONObject(this);
case '[':
back();
return new JSONArray(this);
}
/*
* Handle unquoted text. This could be the values true, false, or
* null, or it can be a number. An implementation (such as this one)
* is allowed to also accept non-standard forms.
* Accumulate characters until we reach the end of the text or a
* formatting character.
*/
final StringBuilder sb = new StringBuilder();
while ((c >= ' ') && (",:]}/\\\"[{;=#".indexOf(c) < 0)) {
sb.append(c);
c = this.next();
}
back();
string = sb.toString().trim();
if ("".equals(string)) {
throw syntaxError("Missing value");
}
return JSONObject.stringToValue(string);
}
/**
* Skip characters until the next character is the requested character. If the requested character is not found, no
* characters are skipped.
*
* @param to A character to skip to.
*
* @return The requested character, or zero if the requested character is not found.
*/
public char skipTo(final char to) throws JSONException {
char c;
try {
final long startIndex = index;
final long startCharacter = character;
final long startLine = line;
reader.mark(1000000);
do {
c = this.next();
if (c == 0) {
reader.reset();
index = startIndex;
character = startCharacter;
line = startLine;
return c;
}
} while (c != to);
} catch (final IOException exception) {
throw new JSONException(exception);
}
back();
return c;
}
/**
* Make a JSONException to signal a syntax error.
*
* @param message The error message.
*
* @return A JSONException object, suitable for throwing
*/
public JSONException syntaxError(final String message) {
return new JSONException(message + toString());
}
/**
* Make a printable string of this JSONTokener.
*
* @return " at {index} [character {character} line {line}]"
*/
@Override
public String toString() {
return " at " + index + " [character " + character + " line " + line + "]";
}
}

View File

@ -0,0 +1,308 @@
package com.intellectualcrafters.json;
import java.io.IOException;
import java.io.Writer;
/**
* JSONWriter provides a quick and convenient way of producing JSON text. The texts produced strictly conform to JSON
* syntax rules. No whitespace is added, so the results are ready for transmission or storage. Each instance of
* JSONWriter can produce one JSON text.
*
* A JSONWriter instance provides a <code>value</code> method for appending values to the text, and a <code>key</code>
* method for adding keys before values in objects. There are <code>array</code> and <code>endArray</code> methods that
* make and bound array values, and <code>object</code> and <code>endObject</code> methods which make and bound object
* values. All of these methods return the JSONWriter instance, permitting a cascade style. For example,
*
*
* <pre>
* new JSONWriter(myWriter).object().key(&quot;JSON&quot;).value(&quot;Hello, World!&quot;).endObject();
* </pre>
*
* which writes
*
*
* <pre>
* {"JSON":"Hello, World!"}
* </pre>
*
* The first method called must be <code>array</code> or <code>object</code>. There are no methods for adding commas or
* colons. JSONWriter adds them for you. Objects and arrays can be nested up to 20 levels deep.
*
* This can sometimes be easier than using a JSONObject to build a string.
*
* @author JSON.org
* @version 2011-11-24
*/
public class JSONWriter {
private static final int maxdepth = 200;
/**
* The writer that will receive the output.
*/
protected final Writer writer;
/**
* The object/array stack.
*/
private final JSONObject stack[];
/**
* The current mode. Values: 'a' (array), 'd' (done), 'i' (initial), 'k' (key), 'o' (object).
*/
protected char mode;
/**
* The comma flag determines if a comma should be output before the next value.
*/
private boolean comma;
/**
* The stack top index. A value of 0 indicates that the stack is empty.
*/
private int top;
/**
* Make a fresh JSONWriter. It can be used to build one JSON text.
*/
public JSONWriter(final Writer w) {
comma = false;
mode = 'i';
stack = new JSONObject[maxdepth];
top = 0;
writer = w;
}
/**
* Append a value.
*
* @param string A string value.
*
* @return this
*
* @throws JSONException If the value is out of sequence.
*/
private JSONWriter append(final String string) throws JSONException {
if (string == null) {
throw new JSONException("Null pointer");
}
if ((mode == 'o') || (mode == 'a')) {
try {
if (comma && (mode == 'a')) {
writer.write(',');
}
writer.write(string);
} catch (final IOException e) {
throw new JSONException(e);
}
if (mode == 'o') {
mode = 'k';
}
comma = true;
return this;
}
throw new JSONException("Value out of sequence.");
}
/**
* Begin appending a new array. All values until the balancing <code>endArray</code> will be appended to this array.
* The <code>endArray</code> method must be called to mark the array's end.
*
* @return this
*
* @throws JSONException If the nesting is too deep, or if the object is started in the wrong place (for example as
* a key or after the end of the outermost array or object).
*/
public JSONWriter array() throws JSONException {
if ((mode == 'i') || (mode == 'o') || (mode == 'a')) {
push(null);
append("[");
comma = false;
return this;
}
throw new JSONException("Misplaced array.");
}
/**
* End something.
*
* @param mode Mode
* @param c Closing character
*
* @return this
*
* @throws JSONException If unbalanced.
*/
private JSONWriter end(final char mode, final char c) throws JSONException {
if (this.mode != mode) {
throw new JSONException(mode == 'a' ? "Misplaced endArray." : "Misplaced endObject.");
}
pop(mode);
try {
writer.write(c);
} catch (final IOException e) {
throw new JSONException(e);
}
comma = true;
return this;
}
/**
* End an array. This method most be called to balance calls to <code>array</code>.
*
* @return this
*
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endArray() throws JSONException {
return end('a', ']');
}
/**
* End an object. This method most be called to balance calls to <code>object</code>.
*
* @return this
*
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endObject() throws JSONException {
return end('k', '}');
}
/**
* Append a key. The key will be associated with the next value. In an object, every value must be preceded by a
* key.
*
* @param string A key string.
*
* @return this
*
* @throws JSONException If the key is out of place. For example, keys do not belong in arrays or if the key is
* null.
*/
public JSONWriter key(final String string) throws JSONException {
if (string == null) {
throw new JSONException("Null key.");
}
if (mode == 'k') {
try {
stack[top - 1].putOnce(string, Boolean.TRUE);
if (comma) {
writer.write(',');
}
writer.write(JSONObject.quote(string));
writer.write(':');
comma = false;
mode = 'o';
return this;
} catch (final IOException e) {
throw new JSONException(e);
}
}
throw new JSONException("Misplaced key.");
}
/**
* Begin appending a new object. All keys and values until the balancing <code>endObject</code> will be appended to
* this object. The <code>endObject</code> method must be called to mark the object's end.
*
* @return this
*
* @throws JSONException If the nesting is too deep, or if the object is started in the wrong place (for example as
* a key or after the end of the outermost array or object).
*/
public JSONWriter object() throws JSONException {
if (mode == 'i') {
mode = 'o';
}
if ((mode == 'o') || (mode == 'a')) {
append("{");
push(new JSONObject());
comma = false;
return this;
}
throw new JSONException("Misplaced object.");
}
/**
* Pop an array or object scope.
*
* @param c The scope to close.
*
* @throws JSONException If nesting is wrong.
*/
private void pop(final char c) throws JSONException {
if (top <= 0) {
throw new JSONException("Nesting error.");
}
final char m = stack[top - 1] == null ? 'a' : 'k';
if (m != c) {
throw new JSONException("Nesting error.");
}
top -= 1;
mode = top == 0 ? 'd' : stack[top - 1] == null ? 'a' : 'k';
}
/**
* Push an array or object scope.
*
* @param jo The scope to open.
*
* @throws JSONException If nesting is too deep.
*/
private void push(final JSONObject jo) throws JSONException {
if (top >= maxdepth) {
throw new JSONException("Nesting too deep.");
}
stack[top] = jo;
mode = jo == null ? 'a' : 'k';
top += 1;
}
/**
* Append either the value <code>true</code> or the value <code>false</code> .
*
* @param b A boolean.
*
* @return this
*
* @throws JSONException
*/
public JSONWriter value(final boolean b) throws JSONException {
return append(b ? "true" : "false");
}
/**
* Append a double value.
*
* @param d A double.
*
* @return this
*
* @throws JSONException If the number is not finite.
*/
public JSONWriter value(final double d) throws JSONException {
return this.value(new Double(d));
}
/**
* Append a long value.
*
* @param l A long.
*
* @return this
*
* @throws JSONException
*/
public JSONWriter value(final long l) throws JSONException {
return append(Long.toString(l));
}
/**
* Append an object value.
*
* @param object The object to append. It can be null, or a Boolean, Number, String, JSONObject, or JSONArray, or an
* object that implements JSONString.
*
* @return this
*
* @throws JSONException If the value is out of sequence.
*/
public JSONWriter value(final Object object) throws JSONException {
return append(JSONObject.valueToString(object));
}
}

View File

@ -0,0 +1,313 @@
package com.intellectualcrafters.json;
/**
* Kim makes immutable eight bit Unicode strings. If the MSB of a byte is set, then the next byte is a continuation
* byte. The last byte of a character never has the MSB reset. Every byte that is not the last byte has the MSB set. Kim
* stands for "Keep it minimal". A Unicode character is never longer than 3 bytes. Every byte contributes 7 bits to the
* character. ASCII is unmodified.
*
* Kim UTF-8 one byte U+007F U+007F two bytes U+3FFF U+07FF three bytes U+10FFF U+FFFF four bytes U+10FFFF
*
* Characters in the ranges U+0800..U+3FFF and U+10000..U+10FFFF will be one byte smaller when encoded in Kim compared
* to UTF-8.
*
* Kim is beneficial when using scripts such as Old South Arabian, Aramaic, Avestan, Balinese, Batak, Bopomofo,
* Buginese, Buhid, Carian, Cherokee, Coptic, Cyrillic, Deseret, Egyptian Hieroglyphs, Ethiopic, Georgian, Glagolitic,
* Gothic, Hangul Jamo, Hanunoo, Hiragana, Kanbun, Kaithi, Kannada, Katakana, Kharoshthi, Khmer, Lao, Lepcha, Limbu,
* Lycian, Lydian, Malayalam, Mandaic, Meroitic, Miao, Mongolian, Myanmar, New Tai Lue, Ol Chiki, Old Turkic, Oriya,
* Osmanya, Pahlavi, Parthian, Phags-Pa, Phoenician, Samaritan, Sharada, Sinhala, Sora Sompeng, Tagalog, Tagbanwa,
* Takri, Tai Le, Tai Tham, Tamil, Telugu, Thai, Tibetan, Tifinagh, UCAS.
*
* A kim object can be constructed from an ordinary UTF-16 string, or from a byte array. A kim object can produce a
* UTF-16 string.
*
* As with UTF-8, it is possible to detect character boundaries within a byte sequence. UTF-8 is one of the world's
* great inventions. While Kim is more efficient, it is not clear that it is worth the expense of transition.
*
* @version 2013-04-18
*/
public class Kim {
/**
* The number of bytes in the kim. The number of bytes can be as much as three times the number of characters.
*/
public int length = 0;
/**
* The byte array containing the kim's content.
*/
private byte[] bytes = null;
/**
* The kim's hashcode, conforming to Java's hashcode conventions.
*/
private int hashcode = 0;
/**
* The memoization of toString().
*/
private String string = null;
/**
* Make a kim from a portion of a byte array.
*
* @param bytes A byte array.
* @param from The index of the first byte.
* @param thru The index of the last byte plus one.
*/
public Kim(final byte[] bytes, final int from, final int thru) {
// As the bytes are copied into the new kim, a hashcode is computed
// using a
// modified Fletcher code.
int sum = 1;
int value;
hashcode = 0;
length = thru - from;
if (length > 0) {
this.bytes = new byte[length];
for (int at = 0; at < length; at += 1) {
value = bytes[at + from] & 0xFF;
sum += value;
hashcode += sum;
this.bytes[at] = (byte) value;
}
hashcode += sum << 16;
}
}
/**
* Make a kim from a byte array.
*
* @param bytes The byte array.
* @param length The number of bytes.
*/
public Kim(final byte[] bytes, final int length) {
this(bytes, 0, length);
}
/**
* Make a new kim from a substring of an existing kim. The coordinates are in byte units, not character units.
*
* @param kim The source of bytes.
* @param from The point at which to take bytes.
* @param thru The point at which to stop taking bytes.
*/
public Kim(final Kim kim, final int from, final int thru) {
this(kim.bytes, from, thru);
}
/**
* Make a kim from a string.
*
* @param string The string.
*
* @throws JSONException if surrogate pair mismatch.
*/
public Kim(final String string) throws JSONException {
final int stringLength = string.length();
hashcode = 0;
length = 0;
// First pass: Determine the length of the kim, allowing for the UTF-16
// to UTF-32 conversion, and then the UTF-32 to Kim conversion.
if (stringLength > 0) {
for (int i = 0; i < stringLength; i += 1) {
final int c = string.charAt(i);
if (c <= 0x7F) {
length += 1;
} else if (c <= 0x3FFF) {
length += 2;
} else {
if ((c >= 0xD800) && (c <= 0xDFFF)) {
i += 1;
final int d = string.charAt(i);
if ((c > 0xDBFF) || (d < 0xDC00) || (d > 0xDFFF)) {
throw new JSONException("Bad UTF16");
}
}
length += 3;
}
}
// Second pass: Allocate a byte array and fill that array with the
// conversion
// while computing the hashcode.
bytes = new byte[length];
int at = 0;
int b;
int sum = 1;
for (int i = 0; i < stringLength; i += 1) {
int character = string.charAt(i);
if (character <= 0x7F) {
bytes[at] = (byte) character;
sum += character;
hashcode += sum;
at += 1;
} else if (character <= 0x3FFF) {
b = 0x80 | (character >>> 7);
bytes[at] = (byte) b;
sum += b;
hashcode += sum;
at += 1;
b = character & 0x7F;
bytes[at] = (byte) b;
sum += b;
hashcode += sum;
at += 1;
} else {
if ((character >= 0xD800) && (character <= 0xDBFF)) {
i += 1;
character = (((character & 0x3FF) << 10) | (string.charAt(i) & 0x3FF)) + 65536;
}
b = 0x80 | (character >>> 14);
bytes[at] = (byte) b;
sum += b;
hashcode += sum;
at += 1;
b = 0x80 | ((character >>> 7) & 0xFF);
bytes[at] = (byte) b;
sum += b;
hashcode += sum;
at += 1;
b = character & 0x7F;
bytes[at] = (byte) b;
sum += b;
hashcode += sum;
at += 1;
}
}
hashcode += sum << 16;
}
}
/**
* Returns the number of bytes needed to contain the character in Kim format.
*
* @param character a Unicode character between 0 and 0x10FFFF.
*
* @return 1, 2, or 3
*
* @throws JSONException if the character is not representable in a kim.
*/
public static int characterSize(final int character) throws JSONException {
if ((character < 0) || (character > 0x10FFFF)) {
throw new JSONException("Bad character " + character);
}
return character <= 0x7F ? 1 : character <= 0x3FFF ? 2 : 3;
}
/**
* Returns the character at the specified index. The index refers to byte values and ranges from 0 to length - 1.
* The index of the next character is at index + Kim.characterSize(kim.characterAt(index)).
*
* @param at the index of the char value. The first character is at 0.
*
* @throws JSONException if at does not point to a valid character.
* @return a Unicode character between 0 and 0x10FFFF.
*/
public int characterAt(final int at) throws JSONException {
final int c = get(at);
if ((c & 0x80) == 0) {
return c;
}
int character;
final int c1 = get(at + 1);
if ((c1 & 0x80) == 0) {
character = ((c & 0x7F) << 7) | c1;
if (character > 0x7F) {
return character;
}
} else {
final int c2 = get(at + 2);
character = ((c & 0x7F) << 14) | ((c1 & 0x7F) << 7) | c2;
if (((c2 & 0x80) == 0) && (character > 0x3FFF) && (character <= 0x10FFFF) && ((character < 0xD800) || (character > 0xDFFF))) {
return character;
}
}
throw new JSONException("Bad character at " + at);
}
/**
* Copy the contents of this kim to a byte array.
*
* @param bytes A byte array of sufficient size.
* @param at The position within the byte array to take the byes.
*
* @return The position immediately after the copy.
*/
public int copy(final byte[] bytes, final int at) {
System.arraycopy(this.bytes, 0, bytes, at, length);
return at + length;
}
/**
* Two kim objects containing exactly the same bytes in the same order are equal to each other.
*
* @param obj the other kim with which to compare.
*
* @return true if this and obj are both kim objects containing identical byte sequences.
*/
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof Kim)) {
return false;
}
final Kim that = (Kim) obj;
if (this == that) {
return true;
}
if (hashcode != that.hashcode) {
return false;
}
return java.util.Arrays.equals(bytes, that.bytes);
}
/**
* Get a byte from a kim.
*
* @param at The position of the byte. The first byte is at 0.
*
* @return The byte.
*
* @throws JSONException if there is no byte at that position.
*/
public int get(final int at) throws JSONException {
if ((at < 0) || (at > length)) {
throw new JSONException("Bad character at " + at);
}
return (bytes[at]) & 0xFF;
}
/**
* Returns a hash code value for the kim.
*/
@Override
public int hashCode() {
return hashcode;
}
/**
* Produce a UTF-16 String from this kim. The number of codepoints in the string will not be greater than the number
* of bytes in the kim, although it could be less.
*
* @return The string. A kim memoizes its string representation.
*
* @throws JSONException if the kim is not valid.
*/
@Override
public String toString() throws JSONException {
if (string == null) {
int c;
int length = 0;
final char chars[] = new char[this.length];
for (int at = 0; at < this.length; at += characterSize(c)) {
c = characterAt(at);
if (c < 0x10000) {
chars[length] = (char) c;
length += 1;
} else {
chars[length] = (char) (0xD800 | ((c - 0x10000) >>> 10));
length += 1;
chars[length] = (char) (0xDC00 | (c & 0x03FF));
length += 1;
}
}
string = new String(chars, 0, length);
}
return string;
}
}

View File

@ -0,0 +1,75 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.json;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
/**
* Converts a Property file data into JSONObject and back.
*
* @author JSON.org
* @version 2014-05-03
*/
public class Property {
/**
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
*
* @param properties java.util.Properties
*
* @return JSONObject
*
* @throws JSONException
*/
public static JSONObject toJSONObject(final java.util.Properties properties) throws JSONException {
final JSONObject jo = new JSONObject();
if ((properties != null) && !properties.isEmpty()) {
final Enumeration enumProperties = properties.propertyNames();
while (enumProperties.hasMoreElements()) {
final String name = (String) enumProperties.nextElement();
jo.put(name, properties.getProperty(name));
}
}
return jo;
}
/**
* Converts the JSONObject into a property file object.
*
* @param jo JSONObject
*
* @return java.util.Properties
*
* @throws JSONException
*/
public static Properties toProperties(final JSONObject jo) throws JSONException {
final Properties properties = new Properties();
if (jo != null) {
final Iterator<String> keys = jo.keys();
while (keys.hasNext()) {
final String name = keys.next();
properties.put(name, jo.getString(name));
}
}
return properties;
}
}

View File

@ -0,0 +1,387 @@
package com.intellectualcrafters.json;
import java.util.Iterator;
/**
* This provides static methods to convert an XML text into a JSONObject, and to covert a JSONObject into an XML text.
*
* @author JSON.org
* @version 2014-05-03
*/
public class XML {
public static final Character AMP = '&';
public static final Character APOS = '\'';
public static final Character BANG = '!';
public static final Character EQ = '=';
public static final Character GT = '>';
public static final Character LT = '<';
public static final Character QUEST = '?';
public static final Character QUOT = '"';
public static final Character SLASH = '/';
public static String escape(final String string) {
final StringBuilder sb = new StringBuilder(string.length());
for (int i = 0, length = string.length(); i < length; i++) {
final char c = string.charAt(i);
switch (c) {
case '&':
sb.append("&amp;");
break;
case '<':
sb.append("&lt;");
break;
case '>':
sb.append("&gt;");
break;
case '"':
sb.append("&quot;");
break;
case '\'':
sb.append("&apos;");
break;
default:
sb.append(c);
}
}
return sb.toString();
}
/**
* Throw an exception if the string contains whitespace. Whitespace is not allowed in tagNames and attributes.
*
* @param string A string.
*
* @throws JSONException
*/
public static void noSpace(final String string) throws JSONException {
int i;
final int length = string.length();
if (length == 0) {
throw new JSONException("Empty string.");
}
for (i = 0; i < length; i += 1) {
if (Character.isWhitespace(string.charAt(i))) {
throw new JSONException("'" + string + "' contains a space character.");
}
}
}
/**
* Scan the content following the named tag, attaching it to the context.
*
* @param x The XMLTokener containing the source string.
* @param context The JSONObject that will include the new material.
* @param name The tag name.
*
* @return true if the close tag is processed.
*
* @throws JSONException
*/
private static boolean parse(final XMLTokener x, final JSONObject context, final String name) throws JSONException {
char c;
int i;
JSONObject jsonobject = null;
String string;
String tagName;
Object token;
// Test for and skip past these forms:
// <!-- ... -->
// <! ... >
// <![ ... ]]>
// <? ... ?>
// Report errors for these forms:
// <>
// <=
// <<
token = x.nextToken();
// <!
if (token == BANG) {
c = x.next();
if (c == '-') {
if (x.next() == '-') {
x.skipPast("-->");
return false;
}
x.back();
} else if (c == '[') {
token = x.nextToken();
if ("CDATA".equals(token)) {
if (x.next() == '[') {
string = x.nextCDATA();
if (!string.isEmpty()) {
context.accumulate("content", string);
}
return false;
}
}
throw x.syntaxError("Expected 'CDATA['");
}
i = 1;
do {
token = x.nextMeta();
if (token == null) {
throw x.syntaxError("Missing '>' after '<!'.");
} else if (token == LT) {
i += 1;
} else if (token == GT) {
i -= 1;
}
} while (i > 0);
return false;
} else if (token == QUEST) {
// <?
x.skipPast("?>");
return false;
} else if (token == SLASH) {
// Close tag </
token = x.nextToken();
if (name == null) {
throw x.syntaxError("Mismatched close tag " + token);
}
if (!token.equals(name)) {
throw x.syntaxError("Mismatched " + name + " and " + token);
}
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped close tag");
}
return true;
} else if (token instanceof Character) {
throw x.syntaxError("Misshaped tag");
// Open tag <
} else {
tagName = (String) token;
token = null;
jsonobject = new JSONObject();
for (;;) {
if (token == null) {
token = x.nextToken();
}
// attribute = value
if (token instanceof String) {
string = (String) token;
token = x.nextToken();
if (token == EQ) {
token = x.nextToken();
if (!(token instanceof String)) {
throw x.syntaxError("Missing value");
}
jsonobject.accumulate(string, XML.stringToValue((String) token));
token = null;
} else {
jsonobject.accumulate(string, "");
}
// Empty tag <.../>
} else if (token == SLASH) {
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped tag");
}
if (jsonobject.length() > 0) {
context.accumulate(tagName, jsonobject);
} else {
context.accumulate(tagName, "");
}
return false;
// Content, between <...> and </...>
} else if (token == GT) {
for (;;) {
token = x.nextContent();
if (token == null) {
if (tagName != null) {
throw x.syntaxError("Unclosed tag " + tagName);
}
return false;
} else if (token instanceof String) {
string = (String) token;
if (!string.isEmpty()) {
jsonobject.accumulate("content", XML.stringToValue(string));
}
// Nested element
} else if (token == LT) {
if (parse(x, jsonobject, tagName)) {
if (jsonobject.length() == 0) {
context.accumulate(tagName, "");
} else if ((jsonobject.length() == 1) && (jsonobject.opt("content") != null)) {
context.accumulate(tagName, jsonobject.opt("content"));
} else {
context.accumulate(tagName, jsonobject);
}
return false;
}
}
}
} else {
throw x.syntaxError("Misshaped tag");
}
}
}
}
/**
* Try to convert a string into a number, boolean, or null. If the string can't be converted, return the string.
* This is much less ambitious than JSONObject.stringToValue, especially because it does not attempt to convert plus
* forms, octal forms, hex forms, or E forms lacking decimal points.
*
* @param string A String.
*
* @return A simple JSON value.
*/
public static Object stringToValue(final String string) {
if ("true".equalsIgnoreCase(string)) {
return Boolean.TRUE;
}
if ("false".equalsIgnoreCase(string)) {
return Boolean.FALSE;
}
if ("null".equalsIgnoreCase(string)) {
return JSONObject.NULL;
}
//If it might be a number, try converting it, first as a Long, and then as a Double. If that doesn't work, return the string.
try {
final char initial = string.charAt(0);
if ((initial == '-') || ((initial >= '0') && (initial <= '9'))) {
final Long value = new Long(string);
if (value.toString().equals(string)) {
return value;
}
}
} catch (NumberFormatException ignore) {
try {
final Double value = new Double(string);
if (value.toString().equals(string)) {
return value;
}
} catch (NumberFormatException ignoreAlso) {
}
}
return string;
}
public static JSONObject toJSONObject(final String string) throws JSONException {
final JSONObject jo = new JSONObject();
final XMLTokener x = new XMLTokener(string);
while (x.more() && x.skipPast("<")) {
parse(x, jo, null);
}
return jo;
}
/**
* Convert a JSONObject into a well-formed, element-normal XML string.
*
* @param object A JSONObject.
*
* @return A string.
*
* @throws JSONException
*/
public static String toString(final Object object) throws JSONException {
return toString(object, null);
}
/**
* Convert a JSONObject into a well-formed, element-normal XML string.
*
* @param object A JSONObject.
* @param tagName The optional name of the enclosing tag.
*
* @return A string.
*
* @throws JSONException
*/
public static String toString(Object object, final String tagName) throws JSONException {
final StringBuilder sb = new StringBuilder();
int i;
JSONArray ja;
JSONObject jo;
String key;
Iterator<String> keys;
int length;
String string;
Object value;
if (object instanceof JSONObject) {
// Emit <tagName>
if (tagName != null) {
sb.append('<');
sb.append(tagName);
sb.append('>');
}
// Loop thru the keys.
jo = (JSONObject) object;
keys = jo.keys();
while (keys.hasNext()) {
key = keys.next();
value = jo.opt(key);
if (value == null) {
value = "";
}
string = value instanceof String ? (String) value : null;
// Emit content in body
if ("content".equals(key)) {
if (value instanceof JSONArray) {
ja = (JSONArray) value;
length = ja.length();
for (i = 0; i < length; i += 1) {
if (i > 0) {
sb.append('\n');
}
sb.append(escape(ja.get(i).toString()));
}
} else {
sb.append(escape(value.toString()));
}
// Emit an array of similar keys
} else if (value instanceof JSONArray) {
ja = (JSONArray) value;
length = ja.length();
for (i = 0; i < length; i += 1) {
value = ja.get(i);
if (value instanceof JSONArray) {
sb.append('<');
sb.append(key);
sb.append('>');
sb.append(toString(value));
sb.append("</");
sb.append(key);
sb.append('>');
} else {
sb.append(toString(value, key));
}
}
} else if ("".equals(value)) {
sb.append('<');
sb.append(key);
sb.append("/>");
// Emit a new tag <k>
} else {
sb.append(toString(value, key));
}
}
if (tagName != null) {
// Emit the </tagname> close tag
sb.append("</");
sb.append(tagName);
sb.append('>');
}
return sb.toString();
// XML does not have good support for arrays. If an array appears in
// a place
// where XML is lacking, synthesize an <array> element.
} else {
if (object.getClass().isArray()) {
object = new JSONArray(object);
}
if (object instanceof JSONArray) {
ja = (JSONArray) object;
length = ja.length();
for (i = 0; i < length; i += 1) {
sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
}
return sb.toString();
} else {
string = (object == null) ? "null" : escape(object.toString());
return (tagName == null) ? "\"" + string + "\"" :
(string.isEmpty()) ? "<" + tagName + "/>" : "<" + tagName + ">" + string + "</" + tagName + ">";
}
}
}
}

View File

@ -0,0 +1,324 @@
package com.intellectualcrafters.json;
/**
* The XMLTokener extends the JSONTokener to provide additional methods for the parsing of XML texts.
*
* @author JSON.org
* @version 2014-05-03
*/
public class XMLTokener extends JSONTokener {
/**
* The table of entity values. It initially contains Character values for amp, apos, gt, lt, quot.
*/
public static final java.util.HashMap<String, Character> entity;
static {
entity = new java.util.HashMap<String, Character>(8);
entity.put("amp", XML.AMP);
entity.put("apos", XML.APOS);
entity.put("gt", XML.GT);
entity.put("lt", XML.LT);
entity.put("quot", XML.QUOT);
}
/**
* Construct an XMLTokener from a string.
*
* @param s A source string.
*/
public XMLTokener(final String s) {
super(s);
}
/**
* Get the text in the CDATA block.
*
* @return The string up to the <code>]]&gt;</code>.
*
* @throws JSONException If the <code>]]&gt;</code> is not found.
*/
public String nextCDATA() throws JSONException {
char c;
int i;
final StringBuilder sb = new StringBuilder();
for (;;) {
c = next();
if (end()) {
throw syntaxError("Unclosed CDATA");
}
sb.append(c);
i = sb.length() - 3;
if ((i >= 0) && (sb.charAt(i) == ']') && (sb.charAt(i + 1) == ']') && (sb.charAt(i + 2) == '>')) {
sb.setLength(i);
return sb.toString();
}
}
}
/**
* Get the next XML outer token, trimming whitespace. There are two kinds of tokens: the '&lt;' character which begins
* a markup tag, and the content text between markup tags.
*
* @return A string, or a '&lt;' Character, or null if there is no more source text.
*
* @throws JSONException
*/
public Object nextContent() throws JSONException {
char c;
StringBuilder sb;
do {
c = next();
} while (Character.isWhitespace(c));
if (c == 0) {
return null;
}
if (c == '<') {
return XML.LT;
}
sb = new StringBuilder();
for (;;) {
if ((c == '<') || (c == 0)) {
back();
return sb.toString().trim();
}
if (c == '&') {
sb.append(nextEntity(c));
} else {
sb.append(c);
}
c = next();
}
}
/**
* Return the next entity. These entities are translated to Characters: <code>&amp; &quot; &gt; &lt;
* &quot;</code>.
*
* @param ampersand An ampersand character.
*
* @return A Character or an entity String if the entity is not recognized.
*
* @throws JSONException If missing ';' in XML entity.
*/
public Object nextEntity(final char ampersand) throws JSONException {
final StringBuilder sb = new StringBuilder();
for (;;) {
final char c = next();
if (Character.isLetterOrDigit(c) || (c == '#')) {
sb.append(Character.toLowerCase(c));
} else if (c == ';') {
break;
} else {
throw syntaxError("Missing ';' in XML entity: &" + sb);
}
}
final String string = sb.toString();
final Object object = entity.get(string);
return object != null ? object : ampersand + string + ";";
}
/**
* Returns the next XML meta token. This is used for skipping over <!...> and <?...?> structures.
*
* @return Syntax characters (<code>&lt; &gt; / = ! ?</code>) are returned as Character, and strings and names are
* returned as Boolean. We don't care what the values actually are.
*
* @throws JSONException If a string is not properly closed or if the XML is badly structured.
*/
public Object nextMeta() throws JSONException {
char c;
char q;
do {
c = next();
} while (Character.isWhitespace(c));
switch (c) {
case 0:
throw syntaxError("Misshaped meta tag");
case '<':
return XML.LT;
case '>':
return XML.GT;
case '/':
return XML.SLASH;
case '=':
return XML.EQ;
case '!':
return XML.BANG;
case '?':
return XML.QUEST;
case '"':
case '\'':
q = c;
for (;;) {
c = next();
if (c == 0) {
throw syntaxError("Unterminated string");
}
if (c == q) {
return Boolean.TRUE;
}
}
default:
for (;;) {
c = next();
if (Character.isWhitespace(c)) {
return Boolean.TRUE;
}
switch (c) {
case 0:
case '<':
case '>':
case '/':
case '=':
case '!':
case '?':
case '"':
case '\'':
back();
return Boolean.TRUE;
}
}
}
}
/**
* Get the next XML Token. These tokens are found inside of angle brackets. It may be one of these characters:
* <code>/ &gt;= ! ?</code> or it may be a string wrapped in single quotes or double quotes, or it may be a name.
*
* @return a String or a Character.
*
* @throws JSONException If the XML is not well formed.
*/
public Object nextToken() throws JSONException {
char c;
char q;
StringBuilder sb;
do {
c = next();
} while (Character.isWhitespace(c));
switch (c) {
case 0:
throw syntaxError("Misshaped element");
case '<':
throw syntaxError("Misplaced '<'");
case '>':
return XML.GT;
case '/':
return XML.SLASH;
case '=':
return XML.EQ;
case '!':
return XML.BANG;
case '?':
return XML.QUEST;
// Quoted string
case '"':
case '\'':
q = c;
sb = new StringBuilder();
for (;;) {
c = next();
if (c == 0) {
throw syntaxError("Unterminated string");
}
if (c == q) {
return sb.toString();
}
if (c == '&') {
sb.append(nextEntity(c));
} else {
sb.append(c);
}
}
default:
// Name
sb = new StringBuilder();
for (;;) {
sb.append(c);
c = next();
if (Character.isWhitespace(c)) {
return sb.toString();
}
switch (c) {
case 0:
return sb.toString();
case '>':
case '/':
case '=':
case '!':
case '?':
case '[':
case ']':
back();
return sb.toString();
case '<':
case '"':
case '\'':
throw syntaxError("Bad character in a name");
}
}
}
}
/**
* Skip characters until past the requested string. If it is not found, we are left at the end of the source with a
* result of false.
*
* @param to A string to skip past.
*
* @throws JSONException
*/
public boolean skipPast(final String to) throws JSONException {
boolean b;
char c;
int i;
int j;
int offset = 0;
final int length = to.length();
final char[] circle = new char[length];
/*
* First fill the circle buffer with as many characters as are in the
* to string. If we reach an early end, bail.
*/
for (i = 0; i < length; i += 1) {
c = next();
if (c == 0) {
return false;
}
circle[i] = c;
}
/* We will loop, possibly for all of the remaining characters. */
for (;;) {
j = offset;
b = true;
/* Compare the circle buffer with the to string. */
for (i = 0; i < length; i += 1) {
if (circle[j] != to.charAt(i)) {
b = false;
break;
}
j += 1;
if (j >= length) {
j -= length;
}
}
/* If we exit the loop with b intact, then victory is ours. */
if (b) {
return true;
}
/* Get the next character. If there isn't one, then defeat is ours. */
c = next();
if (c == 0) {
return false;
}
/*
* Shove the character in the circle buffer and advance the
* circle offset. The offset is mod n.
*/
circle[offset] = c;
offset += 1;
if (offset >= length) {
offset -= length;
}
}
}
}

View File

@ -0,0 +1,241 @@
package com.intellectualcrafters.plot;
import java.io.File;
import java.util.List;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.AbstractTitle;
import com.intellectualcrafters.plot.util.ChatManager;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.InventoryUtil;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.util.WorldUtil;
public interface IPlotMain {
/**
* Log a message to console
* @param message
*/
void log(final String message);
/**
* Get the `PlotSquared` directory (e.g. /plugins/PlotSquared or /mods/PlotSquared)
* @return
*/
File getDirectory();
/**
* Get the directory containing all the worlds
* @return
*/
File getWorldContainer();
/**
* Wrap a player into a PlotPlayer object
* @param obj
* @return
*/
PlotPlayer wrapPlayer(final Object obj);
/**
* Disable the implementation
* - If a full disable isn't feasibly, just disable what it can
*/
void disable();
/**
* Get the version of the PlotSquared being used
* @return
*/
int[] getPluginVersion();
/**
* Get the version of Minecraft that is running
* (used to check what protocols and such are supported)
* @return
*/
int[] getServerVersion();
/**
* Get the nms package prefix
* @return
*/
String getNMSPackage();
/**
* Get the schematic handler
* @return
*/
SchematicHandler initSchematicHandler();
/**
* Get the schematic handler
* @return
*/
ChatManager initChatManager();
/**
* The task manager will run and manage minecraft tasks
* @return
*/
TaskManager getTaskManager();
/**
* Run the task that will kill road mobs
*/
void runEntityTask();
/**
* Register the implementation specific commands
*/
void registerCommands();
/**
* Register the protection system (used to protect blocks and such)
*/
void registerPlayerEvents();
/**
* Register inventory related events (used for inventory guis)
*/
void registerInventoryEvents();
/**
* Register plot plus related events (whatever these are?)
*/
void registerPlotPlusEvents();
/**
* Register force field events (why is this a thing?)
*/
void registerForceFieldEvents();
/**
* Register the WorldEdit hook
*/
boolean initWorldEdit();
/**
* Get the economy provider
* @return
*/
EconHandler getEconomyHandler();
/**
* Get the Plot Queue class
* @return
*/
PlotQueue initPlotQueue();
/**
* Get the World Util class
* @return
*/
WorldUtil initWorldUtil();
/**
* Get the EventUtil class
* @return
*/
EventUtil initEventUtil();
/**
* Get the chunk manager
* @return
*/
ChunkManager initChunkManager();
/**
* Get the setuputils class (used for world creation)
* @return
*/
SetupUtils initSetupUtils();
/**
* Get HybridUtils class (common functions useful for hybrid world generation)
* @return
*/
HybridUtils initHybridUtils();
/**
* Start the metrics task
*/
void startMetrics();
/**
* If a world is already loaded, set the generator (use NMS if required)
* @param world
*/
void setGenerator(final String world);
/**
* Get the UUIDHandlerImplementation which will cache and provide UUIDs
* @return
*/
UUIDHandlerImplementation initUUIDHandler();
/**
* Get the InventoryUtil class (used for implementation specific inventory guis)
* @return
*/
InventoryUtil initInventoryUtil();
/**
* Run the converter for the implementation (not necessarily PlotMe, just any plugin that we can convert from)
* @return
*/
boolean initPlotMeConverter();
/**
* Unregister a PlotPlayer from cache e.g. if they have logged off
* @param player
*/
void unregister(final PlotPlayer player);
/**
* Get the generator wrapper for a world (world) and generator (name)
* @param world
* @param name
* @return
*/
GeneratorWrapper<?> getGenerator(final String world, final String name);
/**
*
*/
GeneratorWrapper<?> wrapPlotGenerator(IndependentPlotGenerator generator);
/**
* Register the chunk processor which will clean out chunks that have too many blockstates or entities
*/
void registerChunkProcessor();
/**
* Register the world initialization events (used to keep track of worlds being generated)
*/
void registerWorldEvents();
/**
* Get the name of the server
* @return
*/
String getServerName();
/**
* Get the class that will manage player titles
* @return
*/
AbstractTitle initTitleManager();
List<String> getPluginIds();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.UUID;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.Argument;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "add",
aliases = { "a" },
description = "Allow a user to build while you are online",
usage = "/plot add <player>",
category = CommandCategory.SETTINGS,
permission = "plots.add",
requiredType = RequiredType.NONE)
public class Add extends SubCommand {
public Add() {
requiredArguments = new Argument[] { Argument.PlayerName };
}
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
MainUtil.sendMessage(plr, C.PLOT_UNOWNED);
return false;
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.add")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return true;
}
UUID uuid;
if (args[0].equalsIgnoreCase("*")) {
uuid = DBFunc.everyone;
} else {
// TODO have a runnable for fetch
uuid = UUIDHandler.getUUID(args[0], null);
}
if (uuid == null) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[0]);
return false;
}
if (plot.isOwner(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_OWNER);
return false;
}
if (plot.getMembers().contains(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_ADDED);
return false;
}
if (plot.removeTrusted(uuid)) {
plot.addMember(uuid);
} else {
if ((plot.getMembers().size() + plot.getTrusted().size()) >= plot.getArea().MAX_PLOT_MEMBERS) {
MainUtil.sendMessage(plr, C.PLOT_MAX_MEMBERS);
return false;
}
if (plot.getDenied().contains(uuid)) {
plot.removeDenied(uuid);
}
plot.addMember(uuid);
}
EventUtil.manager.callMember(plr, plot, uuid, true);
MainUtil.sendMessage(plr, C.MEMBER_ADDED);
return true;
}
}

View File

@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "setalias",
permission = "plots.set.alias",
description = "Set the plot name",
usage = "/plot alias <alias>",
aliases = { "alias", "sa", "name", "rename", "setname", "seta" },
category = CommandCategory.SETTINGS,
requiredType = RequiredType.NONE)
public class Alias extends SetCommand {
@Override
public boolean set(final PlotPlayer plr, final Plot plot, final String alias) {
if (alias.isEmpty()) {
C.COMMAND_SYNTAX.send(plr, getUsage());
return false;
}
if (alias.length() >= 50) {
MainUtil.sendMessage(plr, C.ALIAS_TOO_LONG);
return false;
}
if (alias.contains(" ") || !StringMan.isAsciiPrintable(alias)) {
C.NOT_VALID_VALUE.send(plr);
return false;
}
for (final Plot p : PS.get().getPlots(plot.getArea())) {
if (p.getAlias().equalsIgnoreCase(alias)) {
MainUtil.sendMessage(plr, C.ALIAS_IS_TAKEN);
return false;
}
}
if (UUIDHandler.nameExists(new StringWrapper(alias)) || PS.get().hasPlotArea(alias)) {
MainUtil.sendMessage(plr, C.ALIAS_IS_TAKEN);
return false;
}
plot.setAlias(alias);
MainUtil.sendMessage(plr, C.ALIAS_SET_TO.s().replaceAll("%alias%", alias));
return true;
}
}

View File

@ -0,0 +1,466 @@
package com.intellectualcrafters.plot.commands;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Set;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Configuration;
import com.intellectualcrafters.plot.generator.AugmentedUtils;
import com.intellectualcrafters.plot.generator.HybridGen;
import com.intellectualcrafters.plot.generator.HybridPlotWorld;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotMessage;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.CmdConfirm;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "area",
permission = "plots.area",
category = CommandCategory.ADMINISTRATION,
requiredType = RequiredType.NONE,
description = "Create a new PlotArea",
aliases = { "world" },
usage = "/plot area <create|info|list|tp|regen>")
public class Area extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, String[] args) {
if (args.length == 0) {
C.COMMAND_SYNTAX.send(plr, getUsage());
return false;
}
switch (args[0].toLowerCase()) {
case "c":
case "setup":
case "create": {
if (!Permissions.hasPermission(plr, "plots.area.create")) {
C.NO_PERMISSION.send(plr, "plots.area.create");
return false;
}
switch (args.length) {
case 1: {
C.COMMAND_SYNTAX.send(plr, "/plot area create [world[:id]] [<modifier>=<value>]...");
return false;
}
case 2: {
switch (args[1].toLowerCase()) {
case "pos1": { // Set position 1
HybridPlotWorld area = plr.<HybridPlotWorld> getMeta("area_create_area");
if (area == null) {
C.COMMAND_SYNTAX.send(plr, "/plot area create [world[:id]] [<modifier>=<value>]...");
return false;
}
Location loc = plr.getLocation();
plr.setMeta("area_pos1", loc);
C.SET_ATTRIBUTE.send(plr, "area_pos1", loc.getX() + "," + loc.getZ());
MainUtil.sendMessage(plr, "You will now set pos2: /plot area create pos2"
+ "\nNote: The chosen plot size may result in the created area not exactly matching your second position.");
return true;
}
case "pos2": { // Set position 2 and finish creation for type=2 (partial)
final HybridPlotWorld area = plr.<HybridPlotWorld> getMeta("area_create_area");
if (area == null) {
C.COMMAND_SYNTAX.send(plr, "/plot area create [world[:id]] [<modifier>=<value>]...");
return false;
}
Location pos1 = plr.getLocation();
Location pos2 = plr.<Location> getMeta("area_pos1");
int dx = Math.abs(pos1.getX() - pos2.getX());
int dz = Math.abs(pos1.getZ() - pos2.getZ());
int numx = Math.max(1, (dx + 1 + area.ROAD_WIDTH + (area.SIZE / 2)) / area.SIZE);
int numz = Math.max(1, (dz + 1 + area.ROAD_WIDTH + (area.SIZE / 2)) / area.SIZE);
final int ddx = dx - (numx * area.SIZE - area.ROAD_WIDTH);
final int ddz = dz - (numz * area.SIZE - area.ROAD_WIDTH);
int bx = Math.min(pos1.getX(), pos2.getX()) + ddx;
int bz = Math.min(pos1.getZ(), pos2.getZ()) + ddz;
int tx = Math.max(pos1.getX(), pos2.getX()) - ddx;
int tz = Math.max(pos1.getZ(), pos2.getZ()) - ddz;
int lower = (area.ROAD_WIDTH & 1) == 0 ? area.ROAD_WIDTH / 2 - 1 : area.ROAD_WIDTH / 2;
final int offsetx = bx - (area.ROAD_WIDTH == 0 ? 0 : lower);
final int offsetz = bz - (area.ROAD_WIDTH == 0 ? 0 : lower);
final RegionWrapper region = new RegionWrapper(bx, tx, bz, tz);
Set<PlotArea> areas = PS.get().getPlotAreas(area.worldname, region);
if (!areas.isEmpty()) {
C.CLUSTER_INTERSECTION.send(plr, areas.iterator().next().toString());
return false;
}
final SetupObject object = new SetupObject();
object.world = area.worldname;
object.id = area.id;
object.terrain = area.TERRAIN;
object.type = area.TYPE;
object.min = new PlotId(1, 1);
object.max = new PlotId(numx, numz);
object.plotManager = "PlotSquared";
object.setupGenerator = "PlotSquared";
object.step = area.getSettingNodes();
final String path = "worlds." + area.worldname + ".areas." + area.id + "-" + object.min + "-" + object.max;
CmdConfirm.addPending(plr, "/plot area create pos2 (Creates world)", new Runnable() {
@Override
public void run() {
if (offsetx != 0) {
PS.get().config.set(path + ".road.offset.x", offsetx);
}
if (offsetz != 0) {
PS.get().config.set(path + ".road.offset.z", offsetz);
}
final String world = SetupUtils.manager.setupWorld(object);
if (WorldUtil.IMP.isWorld(world)) {
PS.get().loadWorld(world, null);
C.SETUP_FINISHED.send(plr);
plr.teleport(WorldUtil.IMP.getSpawn(world));
if (area.TERRAIN != 3) {
ChunkManager.largeRegionTask(world, region, new RunnableVal<ChunkLoc>() {
@Override
public void run(final ChunkLoc value) {
AugmentedUtils.generate(world, value.x, value.z, null);
}
}, null);
}
} else {
MainUtil.sendMessage(plr, "An error occured while creating the world: " + area.worldname);
}
}
});
return true;
}
}
}
default: // Start creation
final SetupObject object = new SetupObject();
String[] split = args[1].split(":");
String id;
if (split.length == 2) {
id = split[1];
} else {
id = null;
}
object.world = split[0];
final HybridPlotWorld pa = new HybridPlotWorld(object.world, id, new HybridGen(), null, null);
PlotArea other = PS.get().getPlotArea(pa.worldname, id);
if (other != null && Objects.equals(pa.id, other.id)) {
C.SETUP_WORLD_TAKEN.send(plr, pa.toString());
return false;
}
Set<PlotArea> areas = PS.get().getPlotAreas(pa.worldname);
if (!areas.isEmpty()) {
PlotArea area = areas.iterator().next();
pa.TYPE = area.TYPE;
}
for (int i = 2; i < args.length; i++) {
String[] pair = args[i].split("=");
if (pair.length != 2) {
C.COMMAND_SYNTAX.send(plr, "/plot area create [world[:id]] [<modifier>=<value>]...");
return false;
}
switch (pair[0].toLowerCase()) {
case "s":
case "size": {
pa.PLOT_WIDTH = Integer.parseInt(pair[1]);
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
break;
}
case "g":
case "gap": {
pa.ROAD_WIDTH = Integer.parseInt(pair[1]);
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
break;
}
case "h":
case "height": {
int value = Integer.parseInt(pair[1]);
pa.PLOT_HEIGHT = value;
pa.ROAD_HEIGHT = value;
pa.WALL_HEIGHT = value;
break;
}
case "f":
case "floor": {
pa.TOP_BLOCK = Configuration.BLOCKLIST.parseString(pair[1]);
break;
}
case "m":
case "main": {
pa.MAIN_BLOCK = Configuration.BLOCKLIST.parseString(pair[1]);
break;
}
case "w":
case "wall": {
pa.WALL_FILLING = Configuration.BLOCK.parseString(pair[1]);
break;
}
case "b":
case "border": {
pa.WALL_BLOCK = Configuration.BLOCK.parseString(pair[1]);
break;
}
case "terrain": {
pa.TERRAIN = Integer.parseInt(pair[1]);
object.terrain = pa.TERRAIN;
break;
}
case "type": {
pa.TYPE = Integer.parseInt(pair[1]);
object.type = pa.TYPE;
break;
}
default: {
C.COMMAND_SYNTAX.send(plr, "/plot area create [world[:id]] [<modifier>=<value>]...");
return false;
}
}
}
if (pa.TYPE != 2) {
if (WorldUtil.IMP.isWorld(pa.worldname)) {
C.SETUP_WORLD_TAKEN.send(plr, pa.worldname);
return false;
}
CmdConfirm.addPending(plr, "/plot area " + StringMan.join(args, " "), new Runnable() {
@Override
public void run() {
String path = "worlds." + pa.worldname;
if (!PS.get().config.contains(path)) {
PS.get().config.createSection(path);
}
ConfigurationSection section = PS.get().config.getConfigurationSection(path);
pa.saveConfiguration(section);
pa.loadConfiguration(section);
object.plotManager = "PlotSquared";
object.setupGenerator = "PlotSquared";
String world = SetupUtils.manager.setupWorld(object);
if (WorldUtil.IMP.isWorld(world)) {
C.SETUP_FINISHED.send(plr);
plr.teleport(WorldUtil.IMP.getSpawn(world));
} else {
MainUtil.sendMessage(plr, "An error occured while creating the world: " + pa.worldname);
}
try {
PS.get().config.save(PS.get().configFile);
} catch (IOException e) {
e.printStackTrace();
}
}
});
return true;
}
if (pa.id == null) {
C.COMMAND_SYNTAX.send(plr, "/plot area create [world[:id]] [<modifier>=<value>]...");
return false;
}
if (WorldUtil.IMP.isWorld(pa.worldname)) {
if (!plr.getLocation().getWorld().equals(pa.worldname)) {
plr.teleport(WorldUtil.IMP.getSpawn(pa.worldname));
}
} else {
object.terrain = 0;
object.type = 0;
SetupUtils.manager.setupWorld(object);
plr.teleport(WorldUtil.IMP.getSpawn(pa.worldname));
}
plr.setMeta("area_create_area", pa);
MainUtil.sendMessage(plr, "$1Go to the first corner and use: $2/plot area create pos1");
break;
}
return true;
}
case "i":
case "info": {
if (!Permissions.hasPermission(plr, "plots.area.info")) {
C.NO_PERMISSION.send(plr, "plots.area.info");
return false;
}
PlotArea area;
switch (args.length) {
case 1:
area = plr.getApplicablePlotArea();
break;
case 2:
area = PS.get().getPlotAreaByString(args[1]);
break;
default:
C.COMMAND_SYNTAX.send(plr, "/plot area info [area]");
return false;
}
if (area == null) {
if (args.length == 2) {
C.NOT_VALID_PLOT_WORLD.send(plr, args[1]);
} else {
C.NOT_IN_PLOT_WORLD.send(plr);
}
return false;
}
String name;
double percent;
int claimed = area.getPlotCount();
int clusters = area.getClusters().size();
String region;
String generator = area.getGenerator() + "";
if (area.TYPE == 2) {
PlotId min = area.getMin();
PlotId max = area.getMax();
name = area.worldname + ";" + area.id + ";" + min + ";" + max;
int size = (max.x - min.x + 1) * (max.y - min.y + 1);
percent = claimed == 0 ? 0 : size / (double) claimed;
region = area.getRegion().toString();
} else {
name = area.worldname;
percent = claimed == 0 ? 0 : (100d * claimed) / (Integer.MAX_VALUE);
region = "N/A";
}
String value = "&r$1NAME: " + name
+ "\n$1Type: $2" + area.TYPE
+ "\n$1Terrain: $2" + area.TERRAIN
+ "\n$1Usage: $2" + String.format("%.2f", percent) + "%"
+ "\n$1Claimed: $2" + claimed
+ "\n$1Clusters: $2" + clusters
+ "\n$1Region: $2" + region
+ "\n$1Generator: $2" + generator;
MainUtil.sendMessage(plr, C.PLOT_INFO_HEADER.s() + '\n' + value + '\n' + C.PLOT_INFO_FOOTER.s(), false);
return true;
}
case "l":
case "list": {
if (!Permissions.hasPermission(plr, "plots.area.list")) {
C.NO_PERMISSION.send(plr, "plots.area.list");
return false;
}
int page;
switch (args.length) {
case 1:
page = 0;
break;
case 2:
if (MathMan.isInteger(args[1])) {
page = Integer.parseInt(args[1]);
break;
}
default:
C.COMMAND_SYNTAX.send(plr, "/plot area list [#]");
return false;
}
ArrayList<PlotArea> areas = new ArrayList<>(PS.get().getPlotAreas());
paginate(plr, areas, 8, page, new RunnableVal3<Integer, PlotArea, PlotMessage>() {
@Override
public void run(Integer i, PlotArea area, PlotMessage message) {
String name;
double percent;
int claimed = area.getPlotCount();
int clusters = area.getClusters().size();
String region;
String generator = area.getGenerator() + "";
if (area.TYPE == 2) {
PlotId min = area.getMin();
PlotId max = area.getMax();
name = area.worldname + ";" + area.id + ";" + min + ";" + max;
int size = (max.x - min.x + 1) * (max.y - min.y + 1);
percent = claimed == 0 ? 0 : size / (double) claimed;
region = area.getRegion().toString();
} else {
name = area.worldname;
percent = claimed == 0 ? 0 : Short.MAX_VALUE * Short.MAX_VALUE / (double) claimed;
region = "N/A";
}
PlotMessage tooltip = new PlotMessage()
.text("Claimed=").color("$1").text("" + claimed).color("$2")
.text("\nUsage=").color("$1").text(String.format("%.2f", percent) + "%").color("$2")
.text("\nClusters=").color("$1").text("" + clusters).color("$2")
.text("\nRegion=").color("$1").text(region).color("$2")
.text("\nGenerator=").color("$1").text(generator).color("$2");
// type / terrain
String visit = "/plot area tp " + area.toString();
message.text("[").color("$3")
.text(i + "").command(visit).tooltip(visit).color("$1")
.text("]").color("$3")
.text(" " + name).tooltip(tooltip).command("/plot area info " + area).color("$1").text(" - ").color("$2")
.text(area.TYPE + ":" + area.TERRAIN).color("$3");
}
}, "/plot area list", C.AREA_LIST_HEADER_PAGED.s());
return true;
}
case "regen":
case "regenerate": {
if (!Permissions.hasPermission(plr, "plots.area.regen")) {
C.NO_PERMISSION.send(plr, "plots.area.regen");
return false;
}
final PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
return false;
}
if (area.TYPE != 2) {
MainUtil.sendMessage(plr, "$4Stop the server and delete: " + area.worldname + "/region");
return false;
}
ChunkManager.largeRegionTask(area.worldname, area.getRegion(), new RunnableVal<ChunkLoc>() {
@Override
public void run(ChunkLoc value) {
AugmentedUtils.generate(area.worldname, value.x, value.z, null);
}
}, null);
return true;
}
case "goto":
case "v":
case "teleport":
case "visit":
case "tp": {
if (!Permissions.hasPermission(plr, "plots.area.tp")) {
C.NO_PERMISSION.send(plr, "plots.area.tp");
return false;
}
if (args.length != 2) {
C.COMMAND_SYNTAX.send(plr, "/plot visit [area]");
return false;
}
PlotArea area = PS.get().getPlotAreaByString(args[1]);
if (area == null) {
C.NOT_VALID_PLOT_WORLD.send(plr, args[1]);
return false;
}
Location center;
if (area.TYPE != 2) {
center = WorldUtil.IMP.getSpawn(area.worldname);
} else {
RegionWrapper region = area.getRegion();
center = new Location(area.worldname, region.minX + (region.maxX - region.minX) / 2, 0, region.minZ + (region.maxZ - region.minZ) / 2);
center.setY(WorldUtil.IMP.getHighestBlock(area.worldname, center.getX(), center.getZ()));
}
plr.teleport(center);
return true;
}
case "delete":
case "remove": {
MainUtil.sendMessage(plr, "$1World creation settings may be stored in multiple locations:"
+ "\n$3 - $2Bukkit bukkit.yml"
+ "\n$3 - $2PlotSquared settings.yml"
+ "\n$3 - $2Multiverse worlds.yml (or any world management plugin)"
+ "\n$1Stop the server and delete it from these locations.");
return true;
}
}
C.COMMAND_SYNTAX.send(plr, getUsage());
return false;
}
}

View File

@ -0,0 +1,228 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ByteArrayUtilities;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "auto",
permission = "plots.auto",
category = CommandCategory.CLAIMING,
requiredType = RequiredType.NONE,
description = "Claim the nearest plot",
aliases = { "a" },
usage = "/plot auto [length,width]")
public class Auto extends SubCommand {
public static PlotId getNextPlotId(final PlotId id, final int step) {
final int absX = Math.abs(id.x);
final int absY = Math.abs(id.y);
if (absX > absY) {
if (id.x > 0) {
return new PlotId(id.x, id.y + 1);
} else {
return new PlotId(id.x, id.y - 1);
}
} else if (absY > absX) {
if (id.y > 0) {
return new PlotId(id.x - 1, id.y);
} else {
return new PlotId(id.x + 1, id.y);
}
} else {
if (id.x.equals(id.y) && (id.x > 0)) {
return new PlotId(id.x, id.y + step);
}
if (id.x == absX) {
return new PlotId(id.x, id.y + 1);
}
if (id.y == absY) {
return new PlotId(id.x, id.y - 1);
}
return new PlotId(id.x + 1, id.y);
}
}
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
PlotArea plotarea = plr.getApplicablePlotArea();
if (plotarea == null) {
MainUtil.sendMessage(plr, C.NOT_IN_PLOT_WORLD);
return false;
}
int size_x = 1;
int size_z = 1;
String schematic = null;
if (args.length > 0) {
if (Permissions.hasPermission(plr, "plots.auto.mega")) {
try {
final String[] split = args[0].split(",|;");
size_x = Integer.parseInt(split[0]);
size_z = Integer.parseInt(split[1]);
if ((size_x < 1) || (size_z < 1)) {
MainUtil.sendMessage(plr, "&cError: size<=0");
}
if (args.length > 1) {
schematic = args[1];
}
} catch (NumberFormatException e) {
size_x = 1;
size_z = 1;
schematic = args[0];
// PlayerFunctions.sendMessage(plr,
// "&cError: Invalid size (X,Y)");
// return false;
}
} else {
schematic = args[0];
// PlayerFunctions.sendMessage(plr, C.NO_PERMISSION);
// return false;
}
}
if ((size_x * size_z) > Settings.MAX_AUTO_SIZE) {
MainUtil.sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS_NUM, Settings.MAX_AUTO_SIZE + "");
return false;
}
int removeGrants = 0;
final int currentPlots = Settings.GLOBAL_LIMIT ? plr.getPlotCount() : plr.getPlotCount(plotarea.worldname);
final int diff = currentPlots - plr.getAllowedPlots();
if ((diff + (size_x * size_z)) > 0) {
if (diff < 0) {
MainUtil.sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS_NUM, (-diff) + "");
} else {
if (plr.hasPersistentMeta("grantedPlots")) {
int grantedPlots = ByteArrayUtilities.bytesToInteger(plr.getPersistentMeta("grantedPlots"));
if (grantedPlots < size_x * size_z) {
plr.removePersistentMeta("grantedPlots");
return sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS);
} else {
removeGrants = size_x * size_z;
}
} else {
MainUtil.sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS);
}
}
if (removeGrants == 0) {
return false;
}
}
if ((EconHandler.manager != null) && plotarea.USE_ECONOMY) {
double cost = plotarea.PLOT_PRICE;
cost = (size_x * size_z) * cost;
if (cost > 0d) {
if (EconHandler.manager.getMoney(plr) < cost) {
sendMessage(plr, C.CANNOT_AFFORD_PLOT, "" + cost);
return true;
}
EconHandler.manager.withdrawMoney(plr, cost);
sendMessage(plr, C.REMOVED_BALANCE, cost + "");
}
}
if (removeGrants > 0) {
int grantedPlots = ByteArrayUtilities.bytesToInteger(plr.getPersistentMeta("grantedPlots"));
plr.setPersistentMeta("grantedPlots", ByteArrayUtilities.integerToBytes(grantedPlots - removeGrants));
sendMessage(plr, C.REMOVED_GRANTED_PLOT, "" + removeGrants, "" + (grantedPlots - removeGrants));
}
if (schematic != null && !schematic.equals("")) {
if (!plotarea.SCHEMATICS.contains(schematic.toLowerCase())) {
sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent: " + schematic);
return true;
}
if (!Permissions.hasPermission(plr, "plots.claim." + schematic) && !Permissions.hasPermission(plr, "plots.admin.command.schematic")) {
MainUtil.sendMessage(plr, C.NO_SCHEMATIC_PERMISSION, schematic);
return true;
}
}
if (plotarea.TYPE == 2) {
final PlotId bot = plotarea.getMin();
final PlotId top = plotarea.getMax();
final PlotId origin = new PlotId((bot.x + top.x) / 2, (bot.y + top.y) / 2);
PlotId id = new PlotId(0, 0);
final int width = Math.max((top.x - bot.x) + 1, (top.y - bot.y) + 1);
final int max = width * width;
//
for (int i = 0; i <= max; i++) {
final PlotId currentId = new PlotId(origin.x + id.x, origin.y + id.y);
Plot current = plotarea.getPlotAbs(currentId);
if (current.canClaim(plr)) {
Claim.claimPlot(plr, current, true, true);
return true;
}
id = getNextPlotId(id, 1);
}
// no free plots
MainUtil.sendMessage(plr, C.NO_FREE_PLOTS);
return false;
}
boolean br = false;
if ((size_x == 1) && (size_z == 1)) {
while (!br) {
Plot plot = plotarea.getPlotAbs(getLastPlotId(plotarea));
if (plot.canClaim(plr)) {
Claim.claimPlot(plr, plot, true, true);
br = true;
}
plotarea.setMeta("lastPlot", getNextPlotId(plot.getId(), 1));
}
} else {
while (!br) {
final PlotId start = getNextPlotId(getLastPlotId(plotarea), 1);
final PlotId end = new PlotId((start.x + size_x) - 1, (start.y + size_z) - 1);
plotarea.setMeta("lastPlot", start);
if (plotarea.canClaim(plr, start, end)) {
for (int i = start.x; i <= end.x; i++) {
for (int j = start.y; j <= end.y; j++) {
Plot plot = plotarea.getPlotAbs(new PlotId(i, j));
final boolean teleport = ((i == end.x) && (j == end.y));
Claim.claimPlot(plr, plot, teleport, true);
}
}
if (!plotarea.mergePlots(MainUtil.getPlotSelectionIds(start, end), Settings.MERGE_REMOVES_ROADS, true)) {
return false;
}
br = true;
}
}
}
plotarea.setMeta("lastPlot", new PlotId(0, 0));
return true;
}
public PlotId getLastPlotId(final PlotArea area) {
PlotId value = (PlotId) area.getMeta("lastPlot");
if (value == null) {
value = new PlotId(0, 0);
area.setMeta("lastPlot", value);
return value;
}
return value;
}
}

View File

@ -0,0 +1,75 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.BO3Handler;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "bo3", aliases = { "bo2" }, description = "Mark a plot as done", permission = "plots.bo3", category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE)
public class BO3 extends SubCommand {
public void noArgs(final PlotPlayer plr) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot bo3 export [category] [alias] [-r]");
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot bo3 import <file>");
}
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if ((plot == null) || !plot.hasOwner()) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if ((!plot.isOwner(plr.getUUID())) && !Permissions.hasPermission(plr, "plots.admin.command.bo3")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (args.length == 0) {
noArgs(plr);
return false;
}
switch (args[0].toLowerCase()) {
case "output":
case "save":
case "export": {
return BO3Handler.saveBO3(plr, plot);
}
case "paste":
case "load":
case "import":
case "input": {
// TODO NOT IMPLEMENTED YET
MainUtil.sendMessage(plr, "NOT IMPLEMENTED YET!!!");
return false;
}
default: {
noArgs(plr);
return false;
}
}
}
}

View File

@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "setbiome",
permission = "plots.set.biome",
description = "Set the plot biome",
usage = "/plot biome [biome]",
aliases = { "biome", "sb", "setb", "b" },
category = CommandCategory.APPEARANCE,
requiredType = RequiredType.NONE)
public class Biome extends SetCommand {
@Override
public boolean set(final PlotPlayer plr, final Plot plot, final String value) {
final int biome = WorldUtil.IMP.getBiomeFromString(value);
if (biome == -1) {
String biomes = StringMan.join(WorldUtil.IMP.getBiomeList(), C.BLOCK_LIST_SEPARATER.s());
C.NEED_BIOME.send(plr);
MainUtil.sendMessage(plr, C.SUBCOMMAND_SET_OPTIONS_HEADER.s() + biomes);
return false;
}
if (plot.getRunning() > 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
plot.addRunning();
plot.setBiome(value.toUpperCase(), new Runnable() {
@Override
public void run() {
plot.removeRunning();
MainUtil.sendMessage(plr, C.BIOME_SET_TO.s() + value.toLowerCase());
}
});
return true;
}
}

View File

@ -0,0 +1,110 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.Set;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "buy",
aliases = { "b" },
description = "Buy the plot you are standing on",
usage = "/plot buy",
permission = "plots.buy",
category = CommandCategory.CLAIMING,
requiredType = RequiredType.NONE)
public class Buy extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
if (EconHandler.manager == null) {
return sendMessage(plr, C.ECON_DISABLED);
}
final Location loc = plr.getLocation();
final String world = loc.getWorld();
if (!PS.get().hasPlotArea(world)) {
return sendMessage(plr, C.NOT_IN_PLOT_WORLD);
}
Set<Plot> plots;
Plot plot;
if (args.length > 0) {
try {
plot = MainUtil.getPlotFromString(plr, world, true);
if (plot == null) {
return false;
}
plots = plot.getConnectedPlots();
} catch (final Exception e) {
return sendMessage(plr, C.NOT_VALID_PLOT_ID);
}
} else {
plot = loc.getPlotAbs();
plots = plot.getConnectedPlots();
}
if (plots == null) {
return sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
return sendMessage(plr, C.PLOT_UNOWNED);
}
final int currentPlots = plr.getPlotCount() + plots.size();
if (currentPlots > plr.getAllowedPlots()) {
return sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS);
}
final Flag flag = FlagManager.getPlotFlagRaw(plot, "price");
if (flag == null) {
return sendMessage(plr, C.NOT_FOR_SALE);
}
if (plot.isOwner(plr.getUUID())) {
return sendMessage(plr, C.CANNOT_BUY_OWN);
}
double price = (double) flag.getValue();
if ((EconHandler.manager != null) && (price > 0d)) {
if (EconHandler.manager.getMoney(plr) < price) {
return sendMessage(plr, C.CANNOT_AFFORD_PLOT, "" + price);
}
EconHandler.manager.withdrawMoney(plr, price);
sendMessage(plr, C.REMOVED_BALANCE, price + "");
EconHandler.manager.depositMoney(UUIDHandler.getUUIDWrapper().getOfflinePlayer(plot.owner), price);
final PlotPlayer owner = UUIDHandler.getPlayer(plot.owner);
if (owner != null) {
sendMessage(plr, C.PLOT_SOLD, plot.getId() + "", plr.getName(), price + "");
}
FlagManager.removePlotFlag(plot, "price");
}
for (final Plot current : plots) {
plot.setOwner(plr.getUUID());
}
MainUtil.sendMessage(plr, C.CLAIMED);
return true;
}
}

View File

@ -0,0 +1,19 @@
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "chat",
description = "Toggle plot chat on or off",
usage = "/plot chat [on|off]",
permission = "plots.chat",
category = CommandCategory.CHAT,
requiredType = RequiredType.NONE)
public class Chat extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer player, final String... args) {
return MainCommand.onCommand(player, "plot", new String[] { "toggle", "chat" });
}
}

View File

@ -0,0 +1,149 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ByteArrayUtilities;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SchematicHandler.Schematic;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "claim",
aliases = { "c" },
description = "Claim the current plot you're standing on",
category = CommandCategory.CLAIMING,
requiredType = RequiredType.NONE,
permission = "plots.claim",
usage = "/plot claim")
public class Claim extends SubCommand {
public static boolean claimPlot(final PlotPlayer player, final Plot plot, final boolean teleport, final boolean auto) {
return claimPlot(player, plot, teleport, "", auto);
}
public static boolean claimPlot(final PlotPlayer player, final Plot plot, final boolean teleport, final String schematic, final boolean auto) {
if (plot.hasOwner() || plot.isMerged()) {
return false;
}
final boolean result = EventUtil.manager.callClaim(player, plot, false);
if (result) {
plot.create(player.getUUID(), true);
plot.setSign(player.getName());
MainUtil.sendMessage(player, C.CLAIMED);
if (teleport) {
plot.teleportPlayer(player);
}
final PlotArea plotworld = plot.getArea();
if (plotworld.SCHEMATIC_ON_CLAIM) {
Schematic sch;
if (schematic.isEmpty()) {
sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE);
} else {
sch = SchematicHandler.manager.getSchematic(schematic);
if (sch == null) {
sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE);
}
}
SchematicHandler.manager.paste(sch, plot, 0, 0, new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
if (value) {
MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_SUCCESS);
} else {
MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_FAILED);
}
}
});
}
plotworld.getPlotManager().claimPlot(plotworld, plot);
}
return result;
}
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
String schematic = "";
if (args.length >= 1) {
schematic = args[0];
}
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
return sendMessage(plr, C.NOT_IN_PLOT);
}
final int currentPlots = Settings.GLOBAL_LIMIT ? plr.getPlotCount() : plr.getPlotCount(loc.getWorld());
boolean removeGrantedPlot = false;
if (currentPlots >= plr.getAllowedPlots()) {
if (plr.hasPersistentMeta("grantedPlots")) {
int grantedPlots = ByteArrayUtilities.bytesToInteger(plr.getPersistentMeta("grantedPlots"));
if (grantedPlots < 1) {
plr.removePersistentMeta("grantedPlots");
return sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS);
} else {
removeGrantedPlot = true;
}
} else {
return sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS);
}
}
if (!plot.canClaim(plr)) {
return sendMessage(plr, C.PLOT_IS_CLAIMED);
}
final PlotArea world = plot.getArea();
if ((EconHandler.manager != null) && world.USE_ECONOMY) {
final double cost = world.PLOT_PRICE;
if (cost > 0d) {
if (EconHandler.manager.getMoney(plr) < cost) {
return sendMessage(plr, C.CANNOT_AFFORD_PLOT, "" + cost);
}
EconHandler.manager.withdrawMoney(plr, cost);
sendMessage(plr, C.REMOVED_BALANCE, cost + "");
}
}
if (removeGrantedPlot) {
int grantedPlots = ByteArrayUtilities.bytesToInteger(plr.getPersistentMeta("grantedPlots"));
plr.setPersistentMeta("grantedPlots", ByteArrayUtilities.integerToBytes(grantedPlots - 1));
sendMessage(plr, C.REMOVED_GRANTED_PLOT, "1", "" + (grantedPlots - 1));
}
if (!schematic.equals("")) {
if (world.SCHEMATIC_CLAIM_SPECIFY) {
if (!world.SCHEMATICS.contains(schematic.toLowerCase())) {
return sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent: " + schematic);
}
if (!Permissions.hasPermission(plr, "plots.claim." + schematic) && !Permissions.hasPermission(plr, "plots.admin.command.schematic")) {
return sendMessage(plr, C.NO_SCHEMATIC_PERMISSION, schematic);
}
}
}
return claimPlot(plr, plot, false, schematic, false) || sendMessage(plr, C.PLOT_NOT_CLAIMED);
}
}

View File

@ -0,0 +1,124 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.Set;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.CmdConfirm;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "clear", description = "Clear a plot", permission = "plots.clear", category = CommandCategory.APPEARANCE,
usage = "/plot clear [id]", aliases = "reset")
public class Clear extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
final Location loc = plr.getLocation();
final Plot plot;
if (args.length == 1) {
if (args[0].equalsIgnoreCase("mine")) {
Set<Plot> plots = plr.getPlots();
if (!plots.isEmpty()) {
plot = plots.iterator().next();
} else {
MainUtil.sendMessage(plr, C.NO_PLOTS);
return false;
}
} else {
plot = MainUtil.getPlotFromString(plr, args[0], true);
}
if (plot == null) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot clear [X;Z|mine]");
return false;
}
} else if (args.length == 0) {
plot = loc.getPlotAbs();
if (plot == null) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot clear [X;Z|mine]");
C.NOT_IN_PLOT.send(plr);
return false;
}
} else {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot clear [X;Z|mine]");
return false;
}
if ((!plot.hasOwner() || !plot.isOwner(plr.getUUID())) && !Permissions.hasPermission(plr, "plots.admin.command.clear")) {
return sendMessage(plr, C.NO_PLOT_PERMS);
}
if (plot.getRunning() != 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
if ((FlagManager.getPlotFlagRaw(plot, "done") != null)
&& (!Permissions.hasPermission(plr, "plots.continue") || (Settings.DONE_COUNTS_TOWARDS_LIMIT && (plr.getAllowedPlots() >= plr.getPlotCount())))) {
MainUtil.sendMessage(plr, C.DONE_ALREADY_DONE);
return false;
}
final Runnable runnable = new Runnable() {
@Override
public void run() {
final long start = System.currentTimeMillis();
final boolean result = plot.clear(true, false, new Runnable() {
@Override
public void run() {
plot.unlink();
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
plot.removeRunning();
// If the state changes, then mark it as no longer done
if (FlagManager.getPlotFlagRaw(plot, "done") != null) {
FlagManager.removePlotFlag(plot, "done");
}
if (FlagManager.getPlotFlagRaw(plot, "analysis") != null) {
FlagManager.removePlotFlag(plot, "analysis");
}
MainUtil.sendMessage(plr, C.CLEARING_DONE, "" + (System.currentTimeMillis() - start));
}
});
}
});
if (!result) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
}
else {
plot.addRunning();
}
}
};
if (Settings.CONFIRM_CLEAR && !(Permissions.hasPermission(plr, "plots.confirm.bypass"))) {
CmdConfirm.addPending(plr, "/plot clear " + plot.getId(), runnable);
} else {
TaskManager.runTask(runnable);
}
return true;
}
}

View File

@ -0,0 +1,610 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.BlockLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotCluster;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "cluster",
aliases = { "clusters" },
category = CommandCategory.ADMINISTRATION,
requiredType = RequiredType.NONE,
permission = "plots.cluster",
description = "Manage a plot cluster")
public class Cluster extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
// list, create, delete, resize, invite, kick, leave, helpers, tp, sethome
if (args.length == 0) {
// return arguments
MainUtil.sendMessage(plr, C.CLUSTER_AVAILABLE_ARGS);
return false;
}
final String sub = args[0].toLowerCase();
switch (sub) {
case "l":
case "list": {
if (!Permissions.hasPermission(plr, "plots.cluster.list")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.list");
return false;
}
if (args.length != 1) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster list");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
final Set<PlotCluster> clusters = area.getClusters();
MainUtil.sendMessage(plr, C.CLUSTER_LIST_HEADING, clusters.size() + "");
for (final PlotCluster cluster : clusters) {
// Ignore unmanaged clusters
final String name = "'" + cluster.getName() + "' : " + cluster.toString();
if (plr.getUUID().equals(cluster.owner)) {
MainUtil.sendMessage(plr, C.CLUSTER_LIST_ELEMENT, "&a" + name);
} else if (cluster.helpers.contains(plr.getUUID())) {
MainUtil.sendMessage(plr, C.CLUSTER_LIST_ELEMENT, "&3" + name);
} else if (cluster.invited.contains(plr.getUUID())) {
MainUtil.sendMessage(plr, C.CLUSTER_LIST_ELEMENT, "&9" + name);
} else {
MainUtil.sendMessage(plr, C.CLUSTER_LIST_ELEMENT, cluster.toString());
}
}
return true;
}
case "c":
case "create": {
if (!Permissions.hasPermission(plr, "plots.cluster.create")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.create");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
return false;
}
if (args.length != 4) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster create <name> <id-bot> <id-top>");
return false;
}
// check pos1 / pos2
PlotId pos1 = PlotId.fromString(args[2]);
PlotId pos2 = PlotId.fromString(args[3]);
if ((pos1 == null) || (pos2 == null)) {
MainUtil.sendMessage(plr, C.NOT_VALID_PLOT_ID);
return false;
}
// check if name is taken
final String name = args[1];
if (area.getCluster(name) != null) {
MainUtil.sendMessage(plr, C.ALIAS_IS_TAKEN);
return false;
}
if ((pos2.x < pos1.x) || (pos2.y < pos1.y)) {
PlotId tmp = new PlotId(Math.min(pos1.x, pos2.x), Math.min(pos1.y, pos2.y));
pos2 = new PlotId(Math.max(pos1.x, pos2.x), Math.max(pos1.y, pos2.y));
pos1 = tmp;
}
//check if overlap
PlotCluster cluster = area.getFirstIntersectingCluster(pos1, pos2);
if (cluster != null) {
MainUtil.sendMessage(plr, C.CLUSTER_INTERSECTION, cluster.getName());
return false;
}
// Check if it occupies existing plots
final Set<Plot> plots = area.getPlotSelectionOwned(pos1, pos2);
if (!plots.isEmpty()) {
if (!Permissions.hasPermission(plr, "plots.cluster.create.other")) {
final UUID uuid = plr.getUUID();
for (final Plot plot : plots) {
if (!plot.isOwner(uuid)) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.create.other");
return false;
}
}
}
}
// Check allowed cluster size
cluster = new PlotCluster(area, pos1, pos2, plr.getUUID());
int current;
if (Settings.GLOBAL_LIMIT) {
current = plr.getPlayerClusterCount();
} else {
current = plr.getPlayerClusterCount(plr.getLocation().getWorld());
}
final int allowed = Permissions.hasPermissionRange(plr, "plots.cluster", Settings.MAX_PLOTS);
if ((current + cluster.getArea()) > allowed) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster." + (current + cluster.getArea()));
return false;
}
// create cluster
cluster.settings.setAlias(name);
area.addCluster(cluster);
DBFunc.createCluster(cluster);
// Add any existing plots to the current cluster
for (final Plot plot : plots) {
if (plot.hasOwner()) {
final Flag flag = new Flag(FlagManager.getFlag("cluster"), cluster);
FlagManager.addPlotFlag(plot, flag);
if (!cluster.isAdded(plot.owner)) {
cluster.invited.add(plot.owner);
DBFunc.setInvited(cluster, plot.owner);
}
}
}
MainUtil.sendMessage(plr, C.CLUSTER_ADDED);
return true;
}
case "disband":
case "del":
case "delete": {
if (!Permissions.hasPermission(plr, "plots.cluster.delete")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.delete");
return false;
}
if ((args.length != 1) && (args.length != 2)) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster delete [name]");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
return false;
}
PlotCluster cluster;
if (args.length == 2) {
cluster = area.getCluster(args[1]);
if (cluster == null) {
MainUtil.sendMessage(plr, C.INVALID_CLUSTER, args[1]);
return false;
}
} else {
cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
}
if (!cluster.owner.equals(plr.getUUID())) {
if (!Permissions.hasPermission(plr, "plots.cluster.delete.other")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.delete.other");
return false;
}
}
DBFunc.delete(cluster);
MainUtil.sendMessage(plr, C.CLUSTER_DELETED);
return true;
}
case "res":
case "resize": {
if (!Permissions.hasPermission(plr, "plots.cluster.resize")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.resize");
return false;
}
if (args.length != 3) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster resize <pos1> <pos2>");
return false;
}
// check pos1 / pos2
PlotId pos1 = PlotId.fromString(args[1]);
PlotId pos2 = PlotId.fromString(args[2]);
if ((pos1 == null) || (pos2 == null)) {
MainUtil.sendMessage(plr, C.NOT_VALID_PLOT_ID);
return false;
}
if ((pos2.x < pos1.x) || (pos2.y < pos1.y)) {
pos1 = new PlotId(Math.min(pos1.x, pos2.x), Math.min(pos1.y, pos2.y));
pos2 = new PlotId(Math.max(pos1.x, pos2.x), Math.max(pos1.y, pos2.y));
}
// check if in cluster
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
return false;
}
final PlotCluster cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
if (!cluster.hasHelperRights(plr.getUUID())) {
if (!Permissions.hasPermission(plr, "plots.cluster.resize.other")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.resize.other");
return false;
}
}
//check if overlap
PlotCluster intersect = area.getFirstIntersectingCluster(pos1, pos2);
if (intersect != null) {
MainUtil.sendMessage(plr, C.CLUSTER_INTERSECTION, intersect.getName());
return false;
}
final HashSet<Plot> existing = area.getPlotSelectionOwned(cluster.getP1(), cluster.getP2());
final HashSet<Plot> newplots = area.getPlotSelectionOwned(pos1, pos2);
final HashSet<Plot> removed = ((HashSet<Plot>) existing.clone());
removed.removeAll(newplots);
// Check expand / shrink
if (!removed.isEmpty()) {
if (!Permissions.hasPermission(plr, "plots.cluster.resize.shrink")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.resize.shrink");
return false;
}
}
newplots.removeAll(existing);
if (!newplots.isEmpty()) {
if (!Permissions.hasPermission(plr, "plots.cluster.resize.expand")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.resize.expand");
return false;
}
}
// Check allowed cluster size
int current;
if (Settings.GLOBAL_LIMIT) {
current = plr.getPlayerClusterCount();
} else {
current = plr.getPlayerClusterCount(plr.getLocation().getWorld());
}
current -= cluster.getArea() + (((1 + pos2.x) - pos1.x) * ((1 + pos2.y) - pos1.y));
final int allowed = Permissions.hasPermissionRange(plr, "plots.cluster", Settings.MAX_PLOTS);
if ((current + cluster.getArea()) > allowed) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster." + (current + cluster.getArea()));
return false;
}
for (final Plot plot : removed) {
FlagManager.removePlotFlag(plot, "cluster");
}
for (final Plot plot : newplots) {
FlagManager.addPlotFlag(plot, new Flag(FlagManager.getFlag("cluster"), cluster));
}
// resize cluster
DBFunc.resizeCluster(cluster, pos1, pos2);
MainUtil.sendMessage(plr, C.CLUSTER_RESIZED);
return true;
}
case "add":
case "inv":
case "invite": {
if (!Permissions.hasPermission(plr, "plots.cluster.invite")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.invite");
return false;
}
if (args.length != 2) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster invite <player>");
return false;
}
// check if in cluster
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
final PlotCluster cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
if (!cluster.hasHelperRights(plr.getUUID())) {
if (!Permissions.hasPermission(plr, "plots.cluster.invite.other")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.invite.other");
return false;
}
}
// check uuid
final UUID uuid = UUIDHandler.getUUID(args[1], null);
if (uuid == null) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[2]);
return false;
}
if (!cluster.isAdded(uuid)) {
// add the user if not added
cluster.invited.add(uuid);
DBFunc.setInvited(cluster, uuid);
final PlotPlayer player = UUIDHandler.getPlayer(uuid);
if (player != null) {
MainUtil.sendMessage(player, C.CLUSTER_INVITED, cluster.getName());
}
}
MainUtil.sendMessage(plr, C.CLUSTER_ADDED_USER);
return true;
}
case "k":
case "remove":
case "kick": {
if (!Permissions.hasPermission(plr, "plots.cluster.kick")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.kick");
return false;
}
if (args.length != 2) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster kick <player>");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
final PlotCluster cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
if (!cluster.hasHelperRights(plr.getUUID())) {
if (!Permissions.hasPermission(plr, "plots.cluster.kick.other")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.kick.other");
return false;
}
}
// check uuid
final UUID uuid = UUIDHandler.getUUID(args[1], null);
if (uuid == null) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[1]);
return false;
}
// Can't kick if the player is yourself, the owner, or not added to the cluster
if (uuid.equals(plr.getUUID()) || uuid.equals(cluster.owner) || !cluster.isAdded(uuid)) {
MainUtil.sendMessage(plr, C.CANNOT_KICK_PLAYER, cluster.getName());
return false;
}
if (cluster.helpers.contains(uuid)) {
cluster.helpers.remove(uuid);
DBFunc.removeHelper(cluster, uuid);
}
cluster.invited.remove(uuid);
DBFunc.removeInvited(cluster, uuid);
final PlotPlayer player = UUIDHandler.getPlayer(uuid);
if (player != null) {
MainUtil.sendMessage(player, C.CLUSTER_REMOVED, cluster.getName());
}
for (final Plot plot : new ArrayList<>(PS.get().getPlots(plr.getLocation().getWorld(), uuid))) {
final PlotCluster current = plot.getCluster();
if ((current != null) && current.equals(cluster)) {
plr.getLocation().getWorld();
plot.unclaim();
}
}
MainUtil.sendMessage(plr, C.CLUSTER_KICKED_USER);
return true;
}
case "quit":
case "leave": {
if (!Permissions.hasPermission(plr, "plots.cluster.leave")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.leave");
return false;
}
if ((args.length != 1) && (args.length != 2)) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster leave [name]");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
PlotCluster cluster;
if (args.length == 2) {
cluster = area.getCluster(args[1]);
if (cluster == null) {
MainUtil.sendMessage(plr, C.INVALID_CLUSTER, args[1]);
return false;
}
} else {
cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
}
final UUID uuid = plr.getUUID();
if (!cluster.isAdded(uuid)) {
MainUtil.sendMessage(plr, C.CLUSTER_NOT_ADDED);
return false;
}
if (uuid.equals(cluster.owner)) {
MainUtil.sendMessage(plr, C.CLUSTER_CANNOT_LEAVE);
return false;
}
if (cluster.helpers.contains(uuid)) {
cluster.helpers.remove(uuid);
DBFunc.removeHelper(cluster, uuid);
}
cluster.invited.remove(uuid);
DBFunc.removeInvited(cluster, uuid);
MainUtil.sendMessage(plr, C.CLUSTER_REMOVED, cluster.getName());
for (final Plot plot : new ArrayList<>(PS.get().getPlots(plr.getLocation().getWorld(), uuid))) {
final PlotCluster current = plot.getCluster();
if ((current != null) && current.equals(cluster)) {
plr.getLocation().getWorld();
plot.unclaim();
}
}
return true;
}
case "admin":
case "helper":
case "helpers": {
if (!Permissions.hasPermission(plr, "plots.cluster.helpers")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.helpers");
return false;
}
if (args.length != 3) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster helpers <add|remove> <player>");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
final PlotCluster cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
final UUID uuid = UUIDHandler.getUUID(args[2], null);
if (uuid == null) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[2]);
return false;
}
if (args[1].toLowerCase().equals("add")) {
cluster.helpers.add(uuid);
DBFunc.setHelper(cluster, uuid);
return MainUtil.sendMessage(plr, C.CLUSTER_ADDED_HELPER);
}
if (args[1].toLowerCase().equals("remove")) {
cluster.helpers.remove(uuid);
DBFunc.removeHelper(cluster, uuid);
return MainUtil.sendMessage(plr, C.CLUSTER_REMOVED_HELPER);
}
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster helpers <add|remove> <player>");
return false;
}
case "spawn":
case "home":
case "tp": {
if (!Permissions.hasPermission(plr, "plots.cluster.tp")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.tp");
return false;
}
if (args.length != 2) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster tp <name>");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
final PlotCluster cluster = area.getCluster(args[1]);
if (cluster == null) {
MainUtil.sendMessage(plr, C.INVALID_CLUSTER, args[1]);
return false;
}
final UUID uuid = plr.getUUID();
if (!cluster.isAdded(uuid)) {
if (!Permissions.hasPermission(plr, "plots.cluster.tp.other")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.tp.other");
return false;
}
}
plr.teleport(cluster.getHome());
return MainUtil.sendMessage(plr, C.CLUSTER_TELEPORTING);
}
case "i":
case "info":
case "show":
case "information": {
if (!Permissions.hasPermission(plr, "plots.cluster.info")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.info");
return false;
}
if ((args.length != 1) && (args.length != 2)) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster info [name]");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
PlotCluster cluster;
if (args.length == 2) {
cluster = area.getCluster(args[1]);
if (cluster == null) {
MainUtil.sendMessage(plr, C.INVALID_CLUSTER, args[1]);
return false;
}
} else {
cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
}
final String id = cluster.toString();
String owner = UUIDHandler.getName(cluster.owner);
if (owner == null) {
owner = "unknown";
}
final String name = cluster.getName();
final String size = ((cluster.getP2().x - cluster.getP1().x) + 1) + "x" + ((cluster.getP2().y - cluster.getP1().y) + 1);
final String rights = cluster.isAdded(plr.getUUID()) + "";
String message = C.CLUSTER_INFO.s();
message = message.replaceAll("%id%", id);
message = message.replaceAll("%owner%", owner);
message = message.replaceAll("%name%", name);
message = message.replaceAll("%size%", size);
message = message.replaceAll("%rights%", rights);
MainUtil.sendMessage(plr, message);
return true;
}
case "sh":
case "setspawn":
case "sethome": {
if (!Permissions.hasPermission(plr, "plots.cluster.sethome")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.sethome");
return false;
}
if ((args.length != 1) && (args.length != 2)) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot cluster sethome");
return false;
}
PlotArea area = plr.getApplicablePlotArea();
if (area == null) {
C.NOT_IN_PLOT_WORLD.send(plr);
}
final PlotCluster cluster = area.getCluster(plr.getLocation());
if (cluster == null) {
MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER);
return false;
}
if (!cluster.hasHelperRights(plr.getUUID())) {
if (!Permissions.hasPermission(plr, "plots.cluster.sethome.other")) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.sethome.other");
return false;
}
}
final Location base = cluster.getClusterBottom();
final Location relative = plr.getLocation().subtract(base.getX(), 0, base.getZ());
final BlockLoc blockloc = new BlockLoc(relative.getX(), relative.getY(), relative.getZ());
cluster.settings.setPosition(blockloc);
DBFunc.setPosition(cluster, relative.getX() + "," + relative.getY() + "," + relative.getZ());
return MainUtil.sendMessage(plr, C.POSITION_SET);
}
}
MainUtil.sendMessage(plr, C.CLUSTER_AVAILABLE_ARGS);
return false;
}
}

View File

@ -0,0 +1,71 @@
package com.intellectualcrafters.plot.commands;
/**
* CommandCategory
*
*/
public enum CommandCategory {
/**
* Claiming Commands
*
* Such as: /plot claim
*/
CLAIMING("Claiming"),
/**
* Teleportation Commands
*
* Such as: /plot visit
*/
TELEPORT("Teleport"),
/**
* Protection
*/
SETTINGS("Protection"),
/**
* Chat
*/
CHAT("Chat"),
/**
* Web
*/
SCHEMATIC("Web"),
/**
* Cosmetic
*/
APPEARANCE("Cosmetic"),
/**
* Information Commands
*
* Such as: /plot info
*/
INFO("Info"),
/**
* Debug Commands
*
* Such as: /plot debug
*/
DEBUG("Debug"),
/**
* Administration commands
*/
ADMINISTRATION("Admin");
/**
* The category name (Readable)
*/
private final String name;
/**
* Constructor
*
* @param name readable name
*/
CommandCategory(final String name) {
this.name = name;
}
@Override
public String toString() {
return name;

View File

@ -0,0 +1,51 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.Permissions;
/**
* Created by Citymonstret on 2014-08-03.
*
*/
public class CommandPermission {
/**
* Permission Node
*/
public final String permission;
/**
* @param permission Command Permission
*/
public CommandPermission(final String permission) {
this.permission = permission.toLowerCase();
}
/**
* @param player Does the player have the permission?
*
* @return true of player has the required permission node
*/
public boolean hasPermission(final PlotPlayer player) {
return Permissions.hasPermission(player, permission);
}

View File

@ -0,0 +1,88 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.Arrays;
import java.util.Map.Entry;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.comment.CommentInbox;
import com.intellectualcrafters.plot.object.comment.PlotComment;
import com.intellectualcrafters.plot.util.CommentManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "comment", aliases = { "msg" }, description = "Comment on a plot", category = CommandCategory.CHAT, requiredType = RequiredType.NONE, permission = "plots.comment")
public class Comment extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer player, final String[] args) {
if (args.length < 2) {
sendMessage(player, C.COMMENT_SYNTAX, StringMan.join(CommentManager.inboxes.keySet(), "|"));
return false;
}
final CommentInbox inbox = CommentManager.inboxes.get(args[0].toLowerCase());
if (inbox == null) {
sendMessage(player, C.COMMENT_SYNTAX, StringMan.join(CommentManager.inboxes.keySet(), "|"));
return false;
}
final Location loc = player.getLocation();
final PlotId id = PlotId.fromString(args[1]);
Plot plot = MainUtil.getPlotFromString(player, args[1], false);
int index;
if (plot == null) {
index = 1;
plot = loc.getPlotAbs();
} else {
if (args.length < 4) {
sendMessage(player, C.COMMENT_SYNTAX, StringMan.join(CommentManager.inboxes.keySet(), "|"));
return false;
}
index = 2;
}
if (!inbox.canWrite(plot, player)) {
sendMessage(player, C.NO_PERM_INBOX, "");
return false;
}
final String message = StringMan.join(Arrays.copyOfRange(args, index, args.length), " ");
final PlotComment comment = new PlotComment(loc.getWorld(), id, message, player.getName(), inbox.toString(), System.currentTimeMillis());
final boolean result = inbox.addComment(plot, comment);
if (!result) {
sendMessage(player, C.NO_PLOT_INBOX, "");
sendMessage(player, C.COMMENT_SYNTAX, StringMan.join(CommentManager.inboxes.keySet(), "|"));
return false;
}
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
PlotPlayer pp = entry.getValue();
if (pp.getAttribute("chatspy")) {
MainUtil.sendMessage(pp, "/plot comment " + StringMan.join(args, " "));
}
}
sendMessage(player, C.COMMENT_ADDED);
return true;
}
}

View File

@ -0,0 +1,235 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.CommandDeclaration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@CommandDeclaration(command = "condense", permission = "plots.admin", description = "Condense a plotworld", category = CommandCategory.ADMINISTRATION, requiredType = RequiredType.CONSOLE)
public class Condense extends SubCommand {
public static boolean TASK = false;
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
if ((args.length != 2) && (args.length != 3)) {
MainUtil.sendMessage(plr, "/plot condense <area> <start|stop|info> [radius]");
return false;
}
PlotArea area = PS.get().getPlotAreaByString(args[0]);
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
MainUtil.sendMessage(plr, "INVALID AREA");
return false;
}
switch (args[1].toLowerCase()) {
case "start": {
if (args.length == 2) {
MainUtil.sendMessage(plr, "/plot condense " + area.toString() + " start <radius>");
return false;
}
if (TASK) {
MainUtil.sendMessage(plr, "TASK ALREADY STARTED");
return false;
}
if (args.length == 2) {
MainUtil.sendMessage(plr, "/plot condense " + area.toString() + " start <radius>");
return false;
}
if (!MathMan.isInteger(args[2])) {
MainUtil.sendMessage(plr, "INVALID RADIUS");
return false;
}
final int radius = Integer.parseInt(args[2]);
ArrayList<Plot> plots = new ArrayList<>(PS.get().getPlots(area));
// remove non base plots
Iterator<Plot> iter = plots.iterator();
int maxSize = 0;
ArrayList<Integer> sizes = new ArrayList<>();
while (iter.hasNext()) {
Plot plot = iter.next();
if (!plot.isBasePlot()) {
iter.remove();
continue;
}
int size = plot.getConnectedPlots().size();
if (size > maxSize) {
maxSize = size;
}
sizes.add(size - 1);
}
// Sort plots by size (buckets?)]
ArrayList<Plot>[] buckets = new ArrayList[maxSize];
for (int i = 0; i < plots.size(); i++) {
Plot plot = plots.get(i);
int size = sizes.get(i);
ArrayList<Plot> array = buckets[size];
if (array == null) {
array = new ArrayList<Plot>();
buckets[size] = array;
}
array.add(plot);
}
final ArrayList<Plot> allPlots = new ArrayList<Plot>(plots.size());
for (int i = buckets.length - 1; i >= 0; i--) {
ArrayList<Plot> array = buckets[i];
if (array != null) {
allPlots.addAll(array);
}
}
final int size = allPlots.size();
final int minimum_radius = (int) Math.ceil((Math.sqrt(size) / 2) + 1);
if (radius < minimum_radius) {
MainUtil.sendMessage(plr, "RADIUS TOO SMALL");
return false;
}
final List<PlotId> to_move = new ArrayList<>(getPlots(allPlots, radius));
final List<PlotId> free = new ArrayList<>();
PlotId start = new PlotId(0, 0);
while ((start.x <= minimum_radius) && (start.y <= minimum_radius)) {
Plot plot = area.getPlotAbs(start);
if (plot != null && !plot.hasOwner()) {
free.add(plot.getId());
}
start = Auto.getNextPlotId(start, 1);
}
if ((free.isEmpty()) || (to_move.isEmpty())) {
MainUtil.sendMessage(plr, "NO FREE PLOTS FOUND");
return false;
}
MainUtil.sendMessage(plr, "TASK STARTED...");
Runnable run = new Runnable() {
@Override
public void run() {
if (!TASK) {
MainUtil.sendMessage(plr, "TASK CANCELLED.");
}
if (allPlots.isEmpty()) {
TASK = false;
MainUtil.sendMessage(plr, "TASK COMPLETE. PLEASE VERIFY THAT NO NEW PLOTS HAVE BEEN CLAIMED DURING TASK.");
return;
}
final Runnable task = this;
final Plot origin = allPlots.remove(0);
int i = 0;
while (free.size() > i) {
final Plot possible = origin.getArea().getPlotAbs(free.get(i));
if (possible.hasOwner()) {
free.remove(i);
continue;
}
i++;
final AtomicBoolean result = new AtomicBoolean(false);
result.set(origin.move(possible, new Runnable() {
@Override
public void run() {
if (result.get()) {
MainUtil.sendMessage(plr, "Moving: " + origin + " -> " + possible);
TaskManager.runTaskLater(task, 1);
}
}
}, false));
if (result.get()) {
break;
}
}
if (free.isEmpty()) {
TASK = false;
MainUtil.sendMessage(plr, "TASK FAILED. NO FREE PLOTS FOUND!");
return;
}
if (i >= free.size()) {
MainUtil.sendMessage(plr, "SKIPPING COMPLEX PLOT: " + origin);
}
}
};
TASK = true;
TaskManager.runTaskAsync(run);
return true;
}
case "stop": {
if (!TASK) {
MainUtil.sendMessage(plr, "TASK ALREADY STOPPED");
return false;
}
TASK = false;
MainUtil.sendMessage(plr, "TASK STOPPED");
return true;
}
case "info": {
if (args.length == 2) {
MainUtil.sendMessage(plr, "/plot condense " + area.toString() + " info <radius>");
return false;
}
if (!MathMan.isInteger(args[2])) {
MainUtil.sendMessage(plr, "INVALID RADIUS");
return false;
}
final int radius = Integer.parseInt(args[2]);
final Collection<Plot> plots = area.getPlots();
final int size = plots.size();
final int minimum_radius = (int) Math.ceil((Math.sqrt(size) / 2) + 1);
if (radius < minimum_radius) {
MainUtil.sendMessage(plr, "RADIUS TOO SMALL");
return false;
}
final int max_move = getPlots(plots, minimum_radius).size();
final int user_move = getPlots(plots, radius).size();
MainUtil.sendMessage(plr, "=== DEFAULT EVAL ===");
MainUtil.sendMessage(plr, "MINIMUM RADIUS: " + minimum_radius);
MainUtil.sendMessage(plr, "MAXIMUM MOVES: " + max_move);
MainUtil.sendMessage(plr, "=== INPUT EVAL ===");
MainUtil.sendMessage(plr, "INPUT RADIUS: " + radius);
MainUtil.sendMessage(plr, "ESTIMATED MOVES: " + user_move);
MainUtil.sendMessage(plr, "ESTIMATED TIME: " + "No idea, times will drastically change based on the system performance and load");
MainUtil.sendMessage(plr, "&e - Radius is measured in plot width");
return true;
}
}
MainUtil.sendMessage(plr, "/plot condense " + area.worldname + " <start|stop|info> [radius]");
return false;
}
public Set<PlotId> getPlots(final Collection<Plot> plots, final int radius) {
final HashSet<PlotId> outside = new HashSet<>();
for (final Plot plot : plots) {
if ((plot.getId().x > radius) || (plot.getId().x < -radius) || (plot.getId().y > radius) || (plot.getId().y < -radius)) {
outside.add(plot.getId());
}
}
return outside;
}
}

View File

@ -0,0 +1,49 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.CmdInstance;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.CmdConfirm;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "confirm", permission = "plots.use", description = "Confirm an action", category = CommandCategory.INFO)
public class Confirm extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
final CmdInstance command = CmdConfirm.getPending(plr);
if (command == null) {
MainUtil.sendMessage(plr, C.FAILED_CONFIRM);
return false;
}
CmdConfirm.removePending(plr);
if ((System.currentTimeMillis() - command.timestamp) > 20000) {
MainUtil.sendMessage(plr, C.FAILED_CONFIRM);
return false;
}
TaskManager.runTask(command.command);
return true;
}
}

View File

@ -0,0 +1,68 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "continue",
description = "Continue a plot that was previously marked as done",
permission = "plots.continue",
category = CommandCategory.SETTINGS,
requiredType = RequiredType.NONE)
public class Continue extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if ((plot == null) || !plot.hasOwner()) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.continue")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (!plot.getFlags().containsKey("done")) {
MainUtil.sendMessage(plr, C.DONE_NOT_DONE);
return false;
}
if (Settings.DONE_COUNTS_TOWARDS_LIMIT && (plr.getAllowedPlots() >= plr.getPlotCount())) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.admin.command.continue");
return false;
}
if (plot.getRunning() > 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
FlagManager.removePlotFlag(plot, "done");
MainUtil.sendMessage(plr, C.DONE_REMOVED);
return true;
}
}

View File

@ -0,0 +1,81 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "copy",
permission = "plots.copy",
aliases = { "copypaste" },
category = CommandCategory.CLAIMING,
description = "Copy a plot",
usage = "/plot copy <X;Z>",
requiredType = RequiredType.NONE)
public class Copy extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot1 = loc.getPlotAbs();
if (plot1 == null) {
return !MainUtil.sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot1.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, C.PERMISSION_ADMIN.s())) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (args.length != 1) {
C.COMMAND_SYNTAX.send(plr, getUsage());
return false;
}
final Plot plot2 = MainUtil.getPlotFromString(plr, args[0], true);
if ((plot2 == null)) {
return false;
}
if (plot1.equals(plot2)) {
MainUtil.sendMessage(plr, C.NOT_VALID_PLOT_ID);
C.COMMAND_SYNTAX.send(plr, getUsage());
return false;
}
if (!plot1.getArea().isCompatible(plot2.getArea())) {
C.PLOTWORLD_INCOMPATIBLE.send(plr);
return false;
}
if (plot1.copy(plot2, new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(plr, C.COPY_SUCCESS);
}
})) {
return true;
} else {
MainUtil.sendMessage(plr, C.REQUIRES_UNOWNED);
return false;
}
}
}

View File

@ -0,0 +1,56 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.generator.HybridPlotWorld;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "createroadschematic",
aliases = { "crs" },
category = CommandCategory.ADMINISTRATION,
requiredType = RequiredType.NONE,
permission = "plots.createroadschematic",
description = "Add a road schematic to your world using the roads around your current plot",
usage = "/plot createroadschematic")
public class CreateRoadSchematic extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer player, final String... args) {
final Location loc = player.getLocation();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
return sendMessage(player, C.NOT_IN_PLOT);
}
if (!(loc.getPlotArea() instanceof HybridPlotWorld)) {
return sendMessage(player, C.NOT_IN_PLOT_WORLD);
}
HybridUtils.manager.setupRoadSchematic(plot);
MainUtil.sendMessage(player, "&6Saved new road schematic. To test the road, fly to a few other plots and use /plot debugroadregen");
return true;
}
}

View File

@ -0,0 +1,172 @@
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.database.MySQL;
import com.intellectualcrafters.plot.database.SQLManager;
import com.intellectualcrafters.plot.database.SQLite;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.general.commands.CommandDeclaration;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry;
@CommandDeclaration(
command = "database",
aliases = { "convert" },
category = CommandCategory.ADMINISTRATION,
permission = "plots.database",
description = "Convert/Backup Storage",
requiredType = RequiredType.CONSOLE,
usage = "/plots database [area] <sqlite|mysql|import>"
)
public class Database extends SubCommand {
public static void insertPlots(final SQLManager manager, final ArrayList<Plot> plots, final PlotPlayer player) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
try {
final ArrayList<Plot> ps = new ArrayList<>();
for (final Plot p : plots) {
ps.add(p);
}
MainUtil.sendMessage(player, "&6Starting...");
manager.createPlotsAndData(ps, new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(player, "&6Database conversion finished!");
manager.close();
}
});
} catch (final Exception e) {
MainUtil.sendMessage(player, "Failed to insert plot objects, see stacktrace for info");
e.printStackTrace();
}
}
});
}
@Override
public boolean onCommand(final PlotPlayer player, String[] args) {
if (args.length < 1) {
MainUtil.sendMessage(player, "/plot database [area] <sqlite|mysql|import>");
return false;
}
ArrayList<Plot> plots;
PlotArea area = PS.get().getPlotAreaByString(args[0]);
if (area != null) {
plots = PS.get().sortPlotsByTemp(area.getPlots());
args = Arrays.copyOfRange(args, 1, args.length);
} else {
plots = PS.get().sortPlotsByTemp(PS.get().getPlots());
}
if (args.length < 1) {
MainUtil.sendMessage(player, "/plot database [world] <sqlite|mysql|import>");
MainUtil.sendMessage(player, "[arg] indicates an optional argument");
return false;
}
try {
com.intellectualcrafters.plot.database.Database implementation;
String prefix = "";
switch (args[0].toLowerCase()) {
case "import": {
if (args.length < 2) {
MainUtil.sendMessage(player, "/plot database import [sqlite file] [prefix]");
return false;
}
File file = new File(PS.get().IMP.getDirectory() + File.separator + args[1] + ".db");
if (!file.exists()) {
MainUtil.sendMessage(player, "&6Database does not exist: " + file);
return false;
}
MainUtil.sendMessage(player, "&6Starting...");
implementation = new SQLite(file.getPath());
final SQLManager manager = new SQLManager(implementation, (args.length == 3) ? args[2] : "", true);
final HashMap<String, HashMap<PlotId, Plot>> map = manager.getPlots();
plots = new ArrayList<>();
for (final Entry<String, HashMap<PlotId, Plot>> entry : map.entrySet()) {
String areaname = entry.getKey();
PlotArea pa = PS.get().getPlotAreaByString(areaname);
if (pa != null) {
for (final Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
final Plot plot = entry2.getValue();
if (pa.getOwnedPlotAbs(plot.getId()) != null) {
MainUtil.sendMessage(player, "Skipping duplicate plot: " + plot + " | id=" + plot.temp);
continue;
}
PS.get().updatePlot(plot);
plots.add(entry2.getValue());
}
} else {
HashMap<PlotId, Plot> plotmap = PS.get().plots_tmp.get(areaname);
if (plotmap == null) {
plotmap = new HashMap<>();
PS.get().plots_tmp.put(areaname, plotmap);
}
plotmap.putAll(entry.getValue());
}
}
DBFunc.createPlotsAndData(plots, new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(player, "&6Database conversion finished!");
}
});
return true;
}
case "mysql":
if (args.length < 6) {
return MainUtil.sendMessage(player, "/plot database mysql [host] [port] [username] [password] [database] {prefix}");
}
final String host = args[1];
final String port = args[2];
final String username = args[3];
final String password = args[4];
final String database = args[5];
if (args.length > 6) {
prefix = args[6];
}
implementation = new MySQL(host, port, database, username, password);
break;
case "sqlite":
if (args.length < 2) {
return MainUtil.sendMessage(player, "/plot database sqlite [file]");
}
implementation = new SQLite(PS.get().IMP.getDirectory() + File.separator + args[1] + ".db");
break;
default:
return MainUtil.sendMessage(player, "/plot database [sqlite/mysql]");
}
try {
final SQLManager manager = new SQLManager(implementation, prefix, true);
insertPlots(manager, plots, player);
return true;
} catch (ClassNotFoundException | SQLException e) {
MainUtil.sendMessage(player, "$1Failed to save plots, read stacktrace for info");
MainUtil.sendMessage(player, "&d==== Here is an ugly stacktrace, if you are interested in those things ===");
e.printStackTrace();
MainUtil.sendMessage(player, "&d==== End of stacktrace ====");
MainUtil.sendMessage(player, "$1Please make sure you are using the correct arguments!");
return false;
}
} catch (ClassNotFoundException | SQLException e) {
MainUtil.sendMessage(player, "$1Failed to open connection, read stacktrace for info");
MainUtil.sendMessage(player, "&d==== Here is an ugly stacktrace, if you are interested in those things ===");
e.printStackTrace();
MainUtil.sendMessage(player, "&d==== End of stacktrace ====");
MainUtil.sendMessage(player, "$1Please make sure you are using the correct arguments!");
return false;
}
}
}

View File

@ -0,0 +1,81 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "debug", category = CommandCategory.DEBUG, description = "Show debug information", usage = "/plot debug [msg]", permission = "plots.admin")
public class Debug extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
if ((args.length > 0) && args[0].equalsIgnoreCase("msg")) {
final StringBuilder msg = new StringBuilder();
for (final C c : C.values()) {
msg.append(c.s()).append("\n");
}
MainUtil.sendMessage(plr, msg.toString());
return true;
}
StringBuilder information;
String header, line, section;
{
information = new StringBuilder();
header = C.DEBUG_HEADER.s();
line = C.DEBUG_LINE.s();
section = C.DEBUG_SECTION.s();
}
{
final StringBuilder worlds = new StringBuilder("");
PS.get().foreachPlotArea(new RunnableVal<PlotArea>() {
@Override
public void run(PlotArea value) {
worlds.append(value.toString()).append(" ");
}
});
information.append(header);
information.append(getSection(section, "PlotArea"));
information.append(getLine(line, "Plot Worlds", worlds));
information.append(getLine(line, "Owned Plots", PS.get().getPlots().size()));
information.append(getSection(section, "Messages"));
information.append(getLine(line, "Total Messages", C.values().length));
information.append(getLine(line, "View all captions", "/plot debug msg"));
}
{
MainUtil.sendMessage(plr, information.toString());
}
return true;
}
private String getSection(final String line, final String val) {
return line.replaceAll("%val%", val) + "\n";
}
private String getLine(final String line, final String var, final Object val) {
return line.replaceAll("%var%", var).replaceAll("%val%", "" + val) + "\n";
}
}

View File

@ -0,0 +1,35 @@
package com.intellectualcrafters.plot.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "debugallowunsafe",
description = "Allow unsafe actions until toggled off",
usage = "/plot debugallowunsafe",
category = CommandCategory.DEBUG,
requiredType = RequiredType.NONE,
permission = "plots.debugallowunsafe")
public class DebugAllowUnsafe extends SubCommand {
public static final List<UUID> unsafeAllowed = new ArrayList<>();
@Override
public boolean onCommand(final PlotPlayer plr, final String... args) {
if (unsafeAllowed.contains(plr.getUUID())) {
unsafeAllowed.remove(plr.getUUID());
sendMessage(plr, C.DEBUGALLOWUNSAFE_OFF);
} else {
unsafeAllowed.add(plr.getUUID());
sendMessage(plr, C.DEBUGALLOWUNSAFE_ON);
}
return true;
}
}

View File

@ -0,0 +1,155 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.google.common.collect.BiMap;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.CommandDeclaration;
import java.util.ArrayList;
import java.util.Map;
import java.util.UUID;
@CommandDeclaration(
command = "debugclaimtest",
description = "If you accidentally delete your database, this command will attempt to restore all plots based on the data from plot signs. Execution time may vary",
category = CommandCategory.DEBUG,
requiredType = RequiredType.CONSOLE,
permission = "plots.debugclaimtest")
public class DebugClaimTest extends SubCommand {
public static boolean claimPlot(final PlotPlayer player, final Plot plot, final boolean teleport) {
return claimPlot(player, plot, teleport, "");
}
public static boolean claimPlot(final PlotPlayer player, final Plot plot, final boolean teleport, final String schematic) {
final boolean result = EventUtil.manager.callClaim(player, plot, false);
if (result) {
plot.create(player.getUUID(), true);
plot.setSign(player.getName());
MainUtil.sendMessage(player, C.CLAIMED);
if (teleport) {
plot.teleportPlayer(player);
}
}
return !result;
}
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
if (args.length < 3) {
return !MainUtil
.sendMessage(
null,
"If you accidentally delete your database, this command will attempt to restore all plots based on the data from the plot signs. \n\n&cMissing world arg /plot debugclaimtest {world} {PlotId min} {PlotId max}");
}
PlotArea area = PS.get().getPlotAreaByString(args[0]);
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
C.NOT_VALID_PLOT_WORLD.send(plr, args[0]);
return false;
}
PlotId min, max;
try {
args[1].split(";");
args[2].split(";");
min = PlotId.fromString(args[1]);
max = PlotId.fromString(args[2]);
} catch (final Exception e) {
return !MainUtil.sendMessage(plr,
"&cInvalid min/max values. &7The values are to Plot IDs in the format &cX;Y &7where X;Y are the plot coords\nThe conversion will only check the plots in the selected area.");
}
MainUtil.sendMessage(plr, "&3Sign Block&8->&3PlotSquared&8: &7Beginning sign to plot conversion. This may take a while...");
MainUtil.sendMessage(plr, "&3Sign Block&8->&3PlotSquared&8: Found an excess of 250,000 chunks. Limiting search radius... (~3.8 min)");
final PlotManager manager = area.getPlotManager();
final ArrayList<Plot> plots = new ArrayList<>();
for (final PlotId id : MainUtil.getPlotSelectionIds(min, max)) {
final Plot plot = area.getPlotAbs(id);
if (plot.hasOwner()) {
MainUtil.sendMessage(plr, " - &cDB Already contains: " + plot.getId());
continue;
}
final Location loc = manager.getSignLoc(area, plot);
final ChunkLoc chunk = new ChunkLoc(loc.getX() >> 4, loc.getZ() >> 4);
final boolean result = ChunkManager.manager.loadChunk(area.worldname, chunk, false);
if (!result) {
continue;
}
final String[] lines = WorldUtil.IMP.getSign(loc);
if (lines != null) {
String line = lines[2];
if (line != null && line.length() > 2) {
line = line.substring(2);
final BiMap<StringWrapper, UUID> map = UUIDHandler.getUuidMap();
UUID uuid = map.get(new StringWrapper(line));
if (uuid == null) {
for (final Map.Entry<StringWrapper, UUID> stringWrapperUUIDEntry : map.entrySet()) {
if (stringWrapperUUIDEntry.getKey().value.toLowerCase().startsWith(line.toLowerCase())) {
uuid = stringWrapperUUIDEntry.getValue();
break;
}
}
}
if (uuid == null) {
uuid = UUIDHandler.getUUID(line, null);
}
if (uuid != null) {
MainUtil.sendMessage(plr, " - &aFound plot: " + plot.getId() + " : " + line);
plot.owner = uuid;
plots.add(plot);
} else {
MainUtil.sendMessage(plr, " - &cInvalid playername: " + plot.getId() + " : " + line);
}
}
}
}
if (!plots.isEmpty()) {
MainUtil.sendMessage(plr, "&3Sign Block&8->&3PlotSquared&8: &7Updating '" + plots.size() + "' plots!");
DBFunc.createPlotsAndData(plots, new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(plr, "&6Database update finished!");
}
});
for (final Plot plot : plots) {
PS.get().updatePlot(plot);
}
MainUtil.sendMessage(plr, "&3Sign Block&8->&3PlotSquared&8: &7Complete!");
} else {
MainUtil.sendMessage(plr, "No plots were found for the given search.");
}
return true;
}
}

View File

@ -0,0 +1,448 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
import com.google.common.io.Files;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotAnalysis;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.AbstractTitle;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.ExpireManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "debugexec", permission = "plots.admin", description = "Mutli-purpose debug command", aliases = "exec",
category = CommandCategory.DEBUG)
public class DebugExec extends SubCommand {
private ScriptEngine engine;
private Bindings scope;
public DebugExec() {
try {
if (PS.get() != null) {
final File file = new File(PS.get().IMP.getDirectory(), "scripts" + File.separator + "start.js");
if (file.exists()) {
init();
final String script = StringMan.join(Files
.readLines(new File(new File(PS.get().IMP.getDirectory() + File.separator + "scripts"), "start.js"),
StandardCharsets.UTF_8),
System.getProperty("line.separator"));
scope.put("THIS", this);
scope.put("PlotPlayer", ConsolePlayer.getConsole());
engine.eval(script, scope);
}
}
} catch (IOException | ScriptException e) {}
}
public ScriptEngine getEngine() {
return engine;
}
public Bindings getScope() {
return scope;
}
public void init() {
if (engine != null) {
return;
}
engine = new ScriptEngineManager(null).getEngineByName("nashorn");
if (engine == null) {
engine = new ScriptEngineManager(null).getEngineByName("JavaScript");
}
final ScriptContext context = new SimpleScriptContext();
scope = context.getBindings(ScriptContext.ENGINE_SCOPE);
// stuff
scope.put("MainUtil", new MainUtil());
scope.put("Settings", new Settings());
scope.put("StringMan", new StringMan());
scope.put("MathMan", new MathMan());
scope.put("FlagManager", new FlagManager());
// Classes
scope.put("Location", Location.class);
scope.put("PlotBlock", PlotBlock.class);
scope.put("Plot", Plot.class);
scope.put("PlotId", PlotId.class);
scope.put("Runnable", Runnable.class);
scope.put("RunnableVal", RunnableVal.class);
// Instances
scope.put("PS", PS.get());
scope.put("TaskManager", PS.get().TASK);
scope.put("TitleManager", AbstractTitle.TITLE_CLASS);
scope.put("ConsolePlayer", ConsolePlayer.getConsole());
scope.put("SchematicHandler", SchematicHandler.manager);
scope.put("ChunkManager", ChunkManager.manager);
scope.put("BlockManager", WorldUtil.IMP);
scope.put("SetupUtils", SetupUtils.manager);
scope.put("EventUtil", EventUtil.manager);
scope.put("EconHandler", EconHandler.manager);
scope.put("UUIDHandler", UUIDHandler.implementation);
scope.put("DBFunc", DBFunc.dbManager);
scope.put("HybridUtils", HybridUtils.manager);
scope.put("IMP", PS.get().IMP);
scope.put("MainCommand", MainCommand.getInstance());
// enums
for (final Enum<?> value : C.values()) {
scope.put("C_" + value.name(), value);
}
}
@Override
public boolean onCommand(final PlotPlayer player, final String... args) {
final List<String> allowed_params = Arrays.asList("calibrate-analysis", "remove-flag", "stop-expire", "start-expire", "show-expired", "update-expired", "seen");
if (args.length > 0) {
final String arg = args[0].toLowerCase();
String script;
boolean async = false;
switch (arg) {
case "analyze": {
final Plot plot = player.getCurrentPlot();
if (plot == null) {
MainUtil.sendMessage(player, C.NOT_IN_PLOT);
return false;
}
final PlotAnalysis analysis = plot.getComplexity();
if (analysis != null) {
final int complexity = analysis.getComplexity();
MainUtil.sendMessage(player, "Changes/column: " + analysis.changes / 1.0);
MainUtil.sendMessage(player, "Complexity: " + complexity);
return true;
}
MainUtil.sendMessage(player, "$1Starting task...");
HybridUtils.manager.analyzePlot(plot, new RunnableVal<PlotAnalysis>() {
@Override
public void run(PlotAnalysis value) {
MainUtil.sendMessage(player, "$1Done: $2use $3/plot debugexec analyze$2 for more information");
}
});
return true;
}
case "calibrate-analysis":
if (args.length != 2) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot debugexec analyze <threshold>");
MainUtil.sendMessage(player, "$1<threshold> $2= $1The percentage of plots you want to clear (100 clears 100% of plots so no point calibrating it)");
return false;
}
double threshold;
try {
threshold = Integer.parseInt(args[1]) / 100d;
} catch (final NumberFormatException e) {
MainUtil.sendMessage(player, "$2Invalid threshold: " + args[1]);
MainUtil.sendMessage(player, "$1<threshold> $2= $1The percentage of plots you want to clear as a number between 0 - 100");
return false;
}
PlotAnalysis.calcOptimalModifiers(new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(player, "$1Thank you for calibrating PlotSquared plot expiry");
}
}, threshold);
return true;
case "stop-expire":
if (ExpireManager.task != -1) {
PS.get().TASK.cancelTask(ExpireManager.task);
} else {
return MainUtil.sendMessage(player, "Task already halted");
}
ExpireManager.task = -1;
return MainUtil.sendMessage(player, "Cancelled task.");
case "remove-flag":
if (args.length != 2) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot debugexec remove-flag <flag>");
return false;
}
final String flag = args[1];
for (final Plot plot : PS.get().getBasePlots()) {
if (FlagManager.getPlotFlagRaw(plot, flag) != null) {
FlagManager.removePlotFlag(plot, flag);
}
}
return MainUtil.sendMessage(player, "Cleared flag: " + flag);
case "start-rgar": {
if (args.length != 2) {
MainUtil.sendMessage(player, "&cInvalid syntax: /plot debugexec start-rgar <world>");
return false;
}
PlotArea area = PS.get().getPlotAreaByString(args[1]);
if (area == null) {
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD, args[1]);
return false;
}
boolean result;
if (HybridUtils.regions != null) {
result = HybridUtils.manager.scheduleRoadUpdate(area, HybridUtils.regions, 0);
} else {
result = HybridUtils.manager.scheduleRoadUpdate(area, 0);
}
if (!result) {
MainUtil.sendMessage(player, "&cCannot schedule mass schematic update! (Is one already in progress?)");
return false;
}
return true;
}
case "stop-rgar":
if (!HybridUtils.UPDATE) {
MainUtil.sendMessage(player, "&cTASK NOT RUNNING!");
return false;
}
HybridUtils.UPDATE = false;
MainUtil.sendMessage(player, "&cCancelling task... (please wait)");
return true;
case "start-expire":
if (ExpireManager.task == -1) {
ExpireManager.runTask();
} else {
return MainUtil.sendMessage(player, "Plot expiry task already started");
}
return MainUtil.sendMessage(player, "Started plot expiry task");
case "update-expired":
if (args.length > 1) {
PlotArea area = PS.get().getPlotAreaByString(args[1]);
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
C.NOT_VALID_PLOT_WORLD.send(player, args[1]);
return false;
}
MainUtil.sendMessage(player, "Updating expired plot list");
ExpireManager.updateExpired(area);
return true;
}
return MainUtil.sendMessage(player, "Use /plot debugexec update-expired <world>");
case "show-expired":
if (args.length > 1) {
final String world = args[1];
if (!WorldUtil.IMP.isWorld(world)) {
return MainUtil.sendMessage(player, "Invalid world: " + args[1]);
}
if (!ExpireManager.expiredPlots.containsKey(args[1])) {
return MainUtil.sendMessage(player, "No task for world: " + args[1]);
}
MainUtil.sendMessage(player, "Expired plots (" + ExpireManager.expiredPlots.get(args[1]).size() + "):");
for (final Plot plot : ExpireManager.expiredPlots.get(args[1])) {
MainUtil.sendMessage(player,
" - " + plot.getArea() + ";" + plot.getId().x + ";" + plot.getId().y + ";" + UUIDHandler.getName(plot.owner) + " : " + ExpireManager.dates.get(plot.owner));
}
return true;
}
return MainUtil.sendMessage(player, "Use /plot debugexec show-expired <world>");
case "seen":
if (args.length != 2) {
return MainUtil.sendMessage(player, "Use /plot debugexec seen <player>");
}
final UUID uuid = UUIDHandler.getUUID(args[1], null);
if (uuid == null) {
return MainUtil.sendMessage(player, "player not found: " + args[1]);
}
final OfflinePlotPlayer op = UUIDHandler.getUUIDWrapper().getOfflinePlayer(uuid);
if (op == null || op.getLastPlayed() == 0) {
return MainUtil.sendMessage(player, "player hasn't connected before: " + args[1]);
}
final Timestamp stamp = new Timestamp(op.getLastPlayed());
final Date date = new Date(stamp.getTime());
MainUtil.sendMessage(player, "PLAYER: " + args[1]);
MainUtil.sendMessage(player, "UUID: " + uuid);
MainUtil.sendMessage(player, "Object: " + date.toGMTString());
MainUtil.sendMessage(player, "GMT: " + date.toGMTString());
MainUtil.sendMessage(player, "Local: " + date.toLocaleString());
return true;
case "h":
case "he":
case "?":
case "help":
MainUtil.sendMessage(player, "Possible sub commands: /plot debugexec <" + StringMan.join(allowed_params, "|") + ">");
return false;
case "addcmd":
try {
final String cmd = StringMan.join(Files
.readLines(new File(new File(PS.get().IMP.getDirectory() + File.separator + "scripts"), args[1]),
StandardCharsets.UTF_8),
System.getProperty("line.separator"));
final Command<PlotPlayer> subcommand = new Command<PlotPlayer>(args[1].split("\\.")[0]) {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
try {
scope.put("PlotPlayer", plr);
scope.put("args", args);
engine.eval(cmd, scope);
return true;
} catch (final ScriptException e) {
e.printStackTrace();
MainUtil.sendMessage(player, C.COMMAND_WENT_WRONG);
return false;
}
}
};
MainCommand.getInstance().addCommand(subcommand);
return true;
} catch (IOException e) {
e.printStackTrace();
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot debugexec addcmd <file>");
return false;
}
case "runasync":
async = true;
case "run":
try {
script = StringMan.join(Files.readLines(new File(new File(PS.get().IMP.getDirectory() + File.separator + "scripts"), args[1]), StandardCharsets.UTF_8),
System.getProperty("line.separator"));
if (args.length > 2) {
final HashMap<String, String> replacements = new HashMap<>();
for (int i = 2; i < args.length; i++) {
replacements.put("%s" + (i - 2), args[i]);
}
script = StringMan.replaceFromMap(script, replacements);
}
} catch (final IOException e) {
e.printStackTrace();
return false;
}
break;
case "allcmd":
if (args.length < 3) {
C.COMMAND_SYNTAX.send(player, "/plot debugexec allcmd <condition> <command>");
return false;
}
long start = System.currentTimeMillis();
Command<PlotPlayer> cmd = MainCommand.getInstance().getCommand(args[3]);
String[] params = Arrays.copyOfRange(args, 4, args.length);
if ("true".equals(args[1])) {
Location loc = player.getMeta("location");
Plot plot = player.getMeta("lastplot");
for (Plot current : PS.get().getBasePlots()) {
player.setMeta("location", current.getBottomAbs());
player.setMeta("lastplot", current);
cmd.onCommand(player, params);
}
if (loc == null) {
player.deleteMeta("location");
} else {
player.setMeta("location", loc);
}
if (plot == null) {
player.deleteMeta("lastplot");
} else {
player.setMeta("lastplot", plot);
}
player.sendMessage("&c> " + (System.currentTimeMillis() - start));
return true;
}
init();
scope.put("_2", params);
scope.put("_3", cmd);
script = "_1=PS.getBasePlots().iterator();while(_1.hasNext()){plot=_1.next();if(" + args[1] + "){PlotPlayer.setMeta(\"location\",plot.getBottomAbs());PlotPlayer.setMeta(\"lastplot\",plot);_3.onCommand(PlotPlayer,_2)}}";
break;
case "all":
if (args.length < 3) {
C.COMMAND_SYNTAX.send(player, "/plot debugexec all <condition> <code>");
return false;
}
script = "_1=PS.getBasePlots().iterator();while(_1.hasNext()){plot=_1.next();if(" + args[1] + "){" + StringMan
.join(Arrays.copyOfRange(args, 2, args.length), " ")
+ "}}";
break;
default:
script = StringMan.join(args, " ");
}
if (!ConsolePlayer.isConsole(player)) {
MainUtil.sendMessage(player, C.NOT_CONSOLE);
return false;
}
init();
scope.put("PlotPlayer", player);
PS.debug("> " + script);
try {
if (async) {
final String toExec = script;
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
final long start = System.currentTimeMillis();
Object result = null;
try {
result = engine.eval(toExec, scope);
} catch (final ScriptException e) {
e.printStackTrace();
}
ConsolePlayer.getConsole().sendMessage("> " + (System.currentTimeMillis() - start) + "ms -> " + result);
}
});
} else {
final long start = System.currentTimeMillis();
Object result = engine.eval(script, scope);
ConsolePlayer.getConsole().sendMessage("> " + (System.currentTimeMillis() - start) + "ms -> " + result);
}
return true;
} catch (final ScriptException e) {
e.printStackTrace();
return false;
}
}
return false;
}
}

View File

@ -0,0 +1,78 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.Argument;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "debugfixflags",
usage = "/plot debugfixflags <world>",
permission = "plots.debugfixflags",
description = "Attempt to fix all flags for a world",
requiredType = RequiredType.CONSOLE,
category = CommandCategory.DEBUG)
public class DebugFixFlags extends SubCommand {
public DebugFixFlags() {
requiredArguments = new Argument[] { Argument.String };
}
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
PlotArea area = PS.get().getPlotAreaByString(args[0]);
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
MainUtil.sendMessage(plr, C.NOT_VALID_PLOT_WORLD, args[0]);
return false;
}
MainUtil.sendMessage(plr, "&8--- &6Starting task &8 ---");
for (final Plot plot : area.getPlots()) {
final HashMap<String, Flag> flags = plot.getFlags();
final Iterator<Entry<String, Flag>> i = flags.entrySet().iterator();
boolean changed = false;
while (i.hasNext()) {
if (FlagManager.getFlag(i.next().getKey()) == null) {
changed = true;
i.remove();
}
}
if (changed) {
DBFunc.setFlags(plot, plot.getFlags().values());
}
}
MainUtil.sendMessage(plr, "&aDone!");
return true;
}
}

View File

@ -0,0 +1,52 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.lang.reflect.Field;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "debugloadtest",
permission = "plots.debugloadtest",
description = "This debug command will force the reload of all plots in the DB",
usage = "/plot debugloadtest",
category = CommandCategory.DEBUG,
requiredType = RequiredType.CONSOLE)
public class DebugLoadTest extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
try {
final Field fPlots = PS.class.getDeclaredField("plots");
fPlots.setAccessible(true);
fPlots.set(null, DBFunc.getPlots());
} catch (final Exception e) {
PS.debug("&3===FAILED&3===");
e.printStackTrace();
PS.debug("&3===END OF STACKTRACE===");
}
return true;
}
}

View File

@ -0,0 +1,77 @@
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.HastebinUtility;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.CommandDeclaration;
import java.io.File;
import java.io.IOException;
@CommandDeclaration(
command = "debugpaste",
aliases = { "dp" },
usage = "/plot debugpaste",
description = "Upload settings.yml & latest.log to HasteBin",
permission = "plots.debugpaste",
category = CommandCategory.DEBUG)
public class DebugPaste extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
try {
final String settingsYML = HastebinUtility.upload(PS.get().configFile);
String latestLOG;
try {
latestLOG = HastebinUtility.upload(new File(PS.get().IMP.getDirectory(), "../../logs/latest.log"));
} catch (IOException e) {
MainUtil.sendMessage(plr, "&clatest.log is too big to be pasted, will ignore");
latestLOG = "too big :(";
}
final StringBuilder b = new StringBuilder();
b.append("# Welcome to this paste\n# It is meant to provide us at IntellectualSites with better information about your problem\n\n# We will start with some informational files\n");
b.append("links.settings_yml: '").append(settingsYML).append("'\n");
b.append("links.latest_log: '").append(latestLOG).append("'\n");
b.append("\n# YAAAS! Now let us move on to the server info\n");
b.append("version.server: '").append(PS.get().IMP.getServerVersion()).append("'\n");
b.append("online_mode: ").append(UUIDHandler.getUUIDWrapper() + ";" + !Settings.OFFLINE_MODE).append("\n");
b.append("plugins:");
for (String id : PS.get().IMP.getPluginIds()) {
String[] split = id.split(":");
String[] split2 = split[0].split(";");
String enabled = split.length == 2 ? split[1] : "unknown";
String name = split2[0];
String version = split2.length == 2 ? split2[1] : "unknown";
b.append("\n ").append(name).append(":\n ").append("version: '").append(version).append("'").append("\n enabled: ").append(enabled);
}
b.append("\n\n# YAY! Now, let's see what we can find in your JVM\n");
final Runtime runtime = Runtime.getRuntime();
b.append("memory.free: ").append(runtime.freeMemory()).append("\n");
b.append("memory.max: ").append(runtime.maxMemory()).append("\n");
b.append("java.specification.version: '").append(System.getProperty("java.specification.version")).append("'\n");
b.append("java.vendor: '").append(System.getProperty("java.vendor")).append("'\n");
b.append("java.version: '").append(System.getProperty("java.version")).append("'\n");
b.append("os.arch: '").append(System.getProperty("os.arch")).append("'\n");
b.append("os.name: '").append(System.getProperty("os.name")).append("'\n");
b.append("os.version: '").append(System.getProperty("os.version")).append("'\n\n");
b.append("# Okay :D Great. You are now ready to create your bug report!");
b.append("\n# You can do so at https://github.com/IntellectualSites/PlotSquared/issues");
final String link = HastebinUtility.upload(b.toString());
plr.sendMessage(C.DEBUG_REPORT_CREATED.s().replace("%url%", link));
} catch (final IOException e) {
e.printStackTrace();
}
}
});
return true;
}
}

View File

@ -0,0 +1,79 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.generator.HybridPlotManager;
import com.intellectualcrafters.plot.generator.HybridPlotWorld;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "debugroadregen",
usage = "/plot debugroadregen",
requiredType = RequiredType.NONE,
description = "Regenerate all roads based on the road schematic",
category = CommandCategory.DEBUG,
permission = "plots.debugroadregen")
public class DebugRoadRegen extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer player, final String... args) {
final Location loc = player.getLocation();
final PlotArea plotworld = loc.getPlotArea();
if (!(plotworld instanceof HybridPlotWorld)) {
return sendMessage(player, C.NOT_IN_PLOT_WORLD);
}
final Plot plot = player.getCurrentPlot();
if (plot == null) {
final ChunkLoc chunk = new ChunkLoc(loc.getX() >> 4, loc.getZ() >> 4);
int extend = 0;
if (args.length == 1) {
if (MathMan.isInteger(args[0])) {
try {
extend = Integer.parseInt(args[0]);
} catch (final Exception e) {
C.NOT_VALID_NUMBER.send(player, "(0, <EXTEND HEIGHT>)");
return false;
}
}
}
final boolean result = HybridUtils.manager.regenerateRoad(plotworld, chunk, extend);
MainUtil.sendMessage(player, "&6Regenerating chunk: " + chunk.x + "," + chunk.z + "\n&6 - Result: " + (result ? "&aSuccess" : "&cFailed"));
MainUtil.sendMessage(player, "&cTo regenerate all roads: /plot regenallroads");
} else {
final HybridPlotManager manager = (HybridPlotManager) plotworld.getPlotManager();
manager.createRoadEast(plotworld, plot);
manager.createRoadSouth(plotworld, plot);
manager.createRoadSouthEast(plotworld, plot);
MainUtil.sendMessage(player, "&6Regenerating plot south/east roads: " + plot.getId() + "\n&6 - Result: &aSuccess");
MainUtil.sendMessage(player, "&cTo regenerate all roads: /plot regenallroads");
}
return true;
}
}

View File

@ -0,0 +1,54 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.ArrayList;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "debugsavetest",
permission = "plots.debugsavetest",
category = CommandCategory.DEBUG,
requiredType = RequiredType.CONSOLE,
usage = "/plot debugsavetest",
description = "This command will force the recreation of all plots in the DB")
public class DebugSaveTest extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final ArrayList<Plot> plots = new ArrayList<Plot>();
plots.addAll(PS.get().getPlots());
MainUtil.sendMessage(plr, "&6Starting `DEBUGSAVETEST`");
DBFunc.createPlotsAndData(plots, new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(plr, "&6Database sync finished!");
}
});
return true;
}
}

View File

@ -0,0 +1,100 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.CmdConfirm;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.general.commands.CommandDeclaration;
import java.util.HashSet;
@CommandDeclaration(
command = "delete",
permission = "plots.delete",
description = "Delete a plot",
usage = "/plot delete",
aliases = { "dispose", "del" },
category = CommandCategory.CLAIMING,
requiredType = RequiredType.NONE)
public class Delete extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
return !sendMessage(plr, C.PLOT_UNOWNED);
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.delete")) {
return !sendMessage(plr, C.NO_PLOT_PERMS);
}
final PlotArea plotworld = plot.getArea();
final HashSet<Plot> plots = plot.getConnectedPlots();
final Runnable run = new Runnable() {
@Override
public void run() {
if (plot.getRunning() > 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return;
}
final long start = System.currentTimeMillis();
boolean result = plot.deletePlot(new Runnable() {
@Override
public void run() {
plot.removeRunning();
if ((EconHandler.manager != null) && plotworld.USE_ECONOMY) {
final double value = plotworld.SELL_PRICE * plots.size();
if (value > 0d) {
EconHandler.manager.depositMoney(plr, value);
sendMessage(plr, C.ADDED_BALANCE, value + "");
}
}
MainUtil.sendMessage(plr, C.CLEARING_DONE, "" + (System.currentTimeMillis() - start));
}
});
if (result) {
plot.addRunning();
} else {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
}
}
};
if (Settings.CONFIRM_DELETE && !(Permissions.hasPermission(plr, "plots.confirm.bypass"))) {
CmdConfirm.addPending(plr, "/plot delete " + plot.getId(), run);
} else {
TaskManager.runTask(run);
}
return true;
}
}

View File

@ -0,0 +1,108 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.UUID;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.Argument;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "deny", aliases = { "d", "ban" }, description = "Deny a user from a plot", usage = "/plot deny <player>", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE)
public class Deny extends SubCommand {
public Deny() {
requiredArguments = new Argument[] { Argument.PlayerName };
}
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
MainUtil.sendMessage(plr, C.PLOT_UNOWNED);
return false;
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.deny")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return true;
}
UUID uuid;
if (args[0].equalsIgnoreCase("*")) {
uuid = DBFunc.everyone;
} else {
uuid = UUIDHandler.getUUID(args[0], null);
}
if (uuid == null) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[0]);
return false;
}
if (plot.isOwner(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_OWNER);
return false;
}
if (plot.getDenied().contains(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_ADDED);
return false;
}
plot.removeMember(uuid);
plot.removeTrusted(uuid);
plot.addDenied(uuid);
EventUtil.manager.callDenied(plr, plot, uuid, true);
MainUtil.sendMessage(plr, C.DENIED_ADDED);
if (!uuid.equals(DBFunc.everyone)) {
handleKick(UUIDHandler.getPlayer(uuid), plot);
} else {
for (PlotPlayer pp : plot.getPlayersInPlot()) {
handleKick(pp, plot);
}
}
return true;
}
private void handleKick(final PlotPlayer pp, final Plot plot) {
if (pp == null) {
return;
}
if (!plot.equals(pp.getCurrentPlot())) {
return;
}
if (pp.hasPermission("plots.admin.entry.denied")) {
return;
}
pp.teleport(WorldUtil.IMP.getSpawn(pp.getLocation().getWorld()));
MainUtil.sendMessage(pp, C.YOU_GOT_DENIED);
}
}

View File

@ -0,0 +1,57 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "setdescription",
permission = "plots.set.desc",
description = "Set the plot description",
usage = "/plot desc <description>",
aliases = { "desc", "setdesc", "setd", "description" },
category = CommandCategory.SETTINGS,
requiredType = RequiredType.NONE)
public class Desc extends SetCommand {
@Override
public boolean set(PlotPlayer plr, Plot plot, String desc) {
if (desc.isEmpty()) {
plot.removeFlag("description");
MainUtil.sendMessage(plr, C.DESC_UNSET);
return true;
}
final Flag flag = new Flag(FlagManager.getFlag("description"), desc);
final boolean result = FlagManager.addPlotFlag(plot, flag);
if (!result) {
MainUtil.sendMessage(plr, C.FLAG_NOT_ADDED);
return false;
}
MainUtil.sendMessage(plr, C.DESC_SET);
return true;
}
}

View File

@ -0,0 +1,76 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotAnalysis;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "done", aliases = { "submit" }, description = "Mark a plot as done", permission = "plots.done", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE)
public class Done extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlotAbs();
if ((plot == null) || !plot.hasOwner()) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if ((!plot.isOwner(plr.getUUID())) && !Permissions.hasPermission(plr, "plots.admin.command.done")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (plot.getFlags().containsKey("done")) {
MainUtil.sendMessage(plr, C.DONE_ALREADY_DONE);
return false;
}
if (plot.getRunning() > 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
plot.addRunning();
MainUtil.sendMessage(plr, C.GENERATING_LINK);
HybridUtils.manager.analyzePlot(plot, new RunnableVal<PlotAnalysis>() {
@Override
public void run(PlotAnalysis value) {
plot.removeRunning();
if ((value == null) || (value.getComplexity() >= Settings.CLEAR_THRESHOLD)) {
final Flag flag = new Flag(FlagManager.getFlag("done"), (System.currentTimeMillis() / 1000));
FlagManager.addPlotFlag(plot, flag);
MainUtil.sendMessage(plr, C.DONE_SUCCESS);
} else {
MainUtil.sendMessage(plr, C.DONE_INSUFFICIENT_COMPLEXITY);
}
}
});
return true;
}
}

View File

@ -0,0 +1,71 @@
package com.intellectualcrafters.plot.commands;
import java.net.URL;
import com.intellectualcrafters.jnbt.CompoundTag;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "download", aliases = { "dl" }, category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE, description = "Download your plot", permission = "plots.download")
public class Download extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
if (!Settings.METRICS) {
MainUtil.sendMessage(plr, "&cPlease enable metrics in order to use this command.\n&7 - Or host it yourself if you don't like the free service");
return false;
}
final String world = plr.getLocation().getWorld();
if (!PS.get().hasPlotArea(world)) {
return !sendMessage(plr, C.NOT_IN_PLOT_WORLD);
}
final Plot plot = plr.getCurrentPlot();
if (plot == null) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
MainUtil.sendMessage(plr, C.PLOT_UNOWNED);
return false;
}
if ((!plot.isOwner(plr.getUUID()) || (Settings.DOWNLOAD_REQUIRES_DONE && (FlagManager.getPlotFlagRaw(plot, "done") != null))) && !Permissions.hasPermission(plr, "plots.admin.command.download")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (plot.getRunning() > 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
plot.addRunning();
MainUtil.sendMessage(plr, C.GENERATING_LINK);
SchematicHandler.manager.getCompoundTag(plot, new RunnableVal<CompoundTag>() {
@Override
public void run(final CompoundTag value) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
final URL url = SchematicHandler.manager.upload(value, null, null);
if (url == null) {
MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED);
plot.removeRunning();
return;
}
MainUtil.sendMessage(plr, url.toString());
plot.removeRunning();
}
});
}
});
return true;
}
}

View File

@ -0,0 +1,261 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.flag.AbstractFlag;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.flag.FlagValue;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.StringMan;
import com.plotsquared.general.commands.CommandDeclaration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@CommandDeclaration(
command = "setflag",
aliases = { "f", "flag", "setf", "setflag" },
usage = "/plot flag <set|remove|add|list|info> <flag> <value>",
description = "Set plot flags",
category = CommandCategory.SETTINGS,
requiredType = RequiredType.NONE,
permission = "plots.flag")
public class FlagCmd extends SubCommand {
@Override
public String getUsage() {
return super.getUsage().replaceAll("<flag>", StringMan.join(FlagManager.getFlags(), "|"));
}
@Override
public boolean onCommand(final PlotPlayer player, final String... args) {
/*
* plot flag set fly true
* plot flag remove fly
* plot flag remove use 1,3
* plot flag add use 2,4
* plot flag list
*/
if (args.length == 0) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag <set|remove|add|list|info>");
return false;
}
final Location loc = player.getLocation();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
MainUtil.sendMessage(player, C.NOT_IN_PLOT);
return false;
}
if (!plot.hasOwner()) {
sendMessage(player, C.PLOT_NOT_CLAIMED);
return false;
}
if (!plot.isOwner(player.getUUID()) && !Permissions.hasPermission(player, "plots.set.flag.other")) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.set.flag.other");
return false;
}
if (args.length > 1 && FlagManager.isReserved(args[1])) {
MainUtil.sendMessage(player, C.NOT_VALID_FLAG);
return false;
}
switch (args[0].toLowerCase()) {
case "info": {
if (!Permissions.hasPermission(player, "plots.set.flag")) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.flag.info");
return false;
}
if (args.length != 2) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag info <flag>");
return false;
}
final AbstractFlag af = FlagManager.getFlag(args[1]);
if (af == null) {
MainUtil.sendMessage(player, C.NOT_VALID_FLAG);
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag info <flag>");
return false;
}
// flag key
MainUtil.sendMessage(player, C.FLAG_KEY, af.getKey());
// flag type
MainUtil.sendMessage(player, C.FLAG_TYPE, af.value.getClass().getSimpleName());
// Flag type description
MainUtil.sendMessage(player, C.FLAG_DESC, af.getValueDesc());
return true;
}
case "set": {
if (!Permissions.hasPermission(player, "plots.set.flag")) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.set.flag");
return false;
}
if (args.length < 3) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag set <flag> <value>");
return false;
}
final AbstractFlag af = FlagManager.getFlag(args[1].toLowerCase());
if (af == null) {
MainUtil.sendMessage(player, C.NOT_VALID_FLAG);
return false;
}
final String value = StringMan.join(Arrays.copyOfRange(args, 2, args.length), " ");
if (!Permissions.hasPermission(player, "plots.set.flag." + args[1].toLowerCase() + "." + value.toLowerCase())) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.set.flag." + args[1].toLowerCase() + "." + value.toLowerCase());
return false;
}
final Object parsed = af.parseValueRaw(value);
if (parsed == null) {
MainUtil.sendMessage(player, "&c" + af.getValueDesc());
return false;
}
final Flag flag = new Flag(FlagManager.getFlag(args[1].toLowerCase(), true), parsed);
final boolean result = FlagManager.addPlotFlag(plot, flag);
if (!result) {
MainUtil.sendMessage(player, C.FLAG_NOT_ADDED);
return false;
}
MainUtil.sendMessage(player, C.FLAG_ADDED);
return true;
}
case "remove": {
if (!Permissions.hasPermission(player, "plots.flag.remove")) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.flag.remove");
return false;
}
if (args.length != 2 && args.length != 3) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag remove <flag> [values]");
return false;
}
final AbstractFlag af = FlagManager.getFlag(args[1].toLowerCase());
if (af == null) {
MainUtil.sendMessage(player, C.NOT_VALID_FLAG);
return false;
}
final Flag flag = FlagManager.getPlotFlagAbs(plot, args[1].toLowerCase());
if (!Permissions.hasPermission(player, "plots.set.flag." + args[1].toLowerCase())) {
if (args.length != 2) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.set.flag." + args[1].toLowerCase());
return false;
}
for (final String entry : args[2].split(",")) {
if (!Permissions.hasPermission(player, "plots.set.flag." + args[1].toLowerCase() + "." + entry)) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.set.flag." + args[1].toLowerCase() + "." + entry);
return false;
}
}
}
if (flag == null) {
MainUtil.sendMessage(player, C.FLAG_NOT_IN_PLOT);
return false;
}
if (args.length == 3 && flag.getAbstractFlag().isList()) {
final String value = StringMan.join(Arrays.copyOfRange(args, 2, args.length), " ");
((FlagValue.ListValue) flag.getAbstractFlag().value).remove(flag.getValue(), value);
DBFunc.setFlags(plot, plot.getFlags().values());
} else {
final boolean result = FlagManager.removePlotFlag(plot, flag.getKey());
if (!result) {
MainUtil.sendMessage(player, C.FLAG_NOT_REMOVED);
return false;
}
}
MainUtil.sendMessage(player, C.FLAG_REMOVED);
return true;
}
case "add": {
if (!Permissions.hasPermission(player, "plots.flag.add")) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.flag.add");
return false;
}
if (args.length < 3) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag add <flag> <values>");
return false;
}
final AbstractFlag af = FlagManager.getFlag(args[1].toLowerCase());
if (af == null) {
MainUtil.sendMessage(player, C.NOT_VALID_FLAG);
return false;
}
for (final String entry : args[2].split(",")) {
if (!Permissions.hasPermission(player, "plots.set.flag." + args[1].toLowerCase() + "." + entry)) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.set.flag." + args[1].toLowerCase() + "." + entry);
return false;
}
}
final String value = StringMan.join(Arrays.copyOfRange(args, 2, args.length), " ");
final Object parsed = af.parseValueRaw(value);
if (parsed == null) {
MainUtil.sendMessage(player, "&c" + af.getValueDesc());
return false;
}
Flag flag = FlagManager.getPlotFlag(plot, args[1].toLowerCase());
if (flag == null || !flag.getAbstractFlag().isList()) {
flag = new Flag(FlagManager.getFlag(args[1].toLowerCase(), true), parsed);
} else {
((FlagValue.ListValue) flag.getAbstractFlag().value).add(flag.getValue(), value);
}
final boolean result = FlagManager.addPlotFlag(plot, flag);
if (!result) {
MainUtil.sendMessage(player, C.FLAG_NOT_ADDED);
return false;
}
DBFunc.setFlags(plot, plot.getFlags().values());
MainUtil.sendMessage(player, C.FLAG_ADDED);
return true;
}
case "list":
if (!Permissions.hasPermission(player, "plots.flag.list")) {
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.flag.list");
return false;
}
if (args.length != 1) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag list");
return false;
}
final HashMap<String, ArrayList<String>> flags = new HashMap<>();
for (final AbstractFlag af : FlagManager.getFlags()) {
final String type = af.value.getClass().getSimpleName().replaceAll("Value", "");
if (!flags.containsKey(type)) {
flags.put(type, new ArrayList<String>());
}
flags.get(type).add(af.getKey());
}
String message = "";
String prefix = "";
for (final Map.Entry<String, ArrayList<String>> stringArrayListEntry : flags.entrySet()) {
message += prefix + "&6" + stringArrayListEntry.getKey() + ": &7" + StringMan.join(stringArrayListEntry.getValue(), ", ");
prefix = "\n";
}
MainUtil.sendMessage(player, message);
return true;
}
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag <set|remove|add|list|info>");
return false;
}
}

View File

@ -0,0 +1,221 @@
package com.intellectualcrafters.plot.commands;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.StringMan;
import com.plotsquared.general.commands.Command;
public class GenerateDocs {
public static void main(final String[] args) {
MainCommand.getInstance().addCommand(new WE_Anywhere());
MainCommand.getInstance().addCommand(new Cluster());
final ArrayList<Command<PlotPlayer>> commands = MainCommand.getInstance().getCommands();
log("### Want to document some commands?");
log(" - This page is automatically generated");
log(" - Fork the project and add a javadoc comment to one of the command classes");
log(" - Then do a pull request and it will be added to this page");
log("");
log("# Contents");
for (final CommandCategory category : CommandCategory.values()) {
log("###### " + category.name());
for (final Command<PlotPlayer> command : MainCommand.getCommands(category, null)) {
log(" - [/plot " + command.getCommand() + "](https://github.com/IntellectualSites/PlotSquared/wiki/Commands#" + command.getCommand() + ") ");
}
log("");
}
log("# Commands");
for (final Command<PlotPlayer> command : commands) {
printCommand(command);
}
}
public static void printCommand(final Command<PlotPlayer> command) {
try {
final String clazz = command.getClass().getSimpleName();
final String name = command.getCommand();
// Header
final String source = "https://github.com/IntellectualSites/PlotSquared/tree/master/src/main/java/com/intellectualcrafters/plot/commands/" + clazz + ".java";
log("## [" + name.toUpperCase() + "](" + source + ") ");
final File file = new File("src/main/java/com/intellectualcrafters/plot/commands/" + clazz + ".java");
final List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
final List<String> perms = getPerms(name, lines);
final List<String> usages = getUsage(name, lines);
final String comment = getComments(lines);
log("#### Description");
log("`" + command.getDescription() + "`");
if (!comment.isEmpty()) {
log("##### Comments");
log("``` java");
log(comment);
log("```");
}
log("#### Usage ");
{
String mainUsage = command.getUsage().replaceAll("\\{label\\}", "plot");
if (!usages.isEmpty() && !usages.get(0).equalsIgnoreCase(mainUsage)) {
log("##### Primary ");
log(" - `" + mainUsage + "` ");
log("");
log("##### Other ");
log(" - `" + StringMan.join(usages, "`\n - `") + "` ");
log("");
} else {
log("`" + mainUsage + "` ");
}
}
if (command.getRequiredType() != RequiredType.NONE) {
log("#### Required callers");
log("`" + command.getRequiredType().name() + "`");
}
final Set<String> aliases = command.getAliases();
if (!aliases.isEmpty()) {
log("#### Aliases");
log("`" + StringMan.getString(command.getAliases()) + "`");
}
log("#### Permissions");
if (!perms.isEmpty()) {
log("##### Primary");
log(" - `" + command.getPermission() + "` ");
log("");
log("##### Other");
log(" - `" + StringMan.join(perms, "`\n - `") + "`");
log("");
} else {
log("`" + command.getPermission() + "` ");
}
log("***");
log("");
} catch (final Exception e) {
e.printStackTrace();
}
}
public static List<String> getUsage(String cmd, List<String> lines) {
final Pattern p = Pattern.compile("\"([^\"]*)\"");
HashSet<String> usages = new HashSet<String>();
for (final String line : lines) {
if (line.contains("COMMAND_SYNTAX") && !line.contains("getUsage()")) {
final Matcher m = p.matcher(line);
String prefix = "";
StringBuilder usage = new StringBuilder();
while (m.find()) {
String match = m.group(1);
usage.append(prefix).append(match);
prefix = " <arg> ";
}
if (usage.length() != 0) {
usages.add(usage.toString().trim().replaceAll(" ", " ").replaceAll("\\{label\\}", "plot"));
}
}
}
return new ArrayList<>(usages);
}
public static List<String> getPerms(final String cmd, final List<String> lines) {
final HashSet<String> perms = new HashSet<String>();
final Pattern p = Pattern.compile("\"([^\"]*)\"");
final Pattern p2 = Pattern.compile("C.PERMISSION_\\s*(\\w+)");
String last = null;
for (final String line : lines) {
Matcher m2 = p2.matcher(line);
while (m2.find()) {
perms.add(C.valueOf("PERMISSION_" + m2.group(1)).s());
}
if (line.contains("Permissions.hasPermission(")) {
String[] split = line.split("Permissions.hasPermission");
split = Arrays.copyOfRange(split, 1, split.length);
for (String method : split) {
String perm = method.split("[,|)]")[1].trim();
if (!perm.toLowerCase().equals(perm)) {
if (perm.startsWith("C.")) {
perm = C.valueOf(perm.split("\\.")[1]).s();
}
else {
continue;
}
}
else {
perm = perm.substring(1, perm.length() - 1);
}
perms.add(perm);
}
final Matcher m = p.matcher(line);
while (m.find()) {
String perm = m.group(1);
if (perm.endsWith(".")) {
perm += "<arg>";
}
if (perm.startsWith(".")) {
perms.remove(last);
perms.add(last + perm);
} else if (perm.contains(".")) {
last = perm;
perms.add(perm);
}
}
}
else if (line.contains("Permissions.hasPermissionRange")) {
String[] split = line.split("Permissions.hasPermissionRange");
split = Arrays.copyOfRange(split, 1, split.length);
for (String method : split) {
String perm = method.split("[,|)]")[1].trim();
if (!perm.toLowerCase().equals(perm)) {
if (perm.startsWith("C.")) {
perm = C.valueOf(perm.split("\\.")[1]).s();
}
else {
continue;
}
}
else {
perm = perm.substring(1, perm.length() - 1);
}
perms.add(perm + ".<#>");
}
}
}
switch (cmd.toLowerCase()) {
case "auto":
case "claim": {
perms.add("plots.plot.<#>");
break;
}
}
return new ArrayList<>(perms);
}
public static String getComments(final List<String> lines) {
final StringBuilder result = new StringBuilder();
for (String line : lines) {
line = line.trim();
if (line.startsWith("/** ") || line.startsWith("*/ ") || line.startsWith("* ")) {
line = (line.replaceAll("/[*][*] ", "").replaceAll("[*]/ ", "").replaceAll("[*] ", "")).trim();
result.append(line + "\n");
}
}
return result.toString().trim();
}
public static void log(final String s) {
System.out.println(s);
}
}

View File

@ -0,0 +1,60 @@
package com.intellectualcrafters.plot.commands;
import java.util.UUID;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ByteArrayUtilities;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(
command = "grant",
category = CommandCategory.CLAIMING,
usage = "/plot grant <check|add> [player]",
permission = "plots.grant",
requiredType = RequiredType.NONE
)
public class Grant extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final String arg0 = args[0].toLowerCase();
switch (arg0) {
case "add":
case "check":
if (Permissions.hasPermission(plr, "plots.grant." + arg0)) {
C.NO_PERMISSION.send(plr, "plots.grant." + arg0);
return false;
}
if (args.length > 2) {
break;
}
final UUID uuid = args.length == 2 ? UUIDHandler.getUUIDFromString(args[1]) : plr.getUUID();
if (uuid == null) {
C.INVALID_PLAYER.send(plr, args[1]);
return false;
}
MainUtil.getPersistentMeta(uuid, "grantedPlots", new RunnableVal<byte[]>() {
@Override
public void run(byte[] array) {
if (arg0.equals("check")) { // check
int granted = array == null ? 0 : ByteArrayUtilities.bytesToInteger(array);
C.GRANTED_PLOTS.send(plr, granted);
} else { // add
int amount = 1 + (array == null ? 0 : ByteArrayUtilities.bytesToInteger(array));
boolean replace = array != null;
DBFunc.dbManager.addPersistentMeta(uuid, "grantedPlots", ByteArrayUtilities.integerToBytes(amount), replace);
}
}
});
return true;
}
C.COMMAND_SYNTAX.send(plr, getUsage());
return false;
}
}

View File

@ -0,0 +1,13 @@
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "help", description = "Get this help menu", aliases = { "he" }, category = CommandCategory.INFO)
public class Help extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
return true;
}
}

View File

@ -0,0 +1,34 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "home", aliases = { "h" }, description = "Go to your plot", usage = "/plot home [id|alias]",
category = CommandCategory.TELEPORT, requiredType = RequiredType.NONE)
public class Home extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, String[] args) {
return MainCommand.getInstance().getCommand("visit").onCommand(plr, args);
}
}

View File

@ -0,0 +1,215 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.comment.CommentInbox;
import com.intellectualcrafters.plot.object.comment.PlotComment;
import com.intellectualcrafters.plot.util.CommentManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.plotsquared.general.commands.CommandDeclaration;
import java.util.ArrayList;
import java.util.List;
@CommandDeclaration(
command = "inbox",
description = "Review the comments for a plot",
usage = "/plot inbox [inbox] [delete <index>|clear|page]",
permission = "plots.inbox",
category = CommandCategory.CHAT,
requiredType = RequiredType.NONE)
public class Inbox extends SubCommand {
public void displayComments(final PlotPlayer player, final List<PlotComment> oldComments, int page) {
if ((oldComments == null) || (oldComments.isEmpty())) {
MainUtil.sendMessage(player, C.INBOX_EMPTY);
return;
}
final PlotComment[] comments = oldComments.toArray(new PlotComment[oldComments.size()]);
if (page < 0) {
page = 0;
}
// Get the total pages
// int totalPages = ((int) Math.ceil(12 *
final int totalPages = (int) Math.ceil(comments.length / 12);
if (page > totalPages) {
page = totalPages;
}
// Only display 12 per page
int max = (page * 12) + 12;
if (max > comments.length) {
max = comments.length;
}
final StringBuilder string = new StringBuilder();
string.append(StringMan.replaceAll(C.COMMENT_LIST_HEADER_PAGED.s(), "%amount%", comments.length, "%cur", page + 1, "%max", totalPages + 1, "%word", "all") + "\n");
PlotComment c;
// This might work xD
for (int x = (page * 12); x < max; x++) {
c = comments[x];
String color;
if (player.getName().equals(c.senderName)) {
color = "&a";
} else {
color = "&7";
}
string.append("&8[&7#" + (x + 1) + "&8][&7" + c.world + ";" + c.id + "&8][&6" + c.senderName + "&8]" + color + c.comment + "\n");
}
MainUtil.sendMessage(player, string.toString());
}
@Override
public boolean onCommand(final PlotPlayer player, final String[] args) {
final Plot plot = player.getCurrentPlot();
if (args.length == 0) {
sendMessage(player, C.COMMAND_SYNTAX, "/plot inbox [inbox] [delete <index>|clear|page]");
for (final CommentInbox inbox : CommentManager.inboxes.values()) {
if (inbox.canRead(plot, player)) {
if (!inbox.getComments(plot, new RunnableVal<List<PlotComment>>() {
@Override
public void run(List<PlotComment> value) {
if (value != null) {
int total = 0;
int unread = 0;
for (final PlotComment comment : value) {
total++;
if (comment.timestamp > CommentManager.getTimestamp(player, inbox.toString())) {
unread++;
}
}
if (total != 0) {
String color;
if (unread > 0) {
color = "&c";
} else {
color = "";
}
sendMessage(player, C.INBOX_ITEM, color + inbox.toString() + " (" + total + "/" + unread + ")");
return;
}
}
sendMessage(player, C.INBOX_ITEM, inbox.toString());
}
})) {
sendMessage(player, C.INBOX_ITEM, inbox.toString());
}
}
}
return false;
}
final CommentInbox inbox = CommentManager.inboxes.get(args[0].toLowerCase());
if (inbox == null) {
sendMessage(player, C.INVALID_INBOX, StringMan.join(CommentManager.inboxes.keySet(), ", "));
return false;
}
player.setMeta("inbox:" + inbox.toString(), System.currentTimeMillis());
final int page;
if (args.length > 1) {
switch (args[1].toLowerCase()) {
case "delete": {
if (!inbox.canModify(plot, player)) {
sendMessage(player, C.NO_PERM_INBOX_MODIFY);
return false;
}
if (args.length != 3) {
sendMessage(player, C.COMMAND_SYNTAX, "/plot inbox " + inbox.toString() + " delete <index>");
}
final int index;
try {
index = Integer.parseInt(args[2]);
if (index < 1) {
sendMessage(player, C.NOT_VALID_INBOX_INDEX, index + "");
return false;
}
} catch (final NumberFormatException e) {
sendMessage(player, C.COMMAND_SYNTAX, "/plot inbox " + inbox.toString() + " delete <index>");
return false;
}
if (!inbox.getComments(plot, new RunnableVal<List<PlotComment>>() {
@Override
public void run(List<PlotComment> value) {
final List<PlotComment> comments = value;
if (index > comments.size()) {
sendMessage(player, C.NOT_VALID_INBOX_INDEX, index + "");
return;
}
final PlotComment comment = comments.get(index - 1);
inbox.removeComment(plot, comment);
plot.getSettings().removeComment(comment);
MainUtil.sendMessage(player, C.COMMENT_REMOVED, comment.comment);
}
})) {
sendMessage(player, C.NOT_IN_PLOT);
return false;
}
return true;
}
case "clear": {
if (!inbox.canModify(plot, player)) {
sendMessage(player, C.NO_PERM_INBOX_MODIFY);
}
inbox.clearInbox(plot);
final ArrayList<PlotComment> comments = plot.getSettings().getComments(inbox.toString());
if (comments != null) {
plot.getSettings().removeComments(comments);
}
MainUtil.sendMessage(player, C.COMMENT_REMOVED, "*");
return true;
}
default: {
try {
page = Integer.parseInt(args[1]);
} catch (final NumberFormatException e) {
sendMessage(player, C.COMMAND_SYNTAX, "/plot inbox [inbox] [delete <index>|clear|page]");
return false;
}
}
}
} else {
page = 1;
}
if (!inbox.canRead(plot, player)) {
sendMessage(player, C.NO_PERM_INBOX);
return false;
}
if (!inbox.getComments(plot, new RunnableVal<List<PlotComment>>() {
@Override
public void run(List<PlotComment> value) {
final List<PlotComment> comments = value;
displayComments(player, comments, page);
}
})) {
if (plot == null) {
sendMessage(player, C.NOT_IN_PLOT);
} else {
sendMessage(player, C.PLOT_UNOWNED);
}
return false;
}
return true;
}
}

View File

@ -0,0 +1,174 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import java.util.UUID;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotInventory;
import com.intellectualcrafters.plot.object.PlotItemStack;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "info", aliases = { "i" }, description = "Display plot info", usage = "/plot info <id>",
category = CommandCategory.INFO)
public class Info extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer player, String[] args) {
Plot plot;
String arg;
if (args.length > 0) {
arg = args[0];
switch (arg) {
case "trusted":
case "alias":
case "inv":
case "biome":
case "denied":
case "flags":
case "id":
case "size":
case "members":
case "owner":
case "rating":
plot = MainUtil.getPlotFromString(player, null, false);
break;
default:
plot = MainUtil.getPlotFromString(player, arg, false);
if (args.length == 2) {
arg = args[1];
} else {
arg = null;
}
break;
}
if (plot == null) {
plot = player.getCurrentPlot();
}
} else {
arg = null;
plot = player.getCurrentPlot();
}
if (plot == null) {
MainUtil.sendMessage(player, C.NOT_IN_PLOT);
return false;
}
if (arg != null) {
if (args.length == 1) {
args = new String[0];
} else {
args = new String[] { args[1] };
}
}
if ((args.length == 1) && args[0].equalsIgnoreCase("inv")) {
final PlotInventory inv = new PlotInventory(player) {
@Override
public boolean onClick(final int index) {
// TODO InfoInventory not implemented yet!!!!!!!!
// See plot rating or musicsubcommand on examples
return false;
}
};
final UUID uuid = player.getUUID();
final String name = MainUtil.getName(plot.owner);
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cPlot Info", "&cID: &6" + plot.getId().toString(),
"&cOwner: &6" + name,
"&cAlias: &6" + plot.getAlias(),
"&cBiome: &6" + plot.getBiome().replaceAll("_", "").toLowerCase(),
"&cCan Build: &6" + plot.isAdded(uuid),
"&cIs Denied: &6" + plot.isDenied(uuid)));
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cTrusted", "&cAmount: &6" + plot.getTrusted().size(),
"&8Click to view a list of the trusted users"));
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cMembers", "&cAmount: &6" + plot.getMembers().size(),
"&8Click to view a list of plot members"));
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cDenied", "&cDenied", "&cAmount: &6" + plot.getDenied().size(),
"&8Click to view a list of denied players"));
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cFlags", "&cFlags", "&cAmount: &6" + plot.getFlags().size(),
"&8Click to view a list of plot flags"));
inv.openInventory();
return true;
}
final boolean hasOwner = plot.hasOwner();
boolean containsEveryone;
boolean trustedEveryone;
// Wildcard player {added}
{
containsEveryone = (plot.getTrusted() != null) && plot.getTrusted().contains(DBFunc.everyone);
trustedEveryone = (plot.getMembers() != null) && plot.getMembers().contains(DBFunc.everyone);
}
// Unclaimed?
if (!hasOwner && !containsEveryone && !trustedEveryone) {
MainUtil.sendMessage(player, C.PLOT_INFO_UNCLAIMED, (plot.getId().x + ";" + plot.getId().y));
return true;
}
String info = C.PLOT_INFO.s();
boolean full;
if (arg != null) {
info = getCaption(arg);
if (info == null) {
MainUtil.sendMessage(player, "&6Categories&7: &amembers&7, &aalias&7, &abiome&7, &adenied&7, &aflags&7, &aid&7, &asize&7, &atrusted&7, &aowner&7, &arating");
return false;
}
full = true;
} else {
full = false;
}
MainUtil.format(info, plot, player, full, new RunnableVal<String>() {
@Override
public void run(String value) {
MainUtil.sendMessage(player, C.PLOT_INFO_HEADER.s() + '\n' + value + '\n' + C.PLOT_INFO_FOOTER.s(), false);
}
});
return true;
}
private String getCaption(final String string) {
switch (string) {
case "trusted":
return C.PLOT_INFO_TRUSTED.s();
case "alias":
return C.PLOT_INFO_ALIAS.s();
case "biome":
return C.PLOT_INFO_BIOME.s();
case "denied":
return C.PLOT_INFO_DENIED.s();
case "flags":
return C.PLOT_INFO_FLAGS.s();
case "id":
return C.PLOT_INFO_ID.s();
case "size":
return C.PLOT_INFO_SIZE.s();
case "members":
return C.PLOT_INFO_MEMBERS.s();
case "owner":
return C.PLOT_INFO_OWNER.s();
case "rating":
return C.PLOT_INFO_RATING.s();
default:
return null;
}
}
}

View File

@ -0,0 +1,68 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.general.commands.CommandDeclaration;
@CommandDeclaration(command = "kick", aliases = { "k" }, description = "Kick a player from your plot", permission = "plots.kick", category = CommandCategory.TELEPORT, requiredType = RequiredType.NONE)
public class Kick extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
final Plot plot = loc.getPlot();
if (plot == null) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (((!plot.hasOwner() || !plot.isOwner(plr.getUUID())) && !Permissions.hasPermission(plr, "plots.admin.command.kick"))) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (args.length != 1) {
MainUtil.sendMessage(plr, "&c/plot kick <player>");
return false;
}
final PlotPlayer player = UUIDHandler.getPlayer(args[0]);
if (player == null) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[0]);
return false;
}
final Location otherLoc = player.getLocation();
if (!plr.getLocation().getWorld().equals(otherLoc.getWorld()) || !plot.equals(otherLoc.getPlot())) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[0]);
return false;
}
if (player.hasPermission("plots.admin.entry.denied")) {
C.CANNOT_KICK_PLAYER.send(plr, player.getName());
return false;
}
player.teleport(WorldUtil.IMP.getSpawn(loc.getWorld()));
return true;
}
}

View File

@ -0,0 +1,198 @@
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SchematicHandler.Schematic;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.general.commands.CommandDeclaration;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
@CommandDeclaration(
command = "load",
aliases = { "restore" },
category = CommandCategory.SCHEMATIC,
requiredType = RequiredType.NONE,
description = "Load your plot",
permission = "plots.load",
usage = "/plot restore")
public class Load extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer plr, final String[] args) {
if (!Settings.METRICS) {
MainUtil.sendMessage(plr, "&cPlease enable metrics in order to use this command.\n&7 - Or host it yourself if you don't like the free service");
return false;
}
final String world = plr.getLocation().getWorld();
if (!PS.get().hasPlotArea(world)) {
return !sendMessage(plr, C.NOT_IN_PLOT_WORLD);
}
final Plot plot = plr.getCurrentPlot();
if (plot == null) {
return !sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
MainUtil.sendMessage(plr, C.PLOT_UNOWNED);
return false;
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.load")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return false;
}
if (plot.getRunning() > 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
if (args.length != 0) {
if (args.length == 1) {
final List<String> schematics = plr.getMeta("plot_schematics");
if (schematics == null) {
// No schematics found:
MainUtil.sendMessage(plr, C.LOAD_NULL);
return false;
}
String schem;
try {
schem = schematics.get(Integer.parseInt(args[0]) - 1);
} catch (final Exception e) {
// use /plot load <index>
MainUtil.sendMessage(plr, C.NOT_VALID_NUMBER, "(1, " + schematics.size() + ")");
return false;
}
final URL url;
try {
url = new URL(Settings.WEB_URL + "saves/" + plr.getUUID() + "/" + schem + ".schematic");
} catch (final MalformedURLException e) {
e.printStackTrace();
MainUtil.sendMessage(plr, C.LOAD_FAILED);
return false;
}
plot.addRunning();
MainUtil.sendMessage(plr, C.GENERATING_COMPONENT);
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
final Schematic schematic = SchematicHandler.manager.getSchematic(url);
if (schematic == null) {
plot.removeRunning();
sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent or not in gzip format");
return;
}
SchematicHandler.manager.paste(schematic, plot, 0, 0, new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
plot.removeRunning();
if (value) {
sendMessage(plr, C.SCHEMATIC_PASTE_SUCCESS);
} else {
sendMessage(plr, C.SCHEMATIC_PASTE_FAILED);
}
}
});
}
});
return true;
}
plot.removeRunning();
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot load <index>");
return false;
}
// list schematics
final List<String> schematics = plr.getMeta("plot_schematics");
if (schematics == null) {
plot.addRunning();
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
final List<String> schematics = SchematicHandler.manager.getSaves(plr.getUUID());
plot.removeRunning();
if ((schematics == null) || (schematics.isEmpty())) {
MainUtil.sendMessage(plr, C.LOAD_FAILED);
return;
}
plr.setMeta("plot_schematics", schematics);
displaySaves(plr, 0);
}
});
} else {
displaySaves(plr, 0);
}
return true;
}
public void displaySaves(final PlotPlayer player, final int page) {
final List<String> schematics = player.getMeta("plot_schematics");
for (int i = 0; i < Math.min(schematics.size(), 32); i++) {
try {
final String schem = schematics.get(i);
final String[] split = schem.split("_");
if (split.length != 6) {
continue;
}
final String time = secToTime((System.currentTimeMillis() / 1000) - (Long.parseLong(split[0])));
final String world = split[1];
final PlotId id = PlotId.fromString(split[2] + ";" + split[3]);
final String size = split[4];
final String server = split[5].replaceAll(".schematic", "");
String color;
if (PS.get().IMP.getServerName().replaceAll("[^A-Za-z0-9]", "").equals(server)) {
color = "$4";
} else {
color = "$1";
}
MainUtil.sendMessage(player, "$3[$2" + (i + 1) + "$3] " + color + time + "$3 | " + color + world + ";" + id + "$3 | " + color + size + "x" + size);
} catch (final Exception e) {
e.printStackTrace();
}
}
MainUtil.sendMessage(player, C.LOAD_LIST);
}
public String secToTime(long time) {
final StringBuilder toreturn = new StringBuilder();
if (time >= 33868800) {
int years = (int) (time / 33868800);
time -= years * 33868800;
toreturn.append(years + "y ");
}
if (time >= 604800) {
int weeks = (int) (time / 604800);
time -= weeks * 604800;
toreturn.append(weeks + "w ");
}
if (time >= 86400) {
int days = (int) (time / 86400);
time -= days * 86400;
toreturn.append(days + "d ");
}
if (time >= 3600) {
int hours = (int) (time / 3600);
time -= hours * 3600;
toreturn.append(hours + "h ");
}
if (time >= 60) {
int minutes = (int) (time / 60);
time -= minutes * 60;
toreturn.append(minutes + "m ");
}
if (toreturn.equals("") || (time > 0)) {
toreturn.append((time) + "s ");
}
return toreturn.toString().trim();
}
}

View File

@ -0,0 +1,468 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU 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 General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.StringComparison;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.helpmenu.HelpMenu;
import com.plotsquared.general.commands.Argument;
import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandHandlingOutput;
import com.plotsquared.general.commands.CommandManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
/**
* PlotSquared command class
*
*/
public class MainCommand extends CommandManager<PlotPlayer> {
private static MainCommand instance;
private HashMap<String, Command<PlotPlayer>> setCommands;
private MainCommand() {
super(null, new ArrayList<Command<PlotPlayer>>());
instance = this;
createCommand(new Buy());
createCommand(new Save());
createCommand(new Load());
createCommand(new Confirm());
createCommand(new Template());
createCommand(new Download());
createCommand(new Update());
createCommand(new Template());
createCommand(new Setup());
createCommand(new Area());
createCommand(new DebugSaveTest());
createCommand(new DebugLoadTest());
createCommand(new CreateRoadSchematic());
createCommand(new DebugAllowUnsafe());
createCommand(new RegenAllRoads());
createCommand(new Claim());
createCommand(new Auto());
createCommand(new Visit());
createCommand(new Home());
createCommand(new Set());
createCommand(new Toggle());
createCommand(new Clear());
createCommand(new Delete());
createCommand(new Trust());
createCommand(new Add());
createCommand(new Deny());
createCommand(new Untrust());
createCommand(new Remove());
createCommand(new Undeny());
createCommand(new Info());
createCommand(new list());
createCommand(new Help());
createCommand(new Debug());
createCommand(new SchematicCmd());
createCommand(new plugin());
createCommand(new Purge());
createCommand(new Reload());
createCommand(new Merge());
createCommand(new DebugPaste());
createCommand(new Unlink());
createCommand(new Kick());
createCommand(new Rate());
createCommand(new DebugClaimTest());
createCommand(new Inbox());
createCommand(new Comment());
createCommand(new Database());
createCommand(new Swap());
createCommand(new MusicSubcommand());
createCommand(new DebugRoadRegen());
createCommand(new Trust());
createCommand(new DebugExec());
createCommand(new FlagCmd());
createCommand(new Target());
createCommand(new DebugFixFlags());
createCommand(new Move());
createCommand(new Condense());
createCommand(new Condense());
createCommand(new Copy());
createCommand(new Chat());
createCommand(new Trim());
createCommand(new Done());
createCommand(new Continue());
createCommand(new BO3());
createCommand(new Middle());
createCommand(new Grant());
// set commands
createCommand(new Owner());
createCommand(new Desc());
createCommand(new Biome());
createCommand(new Alias());
createCommand(new SetHome());
if (Settings.ENABLE_CLUSTERS) {
MainCommand.getInstance().addCommand(new Cluster());
}
}
public static MainCommand getInstance() {
if (instance == null) {
instance = new MainCommand();
}
return instance;
}
public static boolean no_permission(final PlotPlayer player, final String permission) {
MainUtil.sendMessage(player, C.NO_PERMISSION, permission);
return false;
}
public static List<Command<PlotPlayer>> getCommandAndAliases(final CommandCategory category, final PlotPlayer player) {
final List<Command<PlotPlayer>> commands = new ArrayList<>();
for (final Command<PlotPlayer> command : getInstance().getCommands()) {
if ((category != null) && !command.getCategory().equals(category)) {
continue;
}
if ((player != null) && !Permissions.hasPermission(player, command.getPermission())) {
continue;
}
commands.add(command);
}
return commands;
}
public static List<Command<PlotPlayer>> getCommands(final CommandCategory category, final PlotPlayer player) {
final List<Command<PlotPlayer>> commands = new ArrayList<>();
for (final Command<PlotPlayer> command : new HashSet<>(getInstance().getCommands())) {
if ((category != null) && !command.getCategory().equals(category)) {
continue;
}
if ((player != null) && !Permissions.hasPermission(player, command.getPermission())) {
continue;
}
commands.add(command);
}
return commands;
}
public static void displayHelp(final PlotPlayer player, String cat, int page, final String label) {
CommandCategory catEnum = null;
if (cat != null) {
if (StringMan.isEqualIgnoreCase(cat, "all")) {
catEnum = null;
} else {
for (final CommandCategory c : CommandCategory.values()) {
if (StringMan.isEqualIgnoreCaseToAny(cat, c.name(), c.toString())) {
catEnum = c;
cat = c.name();
break;
}
}
if (catEnum == null) {
cat = null;
}
}
}
if ((cat == null) && (page == 0)) {
final StringBuilder builder = new StringBuilder();
builder.append(C.HELP_HEADER.s());
for (final CommandCategory c : CommandCategory.values()) {
builder.append("\n" + StringMan.replaceAll(C.HELP_INFO_ITEM.s(), "%category%", c.toString().toLowerCase(), "%category_desc%", c.toString()));
}
builder.append("\n").append(C.HELP_INFO_ITEM.s().replaceAll("%category%", "all").replaceAll("%category_desc%", "Display all commands"));
builder.append("\n" + C.HELP_FOOTER.s());
MainUtil.sendMessage(player, builder.toString(), false);
return;
}
page--;
new HelpMenu(player).setCategory(catEnum).getCommands().generateMaxPages().generatePage(page, label).render();
}
public static boolean onCommand(final PlotPlayer player, final String cmd, String... args) {
// Clear perm caching //
player.deleteMeta("perm");
////////////////////////
int help_index = -1;
String category = null;
Location loc = null;
Plot plot = null;
boolean tp = false;
switch (args.length) {
case 0: {
help_index = 0;
break;
}
case 1: {
if (MathMan.isInteger(args[0])) {
try {
help_index = Integer.parseInt(args[args.length - 1]);
} catch (final NumberFormatException e) {}
break;
}
}
default: {
switch (args[0].toLowerCase()) {
case "he":
case "help":
case "?": {
switch (args.length) {
case 1: {
help_index = 0;
break;
}
case 2: {
if (MathMan.isInteger(args[1])) {
category = null;
try {
help_index = Integer.parseInt(args[1]);
} catch (final NumberFormatException e) {
help_index = 1;
}
} else {
help_index = 1;
category = args[1];
}
break;
}
case 3: {
category = args[1];
if (MathMan.isInteger(args[2])) {
try {
help_index = Integer.parseInt(args[2]);
} catch (final NumberFormatException e) {
help_index = 1;
}
}
break;
}
default: {
C.COMMAND_SYNTAX.send(player, "/" + cmd + "? [#|<term>|category [#]]");
return true;
}
}
break;
}
default: {
if (args.length >= 2) {
PlotArea area = player.getApplicablePlotArea();
Plot newPlot = Plot.fromString(area, args[0]);
if (newPlot == null) {
break;
}
if (!ConsolePlayer.isConsole(player) && (!newPlot.getArea().equals(area) || newPlot.isDenied(player.getUUID())) && !Permissions.hasPermission(player, C.PERMISSION_ADMIN)) {
break;
}
// Save meta
loc = (Location) player.getMeta("location");
plot = (Plot) player.getMeta("lastplot");
tp = true;
// Set loc
player.setMeta("location", newPlot.getBottomAbs());
player.setMeta("lastplot", newPlot);
// Trim command
args = Arrays.copyOfRange(args, 1, args.length);
}
}
}
}
}
if (help_index != -1) {
displayHelp(player, category, help_index, cmd);
return true;
}
if (args[0].contains(":")) {
args[0] = args[0].replaceFirst(":", " ");
}
String fullCmd = StringMan.join(args, " ");
getInstance().handle(player, cmd + " " + fullCmd);
// Restore location
if (tp) {
if (loc == null) {
player.deleteMeta("location");
} else {
player.setMeta("location", loc);
}
if (plot == null) {
player.deleteMeta("lastplot");
} else {
player.setMeta("lastplot", plot);
}
}
return true;
}
public int getMatch(String[] args, Command<PlotPlayer> cmd) {
int count = 0;
String perm = cmd.getPermission();
HashSet<String> desc = new HashSet<String>();
for (String alias : cmd.getAliases()) {
if (alias.startsWith(args[0])) {
count += 5;
}
}
Collections.addAll(desc, cmd.getDescription().split(" "));
for (String arg : args) {
if (perm.startsWith(arg)) {
count++;
}
if (desc.contains(arg)) {
count++;
}
}
String[] usage = cmd.getUsage().split(" ");
for (int i = 0; i < Math.min(4 , usage.length); i++) {
int require;
if (usage[i].startsWith("<")) {
require = 1;
} else {
require = 0;
}
String[] split = usage[i].split("\\|| |\\>|\\<|\\[|\\]|\\{|\\}|\\_|\\/");
for (String aSplit : split) {
for (String arg : args) {
if (StringMan.isEqualIgnoreCase(arg, aSplit)) {
count += 5 - i + require;
}
}
}
}
count += StringMan.intersection(desc, args);
return count;
}
@Override
public int handle(final PlotPlayer plr, final String input) {
final String[] parts = input.split(" ");
String[] args;
String label;
if (parts.length == 1) {
label = null;
args = new String[0];
} else {
label = parts[1];
args = new String[parts.length - 2];
System.arraycopy(parts, 2, args, 0, args.length);
}
Command<PlotPlayer> cmd;
if (label != null) {
if (label.contains(":")) {
// Ref: c:v, this will push value to the last spot in the array
// ex. /p h:2 SomeUsername
// > /p h SomeUsername 2
String[] temp = label.split(":");
label = temp[0];
String[] tempArgs = new String[args.length + 1];
System.arraycopy(args, 0, tempArgs, 0, args.length);
tempArgs[tempArgs.length - 1] = temp[1];
args = tempArgs;
}
cmd = getInstance().commands.get(label.toLowerCase());
} else {
cmd = null;
}
if (cmd == null) {
MainUtil.sendMessage(plr, C.NOT_VALID_SUBCOMMAND);
{
final List<Command<PlotPlayer>> cmds = getCommands(null, plr);
if ((label == null) || (cmds.isEmpty())) {
MainUtil.sendMessage(plr, C.DID_YOU_MEAN, "/plot help");
} else {
final HashSet<String> setargs = new HashSet<>(args.length + 1);
for (final String arg : args) {
setargs.add(arg.toLowerCase());
}
setargs.add(label);
final String[] allargs = setargs.toArray(new String[setargs.size()]);
int best = 0;
for (final Command<PlotPlayer> current : cmds) {
int match = getMatch(allargs, current);
if (match > best) {
cmd = current;
}
}
if (cmd == null) {
cmd = new StringComparison<>(label, getCommandAndAliases(null, plr)).getMatchObject();
}
MainUtil.sendMessage(plr, C.DID_YOU_MEAN, cmd.getUsage().replaceAll("\\{label\\}", parts[0]));
}
}
return CommandHandlingOutput.NOT_FOUND;
}
if (!cmd.getRequiredType().allows(plr)) {
if (ConsolePlayer.isConsole(plr)) {
MainUtil.sendMessage(plr, C.IS_CONSOLE);
} else {
MainUtil.sendMessage(plr, C.NOT_CONSOLE);
}
return CommandHandlingOutput.CALLER_OF_WRONG_TYPE;
}
if (!Permissions.hasPermission(plr, cmd.getPermission())) {
MainUtil.sendMessage(plr, C.NO_PERMISSION, cmd.getPermission());
return CommandHandlingOutput.NOT_PERMITTED;
}
final Argument<?>[] requiredArguments = cmd.getRequiredArguments();
if ((requiredArguments != null) && (requiredArguments.length > 0)) {
boolean success = true;
if (args.length < requiredArguments.length) {
success = false;
} else {
for (int i = 0; i < requiredArguments.length; i++) {
if (requiredArguments[i].parse(args[i]) == null) {
success = false;
break;
}
}
}
if (!success) {
C.COMMAND_SYNTAX.send(plr, cmd.getUsage());
return CommandHandlingOutput.WRONG_USAGE;
}
}
try {
final boolean result = cmd.onCommand(plr, args);
if (!result) {
cmd.getUsage();
// Unecessary!
// if (usage != null && !usage.isEmpty()) {
// MainUtil.sendMessage(plr, usage);
// }
return CommandHandlingOutput.WRONG_USAGE;
}
} catch (final Throwable t) {
t.printStackTrace();
return CommandHandlingOutput.ERROR;
}
return CommandHandlingOutput.SUCCESS;
}
}

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