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() {
|
||||
migrate(scriptsDir, "craftscripts");
|
||||
migrate(saveDir, "schematics");
|
||||
migrate("drawings", "draw.js images");
|
||||
}
|
||||
|
@ -66,10 +66,6 @@ navigation-wand:
|
||||
item: minecraft:compass
|
||||
max-distance: 100
|
||||
|
||||
scripting:
|
||||
timeout: 3000
|
||||
dir: craftscripts
|
||||
|
||||
saving:
|
||||
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
|
||||
max-super-pickaxe-size=5
|
||||
max-brush-radius=10
|
||||
craftscript-dir=craftscripts
|
||||
wand-item=minecraft:wooden_axe
|
||||
shell-save-type=
|
||||
scripting-timeout=3000
|
||||
|
@ -84,12 +84,10 @@ public abstract class LocalConfiguration {
|
||||
public boolean navigationUseGlass = true;
|
||||
public String navigationWand = "minecraft:compass";
|
||||
public int navigationWandMaxDistance = 50;
|
||||
public int scriptTimeout = 3000;
|
||||
public int calculationTimeout = 100;
|
||||
public int maxCalculationTimeout = 300;
|
||||
public Set<String> allowedDataCycleBlocks = new HashSet<>();
|
||||
public String saveDir = "schematics";
|
||||
public String scriptsDir = "craftscripts";
|
||||
public boolean showHelpInfo = true; // unused
|
||||
public int butcherDefaultRadius = -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.util.LogManagerCompat;
|
||||
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.util.Direction;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -745,97 +742,6 @@ public final class WorldEdit {
|
||||
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.
|
||||
*
|
||||
|
@ -333,108 +333,6 @@ public class ClipboardCommands {
|
||||
//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(
|
||||
name = "/place",
|
||||
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")
|
||||
int levels
|
||||
) throws WorldEditException {
|
||||
// From Allink
|
||||
if (levels < 0) {
|
||||
player.print(Caption.of("worldedit.ascend.obstructed"));
|
||||
return;
|
||||
}
|
||||
|
||||
int ascentLevels = 0;
|
||||
while (player.ascendLevel()) {
|
||||
++ascentLevels;
|
||||
@ -102,6 +108,12 @@ public class NavigationCommands {
|
||||
@Arg(desc = "# of levels to descend", def = "1")
|
||||
int levels
|
||||
) throws WorldEditException {
|
||||
// From Allink
|
||||
if (levels < 0) {
|
||||
player.print(Caption.of("worldedit.descend.obstructed"));
|
||||
return;
|
||||
}
|
||||
|
||||
int descentLevels = 0;
|
||||
while (player.descendLevel()) {
|
||||
++descentLevels;
|
||||
|
@ -150,11 +150,11 @@ public class SchematicCommands {
|
||||
public void loadall(
|
||||
Actor actor, LocalSession session,
|
||||
@Arg(desc = "Format name.", def = "fast")
|
||||
String formatName,
|
||||
String formatName,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
String filename,
|
||||
@Switch(name = 'o', desc = "Overwrite/replace existing clipboard(s)")
|
||||
boolean overwrite
|
||||
boolean overwrite
|
||||
// @Switch(name = 'r', desc = "Apply random rotation") <- not implemented below.
|
||||
// boolean randomRotate
|
||||
) throws FilenameException {
|
||||
@ -196,7 +196,7 @@ public class SchematicCommands {
|
||||
public void unload(
|
||||
Actor actor, LocalSession session,
|
||||
@Arg(desc = "File name, requires extension.")
|
||||
String fileName
|
||||
String fileName
|
||||
) throws WorldEditException {
|
||||
URI uri;
|
||||
if (fileName.startsWith("file:/") || fileName.startsWith("http://") || fileName.startsWith("https://")) {
|
||||
@ -204,7 +204,9 @@ public class SchematicCommands {
|
||||
} else {
|
||||
final LocalConfiguration config = this.worldEdit.getConfiguration();
|
||||
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();
|
||||
}
|
||||
|
||||
@ -304,6 +306,7 @@ public class SchematicCommands {
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
// From Allink
|
||||
@Command(
|
||||
name = "load",
|
||||
desc = "Load a schematic into your clipboard"
|
||||
@ -312,9 +315,9 @@ public class SchematicCommands {
|
||||
public void load(
|
||||
Actor actor, LocalSession session,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
String filename,
|
||||
@Arg(desc = "Format name.", def = "fast")
|
||||
String formatName
|
||||
String formatName
|
||||
) throws FilenameException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
@ -323,83 +326,69 @@ public class SchematicCommands {
|
||||
InputStream in = null;
|
||||
try {
|
||||
URI uri;
|
||||
if (formatName.startsWith("url:")) {
|
||||
String t = filename;
|
||||
filename = formatName;
|
||||
formatName = t;
|
||||
}
|
||||
if (filename.startsWith("url:")) {
|
||||
if (!actor.hasPermission("worldedit.schematic.load.web")) {
|
||||
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.web"));
|
||||
|
||||
File saveDir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||
File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS
|
||||
? new File(saveDir, actor.getUniqueId().toString())
|
||||
: saveDir;
|
||||
File file;
|
||||
if (filename.startsWith("#")) {
|
||||
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;
|
||||
}
|
||||
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 {
|
||||
File saveDir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||
File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(saveDir, actor.getUniqueId().toString()) : saveDir;
|
||||
File file;
|
||||
if (filename.startsWith("#")) {
|
||||
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;
|
||||
}
|
||||
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !actor.hasPermission("worldedit.schematic.load.other") && Pattern
|
||||
.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
||||
.matcher(filename)
|
||||
.find()) {
|
||||
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.other"));
|
||||
return;
|
||||
}
|
||||
if (filename.matches(".*\\.[\\w].*")) {
|
||||
format = ClipboardFormats
|
||||
.findByExtension(filename.substring(filename.lastIndexOf('.') + 1));
|
||||
} else {
|
||||
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !actor.hasPermission("worldedit.schematic.load.other") && Pattern
|
||||
.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
||||
.matcher(filename)
|
||||
.find()) {
|
||||
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.other"));
|
||||
return;
|
||||
}
|
||||
if (filename.matches(".*\\.[\\w].*")) {
|
||||
format = ClipboardFormats
|
||||
.findByExtension(filename.substring(filename.lastIndexOf('.') + 1));
|
||||
} else {
|
||||
format = ClipboardFormats.findByAlias(formatName);
|
||||
}
|
||||
format = ClipboardFormats.findByAlias(formatName);
|
||||
}
|
||||
file = MainUtil.resolve(dir, filename, format, false);
|
||||
}
|
||||
if (file == null || !file.exists()) {
|
||||
if (!filename.contains("../")) {
|
||||
dir = this.worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||
file = MainUtil.resolve(dir, filename, format, false);
|
||||
}
|
||||
if (file == null || !file.exists()) {
|
||||
if (!filename.contains("../")) {
|
||||
dir = this.worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
|
||||
file = MainUtil.resolve(dir, filename, format, false);
|
||||
}
|
||||
}
|
||||
if (file == null || !file.exists() || !MainUtil.isInSubDirectory(saveDir, file)) {
|
||||
actor.printError(TextComponent.of("Schematic " + filename + " does not exist! (" + (file != null && file.exists()) +
|
||||
"|" + file + "|" + (file != null && !MainUtil
|
||||
.isInSubDirectory(saveDir, file)) + ")"));
|
||||
}
|
||||
if (file == null || !file.exists() || !MainUtil.isInSubDirectory(saveDir, file)) {
|
||||
actor.printError(TextComponent.of("Schematic " + filename + " does not exist! (" + (file != null && file.exists()) +
|
||||
"|" + file + "|" + (file != null && !MainUtil
|
||||
.isInSubDirectory(saveDir, file)) + ")"));
|
||||
return;
|
||||
}
|
||||
if (format == null) {
|
||||
format = ClipboardFormats.findByFile(file);
|
||||
if (format == null) {
|
||||
actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName)));
|
||||
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);
|
||||
actor.print(Caption.of("fawe.worldedit.schematic.schematic.loaded", filename));
|
||||
} catch (IllegalArgumentException e) {
|
||||
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()))));
|
||||
LOGGER.warn("Failed to load a saved clipboard", e);
|
||||
} 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.SchematicCommands;
|
||||
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.SelectionCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.SnapshotCommands;
|
||||
@ -559,11 +557,6 @@ public final class PlatformCommandManager {
|
||||
RegionCommandsRegistration.builder(),
|
||||
new RegionCommands()
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
ScriptingCommandsRegistration.builder(),
|
||||
new ScriptingCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
SelectionCommandsRegistration.builder(),
|
||||
|
@ -24,6 +24,7 @@ import com.fastasyncworldedit.core.math.Vector3Impl;
|
||||
import com.fastasyncworldedit.core.util.MathMan;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import dev.plex.SanityChecks;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@ -61,7 +62,10 @@ public abstract class Vector3 {
|
||||
}
|
||||
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
|
||||
|
@ -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);
|
||||
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
|
||||
scriptTimeout = getInt("scripting-timeout", scriptTimeout);
|
||||
calculationTimeout = getInt("calculation-timeout", calculationTimeout);
|
||||
maxCalculationTimeout = getInt("max-calculation-timeout", maxCalculationTimeout);
|
||||
saveDir = getString("schematic-save-dir", saveDir);
|
||||
scriptsDir = getString("craftscript-dir", scriptsDir);
|
||||
butcherDefaultRadius = getInt("butcher-default-radius", butcherDefaultRadius);
|
||||
butcherMaxRadius = getInt("butcher-max-radius", butcherMaxRadius);
|
||||
allowSymlinks = getBool("allow-symbolic-links", allowSymlinks);
|
||||
|
@ -127,9 +127,6 @@ public class YAMLConfiguration extends LocalConfiguration {
|
||||
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
allowSymlinks = node.getNode("files", "allow-symbolic-links").getBoolean(false);
|
||||
|
Loading…
Reference in New Issue
Block a user