Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-03 01:50:07 +01:00
Update BukkitImplLoader
Dieser Commit ist enthalten in:
Ursprung
fd8cf1ebba
Commit
75a18b9d5b
@ -3,18 +3,18 @@
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
* This program is distributed in the hope that 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 Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.bukkit.adapter;
|
||||
@ -47,15 +47,14 @@ public class BukkitImplLoader {
|
||||
private static final String CLASS_SUFFIX = ".class";
|
||||
|
||||
private static final String LOAD_ERROR_MESSAGE =
|
||||
"\n**********************************************\n" +
|
||||
"** This WorldEdit version does not fully support your version of Bukkit.\n" +
|
||||
"**\n" +
|
||||
"** When working with blocks or undoing, chests will be empty, signs\n" +
|
||||
"** will be blank, and so on. There will be no support for entity\n" +
|
||||
"** and block property-related functions.\n" +
|
||||
"**\n" +
|
||||
"** Please see https://worldedit.enginehub.org/en/latest/faq/#bukkit-adapters\n" +
|
||||
"**********************************************\n";
|
||||
"\n**********************************************\n"
|
||||
+ "** This WorldEdit version does not fully support your version of Bukkit.\n"
|
||||
+ "**\n" + "** When working with blocks or undoing, chests will be empty, signs\n"
|
||||
+ "** will be blank, and so on. There will be no support for entity\n"
|
||||
+ "** and block property-related functions.\n"
|
||||
+ "**\n"
|
||||
+ "** Please see https://worldedit.enginehub.org/en/latest/faq/#bukkit-adapters\n"
|
||||
+ "**********************************************\n";
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
@ -97,7 +96,9 @@ public class BukkitImplLoader {
|
||||
|
||||
String className = jarEntry.getName().replaceAll("[/\\\\]+", ".");
|
||||
|
||||
if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory()) continue;
|
||||
if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int beginIndex = 0;
|
||||
int endIndex = className.length() - CLASS_SUFFIX.length();
|
||||
@ -155,32 +156,23 @@ public class BukkitImplLoader {
|
||||
*/
|
||||
public BukkitImplAdapter loadAdapter() throws AdapterLoadException {
|
||||
for (String className : adapterCandidates) {
|
||||
System.out.println("Candidate: " + className);
|
||||
try {
|
||||
Class<?> cls = Class.forName(className);
|
||||
if (cls.isSynthetic()){
|
||||
System.out.println(className + " is synthetic, continuing");
|
||||
if (cls.isSynthetic()) {
|
||||
continue;
|
||||
}else{
|
||||
System.out.println(className + " is not synthetic");
|
||||
}
|
||||
if (BukkitImplAdapter.class.isAssignableFrom(cls)) {
|
||||
System.out.println(className + " is assignable from BukkitImplAdapter, returning");
|
||||
return (BukkitImplAdapter) cls.newInstance();
|
||||
}else{
|
||||
System.out.println(className + " is NOT assignable from BukkitImplAdapter, returning");
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.warn("Failed to load the Bukkit adapter class '" + className +
|
||||
"' that is not supposed to be missing", e);
|
||||
log.warn("Failed to load the Bukkit adapter class '" + className
|
||||
+ "' that is not supposed to be missing", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
log.warn("Failed to load the Bukkit adapter class '" + className +
|
||||
"' that is not supposed to be raising this error", e);
|
||||
log.warn("Failed to load the Bukkit adapter class '" + className
|
||||
+ "' that is not supposed to be raising this error", e);
|
||||
} catch (Throwable e) {
|
||||
if (className.equals(customCandidate)) {
|
||||
log.warn("Failed to load the Bukkit adapter class '" + className + "'", e);
|
||||
}else{
|
||||
log.warn(className + " is not custom candidate.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,64 +1,64 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Byte_Array} tag.
|
||||
*/
|
||||
public final class ByteArrayTag extends Tag {
|
||||
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
private final byte[] value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ByteArrayTag(byte[] value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder hex = new StringBuilder();
|
||||
for (byte b : value) {
|
||||
String hexDigits = Integer.toHexString(b).toUpperCase(Locale.ROOT);
|
||||
if (hexDigits.length() == 1) {
|
||||
hex.append("0");
|
||||
}
|
||||
hex.append(hexDigits).append(" ");
|
||||
}
|
||||
return "TAG_Byte_Array(" + hex + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Byte_Array} tag.
|
||||
*/
|
||||
public final class ByteArrayTag extends Tag {
|
||||
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
private final byte[] value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ByteArrayTag(byte[] value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder hex = new StringBuilder();
|
||||
for (byte b : value) {
|
||||
String hexDigits = Integer.toHexString(b).toUpperCase(Locale.ROOT);
|
||||
if (hexDigits.length() == 1) {
|
||||
hex.append("0");
|
||||
}
|
||||
hex.append(hexDigits).append(" ");
|
||||
}
|
||||
return "TAG_Byte_Array(" + hex + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Byte} tag.
|
||||
*/
|
||||
public final class ByteTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_BYTE;
|
||||
}
|
||||
|
||||
private final byte value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ByteTag(byte value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Byte(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Byte} tag.
|
||||
*/
|
||||
public final class ByteTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_BYTE;
|
||||
}
|
||||
|
||||
private final byte value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ByteTag(byte value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Byte(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Double} tag.
|
||||
*/
|
||||
public final class DoubleTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public DoubleTag(double value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Double(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Double} tag.
|
||||
*/
|
||||
public final class DoubleTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public DoubleTag(double value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Double(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Float} tag.
|
||||
*/
|
||||
public final class FloatTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_FLOAT;
|
||||
}
|
||||
|
||||
private final float value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public FloatTag(float value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Float(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Float} tag.
|
||||
*/
|
||||
public final class FloatTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_FLOAT;
|
||||
}
|
||||
|
||||
private final float value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public FloatTag(float value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Float(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Int} tag.
|
||||
*/
|
||||
public final class IntTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_INT;
|
||||
}
|
||||
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public IntTag(int value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Int(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Int} tag.
|
||||
*/
|
||||
public final class IntTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_INT;
|
||||
}
|
||||
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public IntTag(int value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Int(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Long} tag.
|
||||
*/
|
||||
public final class LongTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_LONG;
|
||||
}
|
||||
|
||||
private final long value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public LongTag(long value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Long(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Long} tag.
|
||||
*/
|
||||
public final class LongTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_LONG;
|
||||
}
|
||||
|
||||
private final long value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public LongTag(long value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Long(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,93 +1,93 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.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;
|
||||
public static final int TYPE_BYTE = 1;
|
||||
public static final int TYPE_SHORT = 2;
|
||||
public static final int TYPE_INT = 3;
|
||||
public static final int TYPE_LONG = 4;
|
||||
public static final int TYPE_FLOAT = 5;
|
||||
public static final int TYPE_DOUBLE = 6;
|
||||
public static final int TYPE_BYTE_ARRAY = 7;
|
||||
public static final int TYPE_STRING = 8;
|
||||
public static final int TYPE_LIST = 9;
|
||||
public static final int TYPE_COMPOUND = 10;
|
||||
public static final int TYPE_INT_ARRAY = 11;
|
||||
public static final int TYPE_LONG_ARRAY = 12;
|
||||
|
||||
/**
|
||||
* Default private constructor.
|
||||
*/
|
||||
private NBTConstants() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a type ID to its corresponding {@link Tag} class.
|
||||
*
|
||||
* @param id type ID
|
||||
* @return tag class
|
||||
* @throws IllegalArgumentException thrown if the tag ID is not valid
|
||||
*/
|
||||
public static Class<? extends Tag> getClassFromType(int id) {
|
||||
switch (id) {
|
||||
case TYPE_END:
|
||||
return EndTag.class;
|
||||
case TYPE_BYTE:
|
||||
return ByteTag.class;
|
||||
case TYPE_SHORT:
|
||||
return ShortTag.class;
|
||||
case TYPE_INT:
|
||||
return IntTag.class;
|
||||
case TYPE_LONG:
|
||||
return LongTag.class;
|
||||
case TYPE_FLOAT:
|
||||
return FloatTag.class;
|
||||
case TYPE_DOUBLE:
|
||||
return DoubleTag.class;
|
||||
case TYPE_BYTE_ARRAY:
|
||||
return ByteArrayTag.class;
|
||||
case TYPE_STRING:
|
||||
return StringTag.class;
|
||||
case TYPE_LIST:
|
||||
return ListTag.class;
|
||||
case TYPE_COMPOUND:
|
||||
return CompoundTag.class;
|
||||
case TYPE_INT_ARRAY:
|
||||
return IntArrayTag.class;
|
||||
case TYPE_LONG_ARRAY:
|
||||
return LongArrayTag.class;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown tag type ID of " + id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
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;
|
||||
public static final int TYPE_BYTE = 1;
|
||||
public static final int TYPE_SHORT = 2;
|
||||
public static final int TYPE_INT = 3;
|
||||
public static final int TYPE_LONG = 4;
|
||||
public static final int TYPE_FLOAT = 5;
|
||||
public static final int TYPE_DOUBLE = 6;
|
||||
public static final int TYPE_BYTE_ARRAY = 7;
|
||||
public static final int TYPE_STRING = 8;
|
||||
public static final int TYPE_LIST = 9;
|
||||
public static final int TYPE_COMPOUND = 10;
|
||||
public static final int TYPE_INT_ARRAY = 11;
|
||||
public static final int TYPE_LONG_ARRAY = 12;
|
||||
|
||||
/**
|
||||
* Default private constructor.
|
||||
*/
|
||||
private NBTConstants() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a type ID to its corresponding {@link Tag} class.
|
||||
*
|
||||
* @param id type ID
|
||||
* @return tag class
|
||||
* @throws IllegalArgumentException thrown if the tag ID is not valid
|
||||
*/
|
||||
public static Class<? extends Tag> getClassFromType(int id) {
|
||||
switch (id) {
|
||||
case TYPE_END:
|
||||
return EndTag.class;
|
||||
case TYPE_BYTE:
|
||||
return ByteTag.class;
|
||||
case TYPE_SHORT:
|
||||
return ShortTag.class;
|
||||
case TYPE_INT:
|
||||
return IntTag.class;
|
||||
case TYPE_LONG:
|
||||
return LongTag.class;
|
||||
case TYPE_FLOAT:
|
||||
return FloatTag.class;
|
||||
case TYPE_DOUBLE:
|
||||
return DoubleTag.class;
|
||||
case TYPE_BYTE_ARRAY:
|
||||
return ByteArrayTag.class;
|
||||
case TYPE_STRING:
|
||||
return StringTag.class;
|
||||
case TYPE_LIST:
|
||||
return ListTag.class;
|
||||
case TYPE_COMPOUND:
|
||||
return CompoundTag.class;
|
||||
case TYPE_INT_ARRAY:
|
||||
return IntArrayTag.class;
|
||||
case TYPE_LONG_ARRAY:
|
||||
return LongArrayTag.class;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown tag type ID of " + id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -1,195 +1,195 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A class which contains NBT-related utility methods.
|
||||
*
|
||||
*/
|
||||
public final class NBTUtils {
|
||||
|
||||
/**
|
||||
* Default private constructor.
|
||||
*/
|
||||
private NBTUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type name of a tag.
|
||||
*
|
||||
* @param clazz the tag class
|
||||
* @return The type name.
|
||||
*/
|
||||
public static String getTypeName(Class<? extends Tag> clazz) {
|
||||
if (clazz.equals(ByteArrayTag.class)) {
|
||||
return "TAG_Byte_Array";
|
||||
} else if (clazz.equals(ByteTag.class)) {
|
||||
return "TAG_Byte";
|
||||
} else if (CompoundTag.class.isAssignableFrom(clazz)) {
|
||||
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 if (clazz.equals(LongArrayTag.class)) {
|
||||
return "TAG_Long_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(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 (CompoundTag.class.isAssignableFrom(clazz)) {
|
||||
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 if (clazz.equals(LongArrayTag.class)) {
|
||||
return NBTConstants.TYPE_LONG_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(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;
|
||||
case NBTConstants.TYPE_LONG_ARRAY:
|
||||
return LongArrayTag.class;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid tag type : " + type
|
||||
+ ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a vector from a list tag containing ideally three values: the
|
||||
* X, Y, and Z components.
|
||||
*
|
||||
* <p>For values that are unavailable, their values will be 0.</p>
|
||||
*
|
||||
* @param listTag the list tag
|
||||
* @return a vector
|
||||
*/
|
||||
public static Vector3 toVector(ListTag listTag) {
|
||||
checkNotNull(listTag);
|
||||
return Vector3.at(listTag.asDouble(0), listTag.asDouble(1), listTag.asDouble(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child tag of a NBT structure.
|
||||
*
|
||||
* @param items the map to read from
|
||||
* @param key the key to look for
|
||||
* @param expected the expected NBT class type
|
||||
* @return child tag
|
||||
* @throws InvalidFormatException if the format of the items is invalid
|
||||
*/
|
||||
public static <T extends Tag> T getChildTag(Map<String, Tag> items, String key, Class<T> expected) throws InvalidFormatException {
|
||||
if (!items.containsKey(key)) {
|
||||
throw new InvalidFormatException("Missing a \"" + key + "\" tag");
|
||||
}
|
||||
Tag tag = items.get(key);
|
||||
if (!expected.isInstance(tag)) {
|
||||
throw new InvalidFormatException(key + " tag is not of tag type " + expected.getName());
|
||||
}
|
||||
return expected.cast(tag);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A class which contains NBT-related utility methods.
|
||||
*
|
||||
*/
|
||||
public final class NBTUtils {
|
||||
|
||||
/**
|
||||
* Default private constructor.
|
||||
*/
|
||||
private NBTUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type name of a tag.
|
||||
*
|
||||
* @param clazz the tag class
|
||||
* @return The type name.
|
||||
*/
|
||||
public static String getTypeName(Class<? extends Tag> clazz) {
|
||||
if (clazz.equals(ByteArrayTag.class)) {
|
||||
return "TAG_Byte_Array";
|
||||
} else if (clazz.equals(ByteTag.class)) {
|
||||
return "TAG_Byte";
|
||||
} else if (CompoundTag.class.isAssignableFrom(clazz)) {
|
||||
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 if (clazz.equals(LongArrayTag.class)) {
|
||||
return "TAG_Long_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(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 (CompoundTag.class.isAssignableFrom(clazz)) {
|
||||
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 if (clazz.equals(LongArrayTag.class)) {
|
||||
return NBTConstants.TYPE_LONG_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(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;
|
||||
case NBTConstants.TYPE_LONG_ARRAY:
|
||||
return LongArrayTag.class;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid tag type : " + type
|
||||
+ ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a vector from a list tag containing ideally three values: the
|
||||
* X, Y, and Z components.
|
||||
*
|
||||
* <p>For values that are unavailable, their values will be 0.</p>
|
||||
*
|
||||
* @param listTag the list tag
|
||||
* @return a vector
|
||||
*/
|
||||
public static Vector3 toVector(ListTag listTag) {
|
||||
checkNotNull(listTag);
|
||||
return Vector3.at(listTag.asDouble(0), listTag.asDouble(1), listTag.asDouble(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child tag of a NBT structure.
|
||||
*
|
||||
* @param items the map to read from
|
||||
* @param key the key to look for
|
||||
* @param expected the expected NBT class type
|
||||
* @return child tag
|
||||
* @throws InvalidFormatException if the format of the items is invalid
|
||||
*/
|
||||
public static <T extends Tag> T getChildTag(Map<String, Tag> items, String key, Class<T> expected) throws InvalidFormatException {
|
||||
if (!items.containsKey(key)) {
|
||||
throw new InvalidFormatException("Missing a \"" + key + "\" tag");
|
||||
}
|
||||
Tag tag = items.get(key);
|
||||
if (!expected.isInstance(tag)) {
|
||||
throw new InvalidFormatException(key + " tag is not of tag type " + expected.getName());
|
||||
}
|
||||
return expected.cast(tag);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Short} tag.
|
||||
*/
|
||||
public final class ShortTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_SHORT;
|
||||
}
|
||||
|
||||
private final short value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ShortTag(short value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Short(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Short} tag.
|
||||
*/
|
||||
public final class ShortTag extends NumberTag {
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_SHORT;
|
||||
}
|
||||
|
||||
private final short value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ShortTag(short value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_Short(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,57 +1,57 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The {@code TAG_String} tag.
|
||||
*/
|
||||
public final class StringTag extends Tag {
|
||||
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_STRING;
|
||||
}
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public StringTag(String value) {
|
||||
super();
|
||||
checkNotNull(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_String(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The {@code TAG_String} tag.
|
||||
*/
|
||||
public final class StringTag extends Tag {
|
||||
|
||||
@Override
|
||||
public int getTypeCode() {
|
||||
return NBTConstants.TYPE_STRING;
|
||||
}
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public StringTag(String value) {
|
||||
super();
|
||||
checkNotNull(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_String(" + value + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,40 +1,40 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* Represents a NBT tag.
|
||||
*/
|
||||
public abstract class Tag {
|
||||
|
||||
/**
|
||||
* Gets the value of this tag.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public abstract Object getValue();
|
||||
|
||||
public Object toRaw() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
public abstract int getTypeCode();
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
/**
|
||||
* Represents a NBT tag.
|
||||
*/
|
||||
public abstract class Tag {
|
||||
|
||||
/**
|
||||
* Gets the value of this tag.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public abstract Object getValue();
|
||||
|
||||
public Object toRaw() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
public abstract int getTypeCode();
|
||||
|
||||
}
|
||||
|
@ -1,99 +1,99 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This annotation indicates a command. Methods should be marked with this
|
||||
* annotation to tell {@link CommandsManager} that the method is a command.
|
||||
* Note that the method name can actually be anything.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
|
||||
/**
|
||||
* A list of aliases for the command. The first alias is the most
|
||||
* important -- it is the main name of the command. (The method name
|
||||
* is never used for anything).
|
||||
*
|
||||
* @return Aliases for a command
|
||||
*/
|
||||
String[] aliases();
|
||||
|
||||
/**
|
||||
* Usage instruction. Example text for usage could be
|
||||
* {@code [-h harps] [name] [message]}.
|
||||
*
|
||||
* @return Usage instructions for a command
|
||||
*/
|
||||
String usage() default "";
|
||||
|
||||
/**
|
||||
* @return A short description for the command.
|
||||
*/
|
||||
String desc();
|
||||
|
||||
/**
|
||||
* The minimum number of arguments. This should be 0 or above.
|
||||
*
|
||||
* @return the minimum number of arguments
|
||||
*/
|
||||
int min() default 0;
|
||||
|
||||
/**
|
||||
* The maximum number of arguments. Use -1 for an unlimited number
|
||||
* of arguments.
|
||||
*
|
||||
* @return the maximum number of arguments
|
||||
*/
|
||||
int max() default -1;
|
||||
|
||||
/**
|
||||
* Flags allow special processing for flags such as -h in the command,
|
||||
* allowing users to easily turn on a flag. This is a string with
|
||||
* each character being a flag. Use A-Z and a-z as possible flags.
|
||||
* Appending a flag with a : makes the flag character before a value flag,
|
||||
* meaning that if it is given it must have a value
|
||||
*
|
||||
* @return Flags matching a-zA-Z
|
||||
*/
|
||||
String flags() default "";
|
||||
|
||||
/**
|
||||
* @return A long description for the command.
|
||||
*/
|
||||
String help() default "";
|
||||
|
||||
/**
|
||||
* Get whether any flag can be used.
|
||||
*
|
||||
* @return true if so
|
||||
*/
|
||||
boolean anyFlags() default false;
|
||||
|
||||
/**
|
||||
* Should the command be queued
|
||||
* @return true if so
|
||||
*/
|
||||
boolean queued() default true;
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This annotation indicates a command. Methods should be marked with this
|
||||
* annotation to tell {@link CommandsManager} that the method is a command.
|
||||
* Note that the method name can actually be anything.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
|
||||
/**
|
||||
* A list of aliases for the command. The first alias is the most
|
||||
* important -- it is the main name of the command. (The method name
|
||||
* is never used for anything).
|
||||
*
|
||||
* @return Aliases for a command
|
||||
*/
|
||||
String[] aliases();
|
||||
|
||||
/**
|
||||
* Usage instruction. Example text for usage could be
|
||||
* {@code [-h harps] [name] [message]}.
|
||||
*
|
||||
* @return Usage instructions for a command
|
||||
*/
|
||||
String usage() default "";
|
||||
|
||||
/**
|
||||
* @return A short description for the command.
|
||||
*/
|
||||
String desc();
|
||||
|
||||
/**
|
||||
* The minimum number of arguments. This should be 0 or above.
|
||||
*
|
||||
* @return the minimum number of arguments
|
||||
*/
|
||||
int min() default 0;
|
||||
|
||||
/**
|
||||
* The maximum number of arguments. Use -1 for an unlimited number
|
||||
* of arguments.
|
||||
*
|
||||
* @return the maximum number of arguments
|
||||
*/
|
||||
int max() default -1;
|
||||
|
||||
/**
|
||||
* Flags allow special processing for flags such as -h in the command,
|
||||
* allowing users to easily turn on a flag. This is a string with
|
||||
* each character being a flag. Use A-Z and a-z as possible flags.
|
||||
* Appending a flag with a : makes the flag character before a value flag,
|
||||
* meaning that if it is given it must have a value
|
||||
*
|
||||
* @return Flags matching a-zA-Z
|
||||
*/
|
||||
String flags() default "";
|
||||
|
||||
/**
|
||||
* @return A long description for the command.
|
||||
*/
|
||||
String help() default "";
|
||||
|
||||
/**
|
||||
* Get whether any flag can be used.
|
||||
*
|
||||
* @return true if so
|
||||
*/
|
||||
boolean anyFlags() default false;
|
||||
|
||||
/**
|
||||
* Should the command be queued
|
||||
* @return true if so
|
||||
*/
|
||||
boolean queued() default true;
|
||||
|
||||
}
|
||||
|
@ -1,362 +1,362 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandContext {
|
||||
|
||||
protected final String command;
|
||||
protected final List<String> parsedArgs;
|
||||
|
||||
protected final List<Integer> originalArgIndices;
|
||||
protected final String[] originalArgs;
|
||||
protected final Set<Character> booleanFlags = new HashSet<>();
|
||||
protected final Map<Character, String> valueFlags = new HashMap<>();
|
||||
protected final SuggestionContext suggestionContext;
|
||||
protected final CommandLocals locals;
|
||||
|
||||
public static String[] split(String args) {
|
||||
return args.split(" ", -1);
|
||||
}
|
||||
|
||||
public CommandContext(String args) throws CommandException {
|
||||
this(args.split(" ", -1), null);
|
||||
}
|
||||
|
||||
public CommandContext(String[] args) throws CommandException {
|
||||
this(args, null);
|
||||
}
|
||||
|
||||
public CommandContext(String args, Set<Character> valueFlags) throws CommandException {
|
||||
this(args.split(" ", -1), valueFlags);
|
||||
}
|
||||
|
||||
public CommandContext(String args, Set<Character> valueFlags, boolean allowHangingFlag)
|
||||
throws CommandException {
|
||||
this(args.split(" ", -1), valueFlags, allowHangingFlag, new CommandLocals());
|
||||
}
|
||||
|
||||
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
|
||||
this(args, valueFlags, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given array of arguments.
|
||||
*
|
||||
* <p>Empty arguments are removed from the list of arguments.</p>
|
||||
*
|
||||
* @param args an array with arguments
|
||||
* @param valueFlags a set containing all value flags (pass null to disable value flag parsing)
|
||||
* @param allowHangingFlag true if hanging flags are allowed
|
||||
* @param locals the locals, null to create empty one
|
||||
* @throws CommandException thrown on a parsing error
|
||||
*/
|
||||
public CommandContext(String[] args, Set<Character> valueFlags, boolean allowHangingFlag, CommandLocals locals) throws CommandException {
|
||||
this(args, valueFlags, allowHangingFlag, locals, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given array of arguments.
|
||||
*
|
||||
* <p>Empty arguments are removed from the list of arguments.</p>
|
||||
*
|
||||
* @param args an array with arguments
|
||||
* @param valueFlags a set containing all value flags (pass null to disable value flag parsing)
|
||||
* @param allowHangingFlag true if hanging flags are allowed
|
||||
* @param locals the locals, null to create empty one
|
||||
* @param parseFlags where to parse flags
|
||||
* @throws CommandException thrown on a parsing error
|
||||
*/
|
||||
public CommandContext(String[] args, Set<Character> valueFlags, boolean allowHangingFlag, CommandLocals locals, boolean parseFlags) throws CommandException {
|
||||
if (valueFlags == null) {
|
||||
valueFlags = Collections.emptySet();
|
||||
}
|
||||
|
||||
originalArgs = args;
|
||||
command = args[0];
|
||||
this.locals = locals != null ? locals : new CommandLocals();
|
||||
boolean isHanging = false;
|
||||
SuggestionContext suggestionContext = SuggestionContext.hangingValue();
|
||||
|
||||
// Eliminate empty args and combine multiword args first
|
||||
List<Integer> argIndexList = new ArrayList<>(args.length);
|
||||
List<String> argList = new ArrayList<>(args.length);
|
||||
for (int i = 1; i < args.length; ++i) {
|
||||
isHanging = false;
|
||||
|
||||
String arg = args[i];
|
||||
if (arg.isEmpty()) {
|
||||
isHanging = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
argIndexList.add(i);
|
||||
|
||||
switch (arg.charAt(0)) {
|
||||
case '\'':
|
||||
case '"':
|
||||
final StringBuilder build = new StringBuilder();
|
||||
final char quotedChar = arg.charAt(0);
|
||||
|
||||
int endIndex;
|
||||
for (endIndex = i; endIndex < args.length; ++endIndex) {
|
||||
final String arg2 = args[endIndex];
|
||||
if (arg2.charAt(arg2.length() - 1) == quotedChar && arg2.length() > 1) {
|
||||
if (endIndex != i) build.append(' ');
|
||||
build.append(arg2.substring(endIndex == i ? 1 : 0, arg2.length() - 1));
|
||||
break;
|
||||
} else if (endIndex == i) {
|
||||
build.append(arg2.substring(1));
|
||||
} else {
|
||||
build.append(' ').append(arg2);
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex < args.length) {
|
||||
arg = build.toString();
|
||||
i = endIndex;
|
||||
}
|
||||
|
||||
// In case there is an empty quoted string
|
||||
if (arg.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// else raise exception about hanging quotes?
|
||||
}
|
||||
argList.add(arg);
|
||||
}
|
||||
|
||||
// Then flags
|
||||
|
||||
this.originalArgIndices = new ArrayList<>(argIndexList.size());
|
||||
this.parsedArgs = new ArrayList<>(argList.size());
|
||||
|
||||
if (parseFlags) {
|
||||
for (int nextArg = 0; nextArg < argList.size(); ) {
|
||||
// Fetch argument
|
||||
String arg = argList.get(nextArg++);
|
||||
suggestionContext = SuggestionContext.hangingValue();
|
||||
|
||||
// Not a flag?
|
||||
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z\\?]+$")) {
|
||||
if (!isHanging) {
|
||||
suggestionContext = SuggestionContext.lastValue();
|
||||
}
|
||||
|
||||
originalArgIndices.add(argIndexList.get(nextArg - 1));
|
||||
parsedArgs.add(arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle flag parsing terminator --
|
||||
if (arg.equals("--")) {
|
||||
while (nextArg < argList.size()) {
|
||||
originalArgIndices.add(argIndexList.get(nextArg));
|
||||
parsedArgs.add(argList.get(nextArg++));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Go through the flag characters
|
||||
for (int i = 1; i < arg.length(); ++i) {
|
||||
char flagName = arg.charAt(i);
|
||||
|
||||
if (valueFlags.contains(flagName)) {
|
||||
if (this.valueFlags.containsKey(flagName)) {
|
||||
throw new CommandException("Value flag '" + flagName + "' already given");
|
||||
}
|
||||
|
||||
if (nextArg >= argList.size()) {
|
||||
if (allowHangingFlag) {
|
||||
suggestionContext = SuggestionContext.flag(flagName);
|
||||
break;
|
||||
} else {
|
||||
throw new CommandException("No value specified for the '-" + flagName + "' flag.");
|
||||
}
|
||||
}
|
||||
|
||||
// If it is a value flag, read another argument and add it
|
||||
this.valueFlags.put(flagName, argList.get(nextArg++));
|
||||
if (!isHanging) {
|
||||
suggestionContext = SuggestionContext.flag(flagName);
|
||||
}
|
||||
} else {
|
||||
booleanFlags.add(flagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < argList.size(); i++) {
|
||||
String arg = argList.get(i);
|
||||
originalArgIndices.add(argIndexList.get(i));
|
||||
parsedArgs.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
this.suggestionContext = suggestionContext;
|
||||
}
|
||||
|
||||
public SuggestionContext getSuggestionContext() {
|
||||
return suggestionContext;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public boolean matches(String command) {
|
||||
return this.command.equalsIgnoreCase(command);
|
||||
}
|
||||
|
||||
public String getString(int index) {
|
||||
return parsedArgs.get(index);
|
||||
}
|
||||
|
||||
public String getString(int index, String def) {
|
||||
return index < parsedArgs.size() ? parsedArgs.get(index) : def;
|
||||
}
|
||||
|
||||
public String getJoinedStrings(int initialIndex) {
|
||||
initialIndex = originalArgIndices.get(initialIndex);
|
||||
StringBuilder buffer = new StringBuilder(originalArgs[initialIndex]);
|
||||
for (int i = initialIndex + 1; i < originalArgs.length; ++i) {
|
||||
buffer.append(" ").append(originalArgs[i]);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String getRemainingString(int start) {
|
||||
return getString(start, parsedArgs.size() - 1);
|
||||
}
|
||||
|
||||
public String getString(int start, int end) {
|
||||
StringBuilder buffer = new StringBuilder(parsedArgs.get(start));
|
||||
for (int i = start + 1; i < end + 1; ++i) {
|
||||
buffer.append(" ").append(parsedArgs.get(i));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public int getInteger(int index) throws NumberFormatException {
|
||||
return Integer.parseInt(parsedArgs.get(index));
|
||||
}
|
||||
|
||||
public int getInteger(int index, int def) throws NumberFormatException {
|
||||
return index < parsedArgs.size() ? Integer.parseInt(parsedArgs.get(index)) : def;
|
||||
}
|
||||
|
||||
public double getDouble(int index) throws NumberFormatException {
|
||||
return Double.parseDouble(parsedArgs.get(index));
|
||||
}
|
||||
|
||||
public double getDouble(int index, double def) throws NumberFormatException {
|
||||
return index < parsedArgs.size() ? Double.parseDouble(parsedArgs.get(index)) : def;
|
||||
}
|
||||
|
||||
public String[] getSlice(int index) {
|
||||
String[] slice = new String[originalArgs.length - index];
|
||||
System.arraycopy(originalArgs, index, slice, 0, originalArgs.length - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getPaddedSlice(int index, int padding) {
|
||||
String[] slice = new String[originalArgs.length - index + padding];
|
||||
System.arraycopy(originalArgs, index, slice, padding, originalArgs.length - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getParsedSlice(int index) {
|
||||
String[] slice = new String[parsedArgs.size() - index];
|
||||
System.arraycopy(parsedArgs.toArray(new String[parsedArgs.size()]), index, slice, 0, parsedArgs.size() - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getParsedPaddedSlice(int index, int padding) {
|
||||
String[] slice = new String[parsedArgs.size() - index + padding];
|
||||
System.arraycopy(parsedArgs.toArray(new String[parsedArgs.size()]), index, slice, padding, parsedArgs.size() - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public boolean hasFlag(char ch) {
|
||||
return booleanFlags.contains(ch) || valueFlags.containsKey(ch);
|
||||
}
|
||||
|
||||
public Set<Character> getFlags() {
|
||||
return booleanFlags;
|
||||
}
|
||||
|
||||
public Map<Character, String> getValueFlags() {
|
||||
return valueFlags;
|
||||
}
|
||||
|
||||
public String getFlag(char ch) {
|
||||
return valueFlags.get(ch);
|
||||
}
|
||||
|
||||
public String getFlag(char ch, String def) {
|
||||
final String value = valueFlags.get(ch);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getFlagInteger(char ch) throws NumberFormatException {
|
||||
return Integer.parseInt(valueFlags.get(ch));
|
||||
}
|
||||
|
||||
public int getFlagInteger(char ch, int def) throws NumberFormatException {
|
||||
final String value = valueFlags.get(ch);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
public double getFlagDouble(char ch) throws NumberFormatException {
|
||||
return Double.parseDouble(valueFlags.get(ch));
|
||||
}
|
||||
|
||||
public double getFlagDouble(char ch, double def) throws NumberFormatException {
|
||||
final String value = valueFlags.get(ch);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
public int argsLength() {
|
||||
return parsedArgs.size();
|
||||
}
|
||||
|
||||
public CommandLocals getLocals() {
|
||||
return locals;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandContext {
|
||||
|
||||
protected final String command;
|
||||
protected final List<String> parsedArgs;
|
||||
|
||||
protected final List<Integer> originalArgIndices;
|
||||
protected final String[] originalArgs;
|
||||
protected final Set<Character> booleanFlags = new HashSet<>();
|
||||
protected final Map<Character, String> valueFlags = new HashMap<>();
|
||||
protected final SuggestionContext suggestionContext;
|
||||
protected final CommandLocals locals;
|
||||
|
||||
public static String[] split(String args) {
|
||||
return args.split(" ", -1);
|
||||
}
|
||||
|
||||
public CommandContext(String args) throws CommandException {
|
||||
this(args.split(" ", -1), null);
|
||||
}
|
||||
|
||||
public CommandContext(String[] args) throws CommandException {
|
||||
this(args, null);
|
||||
}
|
||||
|
||||
public CommandContext(String args, Set<Character> valueFlags) throws CommandException {
|
||||
this(args.split(" ", -1), valueFlags);
|
||||
}
|
||||
|
||||
public CommandContext(String args, Set<Character> valueFlags, boolean allowHangingFlag)
|
||||
throws CommandException {
|
||||
this(args.split(" ", -1), valueFlags, allowHangingFlag, new CommandLocals());
|
||||
}
|
||||
|
||||
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
|
||||
this(args, valueFlags, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given array of arguments.
|
||||
*
|
||||
* <p>Empty arguments are removed from the list of arguments.</p>
|
||||
*
|
||||
* @param args an array with arguments
|
||||
* @param valueFlags a set containing all value flags (pass null to disable value flag parsing)
|
||||
* @param allowHangingFlag true if hanging flags are allowed
|
||||
* @param locals the locals, null to create empty one
|
||||
* @throws CommandException thrown on a parsing error
|
||||
*/
|
||||
public CommandContext(String[] args, Set<Character> valueFlags, boolean allowHangingFlag, CommandLocals locals) throws CommandException {
|
||||
this(args, valueFlags, allowHangingFlag, locals, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given array of arguments.
|
||||
*
|
||||
* <p>Empty arguments are removed from the list of arguments.</p>
|
||||
*
|
||||
* @param args an array with arguments
|
||||
* @param valueFlags a set containing all value flags (pass null to disable value flag parsing)
|
||||
* @param allowHangingFlag true if hanging flags are allowed
|
||||
* @param locals the locals, null to create empty one
|
||||
* @param parseFlags where to parse flags
|
||||
* @throws CommandException thrown on a parsing error
|
||||
*/
|
||||
public CommandContext(String[] args, Set<Character> valueFlags, boolean allowHangingFlag, CommandLocals locals, boolean parseFlags) throws CommandException {
|
||||
if (valueFlags == null) {
|
||||
valueFlags = Collections.emptySet();
|
||||
}
|
||||
|
||||
originalArgs = args;
|
||||
command = args[0];
|
||||
this.locals = locals != null ? locals : new CommandLocals();
|
||||
boolean isHanging = false;
|
||||
SuggestionContext suggestionContext = SuggestionContext.hangingValue();
|
||||
|
||||
// Eliminate empty args and combine multiword args first
|
||||
List<Integer> argIndexList = new ArrayList<>(args.length);
|
||||
List<String> argList = new ArrayList<>(args.length);
|
||||
for (int i = 1; i < args.length; ++i) {
|
||||
isHanging = false;
|
||||
|
||||
String arg = args[i];
|
||||
if (arg.isEmpty()) {
|
||||
isHanging = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
argIndexList.add(i);
|
||||
|
||||
switch (arg.charAt(0)) {
|
||||
case '\'':
|
||||
case '"':
|
||||
final StringBuilder build = new StringBuilder();
|
||||
final char quotedChar = arg.charAt(0);
|
||||
|
||||
int endIndex;
|
||||
for (endIndex = i; endIndex < args.length; ++endIndex) {
|
||||
final String arg2 = args[endIndex];
|
||||
if (arg2.charAt(arg2.length() - 1) == quotedChar && arg2.length() > 1) {
|
||||
if (endIndex != i) build.append(' ');
|
||||
build.append(arg2.substring(endIndex == i ? 1 : 0, arg2.length() - 1));
|
||||
break;
|
||||
} else if (endIndex == i) {
|
||||
build.append(arg2.substring(1));
|
||||
} else {
|
||||
build.append(' ').append(arg2);
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex < args.length) {
|
||||
arg = build.toString();
|
||||
i = endIndex;
|
||||
}
|
||||
|
||||
// In case there is an empty quoted string
|
||||
if (arg.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// else raise exception about hanging quotes?
|
||||
}
|
||||
argList.add(arg);
|
||||
}
|
||||
|
||||
// Then flags
|
||||
|
||||
this.originalArgIndices = new ArrayList<>(argIndexList.size());
|
||||
this.parsedArgs = new ArrayList<>(argList.size());
|
||||
|
||||
if (parseFlags) {
|
||||
for (int nextArg = 0; nextArg < argList.size(); ) {
|
||||
// Fetch argument
|
||||
String arg = argList.get(nextArg++);
|
||||
suggestionContext = SuggestionContext.hangingValue();
|
||||
|
||||
// Not a flag?
|
||||
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z\\?]+$")) {
|
||||
if (!isHanging) {
|
||||
suggestionContext = SuggestionContext.lastValue();
|
||||
}
|
||||
|
||||
originalArgIndices.add(argIndexList.get(nextArg - 1));
|
||||
parsedArgs.add(arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle flag parsing terminator --
|
||||
if (arg.equals("--")) {
|
||||
while (nextArg < argList.size()) {
|
||||
originalArgIndices.add(argIndexList.get(nextArg));
|
||||
parsedArgs.add(argList.get(nextArg++));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Go through the flag characters
|
||||
for (int i = 1; i < arg.length(); ++i) {
|
||||
char flagName = arg.charAt(i);
|
||||
|
||||
if (valueFlags.contains(flagName)) {
|
||||
if (this.valueFlags.containsKey(flagName)) {
|
||||
throw new CommandException("Value flag '" + flagName + "' already given");
|
||||
}
|
||||
|
||||
if (nextArg >= argList.size()) {
|
||||
if (allowHangingFlag) {
|
||||
suggestionContext = SuggestionContext.flag(flagName);
|
||||
break;
|
||||
} else {
|
||||
throw new CommandException("No value specified for the '-" + flagName + "' flag.");
|
||||
}
|
||||
}
|
||||
|
||||
// If it is a value flag, read another argument and add it
|
||||
this.valueFlags.put(flagName, argList.get(nextArg++));
|
||||
if (!isHanging) {
|
||||
suggestionContext = SuggestionContext.flag(flagName);
|
||||
}
|
||||
} else {
|
||||
booleanFlags.add(flagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < argList.size(); i++) {
|
||||
String arg = argList.get(i);
|
||||
originalArgIndices.add(argIndexList.get(i));
|
||||
parsedArgs.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
this.suggestionContext = suggestionContext;
|
||||
}
|
||||
|
||||
public SuggestionContext getSuggestionContext() {
|
||||
return suggestionContext;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public boolean matches(String command) {
|
||||
return this.command.equalsIgnoreCase(command);
|
||||
}
|
||||
|
||||
public String getString(int index) {
|
||||
return parsedArgs.get(index);
|
||||
}
|
||||
|
||||
public String getString(int index, String def) {
|
||||
return index < parsedArgs.size() ? parsedArgs.get(index) : def;
|
||||
}
|
||||
|
||||
public String getJoinedStrings(int initialIndex) {
|
||||
initialIndex = originalArgIndices.get(initialIndex);
|
||||
StringBuilder buffer = new StringBuilder(originalArgs[initialIndex]);
|
||||
for (int i = initialIndex + 1; i < originalArgs.length; ++i) {
|
||||
buffer.append(" ").append(originalArgs[i]);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String getRemainingString(int start) {
|
||||
return getString(start, parsedArgs.size() - 1);
|
||||
}
|
||||
|
||||
public String getString(int start, int end) {
|
||||
StringBuilder buffer = new StringBuilder(parsedArgs.get(start));
|
||||
for (int i = start + 1; i < end + 1; ++i) {
|
||||
buffer.append(" ").append(parsedArgs.get(i));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public int getInteger(int index) throws NumberFormatException {
|
||||
return Integer.parseInt(parsedArgs.get(index));
|
||||
}
|
||||
|
||||
public int getInteger(int index, int def) throws NumberFormatException {
|
||||
return index < parsedArgs.size() ? Integer.parseInt(parsedArgs.get(index)) : def;
|
||||
}
|
||||
|
||||
public double getDouble(int index) throws NumberFormatException {
|
||||
return Double.parseDouble(parsedArgs.get(index));
|
||||
}
|
||||
|
||||
public double getDouble(int index, double def) throws NumberFormatException {
|
||||
return index < parsedArgs.size() ? Double.parseDouble(parsedArgs.get(index)) : def;
|
||||
}
|
||||
|
||||
public String[] getSlice(int index) {
|
||||
String[] slice = new String[originalArgs.length - index];
|
||||
System.arraycopy(originalArgs, index, slice, 0, originalArgs.length - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getPaddedSlice(int index, int padding) {
|
||||
String[] slice = new String[originalArgs.length - index + padding];
|
||||
System.arraycopy(originalArgs, index, slice, padding, originalArgs.length - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getParsedSlice(int index) {
|
||||
String[] slice = new String[parsedArgs.size() - index];
|
||||
System.arraycopy(parsedArgs.toArray(new String[parsedArgs.size()]), index, slice, 0, parsedArgs.size() - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getParsedPaddedSlice(int index, int padding) {
|
||||
String[] slice = new String[parsedArgs.size() - index + padding];
|
||||
System.arraycopy(parsedArgs.toArray(new String[parsedArgs.size()]), index, slice, padding, parsedArgs.size() - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public boolean hasFlag(char ch) {
|
||||
return booleanFlags.contains(ch) || valueFlags.containsKey(ch);
|
||||
}
|
||||
|
||||
public Set<Character> getFlags() {
|
||||
return booleanFlags;
|
||||
}
|
||||
|
||||
public Map<Character, String> getValueFlags() {
|
||||
return valueFlags;
|
||||
}
|
||||
|
||||
public String getFlag(char ch) {
|
||||
return valueFlags.get(ch);
|
||||
}
|
||||
|
||||
public String getFlag(char ch, String def) {
|
||||
final String value = valueFlags.get(ch);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getFlagInteger(char ch) throws NumberFormatException {
|
||||
return Integer.parseInt(valueFlags.get(ch));
|
||||
}
|
||||
|
||||
public int getFlagInteger(char ch, int def) throws NumberFormatException {
|
||||
final String value = valueFlags.get(ch);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
public double getFlagDouble(char ch) throws NumberFormatException {
|
||||
return Double.parseDouble(valueFlags.get(ch));
|
||||
}
|
||||
|
||||
public double getFlagDouble(char ch, double def) throws NumberFormatException {
|
||||
final String value = valueFlags.get(ch);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
public int argsLength() {
|
||||
return parsedArgs.size();
|
||||
}
|
||||
|
||||
public CommandLocals getLocals() {
|
||||
return locals;
|
||||
}
|
||||
}
|
||||
|
@ -1,83 +1,83 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class CommandException extends Exception {
|
||||
|
||||
private List<String> commandStack = new ArrayList<>();
|
||||
|
||||
public CommandException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CommandException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
public CommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
public void prependStack(String name) {
|
||||
commandStack.add(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command that was called, which will include the sub-command
|
||||
* (i.e. "/br sphere").
|
||||
*
|
||||
* @param prefix the command shebang character (such as "/") -- may be empty
|
||||
* @param spacedSuffix a suffix to put at the end (optional) -- may be null
|
||||
* @return the command that was used
|
||||
*/
|
||||
public String getCommandUsed(String prefix, @Nullable String spacedSuffix) {
|
||||
checkNotNull(prefix);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
builder.append(prefix);
|
||||
}
|
||||
ListIterator<String> li = commandStack.listIterator(commandStack.size());
|
||||
while (li.hasPrevious()) {
|
||||
if (li.previousIndex() != commandStack.size() - 1) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(li.previous());
|
||||
}
|
||||
if (spacedSuffix != null) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(spacedSuffix);
|
||||
}
|
||||
return builder.toString().trim();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class CommandException extends Exception {
|
||||
|
||||
private List<String> commandStack = new ArrayList<>();
|
||||
|
||||
public CommandException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CommandException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
public CommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
public void prependStack(String name) {
|
||||
commandStack.add(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command that was called, which will include the sub-command
|
||||
* (i.e. "/br sphere").
|
||||
*
|
||||
* @param prefix the command shebang character (such as "/") -- may be empty
|
||||
* @param spacedSuffix a suffix to put at the end (optional) -- may be null
|
||||
* @return the command that was used
|
||||
*/
|
||||
public String getCommandUsed(String prefix, @Nullable String spacedSuffix) {
|
||||
checkNotNull(prefix);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
builder.append(prefix);
|
||||
}
|
||||
ListIterator<String> li = commandStack.listIterator(commandStack.size());
|
||||
while (li.hasPrevious()) {
|
||||
if (li.previousIndex() != commandStack.size() - 1) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(li.previous());
|
||||
}
|
||||
if (spacedSuffix != null) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(spacedSuffix);
|
||||
}
|
||||
return builder.toString().trim();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,39 +1,39 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Indicates a list of permissions that should be checked.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandPermissions {
|
||||
|
||||
/**
|
||||
* A list of permissions. Only one permission has to be met
|
||||
* for the command to be permitted.
|
||||
*
|
||||
* @return a list of permissions strings
|
||||
*/
|
||||
String[] value();
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Indicates a list of permissions that should be checked.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandPermissions {
|
||||
|
||||
/**
|
||||
* A list of permissions. Only one permission has to be met
|
||||
* for the command to be permitted.
|
||||
*
|
||||
* @return a list of permissions strings
|
||||
*/
|
||||
String[] value();
|
||||
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
/**
|
||||
* Thrown when not enough permissions are satisfied.
|
||||
*/
|
||||
public class CommandPermissionsException extends CommandException {
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
/**
|
||||
* Thrown when not enough permissions are satisfied.
|
||||
*/
|
||||
public class CommandPermissionsException extends CommandException {
|
||||
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class CommandUsageException extends CommandException {
|
||||
|
||||
protected String usage;
|
||||
|
||||
public CommandUsageException(String message, String usage) {
|
||||
super(message);
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class CommandUsageException extends CommandException {
|
||||
|
||||
protected String usage;
|
||||
|
||||
public CommandUsageException(String message, String usage) {
|
||||
super(message);
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This annotation indicates that a command can be used from the console.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Console {
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This annotation indicates that a command can be used from the console.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Console {
|
||||
|
||||
}
|
||||
|
@ -1,40 +1,40 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* Constructs new instances.
|
||||
*/
|
||||
public interface Injector {
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the given class.
|
||||
*
|
||||
* @param cls class
|
||||
* @return object
|
||||
* @throws IllegalAccessException thrown on injection fault
|
||||
* @throws InstantiationException thrown on injection fault
|
||||
* @throws InvocationTargetException thrown on injection fault
|
||||
*/
|
||||
Object getInstance(Class<?> cls) throws InvocationTargetException, IllegalAccessException, InstantiationException;
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* Constructs new instances.
|
||||
*/
|
||||
public interface Injector {
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the given class.
|
||||
*
|
||||
* @param cls class
|
||||
* @return object
|
||||
* @throws IllegalAccessException thrown on injection fault
|
||||
* @throws InstantiationException thrown on injection fault
|
||||
* @throws InvocationTargetException thrown on injection fault
|
||||
*/
|
||||
Object getInstance(Class<?> cls) throws InvocationTargetException, IllegalAccessException, InstantiationException;
|
||||
|
||||
}
|
||||
|
@ -1,28 +1,28 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class MissingNestedCommandException extends CommandUsageException {
|
||||
|
||||
public MissingNestedCommandException(String message, String usage) {
|
||||
super(message, usage);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class MissingNestedCommandException extends CommandUsageException {
|
||||
|
||||
public MissingNestedCommandException(String message, String usage) {
|
||||
super(message, usage);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,50 +1,50 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Indicates a nested command. Mark methods with this annotation to tell
|
||||
* {@link CommandsManager} that a method is merely a shell for child
|
||||
* commands. Note that the body of a method marked with this annotation
|
||||
* will never called. Additionally, not all fields of {@link Command} apply
|
||||
* when it is used in conjunction with this annotation, although both
|
||||
* are still required.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NestedCommand {
|
||||
|
||||
/**
|
||||
* A list of classes with the child commands.
|
||||
*
|
||||
* @return a list of classes
|
||||
*/
|
||||
Class<?>[] value();
|
||||
|
||||
/**
|
||||
* If set to true it will execute the body of the tagged method.
|
||||
*
|
||||
* @return true to execute the body of the annotated method
|
||||
*/
|
||||
boolean executeBody() default false;
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Indicates a nested command. Mark methods with this annotation to tell
|
||||
* {@link CommandsManager} that a method is merely a shell for child
|
||||
* commands. Note that the body of a method marked with this annotation
|
||||
* will never called. Additionally, not all fields of {@link Command} apply
|
||||
* when it is used in conjunction with this annotation, although both
|
||||
* are still required.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NestedCommand {
|
||||
|
||||
/**
|
||||
* A list of classes with the child commands.
|
||||
*
|
||||
* @return a list of classes
|
||||
*/
|
||||
Class<?>[] value();
|
||||
|
||||
/**
|
||||
* If set to true it will execute the body of the tagged method.
|
||||
*
|
||||
* @return true to execute the body of the annotated method
|
||||
*/
|
||||
boolean executeBody() default false;
|
||||
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class UnhandledCommandException extends CommandException {
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class UnhandledCommandException extends CommandException {
|
||||
|
||||
}
|
||||
|
@ -1,28 +1,28 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class WrappedCommandException extends CommandException {
|
||||
|
||||
public WrappedCommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class WrappedCommandException extends CommandException {
|
||||
|
||||
public WrappedCommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,369 +1,369 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* String utilities.
|
||||
*/
|
||||
public final class StringUtil {
|
||||
|
||||
private StringUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim a string if it is longer than a certain length.
|
||||
*
|
||||
* @param str the string
|
||||
* @param len the length to trim to
|
||||
* @return a new string
|
||||
*/
|
||||
public static String trimLength(String str, int len) {
|
||||
if (str.length() > len) {
|
||||
return str.substring(0, len);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str the string array
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(String[] str, String delimiter, int initialIndex) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(str[initialIndex]);
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(str[i]);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str the string array
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @param quote the character to put around each entry
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinQuotedString(String[] str, String delimiter,
|
||||
int initialIndex, String quote) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(quote);
|
||||
buffer.append(str[initialIndex]);
|
||||
buffer.append(quote);
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(quote).append(str[i]).append(quote);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str the string array
|
||||
* @param delimiter the delimiter
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(String[] str, String delimiter) {
|
||||
return joinString(str, delimiter, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str an array of objects
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(Object[] str, String delimiter, int initialIndex) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(str[initialIndex].toString());
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(str[i]);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str a list of integers
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(int[] str, String delimiter, int initialIndex) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(Integer.toString(str[initialIndex]));
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(Integer.toString(str[i]));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an list of strings into a string.
|
||||
*
|
||||
* @param str a list of strings
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(Collection<?> str, String delimiter, int initialIndex) {
|
||||
if (str.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Object o : str) {
|
||||
if (i >= initialIndex) {
|
||||
if (i > 0) {
|
||||
buffer.append(delimiter);
|
||||
}
|
||||
|
||||
buffer.append(o);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Find the Levenshtein distance between two Strings.</p>
|
||||
*
|
||||
* <p>This is the number of changes needed to change one String into
|
||||
* another, where each change is a single character modification (deletion,
|
||||
* insertion or substitution).</p>
|
||||
*
|
||||
* <p>The previous implementation of the Levenshtein distance algorithm
|
||||
* was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
|
||||
*
|
||||
* <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
|
||||
* which can occur when my Java implementation is used with very large strings.<br>
|
||||
* This implementation of the Levenshtein distance algorithm
|
||||
* is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtil.getLevenshteinDistance(null, *) = IllegalArgumentException
|
||||
* StringUtil.getLevenshteinDistance(*, null) = IllegalArgumentException
|
||||
* StringUtil.getLevenshteinDistance("","") = 0
|
||||
* StringUtil.getLevenshteinDistance("","a") = 1
|
||||
* StringUtil.getLevenshteinDistance("aaapppp", "") = 7
|
||||
* StringUtil.getLevenshteinDistance("frog", "fog") = 1
|
||||
* StringUtil.getLevenshteinDistance("fly", "ant") = 3
|
||||
* StringUtil.getLevenshteinDistance("elephant", "hippo") = 7
|
||||
* StringUtil.getLevenshteinDistance("hippo", "elephant") = 7
|
||||
* StringUtil.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
|
||||
* StringUtil.getLevenshteinDistance("hello", "hallo") = 1
|
||||
* </pre>
|
||||
*
|
||||
* @param s the first String, must not be null
|
||||
* @param t the second String, must not be null
|
||||
* @return result distance
|
||||
* @throws IllegalArgumentException if either String input {@code null}
|
||||
*/
|
||||
public static int getLevenshteinDistance(String s, String t) {
|
||||
if (s == null || t == null) {
|
||||
throw new IllegalArgumentException("Strings must not be null");
|
||||
}
|
||||
|
||||
/*
|
||||
* The difference between this impl. and the previous is that, rather
|
||||
* than creating and retaining a matrix of size s.length()+1 by
|
||||
* t.length()+1, we maintain two single-dimensional arrays of length
|
||||
* s.length()+1. The first, d, is the 'current working' distance array
|
||||
* that maintains the newest distance cost counts as we iterate through
|
||||
* the characters of String s. Each time we increment the index of
|
||||
* String t we are comparing, d is copied to p, the second int[]. Doing
|
||||
* so allows us to retain the previous cost counts as required by the
|
||||
* algorithm (taking the minimum of the cost count to the left, up one,
|
||||
* and diagonally up and to the left of the current cost count being
|
||||
* calculated). (Note that the arrays aren't really copied anymore, just
|
||||
* switched...this is clearly much better than cloning an array or doing
|
||||
* a System.arraycopy() each time through the outer loop.)
|
||||
*
|
||||
* Effectively, the difference between the two implementations is this
|
||||
* one does not cause an out of memory condition when calculating the LD
|
||||
* over two very large strings.
|
||||
*/
|
||||
|
||||
int n = s.length(); // length of s
|
||||
int m = t.length(); // length of t
|
||||
|
||||
if (n == 0) {
|
||||
return m;
|
||||
} else if (m == 0) {
|
||||
return n;
|
||||
}
|
||||
|
||||
int[] p = new int[n + 1]; // 'previous' cost array, horizontally
|
||||
int[] d = new int[n + 1]; // cost array, horizontally
|
||||
int[] _d; // placeholder to assist in swapping p and d
|
||||
|
||||
// indexes into strings s and t
|
||||
int i; // iterates through s
|
||||
int j; // iterates through t
|
||||
|
||||
char tj; // jth character of t
|
||||
|
||||
int cost; // cost
|
||||
|
||||
for (i = 0; i <= n; ++i) {
|
||||
p[i] = i;
|
||||
}
|
||||
|
||||
for (j = 1; j <= m; ++j) {
|
||||
tj = t.charAt(j - 1);
|
||||
d[0] = j;
|
||||
|
||||
for (i = 1; i <= n; ++i) {
|
||||
cost = s.charAt(i - 1) == tj ? 0 : 1;
|
||||
// minimum of cell to the left+1, to the top+1, diagonally left
|
||||
// and up +cost
|
||||
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1]
|
||||
+ cost);
|
||||
}
|
||||
|
||||
// copy current distance counts to 'previous row' distance counts
|
||||
_d = p;
|
||||
p = d;
|
||||
d = _d;
|
||||
}
|
||||
|
||||
// our last action in the above loop was to switch d and p, so p now
|
||||
// actually has the most recent cost counts
|
||||
return p[n];
|
||||
}
|
||||
|
||||
public static <T extends Enum<?>> T lookup(Map<String, T> lookup, String name, boolean fuzzy) {
|
||||
String testName = name.replaceAll("[ _]", "").toLowerCase(Locale.ROOT);
|
||||
|
||||
T type = lookup.get(testName);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (!fuzzy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int minDist = -1;
|
||||
|
||||
for (Map.Entry<String, T> entry : lookup.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
if (key.charAt(0) != testName.charAt(0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int dist = getLevenshteinDistance(key, testName);
|
||||
|
||||
if ((dist < minDist || minDist == -1) && dist < 2) {
|
||||
minDist = dist;
|
||||
type = entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public static List<String> parseListInQuotes(String[] input, char delimiter, char quoteOpen, char quoteClose) {
|
||||
return parseListInQuotes(input, delimiter, quoteOpen, quoteClose, false);
|
||||
}
|
||||
|
||||
public static List<String> parseListInQuotes(String[] input, char delimiter, char quoteOpen,
|
||||
char quoteClose, boolean appendLeftover) {
|
||||
List<String> parsableBlocks = new ArrayList<>();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (String split : input) {
|
||||
if (split.indexOf(quoteOpen) != -1 && split.indexOf(quoteClose) == -1) {
|
||||
buffer.append(split).append(delimiter);
|
||||
} else if (split.indexOf(quoteClose) != -1 && split.indexOf(quoteOpen) == -1) {
|
||||
buffer.append(split);
|
||||
parsableBlocks.add(buffer.toString());
|
||||
buffer = new StringBuilder();
|
||||
} else if (buffer.length() == 0) {
|
||||
parsableBlocks.add(split);
|
||||
} else {
|
||||
buffer.append(split).append(delimiter);
|
||||
}
|
||||
}
|
||||
if (appendLeftover && buffer.length() != 0) {
|
||||
parsableBlocks.add(buffer.delete(buffer.length() - 1, buffer.length()).toString());
|
||||
}
|
||||
|
||||
return parsableBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a string respecting enclosing quotes.
|
||||
*
|
||||
* @param input the input to split.
|
||||
* @param delimiter the delimiter to split on.
|
||||
* @param open the opening quote character.
|
||||
* @param close the closing quote character.
|
||||
* @return a list of split strings.
|
||||
*/
|
||||
public static List<String> split(String input, char delimiter, char open, char close) {
|
||||
if (input.indexOf(open) == -1 && input.indexOf(close) == -1) {
|
||||
return Arrays.asList(input.split(String.valueOf(delimiter)));
|
||||
}
|
||||
int level = 0;
|
||||
int begin = 0;
|
||||
List<String> split = new ArrayList<>();
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
char c = input.charAt(i);
|
||||
if (c == delimiter && level == 0) {
|
||||
split.add(input.substring(begin, i));
|
||||
begin = i + 1;
|
||||
} else if (c == open) {
|
||||
level++;
|
||||
} else if (c == close) {
|
||||
level--;
|
||||
}
|
||||
}
|
||||
if (begin < input.length()) {
|
||||
split.add(input.substring(begin));
|
||||
}
|
||||
return split;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* String utilities.
|
||||
*/
|
||||
public final class StringUtil {
|
||||
|
||||
private StringUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim a string if it is longer than a certain length.
|
||||
*
|
||||
* @param str the string
|
||||
* @param len the length to trim to
|
||||
* @return a new string
|
||||
*/
|
||||
public static String trimLength(String str, int len) {
|
||||
if (str.length() > len) {
|
||||
return str.substring(0, len);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str the string array
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(String[] str, String delimiter, int initialIndex) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(str[initialIndex]);
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(str[i]);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str the string array
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @param quote the character to put around each entry
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinQuotedString(String[] str, String delimiter,
|
||||
int initialIndex, String quote) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(quote);
|
||||
buffer.append(str[initialIndex]);
|
||||
buffer.append(quote);
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(quote).append(str[i]).append(quote);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str the string array
|
||||
* @param delimiter the delimiter
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(String[] str, String delimiter) {
|
||||
return joinString(str, delimiter, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str an array of objects
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(Object[] str, String delimiter, int initialIndex) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(str[initialIndex].toString());
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(str[i]);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings into a string.
|
||||
*
|
||||
* @param str a list of integers
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(int[] str, String delimiter, int initialIndex) {
|
||||
if (str.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(Integer.toString(str[initialIndex]));
|
||||
for (int i = initialIndex + 1; i < str.length; ++i) {
|
||||
buffer.append(delimiter).append(Integer.toString(str[i]));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an list of strings into a string.
|
||||
*
|
||||
* @param str a list of strings
|
||||
* @param delimiter the delimiter
|
||||
* @param initialIndex the initial index to start form
|
||||
* @return a new string
|
||||
*/
|
||||
public static String joinString(Collection<?> str, String delimiter, int initialIndex) {
|
||||
if (str.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Object o : str) {
|
||||
if (i >= initialIndex) {
|
||||
if (i > 0) {
|
||||
buffer.append(delimiter);
|
||||
}
|
||||
|
||||
buffer.append(o);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Find the Levenshtein distance between two Strings.</p>
|
||||
*
|
||||
* <p>This is the number of changes needed to change one String into
|
||||
* another, where each change is a single character modification (deletion,
|
||||
* insertion or substitution).</p>
|
||||
*
|
||||
* <p>The previous implementation of the Levenshtein distance algorithm
|
||||
* was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
|
||||
*
|
||||
* <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
|
||||
* which can occur when my Java implementation is used with very large strings.<br>
|
||||
* This implementation of the Levenshtein distance algorithm
|
||||
* is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtil.getLevenshteinDistance(null, *) = IllegalArgumentException
|
||||
* StringUtil.getLevenshteinDistance(*, null) = IllegalArgumentException
|
||||
* StringUtil.getLevenshteinDistance("","") = 0
|
||||
* StringUtil.getLevenshteinDistance("","a") = 1
|
||||
* StringUtil.getLevenshteinDistance("aaapppp", "") = 7
|
||||
* StringUtil.getLevenshteinDistance("frog", "fog") = 1
|
||||
* StringUtil.getLevenshteinDistance("fly", "ant") = 3
|
||||
* StringUtil.getLevenshteinDistance("elephant", "hippo") = 7
|
||||
* StringUtil.getLevenshteinDistance("hippo", "elephant") = 7
|
||||
* StringUtil.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
|
||||
* StringUtil.getLevenshteinDistance("hello", "hallo") = 1
|
||||
* </pre>
|
||||
*
|
||||
* @param s the first String, must not be null
|
||||
* @param t the second String, must not be null
|
||||
* @return result distance
|
||||
* @throws IllegalArgumentException if either String input {@code null}
|
||||
*/
|
||||
public static int getLevenshteinDistance(String s, String t) {
|
||||
if (s == null || t == null) {
|
||||
throw new IllegalArgumentException("Strings must not be null");
|
||||
}
|
||||
|
||||
/*
|
||||
* The difference between this impl. and the previous is that, rather
|
||||
* than creating and retaining a matrix of size s.length()+1 by
|
||||
* t.length()+1, we maintain two single-dimensional arrays of length
|
||||
* s.length()+1. The first, d, is the 'current working' distance array
|
||||
* that maintains the newest distance cost counts as we iterate through
|
||||
* the characters of String s. Each time we increment the index of
|
||||
* String t we are comparing, d is copied to p, the second int[]. Doing
|
||||
* so allows us to retain the previous cost counts as required by the
|
||||
* algorithm (taking the minimum of the cost count to the left, up one,
|
||||
* and diagonally up and to the left of the current cost count being
|
||||
* calculated). (Note that the arrays aren't really copied anymore, just
|
||||
* switched...this is clearly much better than cloning an array or doing
|
||||
* a System.arraycopy() each time through the outer loop.)
|
||||
*
|
||||
* Effectively, the difference between the two implementations is this
|
||||
* one does not cause an out of memory condition when calculating the LD
|
||||
* over two very large strings.
|
||||
*/
|
||||
|
||||
int n = s.length(); // length of s
|
||||
int m = t.length(); // length of t
|
||||
|
||||
if (n == 0) {
|
||||
return m;
|
||||
} else if (m == 0) {
|
||||
return n;
|
||||
}
|
||||
|
||||
int[] p = new int[n + 1]; // 'previous' cost array, horizontally
|
||||
int[] d = new int[n + 1]; // cost array, horizontally
|
||||
int[] _d; // placeholder to assist in swapping p and d
|
||||
|
||||
// indexes into strings s and t
|
||||
int i; // iterates through s
|
||||
int j; // iterates through t
|
||||
|
||||
char tj; // jth character of t
|
||||
|
||||
int cost; // cost
|
||||
|
||||
for (i = 0; i <= n; ++i) {
|
||||
p[i] = i;
|
||||
}
|
||||
|
||||
for (j = 1; j <= m; ++j) {
|
||||
tj = t.charAt(j - 1);
|
||||
d[0] = j;
|
||||
|
||||
for (i = 1; i <= n; ++i) {
|
||||
cost = s.charAt(i - 1) == tj ? 0 : 1;
|
||||
// minimum of cell to the left+1, to the top+1, diagonally left
|
||||
// and up +cost
|
||||
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1]
|
||||
+ cost);
|
||||
}
|
||||
|
||||
// copy current distance counts to 'previous row' distance counts
|
||||
_d = p;
|
||||
p = d;
|
||||
d = _d;
|
||||
}
|
||||
|
||||
// our last action in the above loop was to switch d and p, so p now
|
||||
// actually has the most recent cost counts
|
||||
return p[n];
|
||||
}
|
||||
|
||||
public static <T extends Enum<?>> T lookup(Map<String, T> lookup, String name, boolean fuzzy) {
|
||||
String testName = name.replaceAll("[ _]", "").toLowerCase(Locale.ROOT);
|
||||
|
||||
T type = lookup.get(testName);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (!fuzzy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int minDist = -1;
|
||||
|
||||
for (Map.Entry<String, T> entry : lookup.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
if (key.charAt(0) != testName.charAt(0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int dist = getLevenshteinDistance(key, testName);
|
||||
|
||||
if ((dist < minDist || minDist == -1) && dist < 2) {
|
||||
minDist = dist;
|
||||
type = entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public static List<String> parseListInQuotes(String[] input, char delimiter, char quoteOpen, char quoteClose) {
|
||||
return parseListInQuotes(input, delimiter, quoteOpen, quoteClose, false);
|
||||
}
|
||||
|
||||
public static List<String> parseListInQuotes(String[] input, char delimiter, char quoteOpen,
|
||||
char quoteClose, boolean appendLeftover) {
|
||||
List<String> parsableBlocks = new ArrayList<>();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (String split : input) {
|
||||
if (split.indexOf(quoteOpen) != -1 && split.indexOf(quoteClose) == -1) {
|
||||
buffer.append(split).append(delimiter);
|
||||
} else if (split.indexOf(quoteClose) != -1 && split.indexOf(quoteOpen) == -1) {
|
||||
buffer.append(split);
|
||||
parsableBlocks.add(buffer.toString());
|
||||
buffer = new StringBuilder();
|
||||
} else if (buffer.length() == 0) {
|
||||
parsableBlocks.add(split);
|
||||
} else {
|
||||
buffer.append(split).append(delimiter);
|
||||
}
|
||||
}
|
||||
if (appendLeftover && buffer.length() != 0) {
|
||||
parsableBlocks.add(buffer.delete(buffer.length() - 1, buffer.length()).toString());
|
||||
}
|
||||
|
||||
return parsableBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a string respecting enclosing quotes.
|
||||
*
|
||||
* @param input the input to split.
|
||||
* @param delimiter the delimiter to split on.
|
||||
* @param open the opening quote character.
|
||||
* @param close the closing quote character.
|
||||
* @return a list of split strings.
|
||||
*/
|
||||
public static List<String> split(String input, char delimiter, char open, char close) {
|
||||
if (input.indexOf(open) == -1 && input.indexOf(close) == -1) {
|
||||
return Arrays.asList(input.split(String.valueOf(delimiter)));
|
||||
}
|
||||
int level = 0;
|
||||
int begin = 0;
|
||||
List<String> split = new ArrayList<>();
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
char c = input.charAt(i);
|
||||
if (c == delimiter && level == 0) {
|
||||
split.add(input.substring(begin, i));
|
||||
begin = i + 1;
|
||||
} else if (c == open) {
|
||||
level++;
|
||||
} else if (c == close) {
|
||||
level--;
|
||||
}
|
||||
}
|
||||
if (begin < input.length()) {
|
||||
split.add(input.substring(begin));
|
||||
}
|
||||
return split;
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +1,52 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
/**
|
||||
* Raised when an item is used when a block was expected.
|
||||
*/
|
||||
public class NotABlockException extends WorldEditException {
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*/
|
||||
public NotABlockException() {
|
||||
super("This item is not a block.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param input the input that was used
|
||||
*/
|
||||
public NotABlockException(String input) {
|
||||
super("The item '" + input + "' is not a block.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param input the input that was used
|
||||
*/
|
||||
public NotABlockException(int input) {
|
||||
super("The item with the ID " + input + " is not a block.");
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
/**
|
||||
* Raised when an item is used when a block was expected.
|
||||
*/
|
||||
public class NotABlockException extends WorldEditException {
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*/
|
||||
public NotABlockException() {
|
||||
super("This item is not a block.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param input the input that was used
|
||||
*/
|
||||
public NotABlockException(String input) {
|
||||
super("The item '" + input + "' is not a block.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param input the input that was used
|
||||
*/
|
||||
public NotABlockException(int input) {
|
||||
super("The item with the ID " + input + " is not a block.");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,83 +1,83 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.blocks;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
|
||||
/**
|
||||
* Represents a stack of BaseItems.
|
||||
*
|
||||
* <p>This class may be removed in the future.</p>
|
||||
*/
|
||||
public class BaseItemStack extends BaseItem {
|
||||
|
||||
private int amount = 1;
|
||||
|
||||
/**
|
||||
* Construct the object with default stack size of one, with damage value of 0.
|
||||
*
|
||||
* @param itemType The item type
|
||||
*/
|
||||
public BaseItemStack(ItemType itemType) {
|
||||
super(itemType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param itemType The item type
|
||||
* @param amount amount in the stack
|
||||
*/
|
||||
public BaseItemStack(ItemType itemType, int amount) {
|
||||
super(itemType);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param id The item type
|
||||
* @param tag Tag value
|
||||
* @param amount amount in the stack
|
||||
*/
|
||||
public BaseItemStack(ItemType id, CompoundTag tag, int amount) {
|
||||
super(id, tag);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of items in the stack.
|
||||
*
|
||||
* @return the amount
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of items in the stack.
|
||||
*
|
||||
* @param amount the amount to set
|
||||
*/
|
||||
public void setAmount(int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.blocks;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
|
||||
/**
|
||||
* Represents a stack of BaseItems.
|
||||
*
|
||||
* <p>This class may be removed in the future.</p>
|
||||
*/
|
||||
public class BaseItemStack extends BaseItem {
|
||||
|
||||
private int amount = 1;
|
||||
|
||||
/**
|
||||
* Construct the object with default stack size of one, with damage value of 0.
|
||||
*
|
||||
* @param itemType The item type
|
||||
*/
|
||||
public BaseItemStack(ItemType itemType) {
|
||||
super(itemType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param itemType The item type
|
||||
* @param amount amount in the stack
|
||||
*/
|
||||
public BaseItemStack(ItemType itemType, int amount) {
|
||||
super(itemType);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param id The item type
|
||||
* @param tag Tag value
|
||||
* @param amount amount in the stack
|
||||
*/
|
||||
public BaseItemStack(ItemType id, CompoundTag tag, int amount) {
|
||||
super(id, tag);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of items in the stack.
|
||||
*
|
||||
* @return the amount
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of items in the stack.
|
||||
*
|
||||
* @param amount the amount to set
|
||||
*/
|
||||
public void setAmount(int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
|
@ -1,250 +1,250 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.iterator.RegionIterator;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractRegion extends AbstractSet<BlockVector3> implements Region {
|
||||
|
||||
protected World world;
|
||||
|
||||
public AbstractRegion(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return com.google.common.primitives.Ints.saturatedCast(getVolume());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return getMinimumPoint().add(getMaximumPoint()).toVector3().divide(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the iterator.
|
||||
*
|
||||
* @return iterator of points inside the region
|
||||
*/
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return new RegionIterator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
expand(change);
|
||||
contract(change);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRegion clone() {
|
||||
try {
|
||||
return (AbstractRegion) super.clone();
|
||||
} catch (CloneNotSupportedException exc) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2> polygonize(int maxPoints) {
|
||||
if (maxPoints >= 0 && maxPoints < 4) {
|
||||
throw new IllegalArgumentException("Cannot polygonize an AbstractRegion with no overridden polygonize method into less than 4 points.");
|
||||
}
|
||||
|
||||
final BlockVector3 min = getMinimumPoint();
|
||||
final BlockVector3 max = getMaximumPoint();
|
||||
|
||||
final List<BlockVector2> points = new ArrayList<>(4);
|
||||
|
||||
points.add(BlockVector2.at(min.getX(), min.getZ()));
|
||||
points.add(BlockVector2.at(min.getX(), max.getZ()));
|
||||
points.add(BlockVector2.at(max.getX(), max.getZ()));
|
||||
points.add(BlockVector2.at(max.getX(), min.getZ()));
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVolume() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return (max.getX() - min.getX() + 1L)
|
||||
* (max.getY() - min.getY() + 1L)
|
||||
* (max.getZ() - min.getZ() + 1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X-size.
|
||||
*
|
||||
* @return width
|
||||
*/
|
||||
@Override
|
||||
public int getWidth() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return max.getX() - min.getX() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Y-size.
|
||||
*
|
||||
* @return height
|
||||
*/
|
||||
@Override
|
||||
public int getHeight() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return max.getY() - min.getY() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Z-size.
|
||||
*
|
||||
* @return length
|
||||
*/
|
||||
@Override
|
||||
public int getLength() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return max.getZ() - min.getZ() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of chunks.
|
||||
*
|
||||
* @return a set of chunks
|
||||
*/
|
||||
@Override
|
||||
public Set<BlockVector2> getChunks() {
|
||||
final Set<BlockVector2> chunks = new HashSet<>();
|
||||
|
||||
final BlockVector3 minBlock = getMinimumPoint();
|
||||
final BlockVector3 maxBlock = getMaximumPoint();
|
||||
|
||||
final BlockVector2 min = BlockVector2.at(minBlock.getX() >> 4, minBlock.getZ() >> 4);
|
||||
final BlockVector2 max = BlockVector2.at(maxBlock.getX() >> 4, maxBlock.getZ() >> 4);
|
||||
|
||||
for (int X = min.getBlockX(); X <= max.getBlockX(); ++X) {
|
||||
for (int Z = min.getBlockZ(); Z <= max.getBlockZ(); ++Z) {
|
||||
if (containsChunk(X, Z)) {
|
||||
chunks.add(BlockVector2.at(X, Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<BlockVector3> getChunkCubes() {
|
||||
final Set<BlockVector3> chunks = new BlockVectorSet();
|
||||
|
||||
final BlockVector3 min = getMinimumPoint();
|
||||
final BlockVector3 max = getMaximumPoint();
|
||||
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
|
||||
if (!contains(BlockVector3.at(x, y, z))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
chunks.add(BlockVector3.at(
|
||||
x >> ChunkStore.CHUNK_SHIFTS,
|
||||
y >> ChunkStore.CHUNK_SHIFTS,
|
||||
z >> ChunkStore.CHUNK_SHIFTS
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
// Sub-class utilities
|
||||
|
||||
protected final int getWorldMinY() {
|
||||
return world == null ? 0 : world.getMinY();
|
||||
}
|
||||
|
||||
protected final int getWorldMaxY() {
|
||||
return world == null ? 255 : world.getMaxY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int worldHash = this.world == null ? 7 : this.world.hashCode();
|
||||
int result = worldHash ^ (worldHash >>> 32);
|
||||
result = 31 * result + this.getMinimumPoint().hashCode();
|
||||
result = 31 * result + this.getMaximumPoint().hashCode();
|
||||
result = (int) (31 * result + this.getVolume());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Region)) {
|
||||
return false;
|
||||
}
|
||||
Region region = ((Region) o);
|
||||
|
||||
if (Objects.equals(this.getWorld(), region.getWorld())
|
||||
&& this.getMinimumPoint().equals(region.getMinimumPoint())
|
||||
&& this.getMaximumPoint().equals(region.getMaximumPoint())
|
||||
&& this.getVolume() == region.getVolume()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.iterator.RegionIterator;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractRegion extends AbstractSet<BlockVector3> implements Region {
|
||||
|
||||
protected World world;
|
||||
|
||||
public AbstractRegion(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return com.google.common.primitives.Ints.saturatedCast(getVolume());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return getMinimumPoint().add(getMaximumPoint()).toVector3().divide(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the iterator.
|
||||
*
|
||||
* @return iterator of points inside the region
|
||||
*/
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return new RegionIterator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
expand(change);
|
||||
contract(change);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRegion clone() {
|
||||
try {
|
||||
return (AbstractRegion) super.clone();
|
||||
} catch (CloneNotSupportedException exc) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2> polygonize(int maxPoints) {
|
||||
if (maxPoints >= 0 && maxPoints < 4) {
|
||||
throw new IllegalArgumentException("Cannot polygonize an AbstractRegion with no overridden polygonize method into less than 4 points.");
|
||||
}
|
||||
|
||||
final BlockVector3 min = getMinimumPoint();
|
||||
final BlockVector3 max = getMaximumPoint();
|
||||
|
||||
final List<BlockVector2> points = new ArrayList<>(4);
|
||||
|
||||
points.add(BlockVector2.at(min.getX(), min.getZ()));
|
||||
points.add(BlockVector2.at(min.getX(), max.getZ()));
|
||||
points.add(BlockVector2.at(max.getX(), max.getZ()));
|
||||
points.add(BlockVector2.at(max.getX(), min.getZ()));
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVolume() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return (max.getX() - min.getX() + 1L)
|
||||
* (max.getY() - min.getY() + 1L)
|
||||
* (max.getZ() - min.getZ() + 1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X-size.
|
||||
*
|
||||
* @return width
|
||||
*/
|
||||
@Override
|
||||
public int getWidth() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return max.getX() - min.getX() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Y-size.
|
||||
*
|
||||
* @return height
|
||||
*/
|
||||
@Override
|
||||
public int getHeight() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return max.getY() - min.getY() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Z-size.
|
||||
*
|
||||
* @return length
|
||||
*/
|
||||
@Override
|
||||
public int getLength() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return max.getZ() - min.getZ() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of chunks.
|
||||
*
|
||||
* @return a set of chunks
|
||||
*/
|
||||
@Override
|
||||
public Set<BlockVector2> getChunks() {
|
||||
final Set<BlockVector2> chunks = new HashSet<>();
|
||||
|
||||
final BlockVector3 minBlock = getMinimumPoint();
|
||||
final BlockVector3 maxBlock = getMaximumPoint();
|
||||
|
||||
final BlockVector2 min = BlockVector2.at(minBlock.getX() >> 4, minBlock.getZ() >> 4);
|
||||
final BlockVector2 max = BlockVector2.at(maxBlock.getX() >> 4, maxBlock.getZ() >> 4);
|
||||
|
||||
for (int X = min.getBlockX(); X <= max.getBlockX(); ++X) {
|
||||
for (int Z = min.getBlockZ(); Z <= max.getBlockZ(); ++Z) {
|
||||
if (containsChunk(X, Z)) {
|
||||
chunks.add(BlockVector2.at(X, Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<BlockVector3> getChunkCubes() {
|
||||
final Set<BlockVector3> chunks = new BlockVectorSet();
|
||||
|
||||
final BlockVector3 min = getMinimumPoint();
|
||||
final BlockVector3 max = getMaximumPoint();
|
||||
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
|
||||
if (!contains(BlockVector3.at(x, y, z))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
chunks.add(BlockVector3.at(
|
||||
x >> ChunkStore.CHUNK_SHIFTS,
|
||||
y >> ChunkStore.CHUNK_SHIFTS,
|
||||
z >> ChunkStore.CHUNK_SHIFTS
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
// Sub-class utilities
|
||||
|
||||
protected final int getWorldMinY() {
|
||||
return world == null ? 0 : world.getMinY();
|
||||
}
|
||||
|
||||
protected final int getWorldMaxY() {
|
||||
return world == null ? 255 : world.getMaxY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int worldHash = this.world == null ? 7 : this.world.hashCode();
|
||||
int result = worldHash ^ (worldHash >>> 32);
|
||||
result = 31 * result + this.getMinimumPoint().hashCode();
|
||||
result = 31 * result + this.getMaximumPoint().hashCode();
|
||||
result = (int) (31 * result + this.getVolume());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Region)) {
|
||||
return false;
|
||||
}
|
||||
Region region = ((Region) o);
|
||||
|
||||
if (Objects.equals(this.getWorld(), region.getWorld())
|
||||
&& this.getMinimumPoint().equals(region.getMinimumPoint())
|
||||
&& this.getMaximumPoint().equals(region.getMaximumPoint())
|
||||
&& this.getVolume() == region.getVolume()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,336 +1,336 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.polyhedron.Edge;
|
||||
import com.sk89q.worldedit.regions.polyhedron.Triangle;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ConvexPolyhedralRegion extends AbstractRegion {
|
||||
|
||||
/**
|
||||
* Vertices that are contained in the convex hull.
|
||||
*/
|
||||
private final Set<BlockVector3> vertices = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Triangles that form the convex hull.
|
||||
*/
|
||||
private final List<Triangle> triangles = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Vertices that are coplanar to the first 3 vertices.
|
||||
*/
|
||||
private final Set<BlockVector3> vertexBacklog = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Minimum point of the axis-aligned bounding box.
|
||||
*/
|
||||
private BlockVector3 minimumPoint;
|
||||
|
||||
/**
|
||||
* Maximum point of the axis-aligned bounding box.
|
||||
*/
|
||||
private BlockVector3 maximumPoint;
|
||||
|
||||
/**
|
||||
* Accumulator for the barycenter of the polyhedron. Divide by vertices.size() to get the actual center.
|
||||
*/
|
||||
private BlockVector3 centerAccum = BlockVector3.ZERO;
|
||||
|
||||
/**
|
||||
* The last triangle that caused a {@link #contains(BlockVector3)}} to classify a point as "outside". Used for optimization.
|
||||
*/
|
||||
private Triangle lastTriangle;
|
||||
|
||||
/**
|
||||
* Constructs an empty mesh, containing no vertices or triangles.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
public ConvexPolyhedralRegion(@Nullable World world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an independent copy of the given region.
|
||||
*
|
||||
* @param region the region to copy
|
||||
*/
|
||||
public ConvexPolyhedralRegion(ConvexPolyhedralRegion region) {
|
||||
this(region.world);
|
||||
vertices.addAll(region.vertices);
|
||||
triangles.addAll(region.triangles);
|
||||
vertexBacklog.addAll(region.vertexBacklog);
|
||||
|
||||
minimumPoint = region.minimumPoint;
|
||||
maximumPoint = region.maximumPoint;
|
||||
centerAccum = region.centerAccum;
|
||||
lastTriangle = region.lastTriangle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the region, removing all vertices and triangles.
|
||||
*/
|
||||
public void clear() {
|
||||
vertices.clear();
|
||||
triangles.clear();
|
||||
vertexBacklog.clear();
|
||||
|
||||
minimumPoint = null;
|
||||
maximumPoint = null;
|
||||
centerAccum = BlockVector3.ZERO;
|
||||
lastTriangle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a vertex to the region.
|
||||
*
|
||||
* @param vertex the vertex
|
||||
* @return true, if something changed.
|
||||
*/
|
||||
public boolean addVertex(BlockVector3 vertex) {
|
||||
checkNotNull(vertex);
|
||||
|
||||
lastTriangle = null; // Probably not necessary
|
||||
|
||||
if (vertices.contains(vertex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 vertexD = vertex.toVector3();
|
||||
|
||||
if (vertices.size() == 3) {
|
||||
if (vertexBacklog.contains(vertex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (containsRaw(vertexD)) {
|
||||
return vertexBacklog.add(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
vertices.add(vertex);
|
||||
|
||||
centerAccum = centerAccum.add(vertex);
|
||||
|
||||
if (minimumPoint == null) {
|
||||
minimumPoint = maximumPoint = vertex;
|
||||
} else {
|
||||
minimumPoint = minimumPoint.getMinimum(vertex);
|
||||
maximumPoint = maximumPoint.getMaximum(vertex);
|
||||
}
|
||||
|
||||
|
||||
switch (vertices.size()) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
// Incomplete, can't make a mesh yet
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
// Generate minimal mesh to start from
|
||||
final BlockVector3[] v = vertices.toArray(new BlockVector3[0]);
|
||||
|
||||
triangles.add((new Triangle(v[0].toVector3(), v[1].toVector3(), v[2].toVector3())));
|
||||
triangles.add((new Triangle(v[0].toVector3(), v[2].toVector3(), v[1].toVector3())));
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for triangles that face the vertex and remove them
|
||||
final Set<Edge> borderEdges = new LinkedHashSet<>();
|
||||
for (Iterator<Triangle> it = triangles.iterator(); it.hasNext(); ) {
|
||||
final Triangle triangle = it.next();
|
||||
|
||||
// If the triangle can't be seen, it's not relevant
|
||||
if (!triangle.above(vertexD)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the triangle from the mesh
|
||||
it.remove();
|
||||
|
||||
// ...and remember its edges
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
final Edge edge = triangle.getEdge(i);
|
||||
if (borderEdges.remove(edge)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
borderEdges.add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
// Add triangles between the remembered edges and the new vertex.
|
||||
for (Edge edge : borderEdges) {
|
||||
triangles.add(edge.createTriangle(vertexD));
|
||||
}
|
||||
|
||||
if (!vertexBacklog.isEmpty()) {
|
||||
// Remove the new vertex
|
||||
vertices.remove(vertex);
|
||||
|
||||
// Clone, clear and work through the backlog
|
||||
final List<BlockVector3> vertexBacklog2 = new ArrayList<>(vertexBacklog);
|
||||
vertexBacklog.clear();
|
||||
for (BlockVector3 vertex2 : vertexBacklog2) {
|
||||
addVertex(vertex2);
|
||||
}
|
||||
|
||||
// Re-add the new vertex after the backlog.
|
||||
vertices.add(vertex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return !triangles.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return minimumPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return maximumPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return centerAccum.toVector3().divide(vertices.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(BlockVector3... changes) throws RegionOperationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
Vector3 vec = change.toVector3();
|
||||
shiftCollection(vertices, change);
|
||||
shiftCollection(vertexBacklog, change);
|
||||
|
||||
for (int i = 0; i < triangles.size(); ++i) {
|
||||
final Triangle triangle = triangles.get(i);
|
||||
|
||||
final Vector3 v0 = vec.add(triangle.getVertex(0));
|
||||
final Vector3 v1 = vec.add(triangle.getVertex(1));
|
||||
final Vector3 v2 = vec.add(triangle.getVertex(2));
|
||||
|
||||
triangles.set(i, new Triangle(v0, v1, v2));
|
||||
}
|
||||
|
||||
minimumPoint = change.add(minimumPoint);
|
||||
maximumPoint = change.add(maximumPoint);
|
||||
centerAccum = change.multiply(vertices.size()).add(centerAccum);
|
||||
lastTriangle = null;
|
||||
}
|
||||
|
||||
private static void shiftCollection(Collection<BlockVector3> collection, BlockVector3 change) {
|
||||
final List<BlockVector3> tmp = new ArrayList<>(collection);
|
||||
collection.clear();
|
||||
for (BlockVector3 vertex : tmp) {
|
||||
collection.add(change.add(vertex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
if (!isDefined()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final BlockVector3 min = getMinimumPoint();
|
||||
final BlockVector3 max = getMaximumPoint();
|
||||
|
||||
if (!position.containedWithin(min, max)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return containsRaw(position.toVector3());
|
||||
}
|
||||
|
||||
private boolean containsRaw(Vector3 pt) {
|
||||
if (lastTriangle != null && lastTriangle.above(pt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Triangle triangle : triangles) {
|
||||
if (lastTriangle == triangle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (triangle.above(pt)) {
|
||||
lastTriangle = triangle;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Collection<BlockVector3> getVertices() {
|
||||
if (vertexBacklog.isEmpty()) {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
final List<BlockVector3> ret = new ArrayList<>(vertices);
|
||||
ret.addAll(vertexBacklog);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Collection<Triangle> getTriangles() {
|
||||
return triangles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRegion clone() {
|
||||
return new ConvexPolyhedralRegion(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntireCuboid(int bx, int tx, int by, int ty, int bz, int tz) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.polyhedron.Edge;
|
||||
import com.sk89q.worldedit.regions.polyhedron.Triangle;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ConvexPolyhedralRegion extends AbstractRegion {
|
||||
|
||||
/**
|
||||
* Vertices that are contained in the convex hull.
|
||||
*/
|
||||
private final Set<BlockVector3> vertices = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Triangles that form the convex hull.
|
||||
*/
|
||||
private final List<Triangle> triangles = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Vertices that are coplanar to the first 3 vertices.
|
||||
*/
|
||||
private final Set<BlockVector3> vertexBacklog = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Minimum point of the axis-aligned bounding box.
|
||||
*/
|
||||
private BlockVector3 minimumPoint;
|
||||
|
||||
/**
|
||||
* Maximum point of the axis-aligned bounding box.
|
||||
*/
|
||||
private BlockVector3 maximumPoint;
|
||||
|
||||
/**
|
||||
* Accumulator for the barycenter of the polyhedron. Divide by vertices.size() to get the actual center.
|
||||
*/
|
||||
private BlockVector3 centerAccum = BlockVector3.ZERO;
|
||||
|
||||
/**
|
||||
* The last triangle that caused a {@link #contains(BlockVector3)}} to classify a point as "outside". Used for optimization.
|
||||
*/
|
||||
private Triangle lastTriangle;
|
||||
|
||||
/**
|
||||
* Constructs an empty mesh, containing no vertices or triangles.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
public ConvexPolyhedralRegion(@Nullable World world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an independent copy of the given region.
|
||||
*
|
||||
* @param region the region to copy
|
||||
*/
|
||||
public ConvexPolyhedralRegion(ConvexPolyhedralRegion region) {
|
||||
this(region.world);
|
||||
vertices.addAll(region.vertices);
|
||||
triangles.addAll(region.triangles);
|
||||
vertexBacklog.addAll(region.vertexBacklog);
|
||||
|
||||
minimumPoint = region.minimumPoint;
|
||||
maximumPoint = region.maximumPoint;
|
||||
centerAccum = region.centerAccum;
|
||||
lastTriangle = region.lastTriangle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the region, removing all vertices and triangles.
|
||||
*/
|
||||
public void clear() {
|
||||
vertices.clear();
|
||||
triangles.clear();
|
||||
vertexBacklog.clear();
|
||||
|
||||
minimumPoint = null;
|
||||
maximumPoint = null;
|
||||
centerAccum = BlockVector3.ZERO;
|
||||
lastTriangle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a vertex to the region.
|
||||
*
|
||||
* @param vertex the vertex
|
||||
* @return true, if something changed.
|
||||
*/
|
||||
public boolean addVertex(BlockVector3 vertex) {
|
||||
checkNotNull(vertex);
|
||||
|
||||
lastTriangle = null; // Probably not necessary
|
||||
|
||||
if (vertices.contains(vertex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 vertexD = vertex.toVector3();
|
||||
|
||||
if (vertices.size() == 3) {
|
||||
if (vertexBacklog.contains(vertex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (containsRaw(vertexD)) {
|
||||
return vertexBacklog.add(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
vertices.add(vertex);
|
||||
|
||||
centerAccum = centerAccum.add(vertex);
|
||||
|
||||
if (minimumPoint == null) {
|
||||
minimumPoint = maximumPoint = vertex;
|
||||
} else {
|
||||
minimumPoint = minimumPoint.getMinimum(vertex);
|
||||
maximumPoint = maximumPoint.getMaximum(vertex);
|
||||
}
|
||||
|
||||
|
||||
switch (vertices.size()) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
// Incomplete, can't make a mesh yet
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
// Generate minimal mesh to start from
|
||||
final BlockVector3[] v = vertices.toArray(new BlockVector3[0]);
|
||||
|
||||
triangles.add((new Triangle(v[0].toVector3(), v[1].toVector3(), v[2].toVector3())));
|
||||
triangles.add((new Triangle(v[0].toVector3(), v[2].toVector3(), v[1].toVector3())));
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for triangles that face the vertex and remove them
|
||||
final Set<Edge> borderEdges = new LinkedHashSet<>();
|
||||
for (Iterator<Triangle> it = triangles.iterator(); it.hasNext(); ) {
|
||||
final Triangle triangle = it.next();
|
||||
|
||||
// If the triangle can't be seen, it's not relevant
|
||||
if (!triangle.above(vertexD)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the triangle from the mesh
|
||||
it.remove();
|
||||
|
||||
// ...and remember its edges
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
final Edge edge = triangle.getEdge(i);
|
||||
if (borderEdges.remove(edge)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
borderEdges.add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
// Add triangles between the remembered edges and the new vertex.
|
||||
for (Edge edge : borderEdges) {
|
||||
triangles.add(edge.createTriangle(vertexD));
|
||||
}
|
||||
|
||||
if (!vertexBacklog.isEmpty()) {
|
||||
// Remove the new vertex
|
||||
vertices.remove(vertex);
|
||||
|
||||
// Clone, clear and work through the backlog
|
||||
final List<BlockVector3> vertexBacklog2 = new ArrayList<>(vertexBacklog);
|
||||
vertexBacklog.clear();
|
||||
for (BlockVector3 vertex2 : vertexBacklog2) {
|
||||
addVertex(vertex2);
|
||||
}
|
||||
|
||||
// Re-add the new vertex after the backlog.
|
||||
vertices.add(vertex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return !triangles.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return minimumPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return maximumPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return centerAccum.toVector3().divide(vertices.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(BlockVector3... changes) throws RegionOperationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
Vector3 vec = change.toVector3();
|
||||
shiftCollection(vertices, change);
|
||||
shiftCollection(vertexBacklog, change);
|
||||
|
||||
for (int i = 0; i < triangles.size(); ++i) {
|
||||
final Triangle triangle = triangles.get(i);
|
||||
|
||||
final Vector3 v0 = vec.add(triangle.getVertex(0));
|
||||
final Vector3 v1 = vec.add(triangle.getVertex(1));
|
||||
final Vector3 v2 = vec.add(triangle.getVertex(2));
|
||||
|
||||
triangles.set(i, new Triangle(v0, v1, v2));
|
||||
}
|
||||
|
||||
minimumPoint = change.add(minimumPoint);
|
||||
maximumPoint = change.add(maximumPoint);
|
||||
centerAccum = change.multiply(vertices.size()).add(centerAccum);
|
||||
lastTriangle = null;
|
||||
}
|
||||
|
||||
private static void shiftCollection(Collection<BlockVector3> collection, BlockVector3 change) {
|
||||
final List<BlockVector3> tmp = new ArrayList<>(collection);
|
||||
collection.clear();
|
||||
for (BlockVector3 vertex : tmp) {
|
||||
collection.add(change.add(vertex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
if (!isDefined()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final BlockVector3 min = getMinimumPoint();
|
||||
final BlockVector3 max = getMaximumPoint();
|
||||
|
||||
if (!position.containedWithin(min, max)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return containsRaw(position.toVector3());
|
||||
}
|
||||
|
||||
private boolean containsRaw(Vector3 pt) {
|
||||
if (lastTriangle != null && lastTriangle.above(pt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Triangle triangle : triangles) {
|
||||
if (lastTriangle == triangle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (triangle.above(pt)) {
|
||||
lastTriangle = triangle;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Collection<BlockVector3> getVertices() {
|
||||
if (vertexBacklog.isEmpty()) {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
final List<BlockVector3> ret = new ArrayList<>(vertices);
|
||||
ret.addAll(vertexBacklog);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Collection<Triangle> getTriangles() {
|
||||
return triangles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRegion clone() {
|
||||
return new ConvexPolyhedralRegion(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntireCuboid(int bx, int tx, int by, int ty, int bz, int tz) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,430 +1,430 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector2;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.geom.Polygons;
|
||||
import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
|
||||
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a cylindrical region.
|
||||
*/
|
||||
public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
||||
|
||||
private BlockVector2 center;
|
||||
private Vector2 radius;
|
||||
private Vector2 radiusInverse;
|
||||
private int minY;
|
||||
private int maxY;
|
||||
private boolean hasY = false;
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*/
|
||||
public CylinderRegion() {
|
||||
this((World) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
public CylinderRegion(World world) {
|
||||
this(world, BlockVector3.ZERO, Vector2.ZERO, 0, 0);
|
||||
hasY = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param world the world
|
||||
* @param center the center position
|
||||
* @param radius the radius along the X and Z axes
|
||||
* @param minY the minimum Y, inclusive
|
||||
* @param maxY the maximum Y, inclusive
|
||||
*/
|
||||
public CylinderRegion(World world, BlockVector3 center, Vector2 radius, int minY, int maxY) {
|
||||
super(world);
|
||||
setCenter(center.toBlockVector2());
|
||||
setRadius(radius);
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
hasY = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param center the center position
|
||||
* @param radius the radius along the X and Z axes
|
||||
* @param minY the minimum Y, inclusive
|
||||
* @param maxY the maximum Y, inclusive
|
||||
*/
|
||||
public CylinderRegion(BlockVector3 center, Vector2 radius, int minY, int maxY) {
|
||||
super(null);
|
||||
setCenter(center.toBlockVector2());
|
||||
setRadius(radius);
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
hasY = true;
|
||||
}
|
||||
|
||||
public CylinderRegion(CylinderRegion region) {
|
||||
this(region.world, region.getCenter().toBlockPoint(), region.getRadius(), region.minY, region.maxY);
|
||||
hasY = region.hasY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return center.toVector3((maxY + minY) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main center point of the region.
|
||||
*
|
||||
* @param center the center point
|
||||
*/
|
||||
public void setCenter(BlockVector2 center) {
|
||||
this.center = center;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the radius of the cylinder.
|
||||
*
|
||||
* @return the radius along the X and Z axes
|
||||
*/
|
||||
public Vector2 getRadius() {
|
||||
return radius.subtract(0.5, 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the radius of the cylinder.
|
||||
*
|
||||
* @param radius the radius along the X and Z axes
|
||||
*/
|
||||
public void setRadius(Vector2 radius) {
|
||||
this.radius = radius.add(0.5, 0.5);
|
||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends the radius to be at least the given radius.
|
||||
*
|
||||
* @param minRadius the minimum radius
|
||||
*/
|
||||
public void extendRadius(Vector2 minRadius) {
|
||||
setRadius(minRadius.getMaximum(getRadius()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum Y.
|
||||
*
|
||||
* @param y the y
|
||||
*/
|
||||
public void setMinimumY(int y) {
|
||||
hasY = true;
|
||||
minY = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Se the maximum Y.
|
||||
*
|
||||
* @param y the y
|
||||
*/
|
||||
public void setMaximumY(int y) {
|
||||
hasY = true;
|
||||
maxY = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return center.toVector2().subtract(getRadius()).toVector3(minY).toBlockPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return center.toVector2().add(getRadius()).toVector3(maxY).toBlockPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumY() {
|
||||
int worldMax = world != null ? world.getMaxY() - 1 : 255;
|
||||
if (maxY > worldMax) {
|
||||
return maxY = worldMax;
|
||||
}
|
||||
return maxY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumY() {
|
||||
if (minY < 0) {
|
||||
return minY = 0;
|
||||
}
|
||||
return minY;
|
||||
}
|
||||
|
||||
private static final BigDecimal PI = BigDecimal.valueOf(Math.PI);
|
||||
|
||||
@Override
|
||||
public long getVolume() {
|
||||
return BigDecimal.valueOf(radius.getX())
|
||||
.multiply(BigDecimal.valueOf(radius.getZ()))
|
||||
.multiply(PI)
|
||||
.multiply(BigDecimal.valueOf(getHeight()))
|
||||
.setScale(0, RoundingMode.FLOOR)
|
||||
.longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return (int) (2 * radius.getX());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return maxY - minY + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return (int) (2 * radius.getZ());
|
||||
}
|
||||
|
||||
private BlockVector2 calculateDiff2D(BlockVector3... changes) throws RegionOperationException {
|
||||
BlockVector2 diff = BlockVector2.ZERO;
|
||||
for (BlockVector3 change : changes) {
|
||||
diff = diff.add(change.toBlockVector2());
|
||||
}
|
||||
|
||||
if ((diff.getBlockX() & 1) + (diff.getBlockZ() & 1) != 0) {
|
||||
throw new RegionOperationException(TranslatableComponent.of("worldedit.selection.cylinder.error.even-horizontal"));
|
||||
}
|
||||
|
||||
return diff.divide(2).floor();
|
||||
}
|
||||
|
||||
private BlockVector2 calculateChanges2D(BlockVector3... changes) {
|
||||
BlockVector2 total = BlockVector2.ZERO;
|
||||
for (BlockVector3 change : changes) {
|
||||
total = total.add(change.toBlockVector2().abs());
|
||||
}
|
||||
|
||||
return total.divide(2).floor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the region.
|
||||
* Expand the region.
|
||||
*
|
||||
* @param changes array/arguments with multiple related changes
|
||||
*/
|
||||
@Override
|
||||
public void expand(BlockVector3... changes) throws RegionOperationException {
|
||||
center = center.add(calculateDiff2D(changes));
|
||||
radius = radius.add(calculateChanges2D(changes).toVector2());
|
||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
||||
for (BlockVector3 change : changes) {
|
||||
int changeY = change.getBlockY();
|
||||
if (changeY > 0) {
|
||||
maxY += changeY;
|
||||
} else {
|
||||
minY += changeY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract the region.
|
||||
*
|
||||
* @param changes array/arguments with multiple related changes
|
||||
* @throws RegionOperationException
|
||||
*/
|
||||
@Override
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
center = center.subtract(calculateDiff2D(changes));
|
||||
Vector2 newRadius = radius.subtract(calculateChanges2D(changes).toVector2());
|
||||
radius = Vector2.at(1.5, 1.5).getMaximum(newRadius);
|
||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
||||
for (BlockVector3 change : changes) {
|
||||
int height = maxY - minY;
|
||||
int changeY = change.getBlockY();
|
||||
if (changeY > 0) {
|
||||
minY += Math.min(height, changeY);
|
||||
} else {
|
||||
maxY += Math.max(-height, changeY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
center = center.add(change.toBlockVector2());
|
||||
|
||||
int changeY = change.getBlockY();
|
||||
maxY += changeY;
|
||||
minY += changeY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside this region.
|
||||
*/
|
||||
/* Slow and unnecessary
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
final int blockY = position.getBlockY();
|
||||
if (blockY < minY || blockY > maxY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return position.toBlockVector2().subtract(center).toVector2().divide(radius).lengthSq() <= 1;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside this region.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(int x, int y, int z) {
|
||||
if (y < minY || y > maxY) {
|
||||
return false;
|
||||
}
|
||||
return contains(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int x, int z) {
|
||||
double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX();
|
||||
double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ();
|
||||
|
||||
return dx * dx + dz * dz <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
return contains(position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the height of the cylinder to fit the specified Y.
|
||||
*
|
||||
* @param y the y value
|
||||
* @return true if the area was expanded
|
||||
*/
|
||||
public boolean setY(int y) {
|
||||
if (!hasY) {
|
||||
minY = y;
|
||||
maxY = y;
|
||||
hasY = true;
|
||||
return true;
|
||||
} else if (y < minY) {
|
||||
minY = y;
|
||||
return true;
|
||||
} else if (y > maxY) {
|
||||
maxY = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return new FlatRegion3DIterator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<BlockVector2> asFlatRegion() {
|
||||
return () -> new FlatRegionIterator(CylinderRegion.this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string representation in the format.
|
||||
* "(centerX, centerZ) - (radiusX, radiusZ) - (minY, maxY)"
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return center + " - " + radius + "(" + minY + ", " + maxY + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CylinderRegion clone() {
|
||||
return (CylinderRegion) super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2> polygonize(int maxPoints) {
|
||||
return Polygons.polygonizeCylinder(center, radius, maxPoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance with the given center and radius in the X and Z
|
||||
* axes with a Y that extends from the bottom of the extent to the top
|
||||
* of the extent.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param center the center position
|
||||
* @param radius the radius in the X and Z axes
|
||||
* @return a region
|
||||
*/
|
||||
public static CylinderRegion createRadius(Extent extent, BlockVector3 center, double radius) {
|
||||
checkNotNull(extent);
|
||||
checkNotNull(center);
|
||||
Vector2 radiusVec = Vector2.at(radius, radius);
|
||||
int minY = extent.getMinimumPoint().getBlockY();
|
||||
int maxY = extent.getMaximumPoint().getBlockY();
|
||||
return new CylinderRegion(center, radiusVec, minY, maxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(final IChunk chunk, final Filter filter, final ChunkFilterBlock block,
|
||||
final IChunkGet get, final IChunkSet set, boolean full) {
|
||||
int bcx = chunk.getX() >> 4;
|
||||
int bcz = chunk.getZ() >> 4;
|
||||
int tcx = bcx + 15;
|
||||
int tcz = bcz + 15;
|
||||
if (contains(bcx, bcz) && contains(tcx, tcz)) {
|
||||
filter(chunk, filter, block, get, set, minY, maxY, full);
|
||||
return;
|
||||
}
|
||||
super.filter(chunk, filter, block, get, set, full);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector2;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.geom.Polygons;
|
||||
import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
|
||||
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a cylindrical region.
|
||||
*/
|
||||
public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
||||
|
||||
private BlockVector2 center;
|
||||
private Vector2 radius;
|
||||
private Vector2 radiusInverse;
|
||||
private int minY;
|
||||
private int maxY;
|
||||
private boolean hasY = false;
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*/
|
||||
public CylinderRegion() {
|
||||
this((World) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
public CylinderRegion(World world) {
|
||||
this(world, BlockVector3.ZERO, Vector2.ZERO, 0, 0);
|
||||
hasY = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param world the world
|
||||
* @param center the center position
|
||||
* @param radius the radius along the X and Z axes
|
||||
* @param minY the minimum Y, inclusive
|
||||
* @param maxY the maximum Y, inclusive
|
||||
*/
|
||||
public CylinderRegion(World world, BlockVector3 center, Vector2 radius, int minY, int maxY) {
|
||||
super(world);
|
||||
setCenter(center.toBlockVector2());
|
||||
setRadius(radius);
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
hasY = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the region.
|
||||
*
|
||||
* @param center the center position
|
||||
* @param radius the radius along the X and Z axes
|
||||
* @param minY the minimum Y, inclusive
|
||||
* @param maxY the maximum Y, inclusive
|
||||
*/
|
||||
public CylinderRegion(BlockVector3 center, Vector2 radius, int minY, int maxY) {
|
||||
super(null);
|
||||
setCenter(center.toBlockVector2());
|
||||
setRadius(radius);
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
hasY = true;
|
||||
}
|
||||
|
||||
public CylinderRegion(CylinderRegion region) {
|
||||
this(region.world, region.getCenter().toBlockPoint(), region.getRadius(), region.minY, region.maxY);
|
||||
hasY = region.hasY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return center.toVector3((maxY + minY) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main center point of the region.
|
||||
*
|
||||
* @param center the center point
|
||||
*/
|
||||
public void setCenter(BlockVector2 center) {
|
||||
this.center = center;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the radius of the cylinder.
|
||||
*
|
||||
* @return the radius along the X and Z axes
|
||||
*/
|
||||
public Vector2 getRadius() {
|
||||
return radius.subtract(0.5, 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the radius of the cylinder.
|
||||
*
|
||||
* @param radius the radius along the X and Z axes
|
||||
*/
|
||||
public void setRadius(Vector2 radius) {
|
||||
this.radius = radius.add(0.5, 0.5);
|
||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends the radius to be at least the given radius.
|
||||
*
|
||||
* @param minRadius the minimum radius
|
||||
*/
|
||||
public void extendRadius(Vector2 minRadius) {
|
||||
setRadius(minRadius.getMaximum(getRadius()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum Y.
|
||||
*
|
||||
* @param y the y
|
||||
*/
|
||||
public void setMinimumY(int y) {
|
||||
hasY = true;
|
||||
minY = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Se the maximum Y.
|
||||
*
|
||||
* @param y the y
|
||||
*/
|
||||
public void setMaximumY(int y) {
|
||||
hasY = true;
|
||||
maxY = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return center.toVector2().subtract(getRadius()).toVector3(minY).toBlockPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return center.toVector2().add(getRadius()).toVector3(maxY).toBlockPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumY() {
|
||||
int worldMax = world != null ? world.getMaxY() - 1 : 255;
|
||||
if (maxY > worldMax) {
|
||||
return maxY = worldMax;
|
||||
}
|
||||
return maxY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumY() {
|
||||
if (minY < 0) {
|
||||
return minY = 0;
|
||||
}
|
||||
return minY;
|
||||
}
|
||||
|
||||
private static final BigDecimal PI = BigDecimal.valueOf(Math.PI);
|
||||
|
||||
@Override
|
||||
public long getVolume() {
|
||||
return BigDecimal.valueOf(radius.getX())
|
||||
.multiply(BigDecimal.valueOf(radius.getZ()))
|
||||
.multiply(PI)
|
||||
.multiply(BigDecimal.valueOf(getHeight()))
|
||||
.setScale(0, RoundingMode.FLOOR)
|
||||
.longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return (int) (2 * radius.getX());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return maxY - minY + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return (int) (2 * radius.getZ());
|
||||
}
|
||||
|
||||
private BlockVector2 calculateDiff2D(BlockVector3... changes) throws RegionOperationException {
|
||||
BlockVector2 diff = BlockVector2.ZERO;
|
||||
for (BlockVector3 change : changes) {
|
||||
diff = diff.add(change.toBlockVector2());
|
||||
}
|
||||
|
||||
if ((diff.getBlockX() & 1) + (diff.getBlockZ() & 1) != 0) {
|
||||
throw new RegionOperationException(TranslatableComponent.of("worldedit.selection.cylinder.error.even-horizontal"));
|
||||
}
|
||||
|
||||
return diff.divide(2).floor();
|
||||
}
|
||||
|
||||
private BlockVector2 calculateChanges2D(BlockVector3... changes) {
|
||||
BlockVector2 total = BlockVector2.ZERO;
|
||||
for (BlockVector3 change : changes) {
|
||||
total = total.add(change.toBlockVector2().abs());
|
||||
}
|
||||
|
||||
return total.divide(2).floor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the region.
|
||||
* Expand the region.
|
||||
*
|
||||
* @param changes array/arguments with multiple related changes
|
||||
*/
|
||||
@Override
|
||||
public void expand(BlockVector3... changes) throws RegionOperationException {
|
||||
center = center.add(calculateDiff2D(changes));
|
||||
radius = radius.add(calculateChanges2D(changes).toVector2());
|
||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
||||
for (BlockVector3 change : changes) {
|
||||
int changeY = change.getBlockY();
|
||||
if (changeY > 0) {
|
||||
maxY += changeY;
|
||||
} else {
|
||||
minY += changeY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract the region.
|
||||
*
|
||||
* @param changes array/arguments with multiple related changes
|
||||
* @throws RegionOperationException
|
||||
*/
|
||||
@Override
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
center = center.subtract(calculateDiff2D(changes));
|
||||
Vector2 newRadius = radius.subtract(calculateChanges2D(changes).toVector2());
|
||||
radius = Vector2.at(1.5, 1.5).getMaximum(newRadius);
|
||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
||||
for (BlockVector3 change : changes) {
|
||||
int height = maxY - minY;
|
||||
int changeY = change.getBlockY();
|
||||
if (changeY > 0) {
|
||||
minY += Math.min(height, changeY);
|
||||
} else {
|
||||
maxY += Math.max(-height, changeY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
center = center.add(change.toBlockVector2());
|
||||
|
||||
int changeY = change.getBlockY();
|
||||
maxY += changeY;
|
||||
minY += changeY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside this region.
|
||||
*/
|
||||
/* Slow and unnecessary
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
final int blockY = position.getBlockY();
|
||||
if (blockY < minY || blockY > maxY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return position.toBlockVector2().subtract(center).toVector2().divide(radius).lengthSq() <= 1;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside this region.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(int x, int y, int z) {
|
||||
if (y < minY || y > maxY) {
|
||||
return false;
|
||||
}
|
||||
return contains(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int x, int z) {
|
||||
double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX();
|
||||
double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ();
|
||||
|
||||
return dx * dx + dz * dz <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
return contains(position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the height of the cylinder to fit the specified Y.
|
||||
*
|
||||
* @param y the y value
|
||||
* @return true if the area was expanded
|
||||
*/
|
||||
public boolean setY(int y) {
|
||||
if (!hasY) {
|
||||
minY = y;
|
||||
maxY = y;
|
||||
hasY = true;
|
||||
return true;
|
||||
} else if (y < minY) {
|
||||
minY = y;
|
||||
return true;
|
||||
} else if (y > maxY) {
|
||||
maxY = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return new FlatRegion3DIterator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<BlockVector2> asFlatRegion() {
|
||||
return () -> new FlatRegionIterator(CylinderRegion.this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string representation in the format.
|
||||
* "(centerX, centerZ) - (radiusX, radiusZ) - (minY, maxY)"
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return center + " - " + radius + "(" + minY + ", " + maxY + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CylinderRegion clone() {
|
||||
return (CylinderRegion) super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2> polygonize(int maxPoints) {
|
||||
return Polygons.polygonizeCylinder(center, radius, maxPoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance with the given center and radius in the X and Z
|
||||
* axes with a Y that extends from the bottom of the extent to the top
|
||||
* of the extent.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param center the center position
|
||||
* @param radius the radius in the X and Z axes
|
||||
* @return a region
|
||||
*/
|
||||
public static CylinderRegion createRadius(Extent extent, BlockVector3 center, double radius) {
|
||||
checkNotNull(extent);
|
||||
checkNotNull(center);
|
||||
Vector2 radiusVec = Vector2.at(radius, radius);
|
||||
int minY = extent.getMinimumPoint().getBlockY();
|
||||
int maxY = extent.getMaximumPoint().getBlockY();
|
||||
return new CylinderRegion(center, radiusVec, minY, maxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(final IChunk chunk, final Filter filter, final ChunkFilterBlock block,
|
||||
final IChunkGet get, final IChunkSet set, boolean full) {
|
||||
int bcx = chunk.getX() >> 4;
|
||||
int bcz = chunk.getZ() >> 4;
|
||||
int tcx = bcx + 15;
|
||||
int tcz = bcz + 15;
|
||||
if (contains(bcx, bcz) && contains(tcx, tcz)) {
|
||||
filter(chunk, filter, block, get, set, minY, maxY, full);
|
||||
return;
|
||||
}
|
||||
super.filter(chunk, filter, block, get, set, full);
|
||||
}
|
||||
}
|
||||
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -1,36 +1,36 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
|
||||
public class RegionOperationException extends WorldEditException {
|
||||
|
||||
@Deprecated
|
||||
public RegionOperationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public RegionOperationException(Component msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
|
||||
public class RegionOperationException extends WorldEditException {
|
||||
|
||||
@Deprecated
|
||||
public RegionOperationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public RegionOperationException(Component msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,90 +1,90 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions.polyhedron;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class Edge {
|
||||
|
||||
private final Vector3 start;
|
||||
private final Vector3 end;
|
||||
|
||||
public Edge(Vector3 start, Vector3 end) {
|
||||
checkNotNull(start);
|
||||
checkNotNull(end);
|
||||
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof Edge)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Edge otherEdge = (Edge) other;
|
||||
if ((this.start == otherEdge.end) && (this.end == otherEdge.start)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((this.end == otherEdge.end) && (this.start == otherEdge.start)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return start.hashCode() ^ end.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + this.start + "," + this.end + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a triangle from { this.start, this.end, vertex }
|
||||
*
|
||||
* @param vertex the 3rd vertex for the triangle
|
||||
* @return a triangle
|
||||
*/
|
||||
public Triangle createTriangle(Vector3 vertex) {
|
||||
checkNotNull(vertex);
|
||||
return new Triangle(this.start, this.end, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a triangle from { this.start, vertex, this.end }.
|
||||
*
|
||||
* @param vertex the second vertex
|
||||
* @return a new triangle
|
||||
*/
|
||||
public Triangle createTriangle2(Vector3 vertex) {
|
||||
checkNotNull(vertex);
|
||||
return new Triangle(this.start, vertex, this.end);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions.polyhedron;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class Edge {
|
||||
|
||||
private final Vector3 start;
|
||||
private final Vector3 end;
|
||||
|
||||
public Edge(Vector3 start, Vector3 end) {
|
||||
checkNotNull(start);
|
||||
checkNotNull(end);
|
||||
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof Edge)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Edge otherEdge = (Edge) other;
|
||||
if ((this.start == otherEdge.end) && (this.end == otherEdge.start)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((this.end == otherEdge.end) && (this.start == otherEdge.start)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return start.hashCode() ^ end.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + this.start + "," + this.end + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a triangle from { this.start, this.end, vertex }
|
||||
*
|
||||
* @param vertex the 3rd vertex for the triangle
|
||||
* @return a triangle
|
||||
*/
|
||||
public Triangle createTriangle(Vector3 vertex) {
|
||||
checkNotNull(vertex);
|
||||
return new Triangle(this.start, this.end, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a triangle from { this.start, vertex, this.end }.
|
||||
*
|
||||
* @param vertex the second vertex
|
||||
* @return a new triangle
|
||||
*/
|
||||
public Triangle createTriangle2(Vector3 vertex) {
|
||||
checkNotNull(vertex);
|
||||
return new Triangle(this.start, vertex, this.end);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,113 +1,113 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions.polyhedron;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class Triangle {
|
||||
|
||||
private String tag = "Triangle";
|
||||
private final Vector3[] vertices;
|
||||
private final Vector3 normal;
|
||||
private final double maxDotProduct;
|
||||
|
||||
/**
|
||||
* Constructs a triangle with the given vertices (counter-clockwise).
|
||||
*
|
||||
* @param v0 first vertex
|
||||
* @param v1 second vertex
|
||||
* @param v2 third vertex
|
||||
*/
|
||||
public Triangle(Vector3 v0, Vector3 v1, Vector3 v2) {
|
||||
checkNotNull(v0);
|
||||
checkNotNull(v1);
|
||||
checkNotNull(v2);
|
||||
|
||||
vertices = new Vector3[] { v0, v1, v2 };
|
||||
|
||||
this.normal = v1.subtract(v0).cross(v2.subtract(v0)).normalize();
|
||||
this.maxDotProduct = Math.max(Math.max(normal.dot(v0), normal.dot(v1)), normal.dot(v2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the triangle's vertex with the given index, counter-clockwise.
|
||||
*
|
||||
* @param index Vertex index. Valid input: 0..2
|
||||
* @return a vertex
|
||||
*/
|
||||
public Vector3 getVertex(int index) {
|
||||
return vertices[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the triangle's edge with the given index, counter-clockwise.
|
||||
*
|
||||
* @param index Edge index. Valid input: 0..2
|
||||
* @return an edge
|
||||
*/
|
||||
public Edge getEdge(int index) {
|
||||
if (index == vertices.length - 1) {
|
||||
return new Edge(vertices[index], vertices[0]);
|
||||
}
|
||||
return new Edge(vertices[index], vertices[index + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given point is above the plane the triangle is in.
|
||||
*
|
||||
* @param pt the point to test
|
||||
* @return true if the point is below
|
||||
*/
|
||||
public boolean below(Vector3 pt) {
|
||||
checkNotNull(pt);
|
||||
return normal.dot(pt) < maxDotProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given point is above the plane the triangle is in.
|
||||
*
|
||||
* @param pt the point to test
|
||||
* @return true if the point is above
|
||||
*/
|
||||
public boolean above(Vector3 pt) {
|
||||
checkNotNull(pt);
|
||||
return normal.dot(pt) > maxDotProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the triangle's tag.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @return this object
|
||||
*/
|
||||
public Triangle tag(String tag) {
|
||||
checkNotNull(tag);
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return tag + "(" + this.vertices[0] + "," + this.vertices[1] + "," + this.vertices[2] + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions.polyhedron;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class Triangle {
|
||||
|
||||
private String tag = "Triangle";
|
||||
private final Vector3[] vertices;
|
||||
private final Vector3 normal;
|
||||
private final double maxDotProduct;
|
||||
|
||||
/**
|
||||
* Constructs a triangle with the given vertices (counter-clockwise).
|
||||
*
|
||||
* @param v0 first vertex
|
||||
* @param v1 second vertex
|
||||
* @param v2 third vertex
|
||||
*/
|
||||
public Triangle(Vector3 v0, Vector3 v1, Vector3 v2) {
|
||||
checkNotNull(v0);
|
||||
checkNotNull(v1);
|
||||
checkNotNull(v2);
|
||||
|
||||
vertices = new Vector3[] { v0, v1, v2 };
|
||||
|
||||
this.normal = v1.subtract(v0).cross(v2.subtract(v0)).normalize();
|
||||
this.maxDotProduct = Math.max(Math.max(normal.dot(v0), normal.dot(v1)), normal.dot(v2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the triangle's vertex with the given index, counter-clockwise.
|
||||
*
|
||||
* @param index Vertex index. Valid input: 0..2
|
||||
* @return a vertex
|
||||
*/
|
||||
public Vector3 getVertex(int index) {
|
||||
return vertices[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the triangle's edge with the given index, counter-clockwise.
|
||||
*
|
||||
* @param index Edge index. Valid input: 0..2
|
||||
* @return an edge
|
||||
*/
|
||||
public Edge getEdge(int index) {
|
||||
if (index == vertices.length - 1) {
|
||||
return new Edge(vertices[index], vertices[0]);
|
||||
}
|
||||
return new Edge(vertices[index], vertices[index + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given point is above the plane the triangle is in.
|
||||
*
|
||||
* @param pt the point to test
|
||||
* @return true if the point is below
|
||||
*/
|
||||
public boolean below(Vector3 pt) {
|
||||
checkNotNull(pt);
|
||||
return normal.dot(pt) < maxDotProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given point is above the plane the triangle is in.
|
||||
*
|
||||
* @param pt the point to test
|
||||
* @return true if the point is above
|
||||
*/
|
||||
public boolean above(Vector3 pt) {
|
||||
checkNotNull(pt);
|
||||
return normal.dot(pt) > maxDotProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the triangle's tag.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @return this object
|
||||
*/
|
||||
public Triangle tag(String tag) {
|
||||
checkNotNull(tag);
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return tag + "(" + this.vertices[0] + "," + this.vertices[1] + "," + this.vertices[2] + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,274 +1,274 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.InsufficientArgumentsException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
|
||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.expression.invoke.ReturnException;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.util.io.file.FilenameException;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The context given to scripts.
|
||||
*/
|
||||
public class CraftScriptContext extends CraftScriptEnvironment {
|
||||
|
||||
private final List<EditSession> editSessions = new ArrayList<>();
|
||||
private final String[] args;
|
||||
|
||||
public CraftScriptContext(WorldEdit controller,
|
||||
Platform server, LocalConfiguration config,
|
||||
LocalSession session, Player player, String[] args) {
|
||||
super(controller, server, config, session, player);
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an edit session. Every subsequent call returns a new edit session.
|
||||
* Usually you only need to use one edit session.
|
||||
*
|
||||
* @return an edit session
|
||||
*/
|
||||
public EditSession remember() {
|
||||
EditSession editSession = controller.getEditSessionFactory()
|
||||
.getEditSession(player.getWorld(),
|
||||
session.getBlockChangeLimit(), session.getBlockBag(player), player);
|
||||
Request.request().setEditSession(editSession);
|
||||
editSession.enableStandardMode();
|
||||
editSessions.add(editSession);
|
||||
return editSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the calling player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player's session.
|
||||
*
|
||||
* @return a session
|
||||
*/
|
||||
public LocalSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration for WorldEdit.
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public LocalConfiguration getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of edit sessions that have been created.
|
||||
*
|
||||
* @return a list of created {@code EditSession}s
|
||||
*/
|
||||
public List<EditSession> getEditSessions() {
|
||||
return Collections.unmodifiableList(editSessions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a regular message to the user.
|
||||
*
|
||||
* @param message a message
|
||||
*/
|
||||
public void print(String message) {
|
||||
player.printInfo(TextComponent.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message to the user.
|
||||
*
|
||||
* @param message a message
|
||||
*/
|
||||
public void error(String message) {
|
||||
player.printError(TextComponent.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a raw message to the user.
|
||||
*
|
||||
* @param message a message
|
||||
*/
|
||||
public void printRaw(String message) {
|
||||
player.print(TextComponent.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to make sure that there are enough but not too many arguments.
|
||||
*
|
||||
* @param min a number of arguments
|
||||
* @param max -1 for no maximum
|
||||
* @param usage usage string
|
||||
* @throws InsufficientArgumentsException if the arguments are not "sufficiently" good
|
||||
*/
|
||||
public void checkArgs(int min, int max, String usage)
|
||||
throws InsufficientArgumentsException {
|
||||
if (args.length <= min || (max != -1 && args.length - 1 > max)) {
|
||||
throw new InsufficientArgumentsException(TranslatableComponent.of("worldedit.error.incorrect-usage", TextComponent.of(usage)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately terminate execution of the script, but without a failure message.
|
||||
*
|
||||
* @implNote This exits by throwing an exception, which if caught will prevent
|
||||
* the script from exiting
|
||||
*/
|
||||
public void exit() {
|
||||
throw new ReturnException(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an item name or an item ID number.
|
||||
*
|
||||
* @param input input to parse
|
||||
* @param allAllowed true to ignore blacklists
|
||||
* @return a block
|
||||
* @throws NoMatchException if no block was found
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public BaseBlock getBlock(String input, boolean allAllowed) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(!allAllowed);
|
||||
context.setPreferringWildcard(false);
|
||||
|
||||
return controller.getBlockFactory().parseFromListInput(input, context).stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a block.
|
||||
*
|
||||
* @param id the type Id
|
||||
* @return a block
|
||||
* @throws NoMatchException if no block was found
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public BaseBlock getBlock(String id) throws WorldEditException {
|
||||
return getBlock(id, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of blocks as a set. This returns a Pattern.
|
||||
*
|
||||
* @param list the input
|
||||
* @return pattern
|
||||
* @throws NoMatchException if the pattern was invalid
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public Pattern getBlockPattern(String list) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
return controller.getPatternFactory().parseFromInput(list, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of blocks as a set.
|
||||
*
|
||||
* @param list a list
|
||||
* @param allBlocksAllowed true if all blocks are allowed
|
||||
* @return set
|
||||
* @throws NoMatchException if the blocks couldn't be found
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public Set<BaseBlock> getBlocks(String list, boolean allBlocksAllowed) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(!allBlocksAllowed);
|
||||
return controller.getBlockFactory().parseFromListInput(list, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to a file for opening. This method will check to see if the
|
||||
* filename has valid characters and has an extension. It also prevents
|
||||
* directory traversal exploits by checking the root directory and the file
|
||||
* directory. On success, a {@code java.io.File} object will be
|
||||
* returned.
|
||||
*
|
||||
* <p>Use this method if you need to read a file from a directory.</p>
|
||||
*
|
||||
* @param folder sub-directory to look in
|
||||
* @param filename filename (user-submitted)
|
||||
* @param defaultExt default extension to append if there is none
|
||||
* @param exts list of extensions for file open dialog, null for no filter
|
||||
* @return a file
|
||||
* @throws FilenameException if there is a problem with the name of the file
|
||||
*/
|
||||
public File getSafeOpenFile(String folder, String filename, String defaultExt, String... exts) throws FilenameException {
|
||||
File dir = controller.getWorkingDirectoryFile(folder);
|
||||
return controller.getSafeOpenFile(player, dir, filename, defaultExt, exts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to a file for saving. This method will check to see if the
|
||||
* filename has valid characters and has an extension. It also prevents
|
||||
* directory traversal exploits by checking the root directory and the file
|
||||
* directory. On success, a {@code java.io.File} object will be
|
||||
* returned.
|
||||
*
|
||||
* <p>Use this method if you need to read a file from a directory.</p>
|
||||
*
|
||||
* @param folder sub-directory to look in
|
||||
* @param filename filename (user-submitted)
|
||||
* @param defaultExt default extension to append if there is none
|
||||
* @param exts list of extensions for file save dialog, null for no filter
|
||||
* @return a file
|
||||
* @throws FilenameException if there is a problem with the name of the file
|
||||
*/
|
||||
public File getSafeSaveFile(String folder, String filename, String defaultExt, String... exts) throws FilenameException {
|
||||
File dir = controller.getWorkingDirectoryFile(folder);
|
||||
return controller.getSafeSaveFile(player, dir, filename, defaultExt, exts);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.InsufficientArgumentsException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
|
||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.expression.invoke.ReturnException;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.util.io.file.FilenameException;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The context given to scripts.
|
||||
*/
|
||||
public class CraftScriptContext extends CraftScriptEnvironment {
|
||||
|
||||
private final List<EditSession> editSessions = new ArrayList<>();
|
||||
private final String[] args;
|
||||
|
||||
public CraftScriptContext(WorldEdit controller,
|
||||
Platform server, LocalConfiguration config,
|
||||
LocalSession session, Player player, String[] args) {
|
||||
super(controller, server, config, session, player);
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an edit session. Every subsequent call returns a new edit session.
|
||||
* Usually you only need to use one edit session.
|
||||
*
|
||||
* @return an edit session
|
||||
*/
|
||||
public EditSession remember() {
|
||||
EditSession editSession = controller.getEditSessionFactory()
|
||||
.getEditSession(player.getWorld(),
|
||||
session.getBlockChangeLimit(), session.getBlockBag(player), player);
|
||||
Request.request().setEditSession(editSession);
|
||||
editSession.enableStandardMode();
|
||||
editSessions.add(editSession);
|
||||
return editSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the calling player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player's session.
|
||||
*
|
||||
* @return a session
|
||||
*/
|
||||
public LocalSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration for WorldEdit.
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public LocalConfiguration getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of edit sessions that have been created.
|
||||
*
|
||||
* @return a list of created {@code EditSession}s
|
||||
*/
|
||||
public List<EditSession> getEditSessions() {
|
||||
return Collections.unmodifiableList(editSessions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a regular message to the user.
|
||||
*
|
||||
* @param message a message
|
||||
*/
|
||||
public void print(String message) {
|
||||
player.printInfo(TextComponent.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message to the user.
|
||||
*
|
||||
* @param message a message
|
||||
*/
|
||||
public void error(String message) {
|
||||
player.printError(TextComponent.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a raw message to the user.
|
||||
*
|
||||
* @param message a message
|
||||
*/
|
||||
public void printRaw(String message) {
|
||||
player.print(TextComponent.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to make sure that there are enough but not too many arguments.
|
||||
*
|
||||
* @param min a number of arguments
|
||||
* @param max -1 for no maximum
|
||||
* @param usage usage string
|
||||
* @throws InsufficientArgumentsException if the arguments are not "sufficiently" good
|
||||
*/
|
||||
public void checkArgs(int min, int max, String usage)
|
||||
throws InsufficientArgumentsException {
|
||||
if (args.length <= min || (max != -1 && args.length - 1 > max)) {
|
||||
throw new InsufficientArgumentsException(TranslatableComponent.of("worldedit.error.incorrect-usage", TextComponent.of(usage)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately terminate execution of the script, but without a failure message.
|
||||
*
|
||||
* @implNote This exits by throwing an exception, which if caught will prevent
|
||||
* the script from exiting
|
||||
*/
|
||||
public void exit() {
|
||||
throw new ReturnException(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an item name or an item ID number.
|
||||
*
|
||||
* @param input input to parse
|
||||
* @param allAllowed true to ignore blacklists
|
||||
* @return a block
|
||||
* @throws NoMatchException if no block was found
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public BaseBlock getBlock(String input, boolean allAllowed) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(!allAllowed);
|
||||
context.setPreferringWildcard(false);
|
||||
|
||||
return controller.getBlockFactory().parseFromListInput(input, context).stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a block.
|
||||
*
|
||||
* @param id the type Id
|
||||
* @return a block
|
||||
* @throws NoMatchException if no block was found
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public BaseBlock getBlock(String id) throws WorldEditException {
|
||||
return getBlock(id, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of blocks as a set. This returns a Pattern.
|
||||
*
|
||||
* @param list the input
|
||||
* @return pattern
|
||||
* @throws NoMatchException if the pattern was invalid
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public Pattern getBlockPattern(String list) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
return controller.getPatternFactory().parseFromInput(list, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of blocks as a set.
|
||||
*
|
||||
* @param list a list
|
||||
* @param allBlocksAllowed true if all blocks are allowed
|
||||
* @return set
|
||||
* @throws NoMatchException if the blocks couldn't be found
|
||||
* @throws DisallowedUsageException if the block is disallowed
|
||||
*/
|
||||
public Set<BaseBlock> getBlocks(String list, boolean allBlocksAllowed) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(!allBlocksAllowed);
|
||||
return controller.getBlockFactory().parseFromListInput(list, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to a file for opening. This method will check to see if the
|
||||
* filename has valid characters and has an extension. It also prevents
|
||||
* directory traversal exploits by checking the root directory and the file
|
||||
* directory. On success, a {@code java.io.File} object will be
|
||||
* returned.
|
||||
*
|
||||
* <p>Use this method if you need to read a file from a directory.</p>
|
||||
*
|
||||
* @param folder sub-directory to look in
|
||||
* @param filename filename (user-submitted)
|
||||
* @param defaultExt default extension to append if there is none
|
||||
* @param exts list of extensions for file open dialog, null for no filter
|
||||
* @return a file
|
||||
* @throws FilenameException if there is a problem with the name of the file
|
||||
*/
|
||||
public File getSafeOpenFile(String folder, String filename, String defaultExt, String... exts) throws FilenameException {
|
||||
File dir = controller.getWorkingDirectoryFile(folder);
|
||||
return controller.getSafeOpenFile(player, dir, filename, defaultExt, exts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to a file for saving. This method will check to see if the
|
||||
* filename has valid characters and has an extension. It also prevents
|
||||
* directory traversal exploits by checking the root directory and the file
|
||||
* directory. On success, a {@code java.io.File} object will be
|
||||
* returned.
|
||||
*
|
||||
* <p>Use this method if you need to read a file from a directory.</p>
|
||||
*
|
||||
* @param folder sub-directory to look in
|
||||
* @param filename filename (user-submitted)
|
||||
* @param defaultExt default extension to append if there is none
|
||||
* @param exts list of extensions for file save dialog, null for no filter
|
||||
* @return a file
|
||||
* @throws FilenameException if there is a problem with the name of the file
|
||||
*/
|
||||
public File getSafeSaveFile(String folder, String filename, String defaultExt, String... exts) throws FilenameException {
|
||||
File dir = controller.getWorkingDirectoryFile(folder);
|
||||
return controller.getSafeSaveFile(player, dir, filename, defaultExt, exts);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public interface CraftScriptEngine {
|
||||
void setTimeLimit(int milliseconds);
|
||||
|
||||
int getTimeLimit();
|
||||
|
||||
Object evaluate(String script, String filename, Map<String, Object> args)
|
||||
throws ScriptException, Throwable;
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public interface CraftScriptEngine {
|
||||
void setTimeLimit(int milliseconds);
|
||||
|
||||
int getTimeLimit();
|
||||
|
||||
Object evaluate(String script, String filename, Map<String, Object> args)
|
||||
throws ScriptException, Throwable;
|
||||
}
|
||||
|
@ -1,44 +1,44 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
|
||||
public abstract class CraftScriptEnvironment {
|
||||
|
||||
protected WorldEdit controller;
|
||||
protected Player player;
|
||||
protected LocalConfiguration config;
|
||||
protected LocalSession session;
|
||||
protected Platform server;
|
||||
|
||||
public CraftScriptEnvironment(WorldEdit controller, Platform server, LocalConfiguration config, LocalSession session, Player player) {
|
||||
this.controller = controller;
|
||||
this.player = player;
|
||||
this.config = config;
|
||||
this.server = server;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
|
||||
public abstract class CraftScriptEnvironment {
|
||||
|
||||
protected WorldEdit controller;
|
||||
protected Player player;
|
||||
protected LocalConfiguration config;
|
||||
protected LocalSession session;
|
||||
protected Platform server;
|
||||
|
||||
public CraftScriptEnvironment(WorldEdit controller, Platform server, LocalConfiguration config, LocalSession session, Player player) {
|
||||
this.controller = controller;
|
||||
this.player = player;
|
||||
this.config = config;
|
||||
this.server = server;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,77 +1,77 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import org.mozilla.javascript.Callable;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
public class RhinoContextFactory extends ContextFactory {
|
||||
|
||||
protected int timeLimit;
|
||||
|
||||
public RhinoContextFactory(int timeLimit) {
|
||||
this.timeLimit = timeLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Context makeContext() {
|
||||
RhinoContext cx = new RhinoContext(this);
|
||||
try {
|
||||
// Try to set ES6 compat flag (since 1.7.7)
|
||||
Context.class.getDeclaredField("VERSION_ES6");
|
||||
cx.setLanguageVersion(RhinoContext.VERSION_ES6);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// best we can do, compatible with 1.7R2 that many people probably use
|
||||
cx.setLanguageVersion(Context.VERSION_1_7);
|
||||
}
|
||||
cx.setInstructionObserverThreshold(10000);
|
||||
return cx;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void observeInstructionCount(Context cx, int instructionCount) {
|
||||
RhinoContext mcx = (RhinoContext) cx;
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
if (currentTime - mcx.startTime > timeLimit) {
|
||||
throw new Error("Script timed out (" + timeLimit + "ms)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doTopCall(Callable callable, Context cx, Scriptable scope,
|
||||
Scriptable thisObj, Object[] args) {
|
||||
RhinoContext mcx = (RhinoContext) cx;
|
||||
mcx.startTime = System.currentTimeMillis();
|
||||
|
||||
return super.doTopCall(callable, cx, scope, thisObj, args);
|
||||
}
|
||||
|
||||
private static class RhinoContext extends Context {
|
||||
long startTime;
|
||||
|
||||
private RhinoContext(ContextFactory factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import org.mozilla.javascript.Callable;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
public class RhinoContextFactory extends ContextFactory {
|
||||
|
||||
protected int timeLimit;
|
||||
|
||||
public RhinoContextFactory(int timeLimit) {
|
||||
this.timeLimit = timeLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Context makeContext() {
|
||||
RhinoContext cx = new RhinoContext(this);
|
||||
try {
|
||||
// Try to set ES6 compat flag (since 1.7.7)
|
||||
Context.class.getDeclaredField("VERSION_ES6");
|
||||
cx.setLanguageVersion(RhinoContext.VERSION_ES6);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// best we can do, compatible with 1.7R2 that many people probably use
|
||||
cx.setLanguageVersion(Context.VERSION_1_7);
|
||||
}
|
||||
cx.setInstructionObserverThreshold(10000);
|
||||
return cx;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void observeInstructionCount(Context cx, int instructionCount) {
|
||||
RhinoContext mcx = (RhinoContext) cx;
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
if (currentTime - mcx.startTime > timeLimit) {
|
||||
throw new Error("Script timed out (" + timeLimit + "ms)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doTopCall(Callable callable, Context cx, Scriptable scope,
|
||||
Scriptable thisObj, Object[] args) {
|
||||
RhinoContext mcx = (RhinoContext) cx;
|
||||
mcx.startTime = System.currentTimeMillis();
|
||||
|
||||
return super.doTopCall(callable, cx, scope, thisObj, args);
|
||||
}
|
||||
|
||||
private static class RhinoContext extends Context {
|
||||
long startTime;
|
||||
|
||||
private RhinoContext(ContextFactory factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,98 +1,98 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.scripting.compat.BabelScriptTranspiler;
|
||||
import com.sk89q.worldedit.scripting.compat.ScriptTranspiler;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ImporterTopLevel;
|
||||
import org.mozilla.javascript.JavaScriptException;
|
||||
import org.mozilla.javascript.RhinoException;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.WrappedException;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public class RhinoCraftScriptEngine implements CraftScriptEngine {
|
||||
|
||||
private static final ScriptTranspiler TRANSPILER = new BabelScriptTranspiler();
|
||||
private int timeLimit;
|
||||
|
||||
@Override
|
||||
public void setTimeLimit(int milliseconds) {
|
||||
timeLimit = milliseconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeLimit() {
|
||||
return timeLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(String script, String filename, Map<String, Object> args)
|
||||
throws ScriptException, Throwable {
|
||||
String transpiled = CharStreams.toString(TRANSPILER.transpile(new StringReader(script)));
|
||||
RhinoContextFactory factory = new RhinoContextFactory(timeLimit);
|
||||
Context cx = factory.enterContext();
|
||||
cx.setClassShutter(new MinecraftHidingClassShutter());
|
||||
ScriptableObject scriptable = new ImporterTopLevel(cx);
|
||||
Scriptable scope = cx.initStandardObjects(scriptable);
|
||||
|
||||
for (Map.Entry<String, Object> entry : args.entrySet()) {
|
||||
ScriptableObject.putProperty(scope, entry.getKey(),
|
||||
Context.javaToJS(entry.getValue(), scope));
|
||||
}
|
||||
try {
|
||||
return cx.evaluateString(scope, transpiled, filename, 1, null);
|
||||
} catch (Error e) {
|
||||
throw new ScriptException(e.getMessage());
|
||||
} catch (RhinoException e) {
|
||||
if (e instanceof WrappedException) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof WorldEditException) {
|
||||
throw cause;
|
||||
}
|
||||
}
|
||||
|
||||
String msg;
|
||||
int line = (line = e.lineNumber()) == 0 ? -1 : line;
|
||||
|
||||
if (e instanceof JavaScriptException) {
|
||||
msg = String.valueOf(((JavaScriptException) e).getValue());
|
||||
} else {
|
||||
msg = e.getMessage();
|
||||
}
|
||||
|
||||
ScriptException scriptException =
|
||||
new ScriptException(msg, e.sourceName(), line);
|
||||
scriptException.initCause(e);
|
||||
|
||||
throw scriptException;
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.scripting;
|
||||
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.scripting.compat.BabelScriptTranspiler;
|
||||
import com.sk89q.worldedit.scripting.compat.ScriptTranspiler;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ImporterTopLevel;
|
||||
import org.mozilla.javascript.JavaScriptException;
|
||||
import org.mozilla.javascript.RhinoException;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.WrappedException;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public class RhinoCraftScriptEngine implements CraftScriptEngine {
|
||||
|
||||
private static final ScriptTranspiler TRANSPILER = new BabelScriptTranspiler();
|
||||
private int timeLimit;
|
||||
|
||||
@Override
|
||||
public void setTimeLimit(int milliseconds) {
|
||||
timeLimit = milliseconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeLimit() {
|
||||
return timeLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(String script, String filename, Map<String, Object> args)
|
||||
throws ScriptException, Throwable {
|
||||
String transpiled = CharStreams.toString(TRANSPILER.transpile(new StringReader(script)));
|
||||
RhinoContextFactory factory = new RhinoContextFactory(timeLimit);
|
||||
Context cx = factory.enterContext();
|
||||
cx.setClassShutter(new MinecraftHidingClassShutter());
|
||||
ScriptableObject scriptable = new ImporterTopLevel(cx);
|
||||
Scriptable scope = cx.initStandardObjects(scriptable);
|
||||
|
||||
for (Map.Entry<String, Object> entry : args.entrySet()) {
|
||||
ScriptableObject.putProperty(scope, entry.getKey(),
|
||||
Context.javaToJS(entry.getValue(), scope));
|
||||
}
|
||||
try {
|
||||
return cx.evaluateString(scope, transpiled, filename, 1, null);
|
||||
} catch (Error e) {
|
||||
throw new ScriptException(e.getMessage());
|
||||
} catch (RhinoException e) {
|
||||
if (e instanceof WrappedException) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof WorldEditException) {
|
||||
throw cause;
|
||||
}
|
||||
}
|
||||
|
||||
String msg;
|
||||
int line = (line = e.lineNumber()) == 0 ? -1 : line;
|
||||
|
||||
if (e instanceof JavaScriptException) {
|
||||
msg = String.valueOf(((JavaScriptException) e).getValue());
|
||||
} else {
|
||||
msg = e.getMessage();
|
||||
}
|
||||
|
||||
ScriptException scriptException =
|
||||
new ScriptException(msg, e.sourceName(), line);
|
||||
scriptException.initCause(e);
|
||||
|
||||
throw scriptException;
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,96 +1,96 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.util.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
public final class FileDialogUtil {
|
||||
private FileDialogUtil() {
|
||||
}
|
||||
|
||||
public static File showSaveDialog(String[] exts) {
|
||||
JFileChooser dialog = new JFileChooser();
|
||||
|
||||
if (exts != null) {
|
||||
dialog.setFileFilter(new ExtensionFilter(exts));
|
||||
}
|
||||
|
||||
int returnVal = dialog.showSaveDialog(null);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
return dialog.getSelectedFile();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static File showOpenDialog(String[] exts) {
|
||||
JFileChooser dialog = new JFileChooser();
|
||||
|
||||
if (exts != null) {
|
||||
dialog.setFileFilter(new ExtensionFilter(exts));
|
||||
}
|
||||
|
||||
int returnVal = dialog.showOpenDialog(null);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
return dialog.getSelectedFile();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ExtensionFilter extends FileFilter {
|
||||
private Set<String> exts;
|
||||
private String desc;
|
||||
|
||||
private ExtensionFilter(String[] exts) {
|
||||
this.exts = new HashSet<>(Arrays.asList(exts));
|
||||
|
||||
desc = StringUtil.joinString(exts, ",");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String path = f.getPath();
|
||||
int index = path.lastIndexOf('.');
|
||||
if (index == -1 || index == path.length() - 1) {
|
||||
return false;
|
||||
} else {
|
||||
return exts.contains(path.substring(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.util.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
public final class FileDialogUtil {
|
||||
private FileDialogUtil() {
|
||||
}
|
||||
|
||||
public static File showSaveDialog(String[] exts) {
|
||||
JFileChooser dialog = new JFileChooser();
|
||||
|
||||
if (exts != null) {
|
||||
dialog.setFileFilter(new ExtensionFilter(exts));
|
||||
}
|
||||
|
||||
int returnVal = dialog.showSaveDialog(null);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
return dialog.getSelectedFile();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static File showOpenDialog(String[] exts) {
|
||||
JFileChooser dialog = new JFileChooser();
|
||||
|
||||
if (exts != null) {
|
||||
dialog.setFileFilter(new ExtensionFilter(exts));
|
||||
}
|
||||
|
||||
int returnVal = dialog.showOpenDialog(null);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
return dialog.getSelectedFile();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ExtensionFilter extends FileFilter {
|
||||
private Set<String> exts;
|
||||
private String desc;
|
||||
|
||||
private ExtensionFilter(String[] exts) {
|
||||
this.exts = new HashSet<>(Arrays.asList(exts));
|
||||
|
||||
desc = StringUtil.joinString(exts, ",");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String path = f.getPath();
|
||||
int index = path.lastIndexOf('.');
|
||||
if (index == -1 || index == path.length() - 1) {
|
||||
return false;
|
||||
} else {
|
||||
return exts.contains(path.substring(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,250 +1,250 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.SolidBlockMask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class uses an inefficient method to figure out what block a player
|
||||
* is looking towards.
|
||||
*
|
||||
* <p>Originally written by toi. It was ported to WorldEdit and trimmed down by
|
||||
* sk89q. Thanks to Raphfrk for optimization of toi's original class.</p>
|
||||
*/
|
||||
public class TargetBlock {
|
||||
|
||||
private final Extent world;
|
||||
|
||||
private int maxDistance;
|
||||
private double checkDistance, curDistance;
|
||||
private BlockVector3 targetPos = BlockVector3.ZERO;
|
||||
private Vector3 targetPosDouble = Vector3.ZERO;
|
||||
private BlockVector3 prevPos = BlockVector3.ZERO;
|
||||
private Vector3 offset = Vector3.ZERO;
|
||||
|
||||
// the mask which dictates when to stop a trace - defaults to stopping at non-air blocks
|
||||
private Mask stopMask;
|
||||
// the mask which dictates when to stop a solid block trace - default to BlockMaterial#isMovementBlocker
|
||||
private Mask solidMask;
|
||||
|
||||
/**
|
||||
* Constructor requiring a player, uses default values
|
||||
*
|
||||
* @param player player to work with
|
||||
*/
|
||||
public TargetBlock(Player player) {
|
||||
this(player, 300, 0.2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor requiring a player, max distance and a checking distance
|
||||
*
|
||||
* @param player Player to work with
|
||||
* @param maxDistance how far it checks for blocks
|
||||
* @param checkDistance how often to check for blocks, the smaller the more precise
|
||||
*/
|
||||
public TargetBlock(Player player, int maxDistance, double checkDistance) {
|
||||
this(player, player.getWorld(), maxDistance, checkDistance);
|
||||
}
|
||||
|
||||
public TargetBlock(Player player, Extent extent, int maxDistance, double checkDistance) {
|
||||
this.world = player.getWorld();
|
||||
this.setValues(player.getLocation().toVector(), player.getLocation().getYaw(), player.getLocation().getPitch(), maxDistance, 1.65, checkDistance);
|
||||
this.stopMask = new ExistingBlockMask(world);
|
||||
this.solidMask = new SolidBlockMask(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mask used for determine where to stop traces.
|
||||
* Setting to null will restore the default.
|
||||
*
|
||||
* @param stopMask the mask used to stop traces
|
||||
*/
|
||||
public void setStopMask(@Nullable Mask stopMask) {
|
||||
if (stopMask == null) {
|
||||
this.stopMask = new ExistingBlockMask(world);
|
||||
} else {
|
||||
this.stopMask = stopMask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mask used for determine where to stop solid block traces.
|
||||
* Setting to null will restore the default.
|
||||
*
|
||||
* @param solidMask the mask used to stop solid block traces
|
||||
*/
|
||||
public void setSolidMask(@Nullable Mask solidMask) {
|
||||
if (solidMask == null) {
|
||||
this.solidMask = new SolidBlockMask(world);
|
||||
} else {
|
||||
this.solidMask = solidMask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the values, all constructors uses this function
|
||||
*
|
||||
* @param loc location of the view
|
||||
* @param xRotation the X rotation
|
||||
* @param yRotation the Y rotation
|
||||
* @param maxDistance how far it checks for blocks
|
||||
* @param viewHeight where the view is positioned in y-axis
|
||||
* @param checkDistance how often to check for blocks, the smaller the more precise
|
||||
*/
|
||||
private void setValues(Vector3 loc, double xRotation, double yRotation, int maxDistance, double viewHeight, double checkDistance) {
|
||||
this.maxDistance = maxDistance;
|
||||
this.checkDistance = checkDistance;
|
||||
this.curDistance = 0;
|
||||
xRotation = (xRotation + 90) % 360;
|
||||
yRotation *= -1;
|
||||
|
||||
double h = (checkDistance * Math.cos(Math.toRadians(yRotation)));
|
||||
|
||||
offset = Vector3.at((h * Math.cos(Math.toRadians(xRotation))),
|
||||
(checkDistance * Math.sin(Math.toRadians(yRotation))),
|
||||
(h * Math.sin(Math.toRadians(xRotation))));
|
||||
|
||||
targetPosDouble = loc.add(0, viewHeight, 0);
|
||||
targetPos = targetPosDouble.toBlockPoint();
|
||||
prevPos = targetPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any block at the sight. Returns null if out of range or if no
|
||||
* viable target was found. Will try to return the last valid air block it finds.
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getAnyTargetBlock() {
|
||||
boolean searchForLastBlock = true;
|
||||
Location lastBlock = null;
|
||||
while (getNextBlock() != null) {
|
||||
if (stopMask.test(world, targetPos)) {
|
||||
break;
|
||||
} else {
|
||||
if (searchForLastBlock) {
|
||||
lastBlock = getCurrentBlock();
|
||||
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
|
||||
searchForLastBlock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Location currentBlock = getCurrentBlock();
|
||||
return (currentBlock != null ? currentBlock : lastBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block at the sight. Returns null if out of range or if no
|
||||
* viable target was found
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getTargetBlock() {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (getNextBlock() != null && !stopMask.test(world, targetPos)) ;
|
||||
return getCurrentBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block at the sight. Returns null if out of range or if no
|
||||
* viable target was found
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getSolidTargetBlock() {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (getNextBlock() != null && !solidMask.test(world, targetPos)) ;
|
||||
return getCurrentBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next block
|
||||
*
|
||||
* @return next block position
|
||||
*/
|
||||
public Location getNextBlock() {
|
||||
prevPos = targetPos;
|
||||
do {
|
||||
curDistance += checkDistance;
|
||||
|
||||
targetPosDouble = offset.add(targetPosDouble.getX(),
|
||||
targetPosDouble.getY(),
|
||||
targetPosDouble.getZ());
|
||||
targetPos = targetPosDouble.toBlockPoint();
|
||||
} while (curDistance <= maxDistance
|
||||
&& targetPos.getBlockX() == prevPos.getBlockX()
|
||||
&& targetPos.getBlockY() == prevPos.getBlockY()
|
||||
&& targetPos.getBlockZ() == prevPos.getBlockZ());
|
||||
|
||||
if (curDistance > maxDistance) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Location(world, targetPos.toVector3());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current block along the line of vision
|
||||
*
|
||||
* @return block position
|
||||
*/
|
||||
public Location getCurrentBlock() {
|
||||
if (curDistance > maxDistance) {
|
||||
return null;
|
||||
} else {
|
||||
return new Location(world, targetPos.toVector3());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous block in the aimed path
|
||||
*
|
||||
* @return block position
|
||||
*/
|
||||
public Location getPreviousBlock() {
|
||||
return new Location(world, prevPos.toVector3());
|
||||
}
|
||||
|
||||
public Location getAnyTargetBlockFace() {
|
||||
getAnyTargetBlock();
|
||||
Location current = getCurrentBlock();
|
||||
if (current != null)
|
||||
return current.setDirection(current.toVector().subtract(getPreviousBlock().toVector()));
|
||||
else
|
||||
return new Location(world, targetPos.toVector3(), Float.NaN, Float.NaN);
|
||||
}
|
||||
|
||||
public Location getTargetBlockFace() {
|
||||
getTargetBlock();
|
||||
if (getCurrentBlock() == null) return null;
|
||||
return getCurrentBlock().setDirection(getCurrentBlock().toVector().subtract(getPreviousBlock().toVector()));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.SolidBlockMask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class uses an inefficient method to figure out what block a player
|
||||
* is looking towards.
|
||||
*
|
||||
* <p>Originally written by toi. It was ported to WorldEdit and trimmed down by
|
||||
* sk89q. Thanks to Raphfrk for optimization of toi's original class.</p>
|
||||
*/
|
||||
public class TargetBlock {
|
||||
|
||||
private final Extent world;
|
||||
|
||||
private int maxDistance;
|
||||
private double checkDistance, curDistance;
|
||||
private BlockVector3 targetPos = BlockVector3.ZERO;
|
||||
private Vector3 targetPosDouble = Vector3.ZERO;
|
||||
private BlockVector3 prevPos = BlockVector3.ZERO;
|
||||
private Vector3 offset = Vector3.ZERO;
|
||||
|
||||
// the mask which dictates when to stop a trace - defaults to stopping at non-air blocks
|
||||
private Mask stopMask;
|
||||
// the mask which dictates when to stop a solid block trace - default to BlockMaterial#isMovementBlocker
|
||||
private Mask solidMask;
|
||||
|
||||
/**
|
||||
* Constructor requiring a player, uses default values
|
||||
*
|
||||
* @param player player to work with
|
||||
*/
|
||||
public TargetBlock(Player player) {
|
||||
this(player, 300, 0.2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor requiring a player, max distance and a checking distance
|
||||
*
|
||||
* @param player Player to work with
|
||||
* @param maxDistance how far it checks for blocks
|
||||
* @param checkDistance how often to check for blocks, the smaller the more precise
|
||||
*/
|
||||
public TargetBlock(Player player, int maxDistance, double checkDistance) {
|
||||
this(player, player.getWorld(), maxDistance, checkDistance);
|
||||
}
|
||||
|
||||
public TargetBlock(Player player, Extent extent, int maxDistance, double checkDistance) {
|
||||
this.world = player.getWorld();
|
||||
this.setValues(player.getLocation().toVector(), player.getLocation().getYaw(), player.getLocation().getPitch(), maxDistance, 1.65, checkDistance);
|
||||
this.stopMask = new ExistingBlockMask(world);
|
||||
this.solidMask = new SolidBlockMask(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mask used for determine where to stop traces.
|
||||
* Setting to null will restore the default.
|
||||
*
|
||||
* @param stopMask the mask used to stop traces
|
||||
*/
|
||||
public void setStopMask(@Nullable Mask stopMask) {
|
||||
if (stopMask == null) {
|
||||
this.stopMask = new ExistingBlockMask(world);
|
||||
} else {
|
||||
this.stopMask = stopMask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mask used for determine where to stop solid block traces.
|
||||
* Setting to null will restore the default.
|
||||
*
|
||||
* @param solidMask the mask used to stop solid block traces
|
||||
*/
|
||||
public void setSolidMask(@Nullable Mask solidMask) {
|
||||
if (solidMask == null) {
|
||||
this.solidMask = new SolidBlockMask(world);
|
||||
} else {
|
||||
this.solidMask = solidMask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the values, all constructors uses this function
|
||||
*
|
||||
* @param loc location of the view
|
||||
* @param xRotation the X rotation
|
||||
* @param yRotation the Y rotation
|
||||
* @param maxDistance how far it checks for blocks
|
||||
* @param viewHeight where the view is positioned in y-axis
|
||||
* @param checkDistance how often to check for blocks, the smaller the more precise
|
||||
*/
|
||||
private void setValues(Vector3 loc, double xRotation, double yRotation, int maxDistance, double viewHeight, double checkDistance) {
|
||||
this.maxDistance = maxDistance;
|
||||
this.checkDistance = checkDistance;
|
||||
this.curDistance = 0;
|
||||
xRotation = (xRotation + 90) % 360;
|
||||
yRotation *= -1;
|
||||
|
||||
double h = (checkDistance * Math.cos(Math.toRadians(yRotation)));
|
||||
|
||||
offset = Vector3.at((h * Math.cos(Math.toRadians(xRotation))),
|
||||
(checkDistance * Math.sin(Math.toRadians(yRotation))),
|
||||
(h * Math.sin(Math.toRadians(xRotation))));
|
||||
|
||||
targetPosDouble = loc.add(0, viewHeight, 0);
|
||||
targetPos = targetPosDouble.toBlockPoint();
|
||||
prevPos = targetPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any block at the sight. Returns null if out of range or if no
|
||||
* viable target was found. Will try to return the last valid air block it finds.
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getAnyTargetBlock() {
|
||||
boolean searchForLastBlock = true;
|
||||
Location lastBlock = null;
|
||||
while (getNextBlock() != null) {
|
||||
if (stopMask.test(world, targetPos)) {
|
||||
break;
|
||||
} else {
|
||||
if (searchForLastBlock) {
|
||||
lastBlock = getCurrentBlock();
|
||||
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
|
||||
searchForLastBlock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Location currentBlock = getCurrentBlock();
|
||||
return (currentBlock != null ? currentBlock : lastBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block at the sight. Returns null if out of range or if no
|
||||
* viable target was found
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getTargetBlock() {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (getNextBlock() != null && !stopMask.test(world, targetPos)) ;
|
||||
return getCurrentBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block at the sight. Returns null if out of range or if no
|
||||
* viable target was found
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getSolidTargetBlock() {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (getNextBlock() != null && !solidMask.test(world, targetPos)) ;
|
||||
return getCurrentBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next block
|
||||
*
|
||||
* @return next block position
|
||||
*/
|
||||
public Location getNextBlock() {
|
||||
prevPos = targetPos;
|
||||
do {
|
||||
curDistance += checkDistance;
|
||||
|
||||
targetPosDouble = offset.add(targetPosDouble.getX(),
|
||||
targetPosDouble.getY(),
|
||||
targetPosDouble.getZ());
|
||||
targetPos = targetPosDouble.toBlockPoint();
|
||||
} while (curDistance <= maxDistance
|
||||
&& targetPos.getBlockX() == prevPos.getBlockX()
|
||||
&& targetPos.getBlockY() == prevPos.getBlockY()
|
||||
&& targetPos.getBlockZ() == prevPos.getBlockZ());
|
||||
|
||||
if (curDistance > maxDistance) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Location(world, targetPos.toVector3());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current block along the line of vision
|
||||
*
|
||||
* @return block position
|
||||
*/
|
||||
public Location getCurrentBlock() {
|
||||
if (curDistance > maxDistance) {
|
||||
return null;
|
||||
} else {
|
||||
return new Location(world, targetPos.toVector3());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous block in the aimed path
|
||||
*
|
||||
* @return block position
|
||||
*/
|
||||
public Location getPreviousBlock() {
|
||||
return new Location(world, prevPos.toVector3());
|
||||
}
|
||||
|
||||
public Location getAnyTargetBlockFace() {
|
||||
getAnyTargetBlock();
|
||||
Location current = getCurrentBlock();
|
||||
if (current != null)
|
||||
return current.setDirection(current.toVector().subtract(getPreviousBlock().toVector()));
|
||||
else
|
||||
return new Location(world, targetPos.toVector3(), Float.NaN, Float.NaN);
|
||||
}
|
||||
|
||||
public Location getTargetBlockFace() {
|
||||
getTargetBlock();
|
||||
if (getCurrentBlock() == null) return null;
|
||||
return getCurrentBlock().setDirection(getCurrentBlock().toVector().subtract(getPreviousBlock().toVector()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,270 +1,270 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Tree generator.
|
||||
*/
|
||||
public class TreeGenerator {
|
||||
|
||||
public enum TreeType {
|
||||
TREE("Oak tree", "oak", "tree", "regular"),
|
||||
BIG_TREE("Large oak tree", "largeoak", "bigoak", "big", "bigtree"),
|
||||
REDWOOD("Spruce tree", "spruce", "redwood", "sequoia", "sequoioideae"),
|
||||
TALL_REDWOOD("Tall spruce tree", "tallspruce", "bigspruce", "tallredwood", "tallsequoia", "tallsequoioideae"),
|
||||
MEGA_REDWOOD("Large spruce tree", "largespruce", "megaredwood"),
|
||||
RANDOM_REDWOOD("Random spruce tree", "randspruce", "randredwood", "randomredwood", "anyredwood") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { REDWOOD, TALL_REDWOOD, MEGA_REDWOOD };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
BIRCH("Birch tree", "birch", "white", "whitebark"),
|
||||
TALL_BIRCH("Tall birch tree", "tallbirch"),
|
||||
RANDOM_BIRCH("Random birch tree", "randbirch", "randombirch") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { BIRCH, TALL_BIRCH };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
JUNGLE("Jungle tree", "jungle"),
|
||||
SMALL_JUNGLE("Small jungle tree", "smalljungle"),
|
||||
SHORT_JUNGLE("Short jungle tree", "shortjungle") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
return SMALL_JUNGLE.generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
RANDOM_JUNGLE("Random jungle tree", "randjungle", "randomjungle") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { JUNGLE, SMALL_JUNGLE };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
JUNGLE_BUSH("Jungle bush", "junglebush", "jungleshrub"),
|
||||
RED_MUSHROOM("Red mushroom", "redmushroom", "redgiantmushroom"),
|
||||
BROWN_MUSHROOM("Brown mushroom", "brownmushroom", "browngiantmushroom"),
|
||||
RANDOM_MUSHROOM("Random mushroom", "randmushroom", "randommushroom") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { RED_MUSHROOM, BROWN_MUSHROOM };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
SWAMP("Swamp tree", "swamp", "swamptree"),
|
||||
ACACIA("Acacia tree", "acacia"),
|
||||
DARK_OAK("Dark oak tree", "darkoak"),
|
||||
PINE("Pine tree", "pine") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
makePineTree(editSession, pos);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
RANDOM("Random tree", "rand", "random") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = TreeType.values();
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores a map of the names for fast access.
|
||||
*/
|
||||
private static final Map<String, TreeType> lookup = new HashMap<>();
|
||||
private static final Set<String> primaryAliases = Sets.newHashSet();
|
||||
|
||||
private final String name;
|
||||
public final ImmutableList<String> lookupKeys;
|
||||
|
||||
static {
|
||||
for (TreeType type : EnumSet.allOf(TreeType.class)) {
|
||||
for (String key : type.lookupKeys) {
|
||||
lookup.put(key, type);
|
||||
}
|
||||
if (type.lookupKeys.size() > 0) {
|
||||
primaryAliases.add(type.lookupKeys.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TreeType(String name, String... lookupKeys) {
|
||||
this.name = name;
|
||||
this.lookupKeys = ImmutableList.copyOf(lookupKeys);
|
||||
}
|
||||
|
||||
public static Set<String> getAliases() {
|
||||
return Collections.unmodifiableSet(lookup.keySet());
|
||||
}
|
||||
|
||||
public static Set<String> getPrimaryAliases() {
|
||||
return Collections.unmodifiableSet(primaryAliases);
|
||||
}
|
||||
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
return editSession.getWorld().generateTree(this, editSession, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-friendly tree type name.
|
||||
*
|
||||
* @return a name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type from name. May return null.
|
||||
*
|
||||
* @param name name to search
|
||||
* @return a tree type or null
|
||||
*/
|
||||
@Nullable
|
||||
public static TreeType lookup(String name) {
|
||||
return lookup.get(name.replace("_", "").toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
|
||||
private TreeGenerator() {
|
||||
}
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
/**
|
||||
* Makes a terrible looking pine tree.
|
||||
*
|
||||
* @param basePosition the base position
|
||||
*/
|
||||
private static void makePineTree(EditSession editSession, BlockVector3 basePosition)
|
||||
throws MaxChangedBlocksException {
|
||||
int trunkHeight = (int) Math.floor(Math.random() * 2) + 3;
|
||||
int height = (int) Math.floor(Math.random() * 5) + 8;
|
||||
|
||||
BlockState logBlock = BlockTypes.OAK_LOG.getDefaultState();
|
||||
BlockState leavesBlock = BlockTypes.OAK_LEAVES.getDefaultState();
|
||||
|
||||
// Create trunk
|
||||
for (int i = 0; i < trunkHeight; ++i) {
|
||||
if (!setBlockIfAir(editSession, basePosition.add(0, i, 0), logBlock)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Move up
|
||||
basePosition = basePosition.add(0, trunkHeight, 0);
|
||||
|
||||
// Create tree + leaves
|
||||
for (int i = 0; i < height; ++i) {
|
||||
setBlockIfAir(editSession, basePosition.add(0, i, 0), logBlock);
|
||||
|
||||
// Less leaves at these levels
|
||||
double chance = ((i == 0 || i == height - 1) ? 0.6 : 1);
|
||||
|
||||
// Inner leaves
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-1, i, 0), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(1, i, 0), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(0, i, -1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(0, i, 1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(1, i, 1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-1, i, 1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(1, i, -1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-1, i, -1), leavesBlock, chance);
|
||||
|
||||
if (!(i == 0 || i == height - 1)) {
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-2, i, j), leavesBlock, 0.6);
|
||||
}
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(2, i, j), leavesBlock, 0.6);
|
||||
}
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(j, i, -2), leavesBlock, 0.6);
|
||||
}
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(j, i, 2), leavesBlock, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBlockIfAir(editSession, basePosition.add(0, height, 0), leavesBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a tree type. May return null if a tree type by that
|
||||
* name is not found.
|
||||
*
|
||||
* @param type the tree type
|
||||
* @return a tree type or null
|
||||
*/
|
||||
@Nullable
|
||||
public static TreeType lookup(String type) {
|
||||
return TreeType.lookup(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block (only if a previous block was not there) if {@link Math#random()}
|
||||
* returns a number less than the given probability.
|
||||
*
|
||||
* @param position the position
|
||||
* @param block the block
|
||||
* @param probability a probability between 0 and 1, inclusive
|
||||
* @return whether a block was changed
|
||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||
*/
|
||||
private static <B extends BlockStateHolder<B>> boolean setChanceBlockIfAir(EditSession session, BlockVector3 position, B block, double probability)
|
||||
throws MaxChangedBlocksException {
|
||||
return Math.random() <= probability && setBlockIfAir(session, position, block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block only if there's no block already there.
|
||||
*
|
||||
* @param position the position
|
||||
* @param block the block to set
|
||||
* @return if block was changed
|
||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||
*/
|
||||
private static <B extends BlockStateHolder<B>> boolean setBlockIfAir(EditSession session, BlockVector3 position, B block) throws MaxChangedBlocksException {
|
||||
return session.getBlock(position).getBlockType().getMaterial().isAir() && session.setBlock(position, block);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Tree generator.
|
||||
*/
|
||||
public class TreeGenerator {
|
||||
|
||||
public enum TreeType {
|
||||
TREE("Oak tree", "oak", "tree", "regular"),
|
||||
BIG_TREE("Large oak tree", "largeoak", "bigoak", "big", "bigtree"),
|
||||
REDWOOD("Spruce tree", "spruce", "redwood", "sequoia", "sequoioideae"),
|
||||
TALL_REDWOOD("Tall spruce tree", "tallspruce", "bigspruce", "tallredwood", "tallsequoia", "tallsequoioideae"),
|
||||
MEGA_REDWOOD("Large spruce tree", "largespruce", "megaredwood"),
|
||||
RANDOM_REDWOOD("Random spruce tree", "randspruce", "randredwood", "randomredwood", "anyredwood") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { REDWOOD, TALL_REDWOOD, MEGA_REDWOOD };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
BIRCH("Birch tree", "birch", "white", "whitebark"),
|
||||
TALL_BIRCH("Tall birch tree", "tallbirch"),
|
||||
RANDOM_BIRCH("Random birch tree", "randbirch", "randombirch") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { BIRCH, TALL_BIRCH };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
JUNGLE("Jungle tree", "jungle"),
|
||||
SMALL_JUNGLE("Small jungle tree", "smalljungle"),
|
||||
SHORT_JUNGLE("Short jungle tree", "shortjungle") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
return SMALL_JUNGLE.generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
RANDOM_JUNGLE("Random jungle tree", "randjungle", "randomjungle") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { JUNGLE, SMALL_JUNGLE };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
JUNGLE_BUSH("Jungle bush", "junglebush", "jungleshrub"),
|
||||
RED_MUSHROOM("Red mushroom", "redmushroom", "redgiantmushroom"),
|
||||
BROWN_MUSHROOM("Brown mushroom", "brownmushroom", "browngiantmushroom"),
|
||||
RANDOM_MUSHROOM("Random mushroom", "randmushroom", "randommushroom") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = { RED_MUSHROOM, BROWN_MUSHROOM };
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
},
|
||||
SWAMP("Swamp tree", "swamp", "swamptree"),
|
||||
ACACIA("Acacia tree", "acacia"),
|
||||
DARK_OAK("Dark oak tree", "darkoak"),
|
||||
PINE("Pine tree", "pine") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
makePineTree(editSession, pos);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
RANDOM("Random tree", "rand", "random") {
|
||||
@Override
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
TreeType[] choices = TreeType.values();
|
||||
return choices[TreeGenerator.RANDOM.nextInt(choices.length)].generate(editSession, pos);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores a map of the names for fast access.
|
||||
*/
|
||||
private static final Map<String, TreeType> lookup = new HashMap<>();
|
||||
private static final Set<String> primaryAliases = Sets.newHashSet();
|
||||
|
||||
private final String name;
|
||||
public final ImmutableList<String> lookupKeys;
|
||||
|
||||
static {
|
||||
for (TreeType type : EnumSet.allOf(TreeType.class)) {
|
||||
for (String key : type.lookupKeys) {
|
||||
lookup.put(key, type);
|
||||
}
|
||||
if (type.lookupKeys.size() > 0) {
|
||||
primaryAliases.add(type.lookupKeys.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TreeType(String name, String... lookupKeys) {
|
||||
this.name = name;
|
||||
this.lookupKeys = ImmutableList.copyOf(lookupKeys);
|
||||
}
|
||||
|
||||
public static Set<String> getAliases() {
|
||||
return Collections.unmodifiableSet(lookup.keySet());
|
||||
}
|
||||
|
||||
public static Set<String> getPrimaryAliases() {
|
||||
return Collections.unmodifiableSet(primaryAliases);
|
||||
}
|
||||
|
||||
public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException {
|
||||
return editSession.getWorld().generateTree(this, editSession, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-friendly tree type name.
|
||||
*
|
||||
* @return a name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type from name. May return null.
|
||||
*
|
||||
* @param name name to search
|
||||
* @return a tree type or null
|
||||
*/
|
||||
@Nullable
|
||||
public static TreeType lookup(String name) {
|
||||
return lookup.get(name.replace("_", "").toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
|
||||
private TreeGenerator() {
|
||||
}
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
/**
|
||||
* Makes a terrible looking pine tree.
|
||||
*
|
||||
* @param basePosition the base position
|
||||
*/
|
||||
private static void makePineTree(EditSession editSession, BlockVector3 basePosition)
|
||||
throws MaxChangedBlocksException {
|
||||
int trunkHeight = (int) Math.floor(Math.random() * 2) + 3;
|
||||
int height = (int) Math.floor(Math.random() * 5) + 8;
|
||||
|
||||
BlockState logBlock = BlockTypes.OAK_LOG.getDefaultState();
|
||||
BlockState leavesBlock = BlockTypes.OAK_LEAVES.getDefaultState();
|
||||
|
||||
// Create trunk
|
||||
for (int i = 0; i < trunkHeight; ++i) {
|
||||
if (!setBlockIfAir(editSession, basePosition.add(0, i, 0), logBlock)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Move up
|
||||
basePosition = basePosition.add(0, trunkHeight, 0);
|
||||
|
||||
// Create tree + leaves
|
||||
for (int i = 0; i < height; ++i) {
|
||||
setBlockIfAir(editSession, basePosition.add(0, i, 0), logBlock);
|
||||
|
||||
// Less leaves at these levels
|
||||
double chance = ((i == 0 || i == height - 1) ? 0.6 : 1);
|
||||
|
||||
// Inner leaves
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-1, i, 0), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(1, i, 0), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(0, i, -1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(0, i, 1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(1, i, 1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-1, i, 1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(1, i, -1), leavesBlock, chance);
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-1, i, -1), leavesBlock, chance);
|
||||
|
||||
if (!(i == 0 || i == height - 1)) {
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(-2, i, j), leavesBlock, 0.6);
|
||||
}
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(2, i, j), leavesBlock, 0.6);
|
||||
}
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(j, i, -2), leavesBlock, 0.6);
|
||||
}
|
||||
for (int j = -2; j <= 2; ++j) {
|
||||
setChanceBlockIfAir(editSession, basePosition.add(j, i, 2), leavesBlock, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBlockIfAir(editSession, basePosition.add(0, height, 0), leavesBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a tree type. May return null if a tree type by that
|
||||
* name is not found.
|
||||
*
|
||||
* @param type the tree type
|
||||
* @return a tree type or null
|
||||
*/
|
||||
@Nullable
|
||||
public static TreeType lookup(String type) {
|
||||
return TreeType.lookup(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block (only if a previous block was not there) if {@link Math#random()}
|
||||
* returns a number less than the given probability.
|
||||
*
|
||||
* @param position the position
|
||||
* @param block the block
|
||||
* @param probability a probability between 0 and 1, inclusive
|
||||
* @return whether a block was changed
|
||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||
*/
|
||||
private static <B extends BlockStateHolder<B>> boolean setChanceBlockIfAir(EditSession session, BlockVector3 position, B block, double probability)
|
||||
throws MaxChangedBlocksException {
|
||||
return Math.random() <= probability && setBlockIfAir(session, position, block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block only if there's no block already there.
|
||||
*
|
||||
* @param position the position
|
||||
* @param block the block to set
|
||||
* @return if block was changed
|
||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||
*/
|
||||
private static <B extends BlockStateHolder<B>> boolean setBlockIfAir(EditSession session, BlockVector3 position, B block) throws MaxChangedBlocksException {
|
||||
return session.getBlock(position).getBlockType().getMaterial().isAir() && session.setBlock(position, block);
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.io.file;
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.io.file;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.nio.file.Path;
|
||||
|
@ -1,23 +1,23 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.io.file;
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.io.file;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren