mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 09:17:39 +00:00
Merge changes from FAI
This commit is contained in:
parent
bfd919b3cb
commit
221b9ea844
@ -59,7 +59,6 @@ public class BukkitConfiguration extends YAMLConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void migrateLegacyFolders() {
|
private void migrateLegacyFolders() {
|
||||||
migrate(scriptsDir, "craftscripts");
|
|
||||||
migrate(saveDir, "schematics");
|
migrate(saveDir, "schematics");
|
||||||
migrate("drawings", "draw.js images");
|
migrate("drawings", "draw.js images");
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,6 @@ navigation-wand:
|
|||||||
item: minecraft:compass
|
item: minecraft:compass
|
||||||
max-distance: 100
|
max-distance: 100
|
||||||
|
|
||||||
scripting:
|
|
||||||
timeout: 3000
|
|
||||||
dir: craftscripts
|
|
||||||
|
|
||||||
saving:
|
saving:
|
||||||
dir: schematics
|
dir: schematics
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ super-pickaxe-drop-items=true
|
|||||||
disallowed-blocks=minecraft:oak_sapling,minecraft:jungle_sapling,minecraft:dark_oak_sapling,minecraft:spruce_sapling,minecraft:birch_sapling,minecraft:acacia_sapling,minecraft:black_bed,minecraft:blue_bed,minecraft:brown_bed,minecraft:cyan_bed,minecraft:gray_bed,minecraft:green_bed,minecraft:light_blue_bed,minecraft:light_gray_bed,minecraft:lime_bed,minecraft:magenta_bed,minecraft:orange_bed,minecraft:pink_bed,minecraft:purple_bed,minecraft:red_bed,minecraft:white_bed,minecraft:yellow_bed,minecraft:powered_rail,minecraft:detector_rail,minecraft:grass,minecraft:dead_bush,minecraft:moving_piston,minecraft:piston_head,minecraft:sunflower,minecraft:rose_bush,minecraft:dandelion,minecraft:poppy,minecraft:brown_mushroom,minecraft:red_mushroom,minecraft:tnt,minecraft:torch,minecraft:fire,minecraft:redstone_wire,minecraft:wheat,minecraft:potatoes,minecraft:carrots,minecraft:melon_stem,minecraft:pumpkin_stem,minecraft:beetroots,minecraft:rail,minecraft:lever,minecraft:redstone_torch,minecraft:redstone_wall_torch,minecraft:repeater,minecraft:comparator,minecraft:stone_button,minecraft:birch_button,minecraft:acacia_button,minecraft:dark_oak_button,minecraft:jungle_button,minecraft:oak_button,minecraft:spruce_button,minecraft:cactus,minecraft:sugar_cane,minecraft:bedrock
|
disallowed-blocks=minecraft:oak_sapling,minecraft:jungle_sapling,minecraft:dark_oak_sapling,minecraft:spruce_sapling,minecraft:birch_sapling,minecraft:acacia_sapling,minecraft:black_bed,minecraft:blue_bed,minecraft:brown_bed,minecraft:cyan_bed,minecraft:gray_bed,minecraft:green_bed,minecraft:light_blue_bed,minecraft:light_gray_bed,minecraft:lime_bed,minecraft:magenta_bed,minecraft:orange_bed,minecraft:pink_bed,minecraft:purple_bed,minecraft:red_bed,minecraft:white_bed,minecraft:yellow_bed,minecraft:powered_rail,minecraft:detector_rail,minecraft:grass,minecraft:dead_bush,minecraft:moving_piston,minecraft:piston_head,minecraft:sunflower,minecraft:rose_bush,minecraft:dandelion,minecraft:poppy,minecraft:brown_mushroom,minecraft:red_mushroom,minecraft:tnt,minecraft:torch,minecraft:fire,minecraft:redstone_wire,minecraft:wheat,minecraft:potatoes,minecraft:carrots,minecraft:melon_stem,minecraft:pumpkin_stem,minecraft:beetroots,minecraft:rail,minecraft:lever,minecraft:redstone_torch,minecraft:redstone_wall_torch,minecraft:repeater,minecraft:comparator,minecraft:stone_button,minecraft:birch_button,minecraft:acacia_button,minecraft:dark_oak_button,minecraft:jungle_button,minecraft:oak_button,minecraft:spruce_button,minecraft:cactus,minecraft:sugar_cane,minecraft:bedrock
|
||||||
max-super-pickaxe-size=5
|
max-super-pickaxe-size=5
|
||||||
max-brush-radius=10
|
max-brush-radius=10
|
||||||
craftscript-dir=craftscripts
|
|
||||||
wand-item=minecraft:wooden_axe
|
wand-item=minecraft:wooden_axe
|
||||||
shell-save-type=
|
shell-save-type=
|
||||||
scripting-timeout=3000
|
scripting-timeout=3000
|
||||||
|
@ -84,12 +84,10 @@ public abstract class LocalConfiguration {
|
|||||||
public boolean navigationUseGlass = true;
|
public boolean navigationUseGlass = true;
|
||||||
public String navigationWand = "minecraft:compass";
|
public String navigationWand = "minecraft:compass";
|
||||||
public int navigationWandMaxDistance = 50;
|
public int navigationWandMaxDistance = 50;
|
||||||
public int scriptTimeout = 3000;
|
|
||||||
public int calculationTimeout = 100;
|
public int calculationTimeout = 100;
|
||||||
public int maxCalculationTimeout = 300;
|
public int maxCalculationTimeout = 300;
|
||||||
public Set<String> allowedDataCycleBlocks = new HashSet<>();
|
public Set<String> allowedDataCycleBlocks = new HashSet<>();
|
||||||
public String saveDir = "schematics";
|
public String saveDir = "schematics";
|
||||||
public String scriptsDir = "craftscripts";
|
|
||||||
public boolean showHelpInfo = true; // unused
|
public boolean showHelpInfo = true; // unused
|
||||||
public int butcherDefaultRadius = -1;
|
public int butcherDefaultRadius = -1;
|
||||||
public int butcherMaxRadius = -1;
|
public int butcherMaxRadius = -1;
|
||||||
|
@ -52,9 +52,6 @@ import com.sk89q.worldedit.internal.expression.Expression;
|
|||||||
import com.sk89q.worldedit.internal.expression.invoke.ReturnException;
|
import com.sk89q.worldedit.internal.expression.invoke.ReturnException;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.scripting.CraftScriptContext;
|
|
||||||
import com.sk89q.worldedit.scripting.CraftScriptEngine;
|
|
||||||
import com.sk89q.worldedit.scripting.RhinoCraftScriptEngine;
|
|
||||||
import com.sk89q.worldedit.session.SessionManager;
|
import com.sk89q.worldedit.session.SessionManager;
|
||||||
import com.sk89q.worldedit.util.Direction;
|
import com.sk89q.worldedit.util.Direction;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
@ -745,97 +742,6 @@ public final class WorldEdit {
|
|||||||
return event.isCancelled();
|
return event.isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a WorldEdit script.
|
|
||||||
*
|
|
||||||
* @param player the player
|
|
||||||
* @param f the script file to execute
|
|
||||||
* @param args arguments for the script
|
|
||||||
* @throws WorldEditException if something goes wrong
|
|
||||||
*/
|
|
||||||
public void runScript(Player player, File f, String[] args) throws WorldEditException {
|
|
||||||
String filename = f.getPath();
|
|
||||||
int index = filename.lastIndexOf('.');
|
|
||||||
String ext = filename.substring(index + 1);
|
|
||||||
|
|
||||||
if (!ext.equalsIgnoreCase("js")) {
|
|
||||||
player.print(Caption.of("worldedit.script.unsupported"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String script;
|
|
||||||
|
|
||||||
try {
|
|
||||||
InputStream file;
|
|
||||||
|
|
||||||
if (!f.exists()) {
|
|
||||||
file = WorldEdit.class.getResourceAsStream("craftscripts/" + filename);
|
|
||||||
|
|
||||||
if (file == null) {
|
|
||||||
player.print(Caption.of("worldedit.script.file-not-found", TextComponent.of(filename)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
file = new FileInputStream(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataInputStream in = new DataInputStream(file);
|
|
||||||
byte[] data = new byte[in.available()];
|
|
||||||
in.readFully(data);
|
|
||||||
in.close();
|
|
||||||
script = new String(data, 0, data.length, StandardCharsets.UTF_8);
|
|
||||||
} catch (IOException e) {
|
|
||||||
player.print(Caption.of("worldedit.script.read-error", TextComponent.of(e.getMessage())));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalSession session = getSessionManager().get(player);
|
|
||||||
CraftScriptContext scriptContext = new CraftScriptContext(
|
|
||||||
this,
|
|
||||||
getPlatformManager().queryCapability(Capability.USER_COMMANDS),
|
|
||||||
getConfiguration(),
|
|
||||||
session,
|
|
||||||
player,
|
|
||||||
args
|
|
||||||
);
|
|
||||||
|
|
||||||
CraftScriptEngine engine;
|
|
||||||
|
|
||||||
try {
|
|
||||||
engine = new RhinoCraftScriptEngine();
|
|
||||||
} catch (NoClassDefFoundError ignored) {
|
|
||||||
player.print(Caption.of("worldedit.script.no-script-engine"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.setTimeLimit(getConfiguration().scriptTimeout);
|
|
||||||
|
|
||||||
Map<String, Object> vars = new HashMap<>();
|
|
||||||
vars.put("argv", args);
|
|
||||||
vars.put("context", scriptContext);
|
|
||||||
vars.put("player", player);
|
|
||||||
|
|
||||||
try {
|
|
||||||
engine.evaluate(script, filename, vars);
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
// non-exceptional return check
|
|
||||||
if (!(Throwables.getRootCause(e) instanceof ReturnException)) {
|
|
||||||
player.print(Caption.of("worldedit.script.failed", TextComponent.of(e.getMessage())));
|
|
||||||
logger.warn("Failed to execute script", e);
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException | WorldEditException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
player.print(Caption.of("worldedit.script.failed-console", TextComponent.of(e.getClass().getCanonicalName())));
|
|
||||||
logger.warn("Failed to execute script", e);
|
|
||||||
} finally {
|
|
||||||
for (EditSession editSession : scriptContext.getEditSessions()) {
|
|
||||||
editSession.close();
|
|
||||||
session.remember(editSession);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Worldedit's configuration.
|
* Get Worldedit's configuration.
|
||||||
*
|
*
|
||||||
|
@ -333,108 +333,6 @@ public class ClipboardCommands {
|
|||||||
//FAWE end
|
//FAWE end
|
||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
|
||||||
@Command(
|
|
||||||
name = "download",
|
|
||||||
aliases = {"/download"},
|
|
||||||
desc = "Downloads your clipboard through the configured web interface"
|
|
||||||
)
|
|
||||||
@Deprecated
|
|
||||||
@CommandPermissions({"worldedit.clipboard.download"})
|
|
||||||
public void download(
|
|
||||||
final Actor actor,
|
|
||||||
final LocalSession session,
|
|
||||||
@Arg(name = "format", desc = "String", def = "fast") final String formatName
|
|
||||||
) throws WorldEditException {
|
|
||||||
final ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
|
|
||||||
if (format == null) {
|
|
||||||
actor.print(Caption.of("fawe.worldedit.clipboard.clipboard.invalid.format", formatName));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
actor.print(Caption.of("fawe.web.generating.link", formatName));
|
|
||||||
ClipboardHolder holder = session.getClipboard();
|
|
||||||
|
|
||||||
URL url;
|
|
||||||
if (holder instanceof MultiClipboardHolder) {
|
|
||||||
MultiClipboardHolder multi = (MultiClipboardHolder) holder;
|
|
||||||
Set<File> files = new HashSet<>();
|
|
||||||
Set<URI> invalid = new HashSet<>();
|
|
||||||
for (ClipboardHolder cur : multi.getHolders()) {
|
|
||||||
if (cur instanceof URIClipboardHolder) {
|
|
||||||
URIClipboardHolder uriHolder = (URIClipboardHolder) cur;
|
|
||||||
URI uri = uriHolder.getUri();
|
|
||||||
File file = new File(uri.getPath());
|
|
||||||
if (file.exists() && file.isFile()) {
|
|
||||||
files.add(file.getAbsoluteFile());
|
|
||||||
} else if (!uri.getPath().isEmpty()) {
|
|
||||||
invalid.add(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final LocalConfiguration config = WorldEdit.getInstance().getConfiguration();
|
|
||||||
final File working = WorldEdit.getInstance().getWorkingDirectoryFile(config.saveDir).getAbsoluteFile();
|
|
||||||
|
|
||||||
url = MainUtil.upload(null, null, "zip", new RunnableVal<>() {
|
|
||||||
@Override
|
|
||||||
public void run(OutputStream out) {
|
|
||||||
try (ZipOutputStream zos = new ZipOutputStream(out)) {
|
|
||||||
for (File file : files) {
|
|
||||||
String fileName = file.getName();
|
|
||||||
if (MainUtil.isInSubDirectory(working, file)) {
|
|
||||||
fileName = working.toURI().relativize(file.toURI()).getPath();
|
|
||||||
}
|
|
||||||
ZipEntry ze = new ZipEntry(fileName);
|
|
||||||
zos.putNextEntry(ze);
|
|
||||||
Files.copy(file.toPath(), zos);
|
|
||||||
zos.closeEntry();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Clipboard clipboard = holder.getClipboard();
|
|
||||||
final Transform transform = holder.getTransform();
|
|
||||||
final Clipboard target;
|
|
||||||
// If we have a transform, bake it into the copy
|
|
||||||
if (!transform.isIdentity()) {
|
|
||||||
final FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform);
|
|
||||||
target = new BlockArrayClipboard(result.getTransformedRegion(), actor.getUniqueId());
|
|
||||||
target.setOrigin(clipboard.getOrigin());
|
|
||||||
Operations.completeLegacy(result.copyTo(target));
|
|
||||||
} else {
|
|
||||||
target = clipboard;
|
|
||||||
}
|
|
||||||
if (format == BuiltInClipboardFormat.PNG) {
|
|
||||||
try {
|
|
||||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream(Short.MAX_VALUE);
|
|
||||||
ClipboardWriter writer = format.getWriter(baos);
|
|
||||||
writer.write(target);
|
|
||||||
baos.flush();
|
|
||||||
url = ImgurUtility.uploadImage(baos.toByteArray());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
url = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (Settings.settings().WEB.URL.isEmpty()) {
|
|
||||||
actor.print(Caption.of("fawe.error.setting.disable", "web.url"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
url = FaweAPI.upload(target, format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (url == null) {
|
|
||||||
actor.print(Caption.of("fawe.web.generating.link.failed"));
|
|
||||||
} else {
|
|
||||||
String urlText = url.toString();
|
|
||||||
actor.print(Caption.of("fawe.web.download.link", urlText).clickEvent(ClickEvent.openUrl(urlText)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "/place",
|
name = "/place",
|
||||||
desc = "Place the clipboard's contents without applying transformations (e.g. rotate)"
|
desc = "Place the clipboard's contents without applying transformations (e.g. rotate)"
|
||||||
|
@ -77,6 +77,12 @@ public class NavigationCommands {
|
|||||||
@Arg(desc = "# of levels to ascend", def = "1")
|
@Arg(desc = "# of levels to ascend", def = "1")
|
||||||
int levels
|
int levels
|
||||||
) throws WorldEditException {
|
) throws WorldEditException {
|
||||||
|
// From Allink
|
||||||
|
if (levels < 0) {
|
||||||
|
player.print(Caption.of("worldedit.ascend.obstructed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int ascentLevels = 0;
|
int ascentLevels = 0;
|
||||||
while (player.ascendLevel()) {
|
while (player.ascendLevel()) {
|
||||||
++ascentLevels;
|
++ascentLevels;
|
||||||
@ -102,6 +108,12 @@ public class NavigationCommands {
|
|||||||
@Arg(desc = "# of levels to descend", def = "1")
|
@Arg(desc = "# of levels to descend", def = "1")
|
||||||
int levels
|
int levels
|
||||||
) throws WorldEditException {
|
) throws WorldEditException {
|
||||||
|
// From Allink
|
||||||
|
if (levels < 0) {
|
||||||
|
player.print(Caption.of("worldedit.descend.obstructed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int descentLevels = 0;
|
int descentLevels = 0;
|
||||||
while (player.descendLevel()) {
|
while (player.descendLevel()) {
|
||||||
++descentLevels;
|
++descentLevels;
|
||||||
|
@ -150,11 +150,11 @@ public class SchematicCommands {
|
|||||||
public void loadall(
|
public void loadall(
|
||||||
Actor actor, LocalSession session,
|
Actor actor, LocalSession session,
|
||||||
@Arg(desc = "Format name.", def = "fast")
|
@Arg(desc = "Format name.", def = "fast")
|
||||||
String formatName,
|
String formatName,
|
||||||
@Arg(desc = "File name.")
|
@Arg(desc = "File name.")
|
||||||
String filename,
|
String filename,
|
||||||
@Switch(name = 'o', desc = "Overwrite/replace existing clipboard(s)")
|
@Switch(name = 'o', desc = "Overwrite/replace existing clipboard(s)")
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
// @Switch(name = 'r', desc = "Apply random rotation") <- not implemented below.
|
// @Switch(name = 'r', desc = "Apply random rotation") <- not implemented below.
|
||||||
// boolean randomRotate
|
// boolean randomRotate
|
||||||
) throws FilenameException {
|
) throws FilenameException {
|
||||||
@ -196,7 +196,7 @@ public class SchematicCommands {
|
|||||||
public void unload(
|
public void unload(
|
||||||
Actor actor, LocalSession session,
|
Actor actor, LocalSession session,
|
||||||
@Arg(desc = "File name, requires extension.")
|
@Arg(desc = "File name, requires extension.")
|
||||||
String fileName
|
String fileName
|
||||||
) throws WorldEditException {
|
) throws WorldEditException {
|
||||||
URI uri;
|
URI uri;
|
||||||
if (fileName.startsWith("file:/") || fileName.startsWith("http://") || fileName.startsWith("https://")) {
|
if (fileName.startsWith("file:/") || fileName.startsWith("http://") || fileName.startsWith("https://")) {
|
||||||
@ -204,7 +204,9 @@ public class SchematicCommands {
|
|||||||
} else {
|
} else {
|
||||||
final LocalConfiguration config = this.worldEdit.getConfiguration();
|
final LocalConfiguration config = this.worldEdit.getConfiguration();
|
||||||
File working = this.worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
File working = this.worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||||
File root = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working;
|
File root = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS
|
||||||
|
? new File(working, actor.getUniqueId().toString())
|
||||||
|
: working;
|
||||||
uri = new File(root, fileName).toURI();
|
uri = new File(root, fileName).toURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +306,7 @@ public class SchematicCommands {
|
|||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
|
// From Allink
|
||||||
@Command(
|
@Command(
|
||||||
name = "load",
|
name = "load",
|
||||||
desc = "Load a schematic into your clipboard"
|
desc = "Load a schematic into your clipboard"
|
||||||
@ -312,9 +315,9 @@ public class SchematicCommands {
|
|||||||
public void load(
|
public void load(
|
||||||
Actor actor, LocalSession session,
|
Actor actor, LocalSession session,
|
||||||
@Arg(desc = "File name.")
|
@Arg(desc = "File name.")
|
||||||
String filename,
|
String filename,
|
||||||
@Arg(desc = "Format name.", def = "fast")
|
@Arg(desc = "Format name.", def = "fast")
|
||||||
String formatName
|
String formatName
|
||||||
) throws FilenameException {
|
) throws FilenameException {
|
||||||
LocalConfiguration config = worldEdit.getConfiguration();
|
LocalConfiguration config = worldEdit.getConfiguration();
|
||||||
|
|
||||||
@ -323,83 +326,69 @@ public class SchematicCommands {
|
|||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
try {
|
try {
|
||||||
URI uri;
|
URI uri;
|
||||||
if (formatName.startsWith("url:")) {
|
|
||||||
String t = filename;
|
File saveDir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||||
filename = formatName;
|
File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS
|
||||||
formatName = t;
|
? new File(saveDir, actor.getUniqueId().toString())
|
||||||
}
|
: saveDir;
|
||||||
if (filename.startsWith("url:")) {
|
File file;
|
||||||
if (!actor.hasPermission("worldedit.schematic.load.web")) {
|
if (filename.startsWith("#")) {
|
||||||
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.web"));
|
format = ClipboardFormats.findByAlias(formatName);
|
||||||
|
String[] extensions;
|
||||||
|
if (format != null) {
|
||||||
|
extensions = format.getFileExtensions().toArray(new String[0]);
|
||||||
|
} else {
|
||||||
|
extensions = ClipboardFormats.getFileExtensionArray();
|
||||||
|
}
|
||||||
|
file = actor.openFileOpenDialog(extensions);
|
||||||
|
if (file == null || !file.exists()) {
|
||||||
|
actor.print(Caption.of("worldedit.schematic.load.does-not-exist", TextComponent.of(filename)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UUID uuid = UUID.fromString(filename.substring(4));
|
|
||||||
URL webUrl = new URL(Settings.settings().WEB.URL);
|
|
||||||
format = ClipboardFormats.findByAlias(formatName);
|
|
||||||
URL url = new URL(webUrl, "uploads/" + uuid + "." + format.getPrimaryFileExtension());
|
|
||||||
ReadableByteChannel byteChannel = Channels.newChannel(url.openStream());
|
|
||||||
in = Channels.newInputStream(byteChannel);
|
|
||||||
uri = url.toURI();
|
|
||||||
} else {
|
} else {
|
||||||
File saveDir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !actor.hasPermission("worldedit.schematic.load.other") && Pattern
|
||||||
File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(saveDir, actor.getUniqueId().toString()) : saveDir;
|
.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
||||||
File file;
|
.matcher(filename)
|
||||||
if (filename.startsWith("#")) {
|
.find()) {
|
||||||
format = ClipboardFormats.findByAlias(formatName);
|
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.other"));
|
||||||
String[] extensions;
|
return;
|
||||||
if (format != null) {
|
}
|
||||||
extensions = format.getFileExtensions().toArray(new String[0]);
|
if (filename.matches(".*\\.[\\w].*")) {
|
||||||
} else {
|
format = ClipboardFormats
|
||||||
extensions = ClipboardFormats.getFileExtensionArray();
|
.findByExtension(filename.substring(filename.lastIndexOf('.') + 1));
|
||||||
}
|
|
||||||
file = actor.openFileOpenDialog(extensions);
|
|
||||||
if (file == null || !file.exists()) {
|
|
||||||
actor.print(Caption.of("worldedit.schematic.load.does-not-exist", TextComponent.of(filename)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !actor.hasPermission("worldedit.schematic.load.other") && Pattern
|
format = ClipboardFormats.findByAlias(formatName);
|
||||||
.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
}
|
||||||
.matcher(filename)
|
file = MainUtil.resolve(dir, filename, format, false);
|
||||||
.find()) {
|
}
|
||||||
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.other"));
|
if (file == null || !file.exists()) {
|
||||||
return;
|
if (!filename.contains("../")) {
|
||||||
}
|
dir = this.worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||||
if (filename.matches(".*\\.[\\w].*")) {
|
|
||||||
format = ClipboardFormats
|
|
||||||
.findByExtension(filename.substring(filename.lastIndexOf('.') + 1));
|
|
||||||
} else {
|
|
||||||
format = ClipboardFormats.findByAlias(formatName);
|
|
||||||
}
|
|
||||||
file = MainUtil.resolve(dir, filename, format, false);
|
file = MainUtil.resolve(dir, filename, format, false);
|
||||||
}
|
}
|
||||||
if (file == null || !file.exists()) {
|
}
|
||||||
if (!filename.contains("../")) {
|
if (file == null || !file.exists() || !MainUtil.isInSubDirectory(saveDir, file)) {
|
||||||
dir = this.worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
actor.printError(TextComponent.of("Schematic " + filename + " does not exist! (" + (file != null && file.exists()) +
|
||||||
file = MainUtil.resolve(dir, filename, format, false);
|
"|" + file + "|" + (file != null && !MainUtil
|
||||||
}
|
.isInSubDirectory(saveDir, file)) + ")"));
|
||||||
}
|
return;
|
||||||
if (file == null || !file.exists() || !MainUtil.isInSubDirectory(saveDir, file)) {
|
}
|
||||||
actor.printError(TextComponent.of("Schematic " + filename + " does not exist! (" + (file != null && file.exists()) +
|
if (format == null) {
|
||||||
"|" + file + "|" + (file != null && !MainUtil
|
format = ClipboardFormats.findByFile(file);
|
||||||
.isInSubDirectory(saveDir, file)) + ")"));
|
if (format == null) {
|
||||||
|
actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (format == null) {
|
|
||||||
format = ClipboardFormats.findByFile(file);
|
|
||||||
if (format == null) {
|
|
||||||
actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in = new FileInputStream(file);
|
|
||||||
uri = file.toURI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in = new FileInputStream(file);
|
||||||
|
uri = file.toURI();
|
||||||
|
|
||||||
format.hold(actor, uri, in);
|
format.hold(actor, uri, in);
|
||||||
actor.print(Caption.of("fawe.worldedit.schematic.schematic.loaded", filename));
|
actor.print(Caption.of("fawe.worldedit.schematic.schematic.loaded", filename));
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
actor.print(Caption.of("worldedit.schematic.unknown-filename", TextComponent.of(filename)));
|
actor.print(Caption.of("worldedit.schematic.unknown-filename", TextComponent.of(filename)));
|
||||||
} catch (URISyntaxException | IOException e) {
|
} catch (IOException e) {
|
||||||
actor.print(Caption.of("worldedit.schematic.file-not-exist", TextComponent.of(Objects.toString(e.getMessage()))));
|
actor.print(Caption.of("worldedit.schematic.file-not-exist", TextComponent.of(Objects.toString(e.getMessage()))));
|
||||||
LOGGER.warn("Failed to load a saved clipboard", e);
|
LOGGER.warn("Failed to load a saved clipboard", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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.command;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
|
||||||
import com.sk89q.worldedit.LocalSession;
|
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
|
||||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
|
||||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
|
||||||
import com.sk89q.worldedit.command.util.Logging;
|
|
||||||
import com.sk89q.worldedit.entity.Player;
|
|
||||||
import org.enginehub.piston.annotation.Command;
|
|
||||||
import org.enginehub.piston.annotation.CommandContainer;
|
|
||||||
import org.enginehub.piston.annotation.param.Arg;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commands related to scripting.
|
|
||||||
*/
|
|
||||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
|
||||||
public class ScriptingCommands {
|
|
||||||
|
|
||||||
private final WorldEdit worldEdit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance.
|
|
||||||
*
|
|
||||||
* @param worldEdit reference to WorldEdit
|
|
||||||
*/
|
|
||||||
public ScriptingCommands(WorldEdit worldEdit) {
|
|
||||||
checkNotNull(worldEdit);
|
|
||||||
this.worldEdit = worldEdit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command(
|
|
||||||
name = "cs",
|
|
||||||
aliases = {"/cs"},
|
|
||||||
desc = "Execute a CraftScript"
|
|
||||||
)
|
|
||||||
@CommandPermissions("worldedit.scripting.execute")
|
|
||||||
@Logging(ALL)
|
|
||||||
public void execute(
|
|
||||||
Player player, LocalSession session,
|
|
||||||
@Arg(desc = "Filename of the CraftScript to load")
|
|
||||||
String filename,
|
|
||||||
@Arg(desc = "Arguments to the CraftScript", def = "", variable = true)
|
|
||||||
List<String> args
|
|
||||||
) throws WorldEditException {
|
|
||||||
if (!player.hasPermission("worldedit.scripting.execute." + filename)) {
|
|
||||||
player.print(Caption.of("worldedit.execute.script-permissions"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
session.setLastScript(filename);
|
|
||||||
|
|
||||||
File dir = worldEdit.getWorkingDirectoryPath(worldEdit.getConfiguration().scriptsDir).toFile();
|
|
||||||
File f = worldEdit.getSafeOpenFile(player, dir, filename, "js", "js");
|
|
||||||
|
|
||||||
worldEdit.runScript(player, f, Stream.concat(Stream.of(filename), args.stream())
|
|
||||||
.toArray(String[]::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command(
|
|
||||||
name = ".s",
|
|
||||||
aliases = {"/.s"},
|
|
||||||
desc = "Execute last CraftScript"
|
|
||||||
)
|
|
||||||
@CommandPermissions("worldedit.scripting.execute")
|
|
||||||
@Logging(ALL)
|
|
||||||
public void executeLast(
|
|
||||||
Player player, LocalSession session,
|
|
||||||
@Arg(desc = "Arguments to the CraftScript", def = "", variable = true)
|
|
||||||
List<String> args
|
|
||||||
) throws WorldEditException {
|
|
||||||
|
|
||||||
String lastScript = session.getLastScript();
|
|
||||||
|
|
||||||
if (!player.hasPermission("worldedit.scripting.execute." + lastScript)) {
|
|
||||||
player.print(Caption.of("worldedit.execute.script-permissions"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastScript == null) {
|
|
||||||
player.print(Caption.of("worldedit.executelast.no-script"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File dir = worldEdit.getWorkingDirectoryPath(worldEdit.getConfiguration().scriptsDir).toFile();
|
|
||||||
File f = worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js");
|
|
||||||
|
|
||||||
worldEdit.runScript(player, f, Stream.concat(Stream.of(lastScript), args.stream())
|
|
||||||
.toArray(String[]::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -65,8 +65,6 @@ import com.sk89q.worldedit.command.RegionCommands;
|
|||||||
import com.sk89q.worldedit.command.RegionCommandsRegistration;
|
import com.sk89q.worldedit.command.RegionCommandsRegistration;
|
||||||
import com.sk89q.worldedit.command.SchematicCommands;
|
import com.sk89q.worldedit.command.SchematicCommands;
|
||||||
import com.sk89q.worldedit.command.SchematicCommandsRegistration;
|
import com.sk89q.worldedit.command.SchematicCommandsRegistration;
|
||||||
import com.sk89q.worldedit.command.ScriptingCommands;
|
|
||||||
import com.sk89q.worldedit.command.ScriptingCommandsRegistration;
|
|
||||||
import com.sk89q.worldedit.command.SelectionCommands;
|
import com.sk89q.worldedit.command.SelectionCommands;
|
||||||
import com.sk89q.worldedit.command.SelectionCommandsRegistration;
|
import com.sk89q.worldedit.command.SelectionCommandsRegistration;
|
||||||
import com.sk89q.worldedit.command.SnapshotCommands;
|
import com.sk89q.worldedit.command.SnapshotCommands;
|
||||||
@ -559,11 +557,6 @@ public final class PlatformCommandManager {
|
|||||||
RegionCommandsRegistration.builder(),
|
RegionCommandsRegistration.builder(),
|
||||||
new RegionCommands()
|
new RegionCommands()
|
||||||
);
|
);
|
||||||
this.registration.register(
|
|
||||||
commandManager,
|
|
||||||
ScriptingCommandsRegistration.builder(),
|
|
||||||
new ScriptingCommands(worldEdit)
|
|
||||||
);
|
|
||||||
this.registration.register(
|
this.registration.register(
|
||||||
commandManager,
|
commandManager,
|
||||||
SelectionCommandsRegistration.builder(),
|
SelectionCommandsRegistration.builder(),
|
||||||
|
@ -24,6 +24,7 @@ import com.fastasyncworldedit.core.math.Vector3Impl;
|
|||||||
import com.fastasyncworldedit.core.util.MathMan;
|
import com.fastasyncworldedit.core.util.MathMan;
|
||||||
import com.google.common.collect.ComparisonChain;
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||||
|
import dev.plex.SanityChecks;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
@ -61,7 +62,10 @@ public abstract class Vector3 {
|
|||||||
}
|
}
|
||||||
Fawe end
|
Fawe end
|
||||||
*/
|
*/
|
||||||
return new Vector3Impl(x, y, z);
|
// From Allink
|
||||||
|
final double[] saneCoords = SanityChecks.getSane(x, y, z);
|
||||||
|
|
||||||
|
return new Vector3Impl(saneCoords[0], saneCoords[1], saneCoords[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// thread-safe initialization idiom
|
// thread-safe initialization idiom
|
||||||
|
@ -1,278 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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.fastasyncworldedit.core.configuration.Caption;
|
|
||||||
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.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.newEditSessionBuilder()
|
|
||||||
.locatableActor(player)
|
|
||||||
.maxBlocks(session.getBlockChangeLimit())
|
|
||||||
.blockBag(session.getBlockBag(player))
|
|
||||||
.build();
|
|
||||||
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(Caption.of("worldedit.error.incorrect-usage", TextComponent.of(usage)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Immediately terminate execution of the script, but without a failure message.
|
|
||||||
* <p>
|
|
||||||
* 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.getWorkingDirectoryPath(folder).toFile();
|
|
||||||
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.getWorkingDirectoryPath(folder).toFile();
|
|
||||||
return controller.getSafeSaveFile(player, dir, filename, defaultExt, exts);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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;
|
|
||||||
|
|
||||||
public interface CraftScriptEngine {
|
|
||||||
|
|
||||||
void setTimeLimit(int milliseconds);
|
|
||||||
|
|
||||||
int getTimeLimit();
|
|
||||||
|
|
||||||
Object evaluate(String script, String filename, Map<String, Object> args)
|
|
||||||
throws Throwable;
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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.ClassShutter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides Minecraft's obfuscated names from scripts.
|
|
||||||
*/
|
|
||||||
class MinecraftHidingClassShutter implements ClassShutter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean visibleToScripts(String fullClassName) {
|
|
||||||
return fullClassName.contains(".") || fullClassName.length() >= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that 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.WorldEditException;
|
|
||||||
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 javax.script.ScriptException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class RhinoCraftScriptEngine implements CraftScriptEngine {
|
|
||||||
|
|
||||||
private int timeLimit;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getTimeLimit() {
|
|
||||||
return timeLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTimeLimit(int milliseconds) {
|
|
||||||
timeLimit = milliseconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object evaluate(String script, String filename, Map<String, Object> args)
|
|
||||||
throws Throwable {
|
|
||||||
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, script, 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -129,11 +129,9 @@ public class PropertiesConfiguration extends LocalConfiguration {
|
|||||||
}
|
}
|
||||||
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);
|
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);
|
||||||
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
|
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
|
||||||
scriptTimeout = getInt("scripting-timeout", scriptTimeout);
|
|
||||||
calculationTimeout = getInt("calculation-timeout", calculationTimeout);
|
calculationTimeout = getInt("calculation-timeout", calculationTimeout);
|
||||||
maxCalculationTimeout = getInt("max-calculation-timeout", maxCalculationTimeout);
|
maxCalculationTimeout = getInt("max-calculation-timeout", maxCalculationTimeout);
|
||||||
saveDir = getString("schematic-save-dir", saveDir);
|
saveDir = getString("schematic-save-dir", saveDir);
|
||||||
scriptsDir = getString("craftscript-dir", scriptsDir);
|
|
||||||
butcherDefaultRadius = getInt("butcher-default-radius", butcherDefaultRadius);
|
butcherDefaultRadius = getInt("butcher-default-radius", butcherDefaultRadius);
|
||||||
butcherMaxRadius = getInt("butcher-max-radius", butcherMaxRadius);
|
butcherMaxRadius = getInt("butcher-max-radius", butcherMaxRadius);
|
||||||
allowSymlinks = getBool("allow-symbolic-links", allowSymlinks);
|
allowSymlinks = getBool("allow-symbolic-links", allowSymlinks);
|
||||||
|
@ -127,9 +127,6 @@ public class YAMLConfiguration extends LocalConfiguration {
|
|||||||
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
|
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
|
||||||
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);
|
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);
|
||||||
|
|
||||||
scriptTimeout = config.getInt("scripting.timeout", scriptTimeout);
|
|
||||||
scriptsDir = config.getString("scripting.dir", scriptsDir);
|
|
||||||
|
|
||||||
calculationTimeout = config.getInt("calculation.timeout", calculationTimeout);
|
calculationTimeout = config.getInt("calculation.timeout", calculationTimeout);
|
||||||
maxCalculationTimeout = config.getInt("calculation.max-timeout", maxCalculationTimeout);
|
maxCalculationTimeout = config.getInt("calculation.max-timeout", maxCalculationTimeout);
|
||||||
|
|
||||||
|
8
worldedit-core/src/main/java/dev.plex/Maths.java
Normal file
8
worldedit-core/src/main/java/dev.plex/Maths.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package dev.plex;
|
||||||
|
|
||||||
|
// From Allink
|
||||||
|
public class Maths {
|
||||||
|
public static double clamp(double number, double max, double min) {
|
||||||
|
return Math.max(min, Math.min(max, number));
|
||||||
|
}
|
||||||
|
}
|
21
worldedit-core/src/main/java/dev.plex/SanityChecks.java
Normal file
21
worldedit-core/src/main/java/dev.plex/SanityChecks.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package dev.plex;
|
||||||
|
|
||||||
|
// From Allink
|
||||||
|
public class SanityChecks {
|
||||||
|
private static final double UPPER_BOUND = 30_000_000;
|
||||||
|
private static final double LOWER_BOUND = -UPPER_BOUND;
|
||||||
|
|
||||||
|
public static double[] getSane(double x, double y, double z) {
|
||||||
|
final double[] arr = new double[3];
|
||||||
|
|
||||||
|
arr[0] = clamp(x);
|
||||||
|
arr[1] = clamp(y);
|
||||||
|
arr[2] = clamp(z);
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double clamp(double number) {
|
||||||
|
return Maths.clamp(number, UPPER_BOUND, LOWER_BOUND);
|
||||||
|
}
|
||||||
|
}
|
@ -110,9 +110,6 @@ public class ConfigurateConfiguration extends LocalConfiguration {
|
|||||||
navigationWandMaxDistance = node.getNode("navigation-wand", "max-distance").getInt(navigationWandMaxDistance);
|
navigationWandMaxDistance = node.getNode("navigation-wand", "max-distance").getInt(navigationWandMaxDistance);
|
||||||
navigationUseGlass = node.getNode("navigation", "use-glass").getBoolean(navigationUseGlass);
|
navigationUseGlass = node.getNode("navigation", "use-glass").getBoolean(navigationUseGlass);
|
||||||
|
|
||||||
scriptTimeout = node.getNode("scripting", "timeout").getInt(scriptTimeout);
|
|
||||||
scriptsDir = node.getNode("scripting", "dir").getString(scriptsDir);
|
|
||||||
|
|
||||||
saveDir = node.getNode("saving", "dir").getString(saveDir);
|
saveDir = node.getNode("saving", "dir").getString(saveDir);
|
||||||
|
|
||||||
allowSymlinks = node.getNode("files", "allow-symbolic-links").getBoolean(false);
|
allowSymlinks = node.getNode("files", "allow-symbolic-links").getBoolean(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user